点击链接加入群【ゞ攻防闖兲ゞ】:

在COM1 的小例子中,,我们大概知道什么是组件类 ,什么是接口了。这小节呢,我们来实现一下由一个组件类去实现两个接口的过程。


新建项目:

COM2 --- 小例子_编程


我们的 解决方案的 名字是 ComDemoCode ,项目名字是 MathToolKit  这表示 我们的 项目 自动 生成的 DLL  的名字就是 MathToolKit(数学工具包)。


我们的继承关系 有必要 给大家 先 列出来,让大家 看看


COM2 --- 小例子_COM_02


在这里面,IPrimerMath接口 提供 + - * / % 五个基本运算方法,IAdvanceMath接口提供求阶乘方法。


由 CMathTool 去实现 上面的 六个方法 。


COM2 --- 小例子_编程_03


点击下一步,


COM2 --- 小例子_COM_04


默认选中的就是 动态链接库,我们直接点击  Finish。

项目创建完后,我们可以看到出现了两个项目,其中带有 PS 字样的 项目 我们暂时用不到,所以直接在它上面右击,选择 Remove 即可。

COM2 --- 小例子_COM_05


然后我们的项目就变成下面这个样子啦。


COM2 --- 小例子_COM_06


然后我们将视频切换到类视图。


COM2 --- 小例子_COM_07


在类视图的 项目 名字上 右击  选择添加 类


COM2 --- 小例子_编程_08


选择 ATL Simple Object ,点击 Add ,弹出如下所示向导。


COM2 --- 小例子_COM_09


然后在 Short name 里写上 MathTool ,然后我们就会发现其它编辑框的内容都同时发生了变化,见下图。下图所示上半部分比较好理解,就是我们用C++的类方式来实现一个组件类,然后这个C++对应的类的名字就是 Class里面的名字,一般就是 Short name 前面加上一个 C,.h file 和 .cpp file 就是针对 这个类所需要的 头文件和源文件的文件名。下半部分中的 Coclass 就是用来指定我们的组件类的名字,叫MathTool,右边两个我们暂时不关心,如果想要明白,大家把我的这个例子做个 10 遍,每次都重新开始,然后再去看 COM 本质论 等理论书 就容易点啦,右边的东西也就明白啦。Interface 在下面介绍。


COM2 --- 小例子_COM_10


Interface用来指定我们的组件需要实现什么接口,上面我们已经说了要实现 IPrimerMath和IAdvanceMath,所以先将第一个接口改为 IPrimerMath


COM2 --- 小例子_COM_11


然后点击 Next。


COM2 --- 小例子_编程_12


此图中的 Interface 一定要选择 Custom ,暂时不要问为什么。一切都要从简单起步。

然后点击Finish ,可以看到 类视图如下图


COM2 --- 小例子_编程_13


这样,我们就定义了一个接口,只是这个接口没有定义方法而以,下面我们为这个接口添加方法。

在类视图中的 IPrimerMath 接口上 右击 ,选择 Add  --> Add Method,然后弹出下图。


COM2 --- 小例子_编程_14


然后,我们可以看到这里面,有Method name, 就是 函数名啦。

Parameter attributes: 参数属性

in 表示 是 输入参数

out 表示是 输出参数

retval 表示 是返回参数 (Out 和 retval 默认是不可以用的,只有将 Parameter type 修改为 某种类型的指针时才可以 启用它们,因为只能用指针往外带数据,而且选中 retval 后,out就会自动选中)。


添加第一个参数,in  LONG  n1

COM2 --- 小例子_编程_15

添加第二个参数  in LONG n2

COM2 --- 小例子_COM_16


添加第三个参数:  retval & out    LONG *      nResult


COM2 --- 小例子_COM_17


然后点击 Next


COM2 --- 小例子_编程_18


一切默认即可,然后点击 Finish



然后我们打开项目中唯一的  .IDL 的文件,或者 直接在 类视图中 双击  IPrimerMath 接口 ,


COM2 --- 小例子_编程_19


