使用ATL开发COM组件Word下载.docx

上传人:b****6 文档编号:19270744 上传时间:2023-01-04 格式:DOCX 页数:15 大小:369.55KB
下载 相关 举报
使用ATL开发COM组件Word下载.docx_第1页
第1页 / 共15页
使用ATL开发COM组件Word下载.docx_第2页
第2页 / 共15页
使用ATL开发COM组件Word下载.docx_第3页
第3页 / 共15页
使用ATL开发COM组件Word下载.docx_第4页
第4页 / 共15页
使用ATL开发COM组件Word下载.docx_第5页
第5页 / 共15页
点击查看更多>>
下载资源
资源描述

使用ATL开发COM组件Word下载.docx

《使用ATL开发COM组件Word下载.docx》由会员分享,可在线阅读,更多相关《使用ATL开发COM组件Word下载.docx(15页珍藏版)》请在冰豆网上搜索。

使用ATL开发COM组件Word下载.docx

第二,组件必须隐藏内部实现细节(独立于具体编程语言,二进制形式发布)。

每个组件相当于一个黑盒子,对外提供的只是接口(函数)。

如果接口没有发生任何变化时,对组件的修改几乎不会影响应用程序的其它部分。

提供服务的组件称为服务器组件,使用服务的组件称为客户组件。

6、COM的设计思想

COM的设计思想是为了重用,而且是二进制级别的代码重用。

类库也是重用,如MFC,但只是基于源码级别的重用,类库严重依赖于固定的某种语言,如MFC依赖于VC,PFC依赖于PowerBuilder等。

DLL也是重用,但也有很大的局限:

函数重名问题、各编译器对函数的名称修饰不兼容问题、路径问题、DLL与EXE的依赖问题。

COM没有重名问题,因为根本不是通过函数名来调用函数,而是通过虚函数表,自然也不会有函数名修饰的问题。

路径问题也不复存在,因为是通过查注册表来找组件的,放在什么地方都可以,即使在别的机器上也可以。

也不用考虑和EXE的依赖关系了,它们二者之间是松散的结合在一起,可以轻松的换上组件的一个新版本,而应用程序混然不觉。

7、学习COM的目的

要学COM的基本原理,推荐看《COM技术内幕》。

但仅看这样的书是远远不够的。

其实,我们最终的目的是要学会怎么应用COM去编写我们的应用程序,而不是拼命的研究COM本身的机制。

所以我个人觉得对COM的基本原理不需要花大量的时间去追根问底,没有必要,是吃力不讨好的事。

其实我们只需要掌握几个关键概念就够了。

8、用VC开发COM组件所要了解的几个关键概念

(1)、COM组件实际上是一个C++类,而接口都是纯虚类。

(2)、COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch,其中,IUnknown包含三个函数,分别是QueryInterface、AddRef、Release。

(3)、Dispinterface接口、Dual接口以及Custom接口

(4)、COM组件有三种:

进程内COM、本地COM、远程COM。

即它可以是进程内的,即和调用者在同一个进程内;

也可以和调用者在同一个机器上但在不同的进程内;

还可以根本就和调用者在两台机器上。

(5)、COM组件的核心是IDL

IDL是一种用来定义COM接口规范的、大家都认识的接口定义语言,用它来定义的接口,不论放到哪个语言平台上都认识它。

用VC,VB等语言都可以开发COM组件,开发好的COM组件也可以被其他语言调用。

(6)、注册表在COM中的重要作用

首先要知道GUID的概念,COM中所有的类、接口、类型库都用GUID来唯一标识,GUID是一个128位的字串,根据特制算法生成的GUID可以保证是全世界唯一的。

COM组件的创建接口、查询接口都是通过注册表进行的。

有了注册表,应用程序就不需要知道组件的DLL文件名、位置,只需要根据CLSID查就可以了。

当版本升级的时侯,只要改一下注册表信息,就可以神不知鬼不觉的转到新版本的DLL。

(7)、一个典型的自注册的COMDLL所必有的四个函数

●DllGetClassObject:

用于获得类厂指针

●DllRegisterServer:

注册一些必要的信息到注册表中

