如何干净地销毁WebBrowser控件

时间:2011-11-25 20:27:08

标签: c++ visual-studio-2010 webbrowser-control atl 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);
}

谢谢!

3 个答案:

答案 0 :(得分: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()
  15. 不应为WebBrowser控件(CLSID_WebBrowser)调用

    IWebBrowser2->Quit(),它仅适用于Internet Explorer对象(CLSID_InternetExplorer)。

    为什么一定要这么难?

答案 1 :(得分:0)

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

问题可能与您的子线程有关。没有一些额外的工作,您无法访问线程之间的Web浏览器界面。 COM需要初始化为单线程单元(STA)。您需要关注the rules of STAs

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

答案 2 :(得分:0)

如果我使用DialogBox并在其上放置一个IEControl作为资源而DialogBox是从CAxDialogImpl<>派生的。 - 然后当我调用dialogBox的DestroyWindow()时,它会自动执行cleanup() - 这就是我所需要的。 但最初我想摆脱DialogBox本身并直接在我的Window上使用IEControl,似乎没有..