我们可以看到一段语句,我们先从 结构上 下手,我们要 知道 ,上图中选中部分才是一个整体。

[] 内是 一部分,下面是 另一部分。其中下半部分定义了一个 Add 方法。所以,如果我们想要继续添加方法,可以直接复制这一行的数据,然后粘贴,只要改改函数名字及参数就可以了哦。




好了,其实这就是一个 接口的 描述啦。然后再打开 MathTool.h ,我们再看一下 我们的 Add 函数的声明,如下图 :


COM2 --- 小例子_COM_20



好,下面我们继续为这个接口添加更多的 接口函数,如下图:


COM2 --- 小例子_COM_21

好,我们又添加了四个函数,然后在 我们的 C++ 类中  对 四个新添加的 函数 进行 函数声明。


COM2 --- 小例子_编程_22


好,函数也声明了,下面去实现这五个函数(当然是在源文件里啦),为了 布局,我没有进行 算法异常检测。


COM2 --- 小例子_编程_23


这样就将  IPrimerMath 这个接口 提供的五个  函数 实现 了。。


下面,我们要 回忆一下我们前面的 要求,我们是要 用一个 COM组件类 ,实现 多个 接口 。


所以,我们下一步的 工作 就是 为这个 组件类 添加 多个接口。


1、接口描述

   直接在 IDL 文件中 将 IPrimerMath 这个接口的内容 复制,然后 粘贴,进行修改就行了,如下图


COM2 --- 小例子_COM_24


我们可以看到,我修改了接口名字,添加了注释说明,还 对接口提供的 函数  进行了  增删改操作,更重要的一点是,uuid() 里面的值要进行修改,这个值可以 直接 利用 Tools 菜单下的 Create GUID 工具进行获取,如下图,选择 4号,然后点击 New GUID,然后点击 Copy,再把数据 粘贴到 uuid()里面,然后进行稍微的修改就可以了。


COM2 --- 小例子_COM_25


是不是这样就可以了呢?答案是肯定不行的,最起码我们得让 我们的 C++类 去继承 我们新提供的这个接口,并对新接口提供的方法 进行声明 及 实现。


1、继承前

COM2 --- 小例子_COM_26


2、继承后


COM2 --- 小例子_COM_27


下面是 函数声明 及 实现


声明部分:

COM2 --- 小例子_COM_28


实现部分:

COM2 --- 小例子_COM_29


那么是不是上面的东东都搞定了就OK了呢?还不行呢,哈哈,还有两个步骤,就可以成功了。

1、我们要先去看看 我们的组件类的 描述 是怎么描述的


COM2 --- 小例子_COM_30

我们很明显的可以看到 47 -- 50 行,是描述我们的 组件类的,,这里面只有一个 IPrimerMath,其实我们这个组件类是实现了 两个接口哦,所以这里要再添加一个接口


COM2 --- 小例子_编程_31


好,OK了,,那么还有哪一步呢?最后一步就更简单了,先说一下,它的功能,它的功能是帮我们自动完成  接口查询 及 引用计数等 麻烦事项的,也就是说,我们可以利用 IPrimerMath 这个 接口通过查询函数 获取 IAdvanceMath 接口,反过来也就一样的,我们后面会有Demo 程序的。。


那么怎么完成这个功能呢?在 组件类的 头文件中,有一个 映射宏


COM2 --- 小例子_COM_32


然后我们要再添加上我们的 IAdvanceMath 接口的映射,就完成了所有的功能啦。


COM2 --- 小例子_编程_33


好了,现在点击生成吧,,然后 大家可以 找到 下图所示的程序


COM2 --- 小例子_COM_34


然后点击下图所示图标


COM2 --- 小例子_编程_35


然后我们打开我们项目生成的 DLL,可以看到里面有一个组件类 MathTool,有两个接口 IPrimerMath和 IAdvanceMath。


COM2 --- 小例子_COM_36


然后展开节点,查看更多信息,可以看到跟我们设计前的想法是一样的。


COM2 --- 小例子_COM_37


