COM组件设计与应用
- 格式:docx
- 大小:563.18 KB
- 文档页数:15
COM组件技术在电子商务系统中的应用网上购物是电子商务系统的一个重要的组成部分,本文采用COM组件技术实现了网上购物车,增强了网上购物车系统的安全性和使用效率。
标签:COM组件技术电子商务系统网上购物车一、引言目前,对于电子商务来说,如何构建高效率、高性能可重用的系统是一个需要深入研究的课题。
网络通信技术和计算机硬件技术的显著进步不仅有力地支持了电子商务应用的飞跃式发展,同时也大大提高了大型分布式商务软件系统的规模和复杂度,使企业级电子商务系统的构建技术面临新的挑战。
人们迫切希望构建的企业级电子商务系统既具有高性能、高效率、易部署、易维护和高可靠性的优点,又能灵活地适应企业业务需求的不断变化,方便地支持系统的扩展、移植和重用。
二、COM组件技术COM是开发软件组件的一种方法。
组件实际上是一些小的二进制可执行程序,它们可以给应用程序,操作系统,以及其他组件提供服务,能够跨越链接库、应用程序、系统软件甚至网络软件,多个COM对象甚至可以联接起来形成应用程序或组件系统。
它们也是开发人员时刻都在期望的一种技术,利用这种技术开发自定义的COM组件就如同开发动态的,面向对象的API,能轻松地开发出大型而复杂的应用系统,也能尽可能地利用现有的资源,以一种堆砌的方式来构造自己的应用。
COM构架下,人们可以开发出各种各样的功能专一的组件,然后将它们按照需要组合起来,构成复杂的应用系统。
COM(组件对象模型)是一个与操作平台无关的、分布的、面向对象的机制,它能创建可以相互交互的二进制软件模块。
COM的本质特性是COM对象的接口与实现的分离。
这些对象可以用不同的语言实现,其结构也可以不同。
基于COM的组件开发具有以下几点优势:1.同语言的无关性。
COM是二进制的设计标准,它与语言无关,所以生成的模块能够被各种开发工具所共享。
COM类突破了C++修饰符不兼容的限制,能够最大程度地实现基于OOP的模块重用。
2.提供深入系统底层的手段。
COM 组件设计与应用(十七)——持续性作者:杨老师下载源代码一、前言我们写程序,经常需要实现这样的需求:例一、程序运行产生一个窗口,用户关闭的时候需要记录窗口的位置,以便下次运行时保持位置不变;例二、由于程序运行时间很长,今天执行一部分,明天继续执行。
那么在下次运行前要恢复前次的状态;... ... ... ...智慧的老师:以上这些需求,如何实现呢?懵懂的学生:这个简单,只要在程序退出前提取必要的信息保存到文件中,下次运行时再从文件中读出来,设置一下就OK了。
智慧的老师:恩,不错,这位同学的思想值得表扬。
懵懂的学生:不好意思,这都要感谢老师的栽培,我对您的景仰如滔滔江水......智慧的老师:别臭P了,我话还没有说完那......如果你需要提取和保存的信息很多,结构很复杂......怎么办?懵懂的学生:也好办,我设计一个结构来记录这些信息。
智慧的老师:恩......不错。
但如果这些信息提供方是别人写的模块,并且随着版本的不同还经常变化,你怎么办?懵懂的学生:... ...智慧的老师:解决这些问题的方法是---持续性。
二、原理持续性,也叫永久性。
组件方提供IPersistXXX 接口,调用者(容器)提供存储介质,比如文件啦、内存啦、注册表啦、流啦、文本啦......啦啦拉。
需要保存的时候,调用者通过IPersistXXX::Save() 接口函数让组件去自己存储属性信息,而调用者根本不用关心存储格式和存储内容;需要还原状态的时候,调用者打开存储介质,然后同样调用IPersistXXX::Load() 接口函数让组件自己去读取属性信息并完成初始化的设置。
目前,微软定义了如下各种类型的持续性接口,足够满足你的需求了。
我们只要在自己写的组件中实现其中一个或几个持续性接口,那么调用者就可以按照统一的方式和我们的组件协商完成属性信息的保存和状态还原了。
三、持续性接口组件的实现示例程序分别在vc6.0 和 上实现了IPersistStreamInit 接口的COM 组件和调用举例。
试验任务书试验题目:COM 组件对象的设计与应用试验目的:通过对简单COM 组件的编写,加深对COM 理论知识的理解,为更深层的COM 应用做准备。
试验任务:按照组件化程序设计方法,用Visual C++编写实现包含IAdd 、IStr 、IMul 三个接口的.dll 组件,并利用客户端应用程序完成对各接口的充分测试。
试验要求:独立完成COM 组件和客户端测试程序的编写。
在实验报告中记录相关实现代码,并在试验报告中记录试验结果。
要求客户端调用Cat 方法实现自己姓名字符串和班级学号字符串的连接,以及测试加法运算和乘法运算。
试验步骤:1.分析组件结构。
2.编写简单.dll 组件。
3.逐步添加接口。
4.编写客户端应用程序进行测试。
⑴用regedit 命令打开注册表⑵注销操作:RegSvr32 /u c:\XXXXX.dll ⑶注册操作:RegSvr32 c:\XXXXX.dll ⑷在运行客户程序前,必须先注册组件程序。
5.写出上机实验报告。
实验报告格式:1.画出实验所设计的COM组件的结构2.关键代码⑴组件部分的关键代码①idl文件内COM对象和接口的关键定义代码②C++文件中成员函数的关键实现代码⑵客户端测试程序中组件调用部分的关键代码3.实验结果实验参考一、建立ATL工程( 注意:和试验任务书要求的组件结构不同)IUnknown步骤1:建立一个工作区(WorkSpace)。
步骤2:在工作区中,新建一个A TL工程(Project)。
命名为SimpleCom(如图1),并选择DLL方式(如图2)。
图1 新建ATL工程图2 选择DLL类型说明:⑴Dynamic Link Library(DLL) 表示建立一个DLL 的组件程序。
⑵Executable(EXE) 表示建立一个EXE 的组件程序。
⑶Service(EXE) 表示建立一个服务程序,系统启动后就会加载并执行的程序。
⑷Allow merging of proxy/stub code 选择该项表示把“代理/存根”代码合并到组件程序中,否则需要单独编译,单独注册代理存根程序。
一、前言书接上回,话说在doc(Word) 复合文件中,已经解决了保存xls(Excel) 数据的问题了。
那么,接下来又要解决另一个问题:当WORD 程序读取复合文件,遇到了xls 数据的时候,它该如何启动Excel 呢?启动后,又如何让Excel 自己去读入、解析、显示xls 数据呢?二、CLSID 概念有一个非常简单的解决方案,那就是在对象数据的前面,保存有处理这个数据的程序名。
(见下图左上)图一、CLSID 的概念这的确是一个简单的方法,但同时问题也很严重。
在“张三”的计算机上,Excel 的路径是:"c:\office\Excel.exe",如果把这个.doc 文件复制到“李四”的计算机上使用,而“李四”的Excel 的路径是:"d:\Program files\Microsoft Office\Office\Excel.exe",完蛋了于是,微软想出了一个解决方案,那就是不使用直接的路径表示方法,而使用一个叫CLSID(注1)的方式间接描述这些对象数据的处理程序路径。
CLSID 其实就是一个号码,或者说是一个16字节的数。
观察注册表(上图),在HKCR\CLSID\{......}主键下,LocalServer32(DLL组件使用InprocServer32)中保存着程序路径名称。
CLSID 的结构定义如下:typedef struct _GUID {DWORD Data1; // 随机数WORD Data2; // 和时间相关WORD Data3; // 和时间相关BYTE Data4[8]; // 和网卡MAC相关} GUID;typedef GUID CLSID; // 组件IDtypedef GUID IID; // 接口ID#define REFCLSID const CLSID &// 常见的声明和赋值方法CLSID CLSID_Excel ={0x00024500,0x0000,0x0000,{0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46}}; struct __declspec(uuid("00024500-0000-0000-C000-000000000046"))CLSID_Excel;class DECLSPEC_UUID("00024500-0000-0000-C000-000000000046")CLSID_Excel;// 注册表中的表示方法{00024500-0000-0000-C000-000000000046}用一个号码间接表示程序名,的确是个Good idea,实现了组件位置的透明性,并方便地扩展出DCOM (远程组件)。
COM组件技术在电子商务系统中的应用引言电子商务系统已经成为现代商业的重要组成部分。
随着科技的进步和互联网的普及,越来越多的企业选择使用电子商务系统来进行在线销售和交易。
在开发和构建电子商务系统时,选择合适的技术和工具非常关键。
COM组件技术是一种常用的技术,其在电子商务系统中的应用也非常广泛。
本文将探讨COM组件技术在电子商务系统中的应用,并分析其优势和挑战。
COM组件技术概述COM(Component Object Model)是一种面向对象的二进制接口标准,旨在实现不同软件组件之间的互操作性。
COM组件可以通过定义和实现接口来提供特定功能,并通过接口方法进行交互。
COM组件可以用于各种软件开发和集成的场景,并且在Windows操作系统中得到广泛支持。
COM组件技术在电子商务系统中的应用1. 产品管理和库存控制电子商务系统需要管理大量的产品信息和库存数据。
通过使用COM组件技术,可以开发可重用的组件来处理产品管理和库存控制的功能。
这些组件可以提供添加、编辑和删除产品信息的接口,同时还可以实现库存的实时更新和管理。
通过将这些组件集成到电子商务系统中,可以实现高效的产品管理和库存控制。
2. 支付和交易处理电子商务系统的核心功能之一是支付和交易处理。
COM组件技术可以提供安全可靠的支付和交易处理功能。
通过使用COM组件技术,可以实现与第三方支付网关的集成,并提供方便的支付接口。
这些组件可以处理支付请求、验证交易信息,并生成支付确认和交易记录。
通过使用COM组件技术,电子商务系统可以实现快速、安全和准确的支付和交易处理。
3. 订单管理和物流追踪电子商务系统需要管理和追踪大量的订单和物流信息。
通过使用COM组件技术,可以开发可重用的组件来处理订单管理和物流追踪的功能。
这些组件可以提供创建、编辑和取消订单的接口,同时还可以实现订单状态的实时更新和物流信息的跟踪。
通过将这些组件集成到电子商务系统中,可以实现高效的订单管理和物流追踪。
COM 组件设计与应用第一节起源及复合文件一、文件的存储传说350年前,牛顿被苹果砸到了头,于是发现了万有引力。
但到了二十一世纪的现在,任何一个技术的发明和发展,已经不再依靠圣人灵光的一闪。
技术的进步转而是被社会的需求、商业的利益、竞争的压力、行业的渗透等推动的。
微软在Windows平台上的组件技术也不例外,它的发明,有其必然因素。
什么是这个因素那?答案是——文件的存储。
打开记事本程序,输入了一篇文章后,保存。
——这样的文件叫“非结构化文件”;打开电子表格程序,输入一个班的学生姓名和考试成绩,保存。
——这样的文件叫“标准结构化文件”;在我们写的程序中,需要把特定的数据按照一定的结构和顺序写到文件中保存。
——这样的文件叫“自定义结构化文件”;(比如 *.bmp 文件)以上三种类型的文件,大家都见的多了。
那么文件存储就依靠上述的方式能满足所有的应用需求吗?恩~~~,至少从计算机发明后的50多年来,一直是够用的了。
嘿嘿,下面看看商业利益的推动作用,对文件的存储形式产生了什么变化吧。
30岁以上的朋友,我估计以前都使用过以下几个著名的软件:WordStar(独霸DOS下的英文编辑软件),WPS(裘伯君写的中文编辑软件,据说当年的市场占有率高达90%,各种计算机培训班的必修课程),LOTUS-123(莲花公司出品的电子表格软件)......微软在成功地推出 Windows 3.1 后,开始垂涎桌面办公自动化软件领域。
微软的OFFICE 开发部门,各小组分别独立地开发了 WORD 和 EXCEL 等软件,并采用“自定义结构”方式,对文件进行存储。
在激烈的市场竞争下,为了打败竞争对手,微软自然地产生了一个念头------如果我能在 WORD 程序中嵌入 EXCEL,那么用户在购买了我 WORD 软件的情况下,不就没有必要再买 LOTUS-123 了吗?!“恶毒”的计划产生后,他们开始了实施工作,这就是 COM 的前身 OLE 的起源(注1)。
COM 组件设计与应用(十一)—— IDispatch 及双接口的调用一、前言前段时间,由于工作比较忙,没有能及时地写作。
其间收到了很多网友的来信询问和鼓励,在此一并表示感谢。
咳......我也需要工作来养家糊口呀......上回书介绍了两种方法来写自动化(IDispatch)接口的组件程序,一是用MFC 方式编写“纯粹”的 IDispatch 接口;二是用 ATL 方式编写“双接口”的组件。
二、IDispatch 接口和双接口使用者要想调用普通的 COM 组件功能,必须要加载这个组件的类型库(Type library)文件tlb(比如在 VC 中使用 #import)。
然而,在脚本程序中,由于脚本是被解释执行的,所以无法使用加载类型库的方式进行预编译。
那么脚本解释器如何使用 COM 组件那?这就是自动化(IDispatch)组件大显身手的地方了。
IDispatch 接口需要实现4个函数,调用者只通过这4个函数,pVarResult,[out] EXCEPINFO * pExcepInfo,[out] UINT * puArgErr) .... } 其实,就是根据序号进行分支调用啦。
(注3)行效率是比较低的。
ATL 从效率出发,实现了一种叫“双接口(dual)”的接口模式。
下面我们来看看,到底什么是双接口:图一、双接口(dual) 结构示意图从上图中可以看出,所谓双接口,其实是在一个 VTAB 的虚函数表中容纳了三个接口(因为任何接口都是从 IUnknown 派生的,所以就不强调 IUnknown 了,叫做双接口)。
我们如果从任意一个接口中调用 QueryInterface()得到另外的接口指针的话,其实,得到的指针地址都是同使用方式 因为 所以脚本语言使用组件 解释器只认识 IDispatch 接口 可以调用,但执行效率最低编译型语言使用组件 它认识 IDispatch 接口 可以调用,执行效率比较低编译型语言使用组件 它装载类型库后,就认识了 Ixxx 接口可以直接调用 Ixxx 函数,效率最高啦 结论 双接口,既满足脚本语言的使用方便性,又满足编译型语言的使用高效性。
双击代码全选1 H RESULT IUnknown::QueryInterface ( REFIID iid, void** ppv );双击代码全选1 2 3 HRESULT hr;IPersistFile* pIPF;hr = pISL->QueryInterface ( IID_IPersistFile, (void**) &pIPF );双击代码全选1 HRESULT CoCreateInstance ( REFCLSID rclsid, LPUNKNOWN pUnkOuter, DWORD dwClsContext, REFIID riid, LPVOID* ppv );双击代码全选1 2 3 4 5 6 7 8 9 10 11 HRESULT hr_COM;IShellLink* pISL_COM;hr_COM = CoCreateInstance ( CLSID_ShellLink, CLSID NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**) &pISL );if ( SUCCEEDED ( hr_COM ) ){// 用pISL_COM 调用方法}else{// 不能创建COM 对象,hr_COM 为出错代码}双击代码全选1 2 3 4 if ( SUCCEEDED ( hr ) ){pISL_COM->Release();}双击代码全选123456789 10 11 12 13 14 15 16 17 18 19 20 21 22 23WCHAR wszWallpaper [MAX_PATH]; CString strPath; HRESULT hr; IActiveDesktop* pIAD; CoInitialize ( NULL ); hr = CoCreateInstance ( CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**) &pIAD ); if ( SUCCEEDED(hr) ) {hr = pIAD->GetWallpaper ( wszWallpaper, MAX_PATH, 0 );if ( SUCCEEDED(hr) ){wcout << L"Wallpaper path is:/n " << wszWallpaper << endl << endl; }else{cout << _T("GetWallpaper() failed.") << endl << endl; } pIAD->Release(); }else{cout << _T("CoCreateInstance() failed.") << endl << endl;}}CoUninitialize();双击代码全选1 2 3 4 5 6 7 8 9 10 11 CString sWallpaper = wszWallpaper;ANSI IShellLink* pISL;IPersistFile* pIPF;CoInitialize ( NULL );hr = CoCreateInstance ( CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void**) &pISL );if ( SUCCEEDED(hr) ){hr = pISL->SetPath ( sWallpaper );if ( SUCCEEDED(hr) ){1213141516171819 20hr = pISL->QueryInterface ( IID_IPersistFile, (void**) &pIPF );if( SUCCEEDED(hr) ){hr = pIPF->Save ( L"C://wallpaper.lnk", FALSE );pIPF->Release();}}pISL->Release();}CoUninitialize();。
COM技术及其应用的开题报告题目:COM技术及其应用一、选题背景:COM(Component Object Model)是一种面向对象、分布式的软件组件技术,它能够跨语言、跨操作系统和跨网络传输,并且具有高度的复用性、可扩展性和互操作性,被广泛应用于各种软件系统的设计和开发中。
COM技术的应用领域非常广泛,例如:支持OLE(Object Linking and Embedding)客户端/服务器应用程序的开发、创建基于COM的ActiveX控件、编写COM组件以支持Office应用程序等等。
COM技术的高度复用性、可扩展性和互操作性在软件开发领域中具有重要的地位。
然而,COM技术本身也具有复杂性和难度,在使用中需要进行深入的学习和理解。
二、选题目的:本文旨在深入探讨COM技术的原理和应用,介绍COM组件模型、COM接口、COM对象、COM注册表等基本概念,以及COM技术在Windows平台上的实现细节和应用实例。
通过对COM技术的学习和了解,可以提高软件开发人员的技术水平和开发效率,为软件开发提供有力的技术支持和指导。
三、预期内容:1. COM技术的基本概念和基础知识2. COM组件模型和COM接口的原理和应用3. COM对象的创建、销毁和调用方法4. COM注册表的管理和应用5. ActiveX控件的开发和应用实例6. COM技术在Office应用程序中的应用实例四、研究方法:本文将采用文献资料调研和案例分析相结合的研究方法,对COM技术的基础知识、原理和应用实例进行系统性的研究和分析。
通过实际案例的分析和实验验证,深入掌握COM技术的实际应用。
五、论文结构:第一章:绪论第二章:COM技术的基础知识和原理第三章:COM组件模型和COM接口的应用第四章:COM对象的创建、销毁和调用方法第五章:COM注册表的管理和应用第六章:ActiveX控件的开发和应用实例第七章:COM技术在Office应用程序中的应用实例第八章:总结与展望六、研究意义:本文对COM技术的应用与研究,可以提高软件开发人员的技术水平,并为研究COM技术的人员提供一份权威的中文文献,增加国内对COM技术的研究和应用。
COM基础知识收藏COM基础知识(1) COM组件实际上是一个C++类,而接口都是纯虚类。
组件从接口派生而来。
我们可以简单的用纯粹的C++的语法形式来描述COM是个什么东西:class IObject{public:virtual Function1(...) = 0;virtual Function2(...) = 0;....};class MyObject : public IObject{public:virtual Function1(...){...}virtual Function2(...){...}....};IObject就是我们常说的接口,MyObject就是所谓的COM组件。
切记接口都是纯虚类,它所包含的函数都是纯虚函数,而且它没有成员变量。
而COM 组件就是从这些纯虚类继承下来的派生类,它实现了这些虚函数,仅此而已。
从上面也可以看出,COM组件是以C++为基础的,COM中所有函数都是虚函数,都必须通过虚函数表VTable来调用,这一点是无比重要的,必需时刻牢记在心。
(2) COM组件有三个最基本的接口类,分别是IUnknown、IClassFactory、IDispatch。
COM规范规定任何组件、任何接口都必须从IUnknown继承,IUnknown 包含三个函数,分别是QueryInterface、AddRef、Release。
这三个函数是无比重要的,而且它们的排列顺序也是不可改变的。
QueryInterface用于查询组件实现的其它接口,也就是看看这个组件的父类中还有哪些接口类,AddRef 用于增加引用计数,Release用于减少引用计数。
引用计数也是COM中的一个非常重要的概念。
大体上可以这么理解,COM组件是个DLL,当客户程序要用它时就要把它装到内存里。
另一方面,一个组件也不是只给你一个人用的,可能会有很多个程序同时都要用到它。
但实际上DLL只装载了一次,即内存中只有一个COM组件,那COM组件由谁来释放?由客户程序吗?不可能,因为如果你释放了组件,那别人怎么用,所以只能由COM组件自己来负责。
COM组件设计与应用(八)实现多接口作者:杨老师下载源代码一、前言从第五回开始到第七回,咱们用ATL 写了一个简单的COM 组件,之所以说简单,是因为在组件中,只实现了一个自定义(custom)的接口IFun。
当然如果想偷懒的话,我们可以把200 个函数都加到这一个接口中,果真如此的话,恐怕就没有人喜欢使用我们这个组件了。
一个组件既然可以提供多个接口,那么我们在设计的时候,就应该按照函数的功能进行分类,把不同功能分类的函数用多个接口表现出来。
这样可以有如下的一些好处:1、一个接口中的函数个数有限、功能集中,使用者容易学习、记忆和调用。
一个接口到底提供多少个函数合适那?答案是:如果你是黑猩猩,那么一个接口最多3个函数,如果你是人,那么一个接口最好不要超过7个函数。
(注1)2、容易维护。
至少你肉眼搜索的时候也方便一些呀。
3、容易升级。
当我们给组件增加函数的时候,不要修改已经发表的接口,而是提供一个新的接口来完成功能扩展。
(注2)本回书着落在------如何实现一个组件,多个接口。
二、接口结构图一、组件A有2个自定义接口,组件B是A的升级某日,我们设计了组件A,它有2个自定义(custom)接口。
IMathe 有函数Add()完成整数加法,IStr 有函数Cat()完成字符串连接。
忽一日,我们升级组件A到B,欲增加一个函数Mul() 完成整数的乘法。
注意,由于我们已经发表了组件A,因此我们不能把这个函数安排到老接口IMathe 中了。
解决方法是再定义一个新接口IMathe2,在新接口中增加Mul() 函数并依旧保留Add() 函数。
这样,老用户不知道新接口IMathe2 的存在,他仍然使用旧接口IMathe;而新用户则可以抛弃IMathe,直接使用IMathe2 的新接口功能。
看,多平顺的升级方式呀!三、实现3-1、首先用ATL 实现一个自定义(custom)接口IMathe 的COM组件,在接口中完成Add()整数加法函数。
COM 组件设计与应用(十三)——事件和通知(VC6.0)一、前言我的 COM 组件运行时产生一个窗口,当用户双击该窗口的时候,我需要通知调用者;我的 COM 组件用线程方式下载网络上的一个文件,当我完成任务后,需要通知调用者;我的 COM 组件完成一个钟表的功能,当预定时间到达的时候,我需要通知调用者;... ... ... ...本回书开始话说 COM 的事件、通知、连接点......这些内容比较多,我分两次(共四回)来介绍。
二、通知的方法当程序甲方内部发生了某个事件的时候,需要通知乙方,无非使用几个方组件是运行在分布式环境中的,地球另一边计算机上运行的组件,怎么可能给你的窗口发消息那?当然不能!(但话又说回来,对于 ActiveX 这样只能在本地运行的组件,当然也可以发送窗口消息的啦。
)回调函数的方式,是设计 COM 通知方法的基础。
回调函数,本质上是预先把某一函数的指针告诉我,当我有必要的时候,就直接呼叫该函数了,而这个回调函数做了什么,怎么做的,我是根本不关心的。
好了,问你个问题:啥是COM 的接口?接口其实就是一组相关函数的集合(这个定义不严谨,但你可以这么理解哈)。
因此,在COM中不使用“回调函数”而是使用“回调接口”(说的再清楚一些,就是使用一大堆包装好的“回调函数”集),回调接口,我们也叫“接收器接口”。
图一、客户端传递接收器接口指针给COM。
当发生事件时,COM调用接收器接口函数完成通知本回示例程序完成的功能是:客户端启动组件(Simple11.IEvent1.1)并得到接口指针 IEvent1 *;调用接口方法 IEvent1::Advise() 把客户端内部的一个接收器(sink)接口指针(ICallBack *)传递到组件服务器中;调用 IEvent1::Add() 去计算两个整数的和;但是计算结果并不通过该函数返回,而是通过 ICallBack::Fire_Result() 返回给客户端;当客户端不再需要接受事件的时候,调用 IEvent1::Unadvise() 断开和组件的联系。
COM 组件设计与应用(五)——用 ATL 写第一个组件一、前言1、如果你在使用 vc5.0 及以前的版本,请你升级为 vc6.0 或 2003;2、如果你在使用 vc6.0 (ATL 3.0)请阅读本回内容;3、如果你在使用 (ATL 7.0)请阅读下回内容;(当然读读本文内容也不错)4、这第一个组件,除了所有 COM 组件必须的 IUnknown 接口外,我们再实现一个自己定义的接口 IFun,它有两个函数: Add()完成两个数值的加法,Cat()完成两个字符串的连接。
5、下面......好好听讲! 开始了:-)二、建立 ATL 工程步骤2.1:建立一个工作区(WorkSpace)。
步骤2.2:在工作区中,建立一个 ATL 工程(Project)。
示例程序叫Simple1,并选择DLL方式,见图一。
图一、建立 ATL DLL 工程Dynamic Link Library(DLL)表示建立一个 DLL 的组件程序。
Executable(EXE)表示建立一个 EXE 的组件程序。
Service(EXE)表示建立一个服务程序,系统启动后就会加载并执行的程序。
Allow merging of proxy/stub code选择该项表示把“代理/存根”代码合并到组件程序中,否则需要单独编译,单独注册代理存根程序。
代理/存根,这个是什么概念?还记得我们在上回书中介绍的吗?当调用者调用进程外或远程组件功能的时候,其实是代理/存根负责数据交换的。
关于代理/存根的具体变成和操作,以后再说啦......Support MFC除非有特殊的原因,我们写 ATL 程序,最好不要选择该项。
你可能会说,如果没有MFC的支持,那CString怎么办呀?告诉你个秘密吧,一般人我都不告诉他,我后半辈子就靠着这个秘密活着了:1、你会STL吗?可以用 STL 中的 string 代替;2、自己写个 MyString 类,嘿嘿;3、悄悄地、秘密地、不要告诉别人(特别是别告诉微软),把 MFC 中的CString 源码拿过来用;4、使用 CComBSTR 类,至少也能简化我们字符串操作;5、直接用 API 操作字符串,反正我们大家学习 C 语言的时候,都是从这里干起的。
COM 组件设计与应用(七)——编译、注册、调用一、前言上两回中,咱们用 ATL 写了第一个 COM 组件程序,这回中,主要介绍编译、册和调用方法。
示例程序你已经下载了吗?如果还没有下载,vc6.0 的用户点, 的用户点这里。
二、关于编译2-1 最小依赖“最小依赖”,表示编译器会把 ATL 中必须使用的一些函数静态连接到目标程序中。
这样目标文件尺寸会稍大,但独立性更强,安装方便;反之系统执行的时候需要有 ATL.DLL 文件的支持。
如何选择设置为“最小依赖”呢?答案是:删除预定义宏“_ATL_DLL”,操作方法见图一、图二。
图一、在vc6.0中,设置方法图二、在 2003中,设置方法2-2 CRT库如果在 ATL 组件程序中调用了 CRT 的运行时刻库函数,比如开平方 sqrt() ,那么编译的时候可能会报错“error LNK2001: unresolved external symbol _main”。
怎么办?删除预定义宏“_ATL_MIN_CRT”!操作方法也见图一、图二。
( 2003 中的这个项目属性叫“在 ATL 中最小使用 CRT”)2-3 MBCS/UNICODE这个不多说了,在预定义宏中,分别使用 _MBCS 或 _UNICODE。
2-4 IDL 的编译COM 在设计初期,就定了一个目标:要能实现跨语言的调用。
既然是跨语言的,那么组件的接口描述就必须在任何语言环境中都要能够认识。
怎么办?用 .h 文件描述?------ C语言程序员笑了,真方便!BASIC 程序员哭了:-( 因此,微软使用了一个新的文件格式---IDL文件(接口定义描述语言)。
IDL 是一个文本文件,它的语言语法比较简单,很象C。
具体 IDL 文件的讲解,见下一回《COM 组件设计与应用(八)之添加新接口》。
IDL 经过编译,生成二进制的等价类型库文件 TLB 提供给其它语言来使用。
图三示意了 ATL COM 程序编译的过程:图三、ATL 组件程序编译过程说明1:编译后,类型库以 TLB 文件形式单独存在,同时也保存在目标文件的资源中。
实验1. 编写COM组件并调用实验内容在VS2010环境中,使用C#语言编写一个简单的COM组件,然后在 中调用COM组件。
实验目的◆掌握COM组件的编写◆学会调用COM组件环境要求VS2010实验指导(一)C#编写COM组件步骤1:创建C#类库,名称为CLCOMTestInCSharp,如下图:注意:如果在win7下,VS2010要以管理员的身份运行步骤2:在“解决方案资源管理器”中,类“Class1.cs”更名为“CAdd.cs”,并在弹出的对话框选项中选择“是”。
如下图:步骤3:添加接口“IAdd”,并使类“CAdd”继承接口“IAdd”,代码如下:步骤4:在文档最上方添加命名空间“using System.Runtime.InteropServices ”的引用语句。
步骤5:通过菜单“工具”、“创建GUID”创建GUID,如下图:步骤6:“IAdd”接口上方使用该GUID步骤7:同样的方法在类“CAdd”的上方再生成添加一个GUID步骤8:完整代码如下:步骤9:打开“解决方案资源管理器”,打开“AssemblyInfo.cs”,将[assembly: ComVisible(false)]设为true。
步骤10:右击该类库项目,选择“属性”“生成”,将“为COM互操作注册”选中。
如图:步骤11:右击项目,“生成”。
将生成“CLCOMTestInCSharp.dll”、“CLCOMTestInCSharp.tlb”、“CLCOMTestInCSharp.pdb”三个文件(二)中调用C#编写的COM组件步骤1:使用创建“Windows窗体应用程序”项目,命名为“COMTest”。
如下图:步骤2:在窗体上添加一个Button,并将其Text属性设为“使用 调用C#创建的COM组件”步骤3:将“CLCOMTestInCSharp.dll”复制到程序目录,添加引用,选择“浏览”,如下图:步骤4:双击“Button”按钮,添加如下代码:步骤5:执行程序,结果如下图所示:实验报告●简述:COM组件开发步骤记录各个步骤,并截图(注意:各种命名要不同于本实验指导中的命名,以示区别)●实习过程中的技术问题及解决方法。
com原理与应用Com原理与应用。
Com(Component Object Model)是微软公司提出的一种面向对象的组件技术,它是一种用于软件组件之间进行通信和交互的机制。
Com原理及其应用已经在Windows操作系统和许多其他软件开发平台上得到了广泛的应用,对于理解Com原理及其应用,以及在实际开发中的应用具有重要的意义。
Com的核心原理是面向对象和接口。
在Com中,每个组件都是一个对象,对象之间通过接口进行通信。
Com组件可以是任何类型的软件,例如动态链接库(DLL)、ActiveX控件、COM+组件等。
Com组件之间的通信是通过接口来实现的,这种接口是一种规范,定义了组件之间的通信协议。
在Com中,每个组件都有一个唯一的标识符,称为CLSID(Class Identifier),用于标识组件的类型。
另外,每个接口也有一个唯一的标识符,称为IID (Interface Identifier),用于标识接口的类型。
通过这些标识符,可以在运行时动态地加载和调用组件。
Com组件的应用范围非常广泛,可以用于开发各种类型的软件,包括桌面应用程序、Web应用程序、服务器端应用程序等。
Com组件可以通过各种开发语言来实现,例如C++、C#、VB等。
在实际开发中,Com组件可以提供各种功能,例如图形界面、数据访问、网络通信、安全控制等。
在使用Com组件时,需要注意一些问题。
首先,Com组件是基于Windows平台的,因此在其他操作系统上可能无法直接使用。
其次,Com组件的开发和部署需要一定的专业知识和经验,需要遵循一定的规范和标准。
最后,Com组件的性能和稳定性也需要进行充分的测试和优化。
总的来说,Com原理及其应用是软件开发中的重要内容,它提供了一种灵活、可扩展、可重用的组件技术,可以大大提高软件开发的效率和质量。
通过深入理解Com原理及其应用,可以更好地应用Com技术来开发各种类型的软件,满足不同的需求。
COM组件设计与应用(十八)——属性包一、前言书接上回,本回着落在介绍属性包 IPersistPropertyBag 接口的实现方法和调用方式。
属性包,是以“名称 - 值”的方式提供组件持续性的支持,而“名称 - 值”恰恰又适合于用文本方式来表现。
下面的片段是在 HTML 中插入Microsoft MonthView Control ActiveX 控件后的样式:<object classid="clsid:232E456A-87C3-11D1-8BE3-0000F8754DA1"id="MonthView1"><param name="_ExtentX" value="9393"><param name="_ExtentY" value="4974"><param name="_Version" value="393216"><param name="ForeColor" value="0"><param name="MaxSelCount" value="7"><param name="MonthColumns" value="1"><param name="CurrentDate" value="38632"><param name="MaxDate" value="2958465"><param name="MinDate" value="-53688"></object>以文本方式保存组件属性,比较直观、容易修改,上面 HTML 示例中的就很清晰。
IDispatch 接口for vc6.0作者:杨老师下载源代码一、前言终于写到了第九回,我也一直期盼着写这回的内容耶,为啥呢?因为自动化(automation)是非常常用、非常有用、非常精彩的一个COM 功能。
由于WORD、EXCEL 等OFFICE 软件提供了“宏”的功能,就连我们使用的VC开发环境也提供了“宏”功能,更由于HTML、ASP、JSP 等都要依靠脚本(Script)的支持,更体现出了自动化接口的重要性。
如果你使用vc6.0 的开发环境,请继续阅读。
如果你使用 2003,请阅读下一回。
二、IDispatch接口如果是编译型语言,那么我们可以让编译器在编译的时候装载类型库,也就是装载接口的描述。
在第七回文章当中,我们分别使用了#include 方法和#import 方法来实现的。
装载了类型库后,编译器就知道应该如何编译接口函数的调用了---这叫“前绑定”。
但是,如果想在脚本语言中使用组件,问题就大了,因为脚本语言是解释执行的,它执行的时候不会知道具体的函数地址,怎么办?自动化接口就为此诞生了---“后绑定”。
自动化组件,其实就是实现了IDispatch 接口的组件。
IDispatch 接口有4个函数,解释语言的执行器就通过这仅有的4个函数来执行组件所提供的功能。
IDispatch 接口用IDL 形式说明如下:(注1)[object,uuid(00020400-0000-0000-C000-000000000046), // IDispatch 接口的 IID = IID_IDispatchpointer_default(unique)]interface IDispatch : IUnknown{typedef [unique] IDispatch * LPDISPATCH; // 转定义IDispatch * 为 LPDISPATCHHRESULT GetTypeInfoCount([out] UINT * pctinfo); // 有关类型库的这两个函数,咱们以后再说HRESULT GetTypeInfo([in] UINT iTInfo,[in] LCID lcid,[out] ITypeInfo ** ppTInfo);HRESULT GetIDsOfNames( // 根据函数名字,取得函数序号(DISPID)[in] REFIID riid,[in, size_is(cNames)] LPOLESTR * rgszNames,[in] UINT cNames,[in] LCID lcid,[out, size_is(cNames)] DISPID * rgDispId);[local] // 本地版函数HRESULT Invoke( // 根据函数序号,解释执行函数功能[in] DISPID dispIdMember,[in] REFIID riid,[in] LCID lcid,[in] WORD wFlags,[in, out] DISPPARAMS * pDispParams,[out] VARIANT * pVarResult,[out] EXCEPINFO * pExcepInfo,[out] UINT * puArgErr);[call_as(Invoke)] // 远程版函数HRESULT RemoteInvoke([in] DISPID dispIdMember,[in] REFIID riid,[in] LCID lcid,[in] DWORD dwFlags,[in] DISPPARAMS * pDispParams,[out] VARIANT * pVarResult,[out] EXCEPINFO * pExcepInfo,[out] UINT * pArgErr,[in] UINT cVarRef,[in, size_is(cVarRef)] UINT * rgVarRefIdx,[in, out, size_is(cVarRef)] VARIANTARG * rgVarRef );}以上IDispatch 接口函数的讲解,我们留到后回中进行介绍。
如何在组件程序中实现这些函数那?还好,还好,就象IUnknown 一样,MFC 和ATL 都帮我们已经完成了。
本回我们着重介绍组件的编写,下回则介绍组件的调用方法。
三、用MFC 实现自动化组件我写的这整个系列文章---《COM 组件设计与应用》,多是用ATL 写组件程序,但由于自动化非常有用,在后续的文章中,还要给大家介绍组件的“事件”功能,还要介绍如何在MFC 的程序中象WORD 一样支持“宏”的功能。
这些都要用到MFC,所以就给读者唠一唠啦:-)3-1:建立一个工作区(Workspace)3-2:建立一个MFC DLL 工程(Project),工程名称为“Simple5”3-3:一定要选择automation,切记!切记!3-4:建立新类3-5:在新建类中支持automationClass information - Name你随便写个类名子啦Class information - Base class一定要从CComTarget 派生呀,只有它才提供了IDispatch 的支持Automation - None表示不支持自动化,你要选择了它,那就白干啦Automation - Automation支持自动化,但不能被直接实例化。
后面在讲解多个IDispatch 的时候就用到它了,现在先不要着急。
Automation - Createable by type ID一定要选择这个项目,这样我们在后面的调用中,VB就能够CreateObject(),VC 就能够CreateDispatch()对组件对象实例化了。
注意一点,这个ID 其实就是组件的ProgID 啦。
3-6:启动ClassWizard,选择Automation 卡片,准备建立函数3-7:添加函数。
我们要写一个整数加法函数Add()。
3-8:再增加一个转换字符串大小写的函数Upper()。
函数返回值是BSTR,这个没有什么疑问,但参数类型怎么居然是LPCTSTR?在COM 中,字符串不是应该使用BSTR 吗?是的,是应该使用BSTR,但由于我们是用MFC 写自动化组件,它帮我们进行BSTR 和LPCTSTR 之间的转换了。
3-9:好了,下面开始输入程序代码:long CDispSimple::Add(long n1, long n2){return n1 + n2;}BSTR CDispSimple::Upper(LPCTSTR str){CString strResult(str);strResult.MakeUpper();return strResult.AllocSysString();}3-10:编译注册如果上面的操作由于疏忽而发生了错误,那么你可以手工进行改正。
其一、步骤<3-6>的对话窗中有“Delete”操作;其二、你可以打开ODL 文件(注2)进行修改,修改时要特别小心函数的声明中,有一个[id(n)] 的函数序号,可不要乱了;其三、同步修改H/CPP 中的函数声明和函数体;其四、在CPP文件中,根据情况也要修改BEGIN_DISPATCH_MAP/END_DISPATCH_MAP()函数影射宏。
正确编译后,MFC不象ATL那样会自动注册。
你需要手工执行regsvr32.exe 进行注册,或者执行菜单“Tools\Register control”四、用ATL 实现双接口组件(操作方法和步骤,请参考《COM 组件设计与应用(五)》)4-1:建立一个ATL 工程(Project),工程名称为“Simple6”4-2:按默认进行。
选择DLL 类型、不合并代理和存根代码、不支持MFC、不支持MTS4-3:New Atl Object... 选择Simple Object4-4:输入名称和属性,属性按默认进行,也就是dual(双接口)方式(注3)4-5:增加函数。
在ClassView 卡片中,选择接口、鼠标右键菜单、Add Method...Add([in] VARIANT v1, [in] VARIANT v2, [out, retval] VARIANT * pVal);Upper([in] BSTR str, [out,retval] BSTR * pVal);关于Add()函数,你依然可以使用Add([in] long n1, [in] long n2, [out,retval] long * pVal) 方式。
但这次我们没有使用long ,而是使用了VARIANT 做参数和返回值。
这里我先卖个关子,往下看,就知道使用VARIANT 的精彩之处了。
4-6:完成代码STDMETHODIMP CDispSimple::Add(VARIANT v1, VARIANT v2, VARIANT *pVal){::VariantInit( pVal ); // 永远初始化返回值是个好习惯CComVariant v_1( v1 );CComVariant v_2( v2 );if((v1.vt & VT_I4) && (v2.vt & VT_I4) ) // 如果都是整数类型{ // 这里比较没有使用 == ,而使用了运算符 & ,你知道这是为什么吗?v_1.ChangeType( VT_I4 ); // 转换为整数v_2.ChangeType( VT_I4 ); // 转换为整数pVal->vt = VT_I4;pVal->lVal = v_1.lVal + v_2.lVal; // 加法}else{v_1.ChangeType( VT_BSTR ); // 转换为字符串v_2.ChangeType( VT_BSTR ); // 转换为字符串CComBSTR bstr( v_1.bstrVal );bstr.AppendBSTR( v_2.bstrVal ); // 字符串连接pVal->vt = VT_BSTR;pVal->bstrVal = bstr.Detach();}return S_OK;}STDMETHODIMP CDispSimple::Upper(BSTR str, BSTR *pVal){*pVal = NULL; // 永远初始化返回值是个好习惯CComBSTR s(str);s.ToUpper(); // 转换为大写*pVal = s.Copy();return S_OK;}刚才卖的关子,现在开始揭密了......加法函数Add()不使用long类型,而使用VARIANT的好处是:函数内部动态判断参数类型,如果是整数则进行整数加法,如果是字符串,则进行字符串加法(字符串加法就是字符串连接哈)。