ActiveX控件嵌入网页,关闭网页时报错的问题

来源:互联网 发布:mysql查询避免重复 编辑:程序博客网 时间:2024/04/30 08:53

http://community.csdn.net/Expert/topic/3160/3160265.xml?temp=.5274317

出现你说的问题,一般来说是指针问题,很可能是资源没安全释方

你可以跟一下,是否到了 FinalRelease, 如果没到这里,那需要你在 IOleObject_Close release 接口(接口交叉引用造成不能释放),最终达到资源安全是否的目的

ATL 中对应

IOleObject_SetClientSite
IOleObject_Close

在覆盖这2个方法的时候,注意要调 CComControlBase 的相应方法
-------------------------------------------------------------------------------------------

(转)问题:在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 Shepherd)

--------------------------------------
相关资源 http://support.microsoft.com/default.aspx?scid=kb;EN-US;195188