C++ 如何彻底销毁WebBrowser控件

C++ 如何彻底销毁WebBrowser控件,c++,visual-studio-2010,webbrowser-control,atl,iwebbrowser2,C++,Visual Studio 2010,Webbrowser Control,Atl,Iwebbrowser2,我正在VisualC++10中使用ATL来主持浏览器控件。 我的代码与此示例类似: 区别在于我有主窗口,然后子窗口托管浏览器控件。 2分钟后,我必须关闭浏览器,完全关闭浏览器activeX,但此子窗口应处于活动状态,并执行其他操作。但不知何故,这个浏览器控件仍然保留在那里,我可以看到滚动条或其他东西 我也尝试过在现有的子窗口中创建子窗口,在关闭浏览器时,我会销毁子窗口的这个子窗口,但仍然不起作用 这就是我结束的方式: CLOSE() { m_spIWebBrowser2->Navi

我正在VisualC++10中使用ATL来主持浏览器控件。 我的代码与此示例类似:

区别在于我有主窗口,然后子窗口托管浏览器控件。 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浏览器界面时,我经常会触发下一步,以确保前一步有时间完成

问题可能与您的子线程有关。如果不做一些额外的工作,就无法访问线程之间的web浏览器接口。COM需要初始化为单线程单元(STA)。你需要遵循:

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

如果我使用DialogBox并在其上放置一个IECControl作为资源,并且DialogBox是从CAxDialogImpl派生的-那么当我调用DialogBox的DestroyWindow()时,它会自动执行cleanup()-这是我所需要的。 但最初我想摆脱DialogBox本身,直接在我的窗口上使用IECControl,这似乎不是….

我在关闭webbrowser控件时遇到了许多“访问冲突”问题,以下是对我有效的步骤:

  • 不建议任何先前建议的事件(在我的案例中为DWebBrowserEvents2)
  • 如果已附加click events,请按如下方式取消附加它们:
    \u variant\u t v;v、 vt=vt_调度;v、 pdispVal=0;IHTMLDocument2->put_onclick(v)
  • IWebBrowser2->Stop()
  • IWebBrowser2->ExecWB(OLECMDID\u CLOSE,OLECMDEXECOPT\u DONTPROMPTUSER,0,0)
    -通过window.external.CloseWindow()关闭浏览器窗口时,我有未处理的异常,OLECMDID\u CLOSE修复了它
  • IWebBrowser2->put\u Visible(变量\u FALSE)
  • IWebBrowser2->Release()
  • IOleInPlaceObject->InPlaceDeactivate()
  • IOleInPlaceObject->Release()
  • IOleObject->DoVerb(OLEIVERB\u HIDE,NULL,IOleClientSite,0,windowHandle\u,NULL)
  • IOleObject->Close(OLECLOSE\u NOSAVE)
  • OleSetContainedObject(IOleObject,FALSE)
  • IOleObject->SetClientSite(空)
  • CoDisconnectObject(IOleObject,0)
  • IOleObject->Release()
  • 不应为WebBrowser控件(CLSID\u WebBrowser)调用
    IWebBrowser2->Quit()
    ,它仅用于Internet Explorer对象(CLSID\u InternetExplorer)


    为什么这么难?

    我记得关闭webbrowser控件时出现了一个问题,原因是“本地”COM初始化/取消初始化。要支持beast的异步特性,需要在
    main
    中调用CoInitialize。但想必你已经有了?是的那些东西被掩盖了。。我们还在对话框上使用IE控件-这些控件工作正常。我通过主线程在mainwindow上创建了IE控件,然后main生成了一个新线程,从那里我调用navigate()并显示网页,一分钟后我从子线程调用上述close()函数,浏览器控件消失,但仍然存在,原因是有时可以看到IEControl滚动条,并且iexplore.exe(out of)进程也在运行。进程的生存期由引用计数控制。你没有破坏你的智能指针。谢谢,但是:IWebBrowser2*iw;g_spWebBrowser2->查询接口(&iw);ULONG ul=iw->Release();AtlAxWinTerm();不过,它还在继续。谢谢你的意见。但是,编组btw线程没有问题——线程能够成功地控制IE(导航),在多次调用IE控制之间没有问题——工作正常。我刚刚用一个新的Win32应用程序测试了相同的场景,在这两种情况下,主线程和工作线程IE都不会终止。如果线程没有创建浏览器控件,则不允许在不进行编组的情况下从该线程调用浏览器控件。也许编组是在幕后进行的,但这是必要的。只是打个电话可能看起来有用,但谁知道会丢失哪些信息。但是你是说在单线程场景中问题仍然存在吗?是的。如果我使用DialogBox并在其上放置一个IECControl作为资源,DialogBox是从CAxDialogImpl派生的,那么DialogBox的destroywindow()会自动进行清理();投票前一段时间,但需要说的是:这个职位是黄金。在多次打开/关闭后帮助我防止嵌入式浏览器崩溃。是否(5)应该在(3)之前?(5) 防止来自用户的任何新输入。(3) 停止任何正在进行的浏览器活动。考虑用户可能导致浏览器再次在(3)和(5)之间做一些事情,例如通过点击浏览器窗口中的某个地方。在我看来,这是一个潜在的竞争条件。@mitty调用(3)和(4)应该立即执行,我认为它们是在主UI上执行的