●DllUnregisterServer:

卸载注册信息

●DllCanUnloadNow:

系统空闲时会调用这个函数,以确定是否可以卸载DLL

(8)、COM组件的运行机制

●通过查注册表CLSID_Object,得知组件DLL的位置、文件名

●装入DLL库

●使用函数GetProcAddress(...)得到DLL库中函数DllGetClassObject的函数指针

●调用DllGetClassObject

9、完整的COM组件的接口实现示例:

代码见“1.1.ComInterface1”工程,这里无需掌握,只是帮助理解COM的原理。

10、增加查询组件接口QueryInterface()、应用计数增加接口AddRef()、应用计数减少接口Release()后的完整例子。

代码见“1.2.ComInterface2”工程,这里无需掌握,只是帮助理解COM的原理。

二、ATL活动模板库(ActiveTemplateLibrary)

在ATL产生以前,开发COM组件的方法主要有两种:

一是使用COMSDK直接开发COM组件,另一种方式是通过MFC提供的COM支持来实现。

但是这两种方法都非常的复杂、麻烦。

使用ATL开发COM应用是一件比较简单的事情,但是在ATL简单易用的界面后面却包含着复杂的技术。

这些技术包含以下一些方面:

●COM技术

●C++模板类技术(Template)

●C++多继承技术(Multi-Inheritance)

其中,COM技术本文开头有所描述。

C++模板类技术(Template)、C++多继承技术(Multi-Inheritance)在C++理论课中已有详尽描述。

这里最主要的是介绍使用ATL怎么生成一个自己的COM组件,以及怎么使用该组件。

预备知识:

ATL中的数据类型BSTR

BSTR是BASIC中字符串类型的表示方式,是一个指向UNICODE字符串的指针。

有关BSTR的处理函数,参见下表。

API函数

说明

SysAllocString()

申请一个BSTR指针,并初始化为一个字符串

SysFreeString()

释放BSTR内存

SysAllocStringLen()

申请一个指定字符长度的BSTR指针,并初始化为一个字符串

SysAllocStringByteLen()

申请一个指定字节长度的BSTR指针,并初始化为一个字符串

SysReAllocStringLen()

重新申请BSTR指针

CString函数

AllocSysString()

从CString得到BSTR

SetSysString()

重新申请BSTR指针,并复制到CString中

CComBSTR函数

ATL的BSTR包装类。

在atlbase.h中定义

Append()、AppendBSTR()、AppendBytes()、ArrayToBSTR()、BSTRToArray()、AssignBSTR()、Attach()、Detach()、Copy()、CopyTo()、Empty()、Length()、ByteLength()、ReadFromStream()、WriteToStream()、LoadString()、ToLower()、ToUpper()

运算符重载:

!

!

=,==,<

>

&

+=,+,=,BSTR

太多了,但从函数名称不能看出其基本功能。

详细资料,查看MSDN吧。

另外,左侧函数,有很多是ATL7.0提供的,VC6.0下所带的ATL3.0不支持。

由于我们将来主要用ATL开发组件程序,因此使用ATL的CComBSTR为主。

ATL提供了CComBSTR类来简化使用BSTR(见上表)。

ATL中的数据类型VARIANT

C++、BASIC、Java、Pascal、Script......计算机语言多种多样,而它们各自又都有自己的数据类型,COM产生目的,其中之一就是要跨语言。

而VARIANT数据类型就具有跨语言的特性,同时它可以表示(存储)任意类型的数据。

ATL提供CComVariant类来简化使用VARIANT,如:

VARIANTv=CComVariant(任意C++类型);

 

下面我们使用ATL编写一个“将一个字符串转换成大写然后倒置”的COM组件:

1.建立一个ATLCOMAppWizard工程AtlComSample:

2.选择创建的COM类型:

该步骤中的一些选项说明:

动态连接库(DLL):

最终产生一个动态连接库形式的COM服务程序(DLL);

应用程序(Executable):

最终产生一个自注册的可执行的COM服务程序(EXE);

NT服务(Service):

产生一个以NT服务方式运行的COM服务程序(EXE)。

允许嵌入Proxy/Stub代码。

