COM组件(ATL篇)
目录
第1章创建进程内组件
1.1 目标
本章的目标是使用ATL创建一个进程内COM组件。在此组件里,将实现COM类CStatistic及COM接口IStatistic,用来进行统计计算。IStatistic的详细信息如下:
1、方法
void Reset(); //重新开始统计计算
void Add(double dVal); //增加一个数据
2、属性
long Count; //返回数据个数
double Average; //返回平均值
double StdDev; //返回标准差
CStatistic的VC++代码如下:
|
#include <MATH.H> class CStatistic { public: CStatistic() {Reset();} public: void Reset() {memset(this,0,sizeof(*this));} void Add(double dVal) { ++m_nCount; //样本个数 m_dSum += dVal; //所有样本值的和 m_dSum2 += dVal * dVal; //所有样本值的平方和 } public://属性定义(VC++的语法) __declspec(property(get=GetCount)) ULONG Count; __declspec(property(get=GetAverage)) double Average; __declspec(property(get=GetStdDev)) double StdDev; public: ULONG GetCount() const {return m_nCount;} double GetAverage() const { if(m_nCount) { return m_dSum / m_nCount; } return 0.0; } double GetStdDev() const { double d = 0.0; if(m_nCount > 1) { d = (m_nCount * m_dSum2 - m_dSum * m_dSum) / (m_nCount * (m_nCount - 1)); if(d > 0.0) { d = sqrt(d); } } return d; } private: ULONG m_nCount; //样本个数 double m_dSum; //所有样本值的和 double m_dSum2; //所有样本值的平方和 }; |
测试代码如下:
|
ULONG n = 0; double d = 0.0; CStatistic s; s.Reset(); s.Add(1.0); s.Add(2.0); s.Add(3.0); s.Add(4.0); n = s.Count; //(1,2,3,4)的个数 d = s.Average; //(1,2,3,4)的平均值 d = s.StdDev; //(1,2,3,4)的标准差 s.Add(5.0); n = s.Count; //(1,2,3,4,5)的个数 d = s.Average; //(1,2,3,4,5)的平均值 d = s.StdDev; //(1,2,3,4,5)的标准差 |
这个类的优点在于:它能实时获得样本数据的平均值、标准差,且不用把样本数据存入数组,因此可以连续的长时间工作。
1.2 创建项目
1.2.1 VC++6.0
运行VC++6.0,新建"ATL COM AppWizard"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。

图1.1
显示界面如下所示,直接单击"Finish"按钮。

图1.2
显示界面如下,单击"OK"按钮,完成项目创建。

图1.3
1.2.2 VC++2010
运行VC++2010,新建"ATL Project"项目,如下图所示。配置好项目名称、项目目录后,单击"OK"按钮。

图1.4
显示创建向导,界面如下面两张图所示:

图1.5 创建向导——页面一

图1.6 创建向导——页面二
单击上图的"Finish"按钮,完成项目的创建。
1.3 增加COM类
现在,往项目里增加COM类。
1.3.1 VC++6.0
单击【Insert】【New ATL Object...】菜单项

图1.7
显示界面如下。请选中"Objects"里的"Simple Object",然后单击"Next"按钮。

图1.8
显示界面如下,一共有两个页面。

图1.9 增加COM类——页面一
下图所示界面里,Interface有两个选项:Dual表示双接口(也叫自动化接口),它派生自IDispatch;Custom表示自定义接口,它派生自IUnknown。自定义接口直接访问虚函数表,其效率较高。自动化接口效率较低,但是它支持的语言较多。

图1.10 增加COM类——页面二
1.3.2 VC++2010
单击【Project】【Add Class...】菜单项

图1.11
选中"ATL Simple Object",然后单击"Add"按钮

图1.12
显示界面如下,一共有三个页面

图1.13 增加COM类——页面一

图1.14 增加COM类——页面二

图1.15 增加COM类——页面三
1.3.3 项目结构
VC++6.0的类视图里增加了"CStatistic"和"IStatistic"。
IStatistic是COM接口,客户端程序通过它访问COM组件。
CStatistic是COM类,真正的工作由它来完成。

图1.16
同时,idl文件也发生了变化,如下表所示。增加了接口IStatistic,增加了COM类Statistic,这个COM类实现了接口IStatistic。
|
// comDLLatl.idl import "oaidl.idl"; import "ocidl.idl"; [ uuid(0FEBC618-38BC-4A5B-AE09-3C56635F4D73), version(1.0), helpstring("comDLLatl 1.0 Type Library") ] library COMDLLATLLib { importlib("stdole32.tlb"); importlib("stdole2.tlb"); [ object, uuid(7FB59FA6-E715-4C23-9520-DE93293E0B5F), helpstring("IStatistic Interface"), pointer_default(unique) ] interface IStatistic : IUnknown { }; [ uuid(471BF24D-B793-44A1-9205-7BF36A6EB698), helpstring("Statistic Class") ] coclass Statistic { [default] interface IStatistic; }; }; |
1.4 增加方法
1.4.1 VC++6.0
鼠标右键单击接口IStatistic,弹出菜单中单击【Add Method...】菜单项

