如何干净地销毁 WebBrowser 控件
我在 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 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
关闭网络浏览器控件时,我遇到了许多“访问冲突”问题,这些是对我有用的步骤:
_variant_t v; v.vt = VT_DISPATCH; v.pdispVal = 0; IHTMLDocument2->put_onclick(v);
IWebBrowser2->Stop()
IWebBrowser2->ExecWB(OLECMDID_CLOSE, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0)
- 当通过 window.external.CloseWindow() 关闭浏览器窗口 我遇到了未处理的异常OLECMDID_CLOSE 修复了它。IWebBrowser2->put_Visible(VARIANT_FALSE)
IWebBrowser2->Release()
IOleInPlaceObject->InPlaceDeactivate()
IOleInPlaceObject-> Release()
IOleInPlaceObject->InPlaceDeactivate()
释放()IOleObject->DoVerb(OLEIVERB_HIDE, NULL, IOleClientSite, 0, windowHandle_, NULL)
IOleObject->Close(OLECLOSE_NOSAVE)
OleSetContainedObject(IOleObject, FALSE)< /code>
IOleObject->SetClientSite(NULL)
CoDisconnectObject(IOleObject, 0)
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:
_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?
我的经验是,某些调用可能需要消息处理才能正常运行。尝试在对
Navigate
、Stop
等的调用之间发送一些消息。在使用 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 IPostMessage
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:
Initialize the COM library for each thread.
如果我使用 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..