COM原理及代码实例.docx

上传人:b****4 文档编号:4307769 上传时间:2022-11-29 格式:DOCX 页数:17 大小:220.49KB
下载 相关 举报
COM原理及代码实例.docx_第1页
第1页 / 共17页
COM原理及代码实例.docx_第2页
第2页 / 共17页
COM原理及代码实例.docx_第3页
第3页 / 共17页
COM原理及代码实例.docx_第4页
第4页 / 共17页
COM原理及代码实例.docx_第5页
第5页 / 共17页
点击查看更多>>
下载资源
资源描述

COM原理及代码实例.docx

《COM原理及代码实例.docx》由会员分享,可在线阅读,更多相关《COM原理及代码实例.docx(17页珍藏版)》请在冰豆网上搜索。

COM原理及代码实例.docx

COM原理及代码实例

1.COM原理

1.1.COM基本概念介绍

1.什么是COM(ComponentObjectModal)

COM(ComponentObjectModal)是Microsoft组件对象模型的简称。

是一个说明如何建立可动态交替更新组件的规范。

简单地说,COM是一种跨应用和语言共享二进制代码的方法。

与C++不同,它提倡源代码重用。

ATL便是一个很好的例证。

源码级重用虽然好,但只能用于C++。

它还带来了名字冲突的可能性,更不用说不断拷贝重用代码而导致工程膨胀和臃肿。

2.COM组件

COM组件是由以Win32动态链接库(DLL)或可执行文件(EXE)发布的代码所组成。

3.为什么要学习COM

传统的软件开发模式:

传统的软件应用程序发布以后,使用者想得到更完善的软件或者去掉其中的某些内容,只有等软件提供商发布新的版本以后,使用者的这一梦想才能得以实现。

使用COM组件以后:

软件开发人员可以在软件版本发布以后修改或者去掉软件某个不需要部分。

也及应用程序在更高的层次上定制,使得软件更具灵活性、动态性。

是未来应用软件开发的趋势。

4.COM的前身是OLE(ObjectLinkingandEmbedding)对象链接与嵌入。

5.组件:

如积木一样,具有“块”的概念,可以动态的将他们插入或卸出应用程序。

这就需要两个条件:

第一,组件必须动态链接(不因自己的位置改变而改变自身形式);第二,组件必须隐藏内部实现细节(独立与具体编程语言,二进制形式发布)。

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

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

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

1.2.完整的COM组件的接口实现实例

#include

#include

usingnamespacestd;

voidtrace(constchar*pMsg)

{

cout<

}

//抽象接口1

interfaceInteX

{

virtualvoid_stdcallFx1()=0;

virtualvoid_stdcallFx2()=0;

};

//抽象接口2

interfaceInteY

{

virtualvoid_stdcallFy1()=0;

virtualvoid_stdcallFy2()=0;

};

//抽象接口实现

classCompA:

publicInteX,publicInteY

{

public:

//实现接口InteX

virtualvoid_stdcallFx1()

{

cout<<"CompA:

:

Fx1"<

}

virtualvoid_stdcallFx2()

{

cout<<"CompA:

:

Fx2"<

}

//实现接口InteY

virtualvoid_stdcallFy1()

{

cout<<"CompA:

:

Fy1"<

}

virtualvoid_stdcallFy2()

{

cout<<"CompA:

:

Fy2"<

}

};

//客户程序

intmain()