下面,我们就为当前解决方案添加新的项目,


COM2 --- 小例子_COM_38


COM2 --- 小例子_编程_39


COM2 --- 小例子_编程_40


COM2 --- 小例子_COM_41


COM2 --- 小例子_COM_42


这里只要选中 Active Accessibility  即可,它主要是完成对 COM 库的 初始化 及收尾工作。


COM2 --- 小例子_COM_43


然后为对话框添加一个按钮,并响应


COM2 --- 小例子_编程_44


COM2 --- 小例子_COM_45


一个解决方案只有一个项目的时候,当我们点击运行时,它会自动调用我们的项目程序,但是当有多个项目时,这个时候VS就不知道要调用哪一个啦,我们需要给它指定一个,通过下图,我们可以看到 一个项目字体是粗黑体,意思就是说 当我们点击 调试或者运行的时候就会启动这个程序,我们可以在项目上右击,来更改启动项目 ,这个不难,自己摸摸吧。


COM2 --- 小例子_编程_46

改好后,如下图。

COM2 --- 小例子_COM_47


程序运行效果如下图


COM2 --- 小例子_编程_48


点击按钮,弹出对话框,我们可以看到都算对啦。


COM2 --- 小例子_COM_49



这就证明我们的组件是可以的哦。


如果你会C#,你也可以用C#来调用哦。


然后我们这个时候再看这个继承图是不是很容易理解啦


COM2 --- 小例子_COM_50


这里我要讲解一下 我们的 CODE 啊,不然大家还是不明白啊。


再把 CODE 贴一次吧

COM2 --- 小例子_COM_45



好,组件类 提供的 方法 并不能直接 通过 组件类 来进行调用 ,必须要使用 接口去调用 ,也就是说如果我们调用  Add 方法 就必须 要 先获取  IPrimerMath 接口,那么怎么获取这些接口呢?

就是创建一个组件类 实例, 98 行的函数 就是 这个功能,创建一个组件类的 实例,第一个参数 是我们的 组件类的 唯一标识(CLSID),它是非常有规律的哦,CLSID_组件类的名字,第二三参数需要大家看COM原理方面的书来理解,第四个参数,就是指定接口ID,最后就是用来接收接口指针的啦。然后我们就可以调用这个接口的方法啦,然后这个接口还可以通过 106行的 函数来获取 同一个 COM组件类提供的 其它的 接口指针,以用来调用其它接口提供的方法,最后我们要将获取的接口 释放,调用的是接口的 Release() 方法,116行的 代码是 指,如果某个组件类中的实例所提供的接口已经都被释放了,则将这个DLL 卸载出 进程的 地址空间。


关于接口ID及组件类ID的定义,我们可以查看 DLL 项目 中的


用这个例子,大家就可以练手啦,然后COM原理等书 看着也不是很难啦。


下面再说一些话。


很多人再给别人发一些源代码的时候 ,都是搞的 很大,几十M,甚至 上百M,其实这里的文件很多并没有用。


我先将我们这个解决方案的目录层次发上来吧。


这是我们的最顶层目录。

COM2 --- 小例子_COM_52


这是第二层目录

COM2 --- 小例子_编程_53


这是MathToolKit目录

COM2 --- 小例子_编程_54


这是TestMathToolKit目录

COM2 --- 小例子_COM_55




这里面有许多文件都是跟用户相关,或者保存一些信息,在发源码时不需要发这些东西,比如:


所有的 Debug 目录下所有文件及此目录 ,所有的 Release 目录下所有文件及此目录 ,*.aps,*.ncb,

这里面显示的 VS2010图标的 文件,我们可以将鼠标放在它们上面,会有提示信息,一般是 写着与 User 有关,这些文件都是可以删除的。如果大家不放心,可以自己做实验,就是先把所有文件都压缩后做一个备份,然后一个一个的试。


其实这个小项目,压缩完成后,大小才 几十K,如下图


COM2 --- 小例子_COM_56


好了。结束。


代码我们上传的。