2011-11-25 86 views
4

我在VisualC++ 10中使用ATL来托管浏览器控件。 我的代码类似于这个例子:http://msdn.microsoft.com/en-us/library/9d0714y1(v=vs.80).aspx如何清洁地销毁WebBrowser控件

区别是我有主窗口,然后子窗口主持浏览器控制。 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); 
} 

谢谢!

+0

我记得关闭浏览器控件的问题,其中的原因是“本地” COM初始化/反初始化。为了支持野兽的异步特性,需要在'main'中调用CoInitialize。但大概你已经有了? –

+0

是的,这些东西被掩盖了.. 我们也在对话框上使用IE控件 - 这些工作正常。 – hB0

+0

我通过主线程的主窗口创建IE控逆变则主要产生一个新的线程,从那里我打电话导航(),它显示的网页,一分钟后,我把这个上面从子线程中提到的close()函数,浏览器控制消失,但它仍然存在,因为有时IEControl滚动条可见,并且iexplore.exe(out-of)进程也在运行.. – hB0

回答

0

我的经验是有些呼叫可能需要消息处理才能正常工作。尝试在呼叫之间抽取一些消息至Navigate,Stop等。当使用网络浏览器界面I PostMessage时,我经常会触发下一步,以确保上一步有时间完成。

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

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

感谢您的输入。 但是,编组btw线程没有问题 - 并且线程a重新成功地能够控制IE(导航) 多次调用IE控制之间没有问题 - 工作正常。 嗯,我刚刚测试了一个新的Win32应用程序与主线程和工作线程在这两种情况下IE不会终止相同的情况。 – hB0

+0

如果不进行某些编组,则不允许从未创建浏览器控件的线程进行调用。也许编组是在幕后完成的,但这是必要的。只是打电话似乎可行,但谁知道什么消息会丢失。但是你是否也在单线程场景中说这个问题依然存在? –

+0

是的。 如果我使用对话框并在其上掉落IEControl作为资源和对话框从CAxDialogImpl <>衍生的 - 然后在对话框的的DestroyWindow()是自动操作的方式清理(); – hB0

0

如果我使用对话框,并在其上掉落IEControl作为一种资源和对话框从CAxDialogImpl <衍生> - 然后在我打电话对话框中的DestroyWindow(),然后它会自动做清理() - 这是我所要求的。 但是我最初是想摆脱对话框本身并直接在我的窗口中使用了IEControl,似乎不..

8

我有很多问题,“访问冲突”关闭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()

IWebBrowser2->Quit()不应该要求WebBrowser控件(CLSID_WebBrowser),其仅适用于Internet Explorer对象(CLSID_InternetExplorer)。

它为什么一定要这么难?

+1

不久前投票,但需要说的是:**这篇文章是黄金。** *帮助我在多次打开/关闭后防止嵌入式浏览器崩溃* – CodeAngry

+1

不应该(5)在之前(3)? (5)阻止来自用户的任何新输入。(3)停止任何正在进行的浏览器活动。考虑用户可能会导致浏览器在(3)和(5)之间再次执行某些操作,例如通过点击浏览器窗口中的某个地方。把我看作潜在的竞争条件。 – mity

+0

@mitty调用(3)和(4)应立即执行,我认为它们在主UI线程上执行。但是,我不是IE专家,不应该因为您所建议的改变呼叫顺序而受伤。我没有编辑我的答案,因为我没有测试过它。 –