zoukankan      html  css  js  c++  java
  • Activex感知网页刷新关闭事件

    原因

    大多数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 > 
    }

    ---------------------------------

    http://blog.csdn.net/flyingroc0209/article/details/51036113

  • 相关阅读:
    函数声明与函数指针
    【LeetCode】三角形最小路径和
    【LeetCode】字符串中的第一个唯一字符
    【LeetCode】基本计算器II
    【LeetCode】二叉树的最小深度
    【LeetCode】加油站
    java中json与对象的转换
    idea2017 无法使用maven3.6.3版本导入依赖
    springboot项目注册为windows系统服务并设置开机自启
    springmvc上传文件
  • 原文地址:https://www.cnblogs.com/wainiwann/p/7059064.html
Copyright © 2011-2022 走看看