由Microsoft提供的MIDL编译IDL文件以后,将产生用于对象调度(Marshaling)的Proxy/Stub的代码。

在传统方式下,这部分代码与COM服务程序的代码是分离的,但是由于新的COM标准支持多线程环境下的COM对象服务,因此在动态连接库的COM服务程序中也要有Proxy/Stub的支持。

为了支持在网络上的传输,ATL允许用户选择将Proxy/Stub的代码包括在生成的DLL代码中。

这个选项在EXE和NT服务类型的COM应用条件下不可选。

允许支持MFC。

由于ATL对除COM以外的基本的Windows编程方面的支持极为有限,同时许多程序员对MFC又非常熟悉,因此在ATL的工程设置中允许在ATL工程内部支持使用MFC,即可以使用MFC定义的类。

这一特点给开发人员提供了许多方便,特别对于习惯使用MFC的人来说,能够使用MFC提供的各种功能强大的类的支持,而不必直接使用WindowsSDK。

从另一个方面来看,在ATL工程中使用MFC同时就丧失了ATL代码轻量级的特点。

支持MTS。

MTS是MicrosoftTransactionServer的缩写,它是Microsoft在COM技术方面的一个新的分支,这里不做详细说明。

----完成上面的设置以后,可以选择Finish完成工程的设置,ATL将创建相应的工程。

我们选择默认选项,不做任何改动。

3.向工程中加入一个新的ATL类:

首先通过集成环境的"

Insert"

菜单下的"

NewATLObject..."

命令进入"

ATLObjectWizard"

对话框。

如下图所示:

对话框的左边部分说明了待创建对象的基本类型,这里主要有以下几种类型:

●对象(Object):

基本的COM对象类型;

●控件(Control):

ActiveXControl类型的ATL对象;

●其他(Miscellaneous):

辅助功能,如对话框的生成等;

●数据访问(DataAccess):

数据访问,支持MTS等。

对于我们这个一般的COM服务程序,左侧选择对象(Object),右侧选择SimpleObject,点击下一步继续:

4.输入我们这个组件的类名CMyString,其他名字会自动产生,不做改动,点确定:

5.切换到Attributes(属性)标签页:

对象的属性设置是ATL对象创建过程中最复杂的部分,包括以下几个主要部分:

对象的线程模型(ThreadModel):

对象的线程模型是COM对象在多线程环境下被访问时对访问方式的控制,缺省情况下在ATL中采用的是套间模型Apartment,由系统通过消息队列方式提供并发控制。

对象的接口模型(Interface):

COM对象的接口可以是双接口(DualInterface)。

双接口不同于普通接口(CustomInterface)之处在于双接口是从Automation基本接口IDispatch继承的,而普通接口是从IUnknown接口直接继承来的。

缺省的接口模型是双接口。

对象的聚合模型(Aggregate):

COM规范不允许对象的实现继承,但是可以通过聚合方式重用其他的COM对象。

ATL对象属性设置中的聚合模型可以指定待创建的COM对象是否支持聚合模型。

缺省的选项是支持对象的聚合。

对象对错误处理的支持(SupportISupportErrorInfo):

选取这个选项可以在对象的运行过程中支持错误处理。

缺省情况下这个选项不被选中。

对象对连接点的支持(SupportConnectionPoints):

连接点是COM对象的事件机制。

选中这个选项可以使待创建的COM对象具有发出事件的能力。

缺省情况下该选项不被选中。

对象对自由线程调度的支持(FreeThreadMarshaller,简称FTM):

对象的自由线程调度是对象在处于自由线程模型状态下,为了简化对象的访问过程而采用的一种优化策略。

这里我们也使用默认选项,确定。

此时在“ClassView”标签页会增加一个CCMyString类和一个ICMyString接口。

6.为ICMyString接口添加一个方法StringTransfer(),其原型我们定义如下:

HRESULTStringTransfer([in]BSTRInData,[out]BSTR*OutData,[out,retval]long*result);

其中,[in]表示参数方向是输入;

[out]表示参数方向是输出;

[out,retval]表示参数方向是输出,同时可以作为函数运算结果的返回值。

