描述:
看了以前的文档,在网上搜索全部是atl实现的方法
mfc做的activex控件如何取得IWebBrowser2?
解决方案1:
ActiveX控件中访问文档对象模型
知识库文章Q172763 INFO: Accessing the Object Model from Within an ActiveX Control 描述了这个问题的解决方案。可以看到,可以同样使用IOleClientSite来和IE这个控件容器交互。可以使用IOleClientSite::GetContainer得到网页所在HTML文档对象的IOleContainer接口,然后再查询其他接口,例如IHTMLDocument2来进行对DHTML对象模型的访问。
问题:在IE中ActiveX控件的WM_CREATE和WM_DESTORY处理函数没有被调用
概述
IE直到控件第一次可见的时候才创建ActiveX控件,调用WM_CREATE的处理代码。在离开或者关闭页面的时候也没有调用WM_DESTORY的处理代码。在控件大小是0*0的时候也有同样的问题。如果你在这之前(例如window.onload事件的处理代码中)访问控件的窗口或者子窗口,那么不会成功。
原因
大多数ActiveX控件框架,例如MFC和ATL,在本地激活ActiveX控件时创建控件。基于性能上的考虑,直到控件第一次可见的时候,IE才本地激活ActiveX控件。这样包含ActiveX控件的网页载入更加迅速,占用内存更少。这也使得ActiveX控件的WM_CREATE处理代码直到控件第一次可见的时候才被调用。
如果控件支持非窗口激活,那么IE会以非窗口激活方式创建控件,这样在离开或者关闭页面的时候控件的WM_DESTORY处理代码不会被调用。
解决方案
IE在初始化或者退出页面的时候会调用页面中的ActiveX控件的IOleObject::SetClientSite的实现,无论控件是否被本地激活。在初始化页面的时候,传递的指针是宿主的IOleClientSite 接口指针,在离开或者关闭页面的时候,传递的指针是空指针。可以根据这个指针来判断控件的状态,并且执行初始化或者清除的代码。
MFC
MFC对IOleObject::SetClientSite()的实现包含对虚函数COleControl::OnSetClientSite()的调用。这时候可以根据m_pClientSite是否为空指针来判断控件是被加载还是被清除。
// CMyControl 派生于COleControl.
void CMyControl::OnSetClientSite()
{
if (m_pClientSite)
//父窗口及其大小并不重要,因为控件在本地激活时会自动重画和重新定位。
VERIFY (CreateControlWindow (::GetDesktopWindow(), CRect(0,0,0,0), CRect(0,0,0,0)));
else
DestroyWindow();
COleControl::OnSetClientSite();
}
ATL
ATL对IOleObject::SetClientSite()的实现有一个IOleClientSite类型的参数(MFC在对IOleObject::SetClientSite()的实现中保存这个指针到COleControl::m_pClientSite),直接拿来判断就行了。同时,ATL没有重新设置控件的父窗口,所以控件需要手动进行本地激活。
// CMyControl 派生于CComControl
STDMETHOD(SetClientSite)(IOleClientSite *pClientSite)
{
if (pClientSite)
{
RECT rc = {0,0,0,0};
// Don't have access to the container's window so just use the
// desktop. Window will be resized correctly during in-place
// activation.
HWND hWnd = CreateControlWindow(::GetDesktopWindow(), rc);
_ASSERT (hWnd);
}
else
::DestroyWindow(m_hWnd);
return IOleObjectImpl::SetClientSite (pClientSite);
}
HRESULT InPlaceActivate(LONG iVerb, const RECT* prcPosRect)
{
// Get the container's window. _ASSERT (m_spClientSite);
LPOLEINPLACESITE pInPlaceSite = NULL;
HRESULT hr = m_spClientSite->QueryInterface(IID_IOleInPlaceSite, (void **)&pInPlaceSite);
_ASSERT (SUCCEEDED (hr) && pInPlaceSite);
HWND hParent = NULL;
hr = pInPlaceSite->GetWindow (&hParent);
_ASSERT (SUCCEEDED (hr) && hParent);
pInPlaceSite->Release ();
// Set container window as our parent window
SetParent (hParent); < BR > return CComControlBase::InPlaceActivate(iVerb, prcPosRect); < BR > }
重现问题的步骤
使用MFC 或者ATL创建一个ActiveX控件
添加这两个消息的处理函数
使用IE作为调试程序
参考
ActiveX Control Containers(Internet Development SDK)
KB Q195188 PRB: ActiveX Control Window Is Not Created Until Visible in Internet Explorer
Notes on Implementing an OLE Control Container(Kraig Brockschmidt)
Introduction to ActiveX Controls (Internet Development SDK)
Reusing MSHTML (Internet Development SDK)
用ATL和MFC来创建ActiveX控件(George Shepher
Inside OLE, 第二版, Kraig Brockschmidt著 (微软出版社)
Understanding ActiveX and OLE, David Chappell著 (微软出版社)
Inside COM, by Dale Rogerson著 (微软出版社) d)
您可能想查找下面的文章:
- IWebBrowser2::Navigate的问题
- IWebBrowser2::Navigate的问题
- 请教IWebBrowser2问题~~~~~~~~~在线等
- 如何用IWebBrowser2判断当前窗口是否处于激活状态?
- ATL下有没有包装过的(基础是IWebBrowser2)的浏览器控件可用?或者哪里有源代码可以下载?
- 通过IWebBrowser2能获得IE中已经载入的其他插件的接口么?
- 给定一个url,如何用IWebBrowser2接口获得该url的源码?
- 如何在activex中得到IWebBrowser2指针???
- 提问一个IWebBrowser2如何自动保存当前的文件啊,如果用EXECWB会弹出SAVE窗口,我想不让他弹出,比如自动保存到C:下,请问这个怎么搞啊,有点
- 关于IWebBrowser2的get_Width,get_Height问题(解决后将加到200分,不够再加,多谢!)