三 ATL基本使用 这一部分将重点介绍ATL的基本使用过程由于ATL已经被集成在Microsoft Visulal Studio的Visual C++开发环境中因此要使用ATL必须先安装Visual C++在下面的讨论中有关COM的基本知识请参阅有关的文档这里不再详细说明给出的图是在Microsoft Windows 平台下Visual Studio 的使用示意图 使用ATL开发一个COM应用基本可以分为以下几个步骤 创建一个新的ATL工程并对工程的选项进行适当的配置 向新创建的工程添加新的ATL类并对该类进行一些初始配置工作 根据COM应用的基本要求向新的ATL类加入新的接口定义并实现相应的接口成员函数 编译连接工程注册COM应用 下面将根据这些步骤依次介绍ATL的基本使用过程 创建工程 首先启动Visual C++集成开发环境选择File菜单下的New命令在New对话框中选择Project页 选择ATL COM AppWizard项这是创建ATL工程的AppWizard向导入口然后在Project name编辑框中输入工程的名字单击OK按钮进入AppWizard对话框 在AppWizard对话框中主要的设置选项有 COM服务程序的类型 动态连接库(Dynamic Linking Library) 最终产生一个动态连接库(DLL)形式的COM服务程序 应用程序(Executable application)最终产生一个可执行程序类型(EXE)的COM服务程序 NT服务(NT Service)产生一个以NT服务方式运行的COM服务程序 允许嵌入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提供的各种功能强大的类的支持而不必直接使用Windows SDK从另一个方面来看在ATL工程中使用MFC同时就丧失了ATL代码轻量级的特点 支持MTSMTS是Microsoft Transaction Server的缩写它是Microsoft在COM技术方面的一个新的分支这里不作详细说明 完成上面的设置以后可以选择FINISH完成工程的设置ATL将创建相应的工程 加入ATL类 完成工程的创建和设置以后下一步就是向工程中加入一个新的ATL类Visual Studio集成环境提供了向导工具ATL Object Wizard用于加入一个新的ATL类操作过程并不复杂只是一组对话框操作而已 首先通过集成环境的Insert菜单下的New ATL Object…命令进入ATL Object Wizard对话框 这个对话框即为创建ATL对象的向导起始界面对话框的左边部分说明了待创建对象的基本类型这里主要有以下的几种类型 对象(Object)基本的COM对象类型 控制(Control)ActiveX Control类型的ATL对象 其他(Miscellaneous)辅助功能如对话框的生成等 数据访问(Data Access)数据访问支持MTS等 右边部分说明了每种类型的详细内容对于一般的COM服务程序使用对象表中的简单对象(Simple Object)就可以了 选定待创建对象的基本类型以后单击Next>按钮进入下一步进入对象属性设置对话框如图和图所示 对象属性设置分为两个过程先是对象名字标识的设定然后是对对象的基本属性进行设置首先是对象的名字标识设置 在对象标识编辑框中输入待创建对象的名字ATL对象向导将同步地根据用户输入的对象标识设定该对象的C++标识和COM标识对象的C++标识包括对象的类名cpp文件名和头文件名COM标识包括对象在类型库中的CoClass段和实现的主接口的名字同时还有在系统注册表中的类型名以及ProgID 对象名字标识设置完成以后选择对象属性页(Attribute)进入对象的属性设置页面 对象的属性设置是ATL对象创建过程中最复杂的部分包括以下几个主要部分 对象的线程模型(Thread Model) 对象的线程模型是COM对象在多线程环境下被访问时对访问方式的控制缺省情况下在ATL中采用的是套间模型Apartment由系统通过消息队列方式提供并发控制 对象的接口模型(Interface) COM对象的接口可以是双接口(Dual Interface)双接口不同于普通接口(Custom Interface) 之处在于双接口是从Automation基本接口IDispatch继承的而普通接口是从IUnknown接口直接继承来的缺省的接口模型是双接口 对象的聚合模型(Aggregate) COM规范不允许对象的实现继承但是可以通过聚合方式重用其它的COM对象ATL对象属性设置中的聚合模型可以指定待创建的COM对象是否支持聚合模型缺省的选项是支持对象的聚合 对象对错误处理的支持(Support ISupportErrorInfo) 选取这个选项可以在对象的运行过程中支持错误处理缺省情况下这个选项不被选中 对象对连接点的支持(Support Connection Points) 连接点是COM对象的事件机制选中这个选项可以使待创建的COM对象具有发出事件的能力缺省情况下该选项不被选中 对象对自由线程调度的支持(Free Thread Marshaller 简称FTM) 对象的自由线程调度是对象在处于自由线程模型状态下为了简化对象的访问过程而采用的一种优化策略缺省情况下该选项不被选中 对于上述的任何一个选项的详细描述都涉及到COM技术一些核心的内容并且都已超出本文的范围因此本文只对ATL给出的缺省选项加以说明对这些内容感兴趣的读者可以参考Microsoft提供的文档 完成了上面的设置以后就可以按OK按钮完成对象的创建过程下一步就是向所生成的ATL类的接口中加入成员函数的定义以及接口成员函数的实现过程 加入接口定义实现接口函数 加入了ATL类定义之后我们可以打开Visual C++集成环境下项目管理器(Workspace)中的Class View来检查生成的类定义的情况我们可以看到一个新的类已经生成同时还生成了相应的接口定义ATL Object Wizard为我们生成了类定义的h 和cpp文件此外还有用于接口定义的IDL文件有了这些文件以后我们就可以为接口加入成员函数完成类的定义 首先在Class View中选中相应的接口显示为接口IATLTest单击鼠标右键打开菜单如图此弹出式菜单定义了为接口加入属性和方法的操作选取其中的Add Method项可以为接口加入方法成员选取Add Property则可以为接口加入新的属性成员 加入属性和方法的对话框可以参看图和图如果我们要在接口中加入一个方法则选取Add Method菜单命令假设方法名为ABC方法的返回类型为COM规定的HRESULT类型我们也可以定义非HRESULT返回类型的函数但是这需要手工修改接口定义的IDL文件我们定义ABC方法的一个参数为a类型为整数型完成了方法的定义以后单击OK按钮则把此方法加入到接口中 属性的加入过程是类似的属性加入对话框要求指定属性的类型名字以及属性的访问方式在属性和方法的编辑对话框中都有一个Attributes按钮在给出了一个属性或方法的基本定义之后单击此按钮可以对属性和方法的一些高级特性进行设置 方法成员加入以后我们可以通过Class View来检查ATL为我们所做的工作首先我们看到ATL在接口的定义中加入了该方法的定义同时在对应的ATL类定义中也加入了一个相应的方法的定义在类对应的cpp文件中加入了此方法的实现框架此后我们只要在这个函数框架中加入该方法的代码逻辑一个接口函数的定义和实现就基本完成了依照这种方式我们可以完成整个COM对象的定义和实现 完成以上的步骤之后我们就可以编译连接应用了 编译连接应用注册COM服务程序 对ATL工程的编译连接过程包括下面的几个步骤 使用MIDL编译工程的IDL文件形成接口定义的头文件和用于调度(Marshalling)的代码 编译工程的cpp文件形成目标文件 连接目标文件形成应用模块 注册COM服务程序 关于工程编译连接的其它部分同Visual C++中MFC工程的编译连接过程相似这里只重点介绍一下COM服务程序的注册过程 在ATL中COM服务程序的注册是在工程编译连接的最后阶段由ATL辅助完成的在手工的COM编程中服务程序的注册是比较麻烦的工作在ATL中系统通过读取在建立工程过程中形成的注册脚本文件来完成注册工作注册脚本(Register Script 简称RGS)是ATL提供的文本方式的注册辅助文件下面是注册脚本文件的一个实例 HKCR - 表示注册表中COM对象的注册项是HKEY_CLASS_ROOT的缩写 { AuthTestActiveXObject = s ActiveXObject Class { CLSID |