原因

大多数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(,,,), CRect(,,,)));
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 = {,,,};
// 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

最新文章

  1. November 3rd Week 45th Thursday 2016
  2. Python 字符串反转
  3. String类型和基本数据类型之间的转换
  4. list操作 foreach和for的区别
  5. 用for循环打印菱形
  6. Fragment+FragmentTabHost组件实现常见主页面(仿微信新浪)
  7. Linux下c函数dlopen实现加载动态库so文件代码举例
  8. Delphi窗体中禁用最大化按钮
  9. glance image cache
  10. CSS设计指南之理解盒子模型
  11. Thinking in scala (7)---- f(n)=f(n-1)+2f(n-2)+3f(n-3)
  12. less可以做什么?less详解!(less嵌套选择器实现纯CSS二级导航)
  13. C程序设计语言(第二版)--- 习题选
  14. UI设计之动画—从虚拟到现实
  15. 深入解析HashMap、HashTable
  16. python dict的函数
  17. 微信小程序常见问题
  18. jQuery——检测滚动条是否到达底部
  19. 矩形嵌套(dp)
  20. Zookeeper笔记之使用zk实现集群选主

热门文章

  1. C#文件与文件夹操作
  2. 内存保护机制及绕过方案——通过覆盖SEH异常处理函数绕过/GS机制
  3. docker-es
  4. AngularJs 中的transclude的理解
  5. How do I create zip file in Servlet for download?
  6. 你所不知道的,Java 中操作符的秘密?
  7. GIT多人合作开发
  8. LeetCode Construct Binary Tree from String
  9. #51单片机#超声波测距(HC-SR04)的使用方法
  10. JAVA单例模式:懒汉式,饿汉式