源代码下载:MyActiveX20081229.rar
声明:本文代码基于CodeProject的文章《A Complete ActiveX Web Control Tutorial》修改而来,因此同样遵循Code Project Open License (CPOL)。
在上一篇文章《COM组件开发实践(七)---多线程ActiveX控件和自动调整ActiveX控件大小(上)》中介绍了ActiveX控件中使用多线程的基本需求,并提出了一个简单的线程模型,但却出现了意想不到的问题,本文将尝试给出问题的一个可行的解法,并同时解决上文中提出的第二个问题。
其实解决的思路也很简单,一开始我也早就想到了的,就是使用让子线程PostMessage来发出自定义的消息来通知主线程,特定的事件已经发生了,需求主线程去响应。这不是什么了不起的想法,但我对子线程PostMessage非常恐惧,因为以前的一个项目中就是这个问题导致了内存泄露,所以这个方案一开始就被我否定了。
遍寻解决之道不可得时,只得在csdn的论坛上发贴求教高手了,具体的讨论请参考这个帖子:
http://topic.csdn.net/u/20081226/17/9bf0ae08-c54d-4934-b1b2-91baa27ff76e.html
看到jameshooo(胡柏华)的回帖后,还是决定回到起点,尝试用PostMessage这个方案。
首先自定义两个事件,分别表示操作成功和操作失败
#define WM_OPTSUCCESS WM_APP+101 //操作成功
#define WM_OPTFAILED WM_APP+102    //操作失败
然后回调函数中就变得非常简单,只需要post对应的事件即可。
复制代码
/
//回调函数
/
void CMyActiveXCtrl::OnSuccesful()
{//操作成功
this->PostMessage(WM_OPTSUCCESS,(WPARAM)NULL,(LPARAM)NULL);
}
void CMyActiveXCtrl::OnFailed()
{//操作失败
this->PostMessage(WM_OPTFAILED,(WPARAM)NULL,(LPARAM)NULL);
}
复制代码
再重载消息处理函数WindowProc,在其中调用外部的JavaScript函数或者Fire出外部页面可以响应的事件。
复制代码
LRESULT CMyActiveXCtrl::WindowProc(UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_OPTSUCCESS:
{//操作成功,通知外部页面
CString strOnLoaded("OnLoaded");
this->CallJScript(strOnLoaded);
return 0;
}
case WM_OPTFAILED:
{//操作失败,通知外部页面
//这里不写了,同上面
}
}
return   COleControl::WindowProc(msg,wParam,lParam);   
}
复制代码
在OnCreate函数中加入启动工作线程代码:
复制代码
int CMyActiveXCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
m_MainDialog.Create(IDD_MAINDIALOG, this);
pThread.SetICallBack(this);//设置主线程回调函数
pThread.Start();//启动工作线程
return 0;
}
复制代码
重载掉OnClose函数,在其中加入关闭工作线程的代码:
复制代码
void CMyActiveXCtrl::OnClose(DWORD dwSaveOption)
{
pThread.Stop(true);//强行关闭工作线程
COMRELEASE(pWebBrowser);
COMRELEASE(pHTMLDocument);
COleControl::OnClose(dwSaveOption);
}
复制代码
到此为止,一个多线程的ActiveX控件就诞生了。这里是不会发生以前我遇到的内存泄露的,因为情况不同了,只是在回调函数中简单的post一个message,并没有new一个内存区域并将这块内存作为参数post给主线程,后面这种情况是可能会内存泄露的。
Ok,下面来考虑第二个问题,先简单介绍下具体需求:就是一个AcitveX控件会用到不同的页面中,每个页面对这个控件的需求也不同,也就要求在两个不同的页面中,控件显示的大小也不同。
jameshooo(胡柏华) 回帖说:“改变控件大小要通知容器,由容器再反过来通知控件改变大小,不然没有任何效果。调用IOleInPlaceSite::OnPosRectChange即可”。因此就根据这个来尝试提出一个解决方案来。
假设有两种模式的控件,一种是“普通”模式, 如下图所示:
一种是“特殊”模式,
为了区别开两者,就考虑在web页面中通过设置参数的方式来通知ActiveX控件,对于不同的模式填充不同的对话框就可以了。我们在web页面中控件部分加入如下参数:
<PARAM NAME="IsSpecial" VALUE="TRUE">
相应的在CMyActiveXCtrl类中加入一个变量,这里为简单起见,选择了类型为CString型,主要是为了传参数方便。
CString m_bIsSpecial;//是否是"特殊"页面
Web页面传入的参数值在下面这个函数中读取:
复制代码
void CMyActiveXCtrl::DoPropExchange(CPropExchange* pPX)
{
ExchangeVersion(pPX, MAKELONG(_wVerMinor, _wVerMajor));
COleControl::DoPropExchange(pPX);
PX_String(pPX,   _T("IsSpecial"),   m_bIsSpecial); //读取外部设置的参数
}
复制代码
为了供控件选择,这里提供了两种模式的对话框:
public:
CMyDlgTwo m_dlgSpecial;//特殊模式
CMyDlgThree m_dlgCommon;//普通模式
然后在创建和绘制对话框时,通过检测参数是否为空就知道待创建的对话框类型到底是“普通“还是”特殊“了。
复制代码
int CMyActiveXCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (COleControl::OnCreate(lpCreateStruct) == -1)
return -1;
CRect newRc; 
if(m_bIsSpecial.Compare(_T(""))==0)
{//没设置参数,"普通“模式
this->m_dlgCommon.Create(IDD_DIALOG3,this);
//设置控件的大小
newRc.left = 0; 
newRc.top = 0; 
newRc.right = 200; 
newRc.bottom = 200; 
}
else
{//设置了参数,”特殊“模式
this->m_dlgSpecial.Create(IDD_DIALOG2,this);
//设置控件的大小
newRc.left = 0; 
newRc.top = 0; 
newRc.right = 200; 
newRc.bottom = 200; 
}
this->m_pInPlaceSite->OnPosRectChange(&newRc);
return 0;
}
void CMyActiveXCtrl::OnDraw(
CDC* pdc, const CRect& rcBounds, const CRect& rcInvalid)
{
if (!pdc)
return;
if(m_bIsSpecial.Compare(_T(""))==0)
{//没设置参数,"普通“模式
this->m_dlgCommon.MoveWindow(rcBounds,TRUE);
}
else
{//设置了参数,”特殊“模式
this->m_dlgSpecial.MoveWindow(rcBounds,TRUE);
}
}
复制代码
本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2008/12/29/1364791.html,如需转载请自行联系原作者