图1.17
下图就是增加方法的界面。这里增加了方法void Add(double dVal)。单击"OK"按钮,完成方法的增加。注意:对于自动化接口,Return Type只能是HRESULT。

图1.18
可使用同样的方法,增加方法void Reset()。
1.4.2 VC++2010
鼠标右键单击接口IStatistic,弹出菜单中单击【Add】【Add Method...】。

图1.19
增加方法的界面如下。与VC++6.0的大致相同。单击"Finish"按钮,完成方法void Add(DOUBLE dVal)的添加。

图1.20
可使用同样的方法,增加方法void Reset()。
1.5 增加属性
1.5.1 VC++6.0
在图1.17中,单击【Add Property...】菜单项。显示界面如下:
这里增加了属性long Count。注意:没有设置"Put function",说明这个属性是只读属性。
单击"OK"按钮,完成属性的增加。

图1.21
同样方法,可以增加属性double Average和double StdDev。
1.5.2 VC++2010
在图1.19中,单击【Add Property...】菜单项。显示界面如下:
这里增加了属性ULONG Count。注意:没有设置"Put function",说明这个属性是只读属性。
单击"Finish"按钮,完成属性的增加。

图1.22
同样方法,可以增加属性double Average和double StdDev。
1.6 删除方法、属性
使用ATL,删除属性、方法,似乎只能手动进行,相当的麻烦。
1.7 编码
1.7.1 增加成员变量
请给CStatistic增加三个成员变量
|
private: ULONG m_nCount; double m_dSum; double m_dSum2; |
1.7.2 初始化成员变量
CStatistic的构造函数里,初始化这三个成员变量
|
CStatistic() { m_nCount = 0; m_dSum = 0.0; m_dSum2 = 0.0; } |
1.7.3 实现Add
|
STDMETHODIMP CStatistic::Add(double dVal) { ++m_nCount; //样本个数 m_dSum += dVal; //所有样本值的和 m_dSum2 += dVal * dVal; //所有样本值的平方和 return S_OK; } |
1.7.4 实现Reset
|
STDMETHODIMP CStatistic::Reset() { m_nCount = 0; m_dSum = 0.0; m_dSum2 = 0.0; return S_OK; } |
1.7.5 实现get_Count
|
STDMETHODIMP CStatistic::get_Count(long *pVal) { *pVal = m_nCount; return S_OK; } |
1.7.6 实现get_Average
|
STDMETHODIMP CStatistic::get_Average(double *pVal) { if(m_nCount) { *pVal = m_dSum / m_nCount; } else { *pVal = 0.0; } return S_OK; } |
1.7.7 实现get_StdDev
|
STDMETHODIMP CStatistic::get_StdDev(double *pVal) { *pVal = 0.0; if(m_nCount > 1) { *pVal = (m_nCount * m_dSum2 - m_dSum * m_dSum) / (m_nCount * (m_nCount - 1)); if(*pVal > 0.0) { *pVal = sqrt(*pVal); } } return S_OK; } |
1.8 注册、注销
编译comDLLatl,即可得到进程内COM组件comDLLatl.dll。使用它之前,需要注册。
注册组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllRegisterServer函数
|
regsvr32 comDLLatl.dll |
|
Rundll32 comDLLatl.dll,DllRegisterServer |
注销组件可使用如下任意一条命令。它们原理相同:都是载入comDLLatl.dll,然后调用DllUnregisterServer函数
|
regsvr32 /u comDLLatl.dll |
|
Rundll32 comDLLatl.dll,DllUnregisterServer |
注意:VC++2010可以编译生成64位的COM组件。在64位操作系统上,regsvr32.exe和Rundll32.exe将自动识别COM组件是32位的还是64位的。注册信息会写入注册表的如下几个位置。注意这里的<ProgID>其实就是comDLLatl.Statistic。
|
HKEY_LOCAL_MACHINE\SOFTWARE\Classes\TypeLib\ HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Interface\ HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID HKEY_LOCAL_MACHINE\SOFTWARE\Classes\<ProgID> |
对于64位组件,注册程序直接访问上述注册表项;对于32位组件,注册程序会将上述注册表项映射至32位的注册表项。如此一来,同一个组件的32位、64位是可以同时注册在64位Windows上的,它们互不干涉。
第2章 VC++使用组件
2.1 #import
请参考《COM组件(MFC篇)》。需要注意的是:MFC创建的COM组件,其接口必定是Dual接口(图1.10、图1.15中的Interface选项),也就是派生自IDispatch的自动化接口。ATL可以创建Custom接口,这种接口将派生自IUnknown,tli文件里的函数通过虚函数实现,效率较高。Custom接口的不足之处在于:它可能不能被某些脚本语言(如:VBS)调用。
2.2 MFC包装类
如果接口是Dual接口,就可以生成MFC包装类。具体操作请参考《COM组件(MFC篇)》。
2.3 C语言调用
使用C语言也可以访问COM组件。
如果接口是Dual接口,请参考《COM组件(MFC篇)》。
如果接口是Custom接口,则可以使用编译类型库时产生的C/C++头文件。如下面这段代码:(节选自comDLLatl_i.h)
|
#define IStatistic_Add(This,dVal) ((This)->lpVtbl->Add(This,dVal)) #define IStatistic_get_Count(This,pVal) ((This)->lpVtbl->get_Count(This,pVal)) |
亦即:可以通过宏IStatistic_Add、IStatistic_get_Count去访问方法、属性。
COM组件(ATL篇)的更多相关文章
- JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- 【转】JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)
前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己 ...
- 数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇
HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打 ...
- 我心中的核心组件(可插拔的AOP)~消息组件~完善篇
回到目录 为什么要有本篇文章 本篇文章主要实现了RTX消息生产者,并且完成了整体的设计方式,之前在设计时消息生产者全局使用单一的生产方式,即一个项目里使用了Email就不能使用SMS,这种设计方法和实 ...
- ActiveX控件(ATL篇)
目录 第1章 VC++6.0创建 2 1.1 目标 2 1.2 创建项目 2 1.3 增加COM类 4 1.4 属性 7 1.5 事件 8 1.6 实现连接点 ...
- Bootstrap组件福利篇:十二款好用的组件推荐
阅读目录 一.时间组件 1.效果展示 2.源码说明 3.代码示例 二.自增器组件 1.效果展示 2.源码说明 3.代码示例 三.加载效果 一.实用型 二.炫酷型 四.流程图小插件 1.效果展示 2.源 ...
- UI2CODE智能生成代码——组件识别篇
1.背景 在<UI2CODE——整体设计篇>中,我们介绍了UI2CODE工程的整体流程: 在组件识别这个环节,需要有一种处理布局信息的方法,来解析和计算控件间的布局关系(比如识别业务组件( ...
- 【Flutter组件终结篇】332个组件 658页PDF
老孟导读:历时1年的时间,整理完成了330+组件的详细用法,不仅包含UI组件,还包含了功能性的组件. 虽然整理了 330+的组件基本用法,但并不是让你每一个都学习一遍,任何技术基本都是掌握 20%就可 ...
- Angular2开发拙见——组件规划篇
本文集中讲讲笔者目前使用ng2来开发项目时对其组件的使用的个人的一些拙劣的经验. 先简单讲讲从ng1到ng2框架下组件的职责与地位: ng1中的一大特色--指令,分为属性型.标签型.css类型和注释型 ...
随机推荐
- linux(centos)下SVN服务器如何搭建
检测是否符合pptp的搭建环境的要求 使用下面的指令: 123 cat /dev/net/tun如果这条指令显示结果为下面的文本,则表明通过:cat: /dev/net/tun: File descr ...
- dubbo源码之四——服务发布二
dubbo版本:2.5.4 2. 服务提供者暴露一个服务的详细过程 上图是服务提供者暴露服务的主过程: 首先ServiceConfig类拿到对外提供服务的实际类ref(如:HelloWorldImpl ...
- Python3基础 ,= 一个等式给多个变量赋值
镇场诗:---大梦谁觉,水月中建博客.百千磨难,才知世事无常.---今持佛语,技术无量愿学.愿尽所学,铸一良心博客.------------------------------------------ ...
- 双4G LTE
我们即将上市的Xplay3S将支持双4G LTE(TDD-LTE+FDD-LTE),那什么是4G LTE呢,今天来给大家科普下4G LTE网络知识. 什么是TDD-LTE/FDD-LTE? LTE是通 ...
- ASP.NET文件的上传下载提交分页
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" Auto ...
- UVA 11795 七 Mega Man's Mission
七 Mega Man's Mission Time Limit:1000MS Memory Limit:0KB 64bit IO Format:%lld & %llu Subm ...
- git fetch 的简单用法:更新远程代码到本地仓库
方式一 1. 查看远程仓库 1 2 3 4 5 6 $ git remote -v eoecn https://github.com/eoecn/android-app.git (fetch) eoe ...
- NPO与X7R、X5R、Y5V、Z5U神马的有啥区别
主要是介质材料不同.不同介质种类由于它的主要极化类型不一样,其对电场变化的响应速度和极化率亦不一样. 在相同的体积下的容量就不同,随之带来的电容器的介质损耗.容量稳定性等也就不同.介质材料划按容量的温 ...
- ajax请求、servlet返回json数据
ajax请求.servlet返回json数据 1.方式一 response.setcontenttype("text/html;charset=utf-8"); response. ...
- ALV详解:OO SALV
声明:原创作品,转载时请注明文章来自SAP师太技术博客( 博/客/园www.cnblogs.com):www.cnblogs.com/jiangzhengjun,并以超链接形式标明文章原始出处,否则将 ...