一个函数中,可以有多个[in]、[out],但[retval]只能有一个,并且要和[out]组合后在最后一个位置。

在CmyString.cpp中,给添加的方法加入如下代码:

CComBSTRstrSource=InData;

CComBSTRtempSource=InData;

boolbNeedToUpper=true;

intj=(int)strSource.Length()-1;

//实现字符串到大写字母的转换并进行逆序转换

for(inti=0;

i<

(int)strSource.Length();

i++)

{

if(strSource[i]>

='

a'

&

&

strSource[i]<

z'

bNeedToUpper)

{

strSource[i]=strSource[i]-32;

bNeedToUpper=true;

}

if(strSource[i]=='

'

)bNeedToUpper=false;

tempSource[j]=strSource[i];

j=j-1;

}

*OutData=tempSource;

return*result;

编译链接,通过。

COM组件开发完毕。

检查生成的文件,发现系统在Debug目录下生成了一个动态链接库文件AtlComSample.dll,在工程目录下生成了一个类型库文件AtlComSample.tlb。

这2个文件就是用ATL开COM组件的成果。

你现在就可以发布这2个文件给另外的COM使用者了。

其中的DLL文件就是COM组件,使用之前必须使用RegSrv32.exe进行注册。

TLB文件是提供给开发者使用的,在后面使用COM组件的例子中我们会看到是如何使用该TLB文件的。

直接在DOS执行RegSvr32命令,得到如下的用法提示:

注册一个COM组件的命令:

regsvr32c:

\aa\xyz.dll

取消注册COM组件的命令:

regsvr32/uc:

注册一个组件或者取消注册一个组件,都会在注册表中有所反应。

其实,编译之后,VC已经在背后帮我们自动注册好了该COM组件。

使用注册表编辑器RegEdit.exe查找AtlComSample,可以发现我们这个组件已经被注册好了,见下图:

注意其中CurVer下的一个字符串:

“AtlComSample.CmyString.1”,它是我们引用这个组件的ProgID。

下面我们在VC中来使用这个组件。

6.另外新建一个MFC对话框工程MycomClient,并添加工程到当前工作区中:

7.使用MFC类向导将上个工程中开发好的组件AtlComSample添加到当前工程中:

类向导AddClassFromatypelibrary选择AtlComSample.tlb文件打开。

之后,你会发现在ClassView标签页下多了一个类:

ICMyString。

这个就是导入进来的COM组件的类,其中包含了我们在上个工程中所写的StringTransfer函数。

同时在项目目录下多了2个文件:

AtlComSample.h和AtlComSample.cpp。

下面我们就可以使用它了。

8.设计如下对话框界面:

关联如下变量:

对“字符串转换”按钮添加如下响应代码:

#include"

atlcomsample.h"

//别忘了加COM组件的头文件

voidCMyComClientDlg:

:

OnBtnTransfer()

{

ICMyStringm_MyString;

//创建COM对象:

这里的字符串一定要和注册表中的ProgID一致!

if(!

m_MyString.CreateDispatch("

AtlComSample.CmyString.1"

))

MessageBox("

创建COM组件失败:

请检查ProgID是否正确,组件是否已经注册"

);

UpdateData(true);

//得到源字符串放到m_SourceString中

BSTRbstrDestStr=SysAllocString(L"

"

m_MyString.StringTransfer(m_SourceString,&

bstrDestStr);

//调用COM接口

m_DestString=bstrDestStr;

//得到转换后结果字符串

UpdateData(false);

//将结果字符串显示到编辑框中

}

运行结果如下:

总结:

1、用ATL开发COM组件:

作业:

1、参考上例,使用ATL建立一个COM组件接口MiniStringCom,实现2个接口函数:

First2Upper“将给定字符串首字母大写化”,MergeString“将给定的2个字符串合并成1个字符串”,并在客户程序中进行使用。

2、选修:

在MSDN中查找“ATLTutorial”,即可找到微软提供的用ATL开发COM组件的教程。

按照该教程中的7个步骤,实现一个用多边形逼近圆的图形算法。

有时间则翻译并讲解。

3、选修:

阅读文章《COM组件设计与应用.mht》

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 职业规划

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1