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类型和注释型 ...
随机推荐
- 华东交通大学2016年ACM“双基”程序设计竞赛 1002
Problem Description 今天小学弟又训练完了,但是小学弟又不想看球赛,于是小学弟看马赛了.他发现马鞍是一个奇怪的东西.于是小学弟根据马鞍定义了一种马鞍数:在一个二位矩阵中,马鞍数在当前 ...
- c#存储过程
1. 只返回单一记录集的存储过程 SqlConnection sqlconn = new SqlConnection(conn); SqlCommand cmd = new SqlCo ...
- 嵌入式学习_AD学习篇
AD基础使用: 1.建立一个工作区 (.DsnWrk) workspace 2.建立一个PCB工程(.PrjPCB) project 3.建立一个PCB原理图文件(理论上告诉你两个点连接起来) 建立 ...
- JavaScript的循环语句
JavaScript的循环语句 1.JavaScript的循环语句 (1)for循环语句 - 循环代码块一定的次数: (2)for/in循环语句 - 循环遍历对象的属性: (3)while循环语句 - ...
- Hibernate中的PO
Hibernate中的PO PO就是持久化对象,它的作用就是完成持久化操作,即通过以面向对象的方式操作该对象对数据库中的数据执行增.删.改.查的操作. Hibernate是低侵入式的设计,完全采用Ja ...
- AutoLayout +Masonary
1, Masonry介绍与使用实践(快速上手Autolayout) http://adad184.com/2014/09/28/use-masonry-to-quick-solve-autolayou ...
- CodeForces 471C MUH and House of Cards
MUH and House of Cards Time Limit:1000MS Memory Limit:262144KB 64bit IO Format:%I64d & % ...
- Cheatsheet: 2014 01.15 ~ 01.30
Web How to upload file in Node.js Create Echo Server in Node.js Near-Realtime Analytics with MongoDB ...
- Have You Ever Wondered About the Difference Between NOT NULL and DEFAULT?
https://blog.jooq.org/2014/11/11/have-you-ever-wondered-about-the-difference-between-not-null-and-de ...
- 如何设计点击点击一个div,其他div做出对应反应,以及获取一个节点下的子节点
<div id="show"> <div>1</div> <div>2</div> <div>3</d ...