Developing COM Components using VC-ATL(2-5)

 

对组件的十一个文件的剖析

一、stdafx.h

代码选取

#define STRICT

#ifndef _WIN32_WINNT

#define _WIN32_WINNT 0x0400

#endif

#define _ATL_APARTMENT_THREADED

#include

#include

#include

//You may derive a class from CComModule and use it if you want to override

//something, but do not change the name of _Module

extern CComModule _Module;

#include

代码剖析

n          包含了ATL头文件

#include

#include

n          两个声明

#define _ATL_APARTMENT_THREADED

定义了将成为apartment模型的DLL默认线程模型。

_ModuleCComModule类型的对象,CComModule实现了COM服务器的基本功能,实现并提供了诸如注册、实例化所支持对象以及通过对象映射管理生命周期等服务。注意因为它通过ATL头文件所引用,所以CComModule对象必须是全局的且必须命名为_Module

另外,这个类也是ATL的中心,正如主函数对任何程序的入口点(C/C++),这个类的模块对象处理几个任务,如:服务器锁计数、注册本地服务器的类工厂、根据注册表注册和反注册。

 

二、stdafx.cpp

#ifdef _ATL_STATIC_REGISTRY

#include

#include

#endif

#include

 

三、MyProj.def输出定义文件

     代码选取

; MyProj.def : Declares the module parameters.

LIBRARY      "MyProj.DLL"

EXPORTS

         DllCanUnloadNow     @1 PRIVATE

         DllGetClassObject   @2 PRIVATE

         DllRegisterServer   @3 PRIVATE

         DllUnregisterServer @4 PRIVATE

代码剖析

也称模块定义文件,只有进程内服务器DLL才产生,它提供了被链接程序的信息(DLL文件的名字)

 

四、MyProj.tlb类型库

编绎后生成,客户端使用时用#import方式导入之。

 

五、MyProj.idl接口定义语言文件

    代码选取

import "oaidl.idl"; //此文件包括IDispatch接口的定义,import相当于#include

import "ocidl.idl";

         [

                   object,

                   uuid(65460F9C-3BAB-4055-885A-8ED59F5FA9B0),

                   dual,

                   helpstring("IMyCom Interface"),

                   pointer_default(unique)

         ]

         interface IMyCom : IDispatch

         {

                   [id(1), helpstring("method MyF1")] HRESULT MyF1();

                   [id(2), helpstring("method MyF2")] HRESULT MyF2([in] BSTR str,[out, retval] int* val);

                   [id(3), helpstring("method MyF3")] HRESULT MyF3([in] BSTR str,[out, retval] BSTR* retstr);

                   [id(4), helpstring("method MyF4")] HRESULT MyF4([in] int x,[out, retval] int* val);

         };

 

[

         uuid(FE651184-11DE-4D01-BD69-B07DDFA12D0C),

         version(1.0),

         helpstring("MyProj 1.0 Type Library")

]

library MYPROJLib

{

         importlib("stdole32.tlb");

         importlib("stdole2.tlb");

 

         [

                   uuid(FEB7BDEF-FB6F-446B-BE31-DF0A3AD391BA),

                   helpstring("MyCom Class")

         ]

         coclass MyCom

         {

                   [default] interface IMyCom;

         };

};

代码剖析

IDL文件由三部分组成,每部分又都由一对中括号和一对大括号组成。每部分也都包含一个UUID来唯一的标识自己

n          接口部分:COM接口定义

[

                   object,

                   uuid(65460F9C-3BAB-4055-885A-8ED59F5FA9B0), //接口唯一标识符(GUID/IID)

                   dual, //表示客户机可用两种方法访问这个接口,一种是支持指针的非脚本语言,如VC;一种是非脚本语言,如VBASP

                   helpstring("IMyCom Interface"), //将提示字符串与此接口建立联系

                   pointer_default(unique) //指定除参数表中所列属性之外所有指针的缺省特征,unique表示指针可以是NULL,但不支持别名

         ]

         interface IMyCom : IDispatch

         {

                   [id(1), helpstring("method MyF1")] HRESULT MyF1();

                   [id(2), helpstring("method MyF2")] HRESULT MyF2([in] BSTR str,[out, retval] int* val);

                   [id(3), helpstring("method MyF3")] HRESULT MyF3([in] BSTR str,[out, retval] BSTR* retstr);

                   [id(4), helpstring("method MyF4")] HRESULT MyF4([in] int x,[out, retval] int* val);

         };//接口中的方法

n          类型库部分

[

         uuid(FE651184-11DE-4D01-BD69-B07DDFA12D0C),

         version(1.0),

         helpstring("MyProj 1.0 Type Library")

]

library MYPROJLib

{

         importlib("stdole32.tlb");

         importlib("stdole2.tlb");

                   <组件类部分>

};

n          组件类部分(组件类嵌套在类型库里面)

     [

              uuid(FEB7BDEF-FB6F-446B-BE31-DF0A3AD391BA),

              helpstring("MyCom Class")

     ]

     coclass MyCom

     {

              [default] interface IMyCom;

     };

手工为接口添加一个方法,该修改哪些地方?

        假设组件类名叫CMyCom,接口叫IMyCom,要加入的方法是MyF5

首先在IDL文件中找到接口IMyCom的定义,在其中加入如下方法定义:

        [id(5), helpstring("method MyF5")] HRESULT MyF1([out,retval] VARIANT_BOOL *ret);

注意:id中的数字不要和已经存在的id重复。

其次,在CMyCom的类定义头文件中加入如下成员函数声明:

public:

STDMETHOD(MyF5)(/*[out, retval]*/ VARIANT_BOOL *ret);

最后,在CMyCom类的实现Cpp文件中加入函数的实现:

STDMETHODIMP CMyCom::MyF5(VARIANT_BOOL *ret)

{

         AFX_MANAGE_STATE(AfxGetStaticModuleState())

         // TODO: Add your implementation code here

     *ret = VARAINT_TRUE;

         return S_OK;

}


作者Blog: http://blog.csdn.net/callzjy/

你可能感兴趣的:(COM)