COM组件开发实践(八)---多线程ActiveX控件和自动调整ActiveX控件大小(下)相关推荐

  1. 《COM组件开发实践》系列文章

    COM组件开发系列链接: 1,COM组件开发实践(一) 2,COM组件开发实践(二) 3,COM组件开发实践(三) 4,COM组件开发实践(四)---From C++ to COM :Part 1 5 ...

  2. Vite + React 组件开发实践

    简介: 毫不夸张的说,Vite 给前端带来的绝对是一次革命性的变化.或者也可以说是 Vite 背后整合的 esbuild . Browser es modules.HMR.Pre-Bundling 等 ...

  3. awtk开发实践——学习篇27: guage_pointer(仪表指针控件)

    说明:   本文章旨在总结备份.方便以后查询,由于是个人总结,如有不对,欢迎指正:另外,内容大部分来自网络.书籍.和各类手册,如若侵权请告知,马上删帖致歉.   QQ 群 号:513683159 [相 ...

  4. COM组件开发实践(七)---多线程ActiveX控件和自动调整ActiveX控件大小(上)

    声明:本文代码基于CodeProject的文章<A Complete ActiveX Web Control Tutorial>修改而来,因此同样遵循Code Project Open L ...

  5. Salesforce Lightning开发学习(二)Component组件开发实践

    lightning的组件区分标准组件.自定义组件和AppExchange组件.标准组件由SF提供,自定义组件由developer自行开发,AppExchange组件由合作伙伴建立.下面我们写一个简单的 ...

  6. 【组件开发实践】云巧流程组件对接实践

    1. 用户需求 假设A系统有如下员工请假审批流场景: 员工请假小于等于3天,只需主管直接审批:大于3天需要主管先审批,审批通过后再由二级主管进行审批.当员工请假审批流节后后,需要通知A系统进行业务处理 ...

  7. Qt (高仿Visio)流程图组件开发(二) 基本图元绘制 图元间连线绘制

    文章目录 本系列目录 前言 一.如何绘制图元 二.两图元之间如何连线 三.如何实现线跟随图元移动 四.线的位置判断 总结 本系列目录 Qt (高仿Visio)流程图组件开发(一) 效果展示及基本开发框 ...

  8. Qt (高仿Visio)流程图组件开发(三) 图元基类如何定义,流程图多种图元类型实现

    文章目录 本系列目录 前言 一.图元基类的定义 1.图元信息基类结构体 2.图元位置 3.父子对象关系 二.自定义图元实现 1.自定义图元基类(FlowchartGraphicsItem)与Qt原生图 ...

  9. Qt (高仿Visio)流程图组件开发(九) 流程图 代码展示

    文章目录 本系列目录 本系列目录 Qt (高仿Visio)流程图组件开发(一) 效果展示及基本开发框架构思 Qt (高仿Visio)流程图组件开发(二) 基本图元绘制 图元间连线绘制 Qt (高仿Vi ...

最新文章

  1. 【动态规划专题】最长上升子序列模型
  2. mongodb 重启_mongodb历险记
  3. 程序员应该具备的能力
  4. 数据分析从零开始,新手小白如何入门?
  5. CORS--跨域资源共享
  6. Sharepoint 自定义字段类型
  7. STM32F7xx —— LAN8720(FreeRTOS+LWIP)
  8. Linux I2C App 开发示例
  9. linux crontab定时任务详解
  10. IAR astyle代码美化
  11. 卡尔曼滤波的基本原理
  12. 高项信息系统项目管理师考试大纲——重点知识
  13. SI和DI寄存器(0703)
  14. myeclipse9.1 安装svn(图)
  15. 2016/4/22 图形用户界面
  16. 2022-01-31的新年flag
  17. TCP协议和UDP协议的对比
  18. 4k电视测试软件准确吗,如何检测自家的电视是真4K还是假4K?当贝市场告诉你
  19. latex 数学公式_推荐一款编写数学公式的国产神器:AxMath,可与LATEX双向转换
  20. 2018国内优秀开源镜像站汇总

热门文章

  1. 在ActionBar显示ShareActionProvider分享文本,点击可以打开进行分享(19)
  2. 浏览器崩溃时提示137错误
  3. 3.25Day06元组、字典、集合常用及内置方法
  4. 对象的notify方法的含义和对象锁释放的三种情况
  5. 织梦手机网站建设 并配置二级域名
  6. [APUE]文件和目录(中)
  7. [Lua]50行代码的解释器,用来演示lambda calculus
  8. 维基链锚定行业缺口,定位发展一体化DeFi,持续开发出各类产品应用,包括去中心化抵押借贷系统Wayki-CDP(含稳定币WUSD)、去中心化交易所Wayki-DEX、去中心化合成资产协议Wayki-X
  9. Oracle真实世界数据链——将现实世界和区块链世界相互打通——让主流币爆涨十倍的项目
  10. 班门弄斧?基于BCE的Lightningspin应用对比ChainBet