COM组件(ATL篇)

目录

第1章创建进程内组件    1

1.1 目标    1

1.2 创建项目    3

1.2.1 VC++6.0    3

1.2.2 VC++2010    5

1.3 增加COM类    6

1.3.1 VC++6.0    6

1.3.2 VC++2010    8

1.3.3 项目结构    12

1.4 增加方法    13

1.4.1 VC++6.0    13

1.4.2 VC++2010    14

1.5 增加属性    16

1.5.1 VC++6.0    16

1.5.2 VC++2010    17

1.6 删除方法、属性    17

1.7 编码    17

1.7.1 增加成员变量    17

1.7.2 初始化成员变量    18

1.7.3 实现Add    18

1.7.4 实现Reset    18

1.7.5 实现get_Count    18

1.7.6 实现get_Average    19

1.7.7 实现get_StdDev    19

1.8 注册、注销    19

第2章 VC++使用组件    21

2.1 #import    21

2.2 MFC包装类    21

2.3 C语言调用    21

第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去访问方法、属性。

时间: 2024-10-23 11:30:30

COM组件(ATL篇)的相关文章

Oracle内存组件理论篇一

目标 1.SGA结构 2.PGA结构 1.SGA Shared pool 1).共享池是对SQL.PL/SQL程序进行语法分析.编译.执行的内存区域. 在执行SELECT * FROM emp语句时,会对sql语句进行语法分析->编译->生成执行计划->运行执行计划等,这些操作都在共享池中完成: 如果再次执行SELECT * FROM emp语句时,会在共享池中查找是否有相同的sql,如果存在则省去编译.生成执行计划操作步骤而是直接运行执行计划. 因此养成良好的编码习惯对于提高oracl

【转】JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐(二)

前言:上篇 JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐 分享了几个项目中比较常用的组件,引起了许多园友的关注.这篇还是继续,因为博主觉得还有几个非常简单.实用的组件,实在不愿自己一人独享,没办法,谁让博主这么爱分享呢~~ 本文原创地址:http://www.cnblogs.com/landeanfen/p/5603790.html 七.多值输入组件manifest 关于文本框的多值输入,一直是一个比较常见的需求,今天博主推荐一款好用的多值输入组件给大家,不要谢我,请叫我“红

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 实现连接点    9 1.7 编码    11 1.7.1 增加成员变量    11 1.7.2 初始化成员变量    11 1.7.3 完成属性赋值代码    11 1.7.4 完成控件绘制代码    11 1.7.5 响应鼠标左键按下消息    13 1.7.6 修改DllUnregisterServer   

Android应用Preference相关及源码浅析(Preference组件家族篇)

1 前言 前一篇(点我阅读前一篇<Android应用Preference相关及源码浅析(SharePreferences篇)>)我们讨论分析使用了Android的SharePreferences,相信看过的朋友都有了自己的感悟与理解,这一篇我们继续乘热打铁来说说SharePreferences的衍生品--Preference组件. 其实Preference组件大家一定不陌生,因为Android系统的Setting应用及我们市面上一些符合Android设计思想的应用的设置界面一般都会用它来实现,

数百个 HTML5 例子学习 HT 图形组件 – 拓扑图篇

HT 是啥:Everything you need to create cutting-edge 2D and 3D visualization. 这口号是当年心目中的产品方向,接着就朝这个方向慢慢打磨,如今 HT 算是达到了这样的效果,谈不上用尽洪荒之力,但我们对产品结果很满意,特别是 HT 的用户手册,将例子和文档无缝融合一体,小小 10 来兆开发包居然包含了四十五份手册,数百个活生生的 HTML5 例子,还没体验过的同学可以点击 http://www.hightopo.com/guide/

我心中的核心组件(可插拔的AOP)~消息组件~完善篇

回到目录 为什么要有本篇文章 本篇文章主要实现了RTX消息生产者,并且完成了整体的设计方式,之前在设计时消息生产者全局使用单一的生产方式,即一个项目里使用了Email就不能使用SMS,这种设计方法和实际不相符,虽然在性能上是最佳的(采用了单例模型,维护一个生产者,使用策略模式进行生产者的实现,使用工厂模式生产具体生产者),实际项目中,应该是可以自动选择消息生产者的,当然为了程序的性能,我们还必须使用单例模式来生产具体生产者,这种单例,在本程序中,采用了具体类型,具体单例的方法,即Email自己维

JS组件系列——Bootstrap组件福利篇:几款好用的组件推荐

前言:之前分享过很多bootstrap常用组件,包括表格.表单验证.文件上传.复选下拉框.弹出框等.这段时间,博主又收藏了一些好用的组件(有些在项目中已经用起来了),经过两天的时间,已经整理出了一部分,本着“好东西要与人分享”的原则,今天还是来点福利,将博主收藏的东西分享出来,供需要的园友参考.组件大部分都是些开源组件,也有部分是博主自己在网上找到然后改写出来的效果,可能不尽如人意,有兴趣的且看看吧. 一.时间组件 bootstrap风格的时间组件非常多,你可以在github上面随便搜索“dat

Android笔记(五十八)Android总结:四大组件——Activity篇

什么是Activity Activity是一种包含用户界面的组件,主要用于和用户进行交互,一个APP通常由多个Activity组成. 每个Activity都对应一个布局文件,通过setContentView()方法来载入布局文件.并且通过用户对布局文件中的组件所发出的事件来做出相应的反映. Activity的四种状态 1)激活状态,此时activity运行在屏幕前台 2)暂停状态,此时activity失去焦点,但是用户仍然可以看到(例如这个activity上遮盖了一个透明的或者非全屏的activ

Android笔记(六十)Android总结:四大组件——BroadcastReceiver篇

什么是BroadcastReceiver BroadcastReceiver是Android体系的四大组件之一,本质上是一种全局的监听器,用于监听系统全局的广播消息,正式因为其本质为全局监听,因此可以非常方便的实现系统中不同组件之间的通信.也方便我们自己的app针对系统开机.电量低等广播做出相应反映.同时我们也可以自己发送广播,来实现不同组件之间的通信 系统接收短信广播,然后弹出Toast: package cn.lixyz.broadcastreceiver; import android.a