如何干净地销毁WebBrowser控件

hB0*_*hB0 4 c++ atl webbrowser-control visual-studio-2010 iwebbrowser2

我在VisualC++ 10中使用ATL来托管浏览器控件.我的代码与此示例类似:http://msdn.microsoft.com/en-us/library/9d0714y1(v = vs.80).aspx

区别在于我有主窗口,然后子窗口承载浏览器控件.2分钟后我必须关闭浏览器完全杀死浏览器activeX但这个子窗口应该还活着并做其他事情.但不知何故,这个浏览器控件仍然存在,我可以看到滚动条或其他东西..

我还尝试通过创建子窗口到现有子窗口,并在关闭浏览器时,然后销毁这个孩子的孩子 - 但它仍然无法正常工作!

这就是我关闭的方式:

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);
}
Run Code Online (Sandbox Code Playgroud)

谢谢!

Cza*_*zak 10

关闭webbrowser控件时,我遇到了"访问冲突"的许多问题,这些步骤对我有用:

  1. 取消任何先前建议的事件(在我的情况下为DWebBrowserEvents2).
  2. 如果您附加了点击事件,请按照以下方式取消附加: _variant_t v; v.vt = VT_DISPATCH; v.pdispVal = 0; IHTMLDocument2->put_onclick(v);
  3. IWebBrowser2->Stop()
  4. IWebBrowser2->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0) - 当通过window.external.CloseWindow()关闭浏览器窗口时,我有未处理的异常,OLECMDID_CLOSE修复了它.
  5. IWebBrowser2->put_Visible(VARIANT_FALSE)
  6. IWebBrowser2->Release()
  7. IOleInPlaceObject->InPlaceDeactivate()
  8. IOleInPlaceObject->Release()
  9. IOleObject->DoVerb(OLEIVERB_HIDE, NULL, IOleClientSite, 0, windowHandle_, NULL)
  10. IOleObject->Close(OLECLOSE_NOSAVE)
  11. OleSetContainedObject(IOleObject, FALSE)
  12. IOleObject->SetClientSite(NULL)
  13. CoDisconnectObject(IOleObject, 0)
  14. IOleObject->Release()

IWebBrowser2->Quit() 不应该为WebBrowser控件(CLSID_WebBrowser)调用它,它仅适用于Internet Explorer对象(CLSID_InternetExplorer).

为什么一定要这么难?


Hei*_*cht 0

我的经验是,某些调用可能需要消息处理才能正常运行。尝试在调用之间发送一些消息NavigateStop等等。在使用网络浏览器界面时,我PostMessage自己经常触发下一步,以确保上一步有时间完成。

该问题可能与您的子线程有关。如果不做一些额外的工作,您就无法在线程之间访问 Web 浏览器界面。COM 需要初始化为单线程单元 (STA)。并且您需要遵守STA的规则

  • 每个对象应该只存在于一个线程上(在单线程单元内)。为每个线程初始化 COM 库。
  • 在公寓之间传递对象时,整理所有指向对象的指针。
  • 每个单线程单元必须有一个消息循环来处理来自其他进程和同一进程内的单元的调用。没有对象的单线程单元(仅限客户端)也需要一个消息循环来调度某些应用程序使用的广播消息。
  • ...