我正在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);
}
谢谢!
我在关闭Web浏览器控件时遇到了许多"访问违规"问题,以下是对我有效的步骤:
- 取消通知任何以前建议的事件(在我的情况下为DWebBrowserEvents2(
- 如果您已附加点击事件,请按如下方式取消附加:
_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((关闭浏览器窗口时,我遇到了未处理的异常,OLCMDID_CLOSE修复了它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()
不应为WebBrowser控件(CLSID_WebBrowser(调用IWebBrowser2->Quit()
,它仅用于Internet Explorer对象(CLSID_InternetExplorer(。
为什么一定要这么难?
我的经验是,有些调用可能需要消息处理才能正常工作。尝试在对Navigate
、Stop
等的调用之间发送一些消息。在使用web浏览器界面时,我经常自己PostMessage
来触发下一步,以确保上一步有时间完成。
问题可能与您的子线程有关。如果没有一些额外的工作,就无法访问线程之间的web浏览器接口。COM需要初始化为单线程单元(STA(。你需要遵守STA的规则:
- 每个对象应该只存在于一个线程上(在一个单线程单元内(。初始化每个线程的COM库
- 在公寓之间传递对象时,封送所有指向对象的指针
- 每个单线程单元都必须有一个消息循环来处理来自其他进程和同一进程内单元的调用。没有对象的单线程单元(仅限客户端(还需要一个消息循环来调度一些应用程序使用的广播消息
如果我使用DialogBox并将其上的IEControl作为资源删除,并且DialogBox是从CAxDialogImpl<>-然后,当我调用dialogBox的DestroyWindow((时,它会自动执行cleanup((,这正是我所需要的。但最初我想摆脱DialogBox本身,直接在我的Window上使用IEControl,似乎不是。。