如何干净地销毁 WebBrowser 控件

发布于 2024-12-17 19:41:44 字数 706 浏览 5 评论 0原文

我在 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);
}

谢谢!

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!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

缺⑴份安定 2024-12-24 19:41:45

关闭网络浏览器控件时,我遇到了许多“访问冲突”问题,这些是对我有用的步骤:

  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() IOleInPlaceObject->InPlaceDeactivate()释放()
  9. IOleObject->DoVerb(OLEIVERB_HIDE, NULL, IOleClientSite, 0, windowHandle_, NULL)
  10. IOleObject->Close(OLECLOSE_NOSAVE)
  11. OleSetContainedObject(IOleObject, FALSE)< /code>
  12. IOleObject->SetClientSite(NULL)
  13. CoDisconnectObject(IOleObject, 0)
  14. IOleObject->Release()

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

为什么一定要这么难?

I had many problems with "access violation" when closing webbrowser control, these are the steps that worked for me:

  1. Unadvise any previously advised events (DWebBrowserEvents2 in my case).
  2. If you've attached click events unattach them like this: _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) - when closing browser window through window.external.CloseWindow() I had unhandled exceptions and OLECMDID_CLOSE fixed it.
  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() 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?

傻比既视感 2024-12-24 19:41:45

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

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

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

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.
  • ...
时光瘦了 2024-12-24 19:41:45

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

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..

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文