问题
I am using ATL in VisualC++10 to host browser control. My code is similar to this example: http://msdn.microsoft.com/en-us/library/9d0714y1(v=vs.80).aspx
Difference is I have main window and then child window hosts the browser control. After 2 minutes i have to close the browser completely kill the browser activeX but this child window should be alive and do something else. But somehow this browser control still stays there, i can either see scrollbars or something..
I have also tried by creating child window to an existing child window, and at the time of closing browser I then destroy this child of a child - but still it does not work!
This is how I am closing:
CLOSE()
{
m_spIWebBrowser2->Navigate(bstrURL, &vEmpty, &vEmpty, &vEmpty, &vEmpty);
m_spIWebBrowser2->Stop();
m_spIWebBrowser2->put_Visible(VARIANT_FALSE);
m_spIWebBrowser2->Quit();
DestroyWindow(m_wndChild.m_hWnd);
}
Thanks!
回答1:
I had many problems with "access violation" when closing webbrowser control, these are the steps that worked for me:
- Unadvise any previously advised events (DWebBrowserEvents2 in my case).
- If you've attached click events unattach them like this:
_variant_t v; v.vt = VT_DISPATCH; v.pdispVal = 0; IHTMLDocument2->put_onclick(v);
IWebBrowser2->Stop()
IWebBrowser2->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0)
- when closing browser window through window.external.CloseWindow() I had unhandled exceptions and OLECMDID_CLOSE fixed it.IWebBrowser2->put_Visible(VARIANT_FALSE)
IWebBrowser2->Release()
IOleInPlaceObject->InPlaceDeactivate()
IOleInPlaceObject->Release()
IOleObject->DoVerb(OLEIVERB_HIDE, NULL, IOleClientSite, 0, windowHandle_, NULL)
IOleObject->Close(OLECLOSE_NOSAVE)
OleSetContainedObject(IOleObject, FALSE)
IOleObject->SetClientSite(NULL)
CoDisconnectObject(IOleObject, 0)
IOleObject->Release()
IWebBrowser2->Quit()
should not be called for WebBrowser control (CLSID_WebBrowser), it is intended only for Internet Explorer object (CLSID_InternetExplorer).
Why must it be so hard?
回答2:
My experience is that some calls might need message processing to function properly. Try to pump some messages between your calls to Navigate
, Stop
etc. When working with the web browser interfaces I PostMessage
myself often to trigger the next step to make sure the previous step had time to complete.
The problem might be related to your child thread. You cannot access web browser interfaces between threads without some additional work. COM needs to be initialized as single-threaded apartment (STA). And you need to follow the rules of STAs:
- Every object should live on only one thread (within a single-threaded apartment). Initialize the COM library for each thread.
- Marshal all pointers to objects when passing them between apartments.
- Each single-threaded apartment must have a message loop to handle calls from other processes and apartments within the same process. Single-threaded apartments without objects (client only) also need a message loop to dispatch the broadcast messages that some applications use.
- ...
回答3:
If I use DialogBox and drop a IEControl on it as a resource and DialogBox is derived from CAxDialogImpl<> - then while I call DestroyWindow() of dialogBox then it is automatically doing the cleanup() - which is what I required. But originally I wanted to get rid of DialogBox itself and use IEControl directly on my Window, it seems not..
来源:https://stackoverflow.com/questions/8273910/how-to-cleanly-destroy-webbrowser-control