{

trace("客户:

创建组件的一个实例。

");

CompA*pcompa=newCompA;

InteX*pintex=pcompa;

trace("客户:

使用组件InteX接口。

");

pintex->Fx1();

pintex->Fx2();

InteY*pintey=pcompa;

trace("客户:

使用组件InteY接口。

");

pintey->Fy1();

pintey->Fy2();

trace("客户:

删除组件。

");

deletepcompa;

return0;

}

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

#include

#include

usingnamespacestd;

voidtrace(constchar*pMsg)

{

cout<

}

//GUID全局唯一标示符

externconstIIDIID_InteX;

externconstIIDIID_InteY;

externconstIIDIID_InteZ;

//接口实现

interfaceInteX:

IUnknown

{

virtualvoid_stdcallFx()=0;

};

interfaceInteY:

IUnknown

{

virtualvoid_stdcallFy()=0;

};

interfaceInteZ:

IUnknown

{

virtualvoid_stdcallFz()=0;

};

//抽象接口实现

classCompA:

publicInteX,publicInteY

{

//IUnknown实现

virtualHRESULTSTDMETHODCALLTYPEQueryInterface(constIID&iid,void**ppv);

virtualULONGSTDMETHODCALLTYPEAddRef();

virtualULONGSTDMETHODCALLTYPERelease();

//实现接口InteX

virtualvoid_stdcallFx()

{

cout<<"CompA:

:

Fx"<

}

//实现接口InteY

virtualvoid_stdcallFy()

{

cout<<"CompA:

:

Fy"<

}

ULONGm_cRef;

public:

CompA():

m_cRef(0){}

~CompA(){trace("析构CompA自身");}

};

HRESULTSTDMETHODCALLTYPECompA:

:

QueryInterface(constIID&iid,void**ppv)

{

if(iid==IID_IUnknown)

{

trace("CompA():

:

QueryInterface:

返回指向IUnknown本身的指针.");

*ppv=static_cast(this);

}

elseif(iid==IID_InteX)

{

trace("CompA():

:

QueryInterface:

返回指向InteX的指针.");

*ppv=static_cast(this);

}

elseif(iid==IID_InteY)

{

trace("CompA():

:

QueryInterface:

返回指向InteY的指针.");

*ppv=static_cast(this);

}

else

{

trace("CompA():

:

QueryInterface:

接口不支持.");

*ppv=NULL;

returnE_NOINTERFACE;

}

reinterpret_cast(*ppv)->AddRef();

returnS_OK;

}

ULONGSTDMETHODCALLTYPECompA:

:

AddRef()

{

cout<<"CompA():

:

AddRef="<

增加接口引用计数<<'.'<

returnm_cRef;

}

ULONGSTDMETHODCALLTYPECompA:

:

Release()

{

cout<<"CompA():

:

Release="<

if(0==m_cRef)

{

deletethis;

return0;

}

returnm_cRef;

}

//创建实例函数

IUnknown*CreateInstance()

{

IUnknown*pinte=static_cast(newCompA);

pinte->AddRef();

returnpinte;

}

//IIDs

constIIDIID_InteX=

{0x32bb832c,0xb41a,0x11cf,

{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};

constIIDIID_InteY=

{0x32bb832d,0xb41a,0x11cf,

{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};

constIIDIID_InteZ=

{0x32bb832e,0xb41a,0x11cf,

{0xa6,0xbb,0x0,0x80,0xc7,0xb2,0xd6,0x82}};

//客户程序

intmain()

{

HRESULThr;

trace("客户:

获得IUnknown的一个指针");

IUnknown*piunknown=CreateInstance();

trace("客户:

获得InteX的接口");

InteX*pintex=NULL;

hr=piunknown->QueryInterface(IID_InteX,(void**)&pintex);

if(SUCCEEDED(hr))

{

trace("客户成功获得组件InteX");

pintex->Fx();

pintex->Release();

}

trace("客户:

获得InteY的接口");

InteY*pintey=NULL;

hr=piunknown->QueryInterface(IID_InteY,(void**)&pintey);

if(SUCCEEDED(hr))

{

trace("客户成功获得组件InteY");

pintey->Fy();

pintey->Release();

}

trace("客户尝试获得不支持的InteZ组件接口");

InteZ*pintez=NULL;

hr=piunknown->QueryInterface(IID_InteZ,(void**)&pintez);

if(SUCCEEDED(hr))

{

trace("客户成功获得组件InteZ");

pintez->Fz();

pintez->Release();

}

else

{

trace("客户不能成功获得组件InteZ");

}

trace("客户释放IUnknown借口");

piunknown->Release();

return0;

}

1.3.ATL——活动模板库(TheActiveTemplateLibrary)

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

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

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

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

∙COM技术

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

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

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

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

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

1.建立一个ATL工程:

图11-1

2.选择创建的COM类型:

图11-2

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

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

应用程序(Executableapplication)最终产生一个可执行程序类型(EXE)的COM服务程序;

NT服务(NTService)产生一个以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提供的各种功能强大的类的支持,而不必直接使用WindowsSDK。

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

●支持MTS。

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

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

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

首先通过集成环境的"Insert"菜单下的"NewATLObject..."命令进入"ATLObjectWizard"对话框。

如下图所示:

图11-3

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

●对象(Object)基本的COM对象类型;

●控制(Control)ActiveXControl类型的ATL对象;

●其他(Miscellaneous)辅助功能,如对话框的生成等;

●数据访问(DataAccess)数据访问,支持MTS等。

对于一般的COM服务程序,选择 对象(Object),点击下一步继续:

3.输入引入的类名:

图11-4

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

图11-5

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

∙对象的线程模型(ThreadModel):

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

∙对象的接口模型(Interface):

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

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

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

∙对象的聚合模型(Aggregate):

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

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

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

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

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

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

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

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

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

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

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

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

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

5.给引入的类添加方法:

图11-6

图11-7

给添加的方法加入如下代码:

图11-8

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;

6.添加工程到当前工程中:

图11-9

7.添加类到当前工程中:

图11-10

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

图11-11

关联如下变量:

图11-12

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

voidCMyComClientDlg:

:

OnTransfer()

{

ICMyStrm_MyString;

//创建COM对象

if(!

m_MyString.CreateDispatch("AtlComSample.cmystr.1"))

MessageBox("CreateUserInfoerror");

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

UpdateData(true);

//调用COM接口

BSTRbstrDestStr=SysAllocString(L"");

m_MyString.StringTransfer(m_SourceString,&bstrDestStr);

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

m_DestString=bstrDestStr;

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

UpdateData(false);

}

运行结果如下:

图11-13

练习:

使用同样ATL的方法,建立自己的COM组件并在客户程序中进行使用。

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

当前位置:首页 > 解决方案 > 学习计划

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

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