COM原理及应用之统一数据传输
1、概述
COM提供了应用之间数据交换的标准方案,称为统一数据传输(UDT,uniform data transfer)。统一数据传输技术建立在结构化存储技术的基础之上,它通过一个“数据对象”来表达要传输的数据信息,因此,统一数据传输技术的核心在于数据对象的定义和实现。剪贴板和拖-放是统一数据传输的两个典型应用。
2、数据交换标准
早期的OLE1.0版本使用DDE(Dynamic Data Exchange,动态数据交换)作为数据交换标准,但DDE使用的格式比较简单,并且只能用全局内存作为传输介质,所以传输的效率和功能都受限制。 OLE2.0版本引入了COM作为其基本的结构模型,使用COM提供的统一数据传输作为其数据交换机制,可直接在不同介质之间进行传输。
3、数据交换与传输协议的分离
在不同应用之间进行数据传输操作包括两方面的内容,首先是数据格式的统一,其次是传输协议的建立。
以前采用DDE方式只能使用简单的数据结构对信息进行描述,COM的统一数据传输机制使用“数据对象”作为信息实体,数据对象通过IDataObject 接口暴露其内部信息。由于数据对象本身是一个COM对象,因此它不仅可以表达一般的结构化信息,也可以表达一些非结构化信息,甚至是动态信息。 IDataObject接口为应用程序进行数据传输建立了标准。在Windows平台上,最基本的传输协议为剪贴板、拖-放,应用程序通常利用这两种协议获得数据对象。
在统一数据机制引入到Windows系统之前,Windows提供了许多API函数以及预定义的消息用于应用之间传输数据的桥梁。这些API函数把传输协议和传输数据信息绑在一起,比如用于处理剪贴板数据传送的一组函数:GetClipboardData、SetClipboardData和 CloseClipboard等,而DDE则通过发送消息作为数据传送的手段。
COM提供的统一数据传输机制可很好地避免Windows API函数的数据传输的限制,一方面它定义了两个数据结构FORMATETC和STGMEDIUM,分别用来描述数据格式和存储介质,使新的机制可适应更广泛的数据类型和存储介质;另一方面它为数据对象提供了“数据表化通知”的机制。
数据对象的概念使统一数据传输机制不仅可用于应用之间传输数据,也可以成为组件程序之间的信息交换标准。
4、剪贴板
剪贴板是一个全系统共享的数据缓冲区,每个应用都可以通过系统提供的API函数访问剪贴板。它的三个标准操作是:剪切、复制、粘贴。
Windows系统在引入COM的统一数据传输机制之前,提供了一组API函数以及预定义的CF_***标准格式,这些格式包括文本类型、位图类型、图元文件(metafile)数据等,而且这些数据必须存放在全局内存中。但剪贴板技术与数据对象结合之后,情况有了很大的变化,可用于传输数据对象,比如 OLE文档对象、ActiveX控制对象等,或者是应用程序中自定义的数据对象,只要此对象实现IDataObject接口即可。剪贴板成为数据对象的提供方和接收方之间的通信协议,而且这种通信方式是异步进行的。
5、拖-放
拖-放技术也是基本的传输协议,它的使用方式与剪贴板有所不同,程序采用同步的方式进行。
6、数据结构FORMATETC和STGMEDIUM
FORMATETC结构定义了用于传输的数据格式,它扩充了基本的剪贴板数据格式;STGMEDIUM结构定义了用于传输的介质类型,它即可以描述常用的全局内存,也可以描述其他的存储介质。
7、数据对象和IDataObject接口
统一数据传输中的数据对象是一个COM对象,它实现了IDataObject接口。在数据对象的实现方(即提供方)和客户(即接收方)之间,IDataObject接口为两者建立了标准,而各种传输协议如剪贴板和拖-放等,它们所传递的实际上是IDataObject接口指针。
8、通报连接机制
为了实现从数据对象到客户程序的通信过程,要求数据对象在状态发生变化时能主动通知客户程序,而客户程序必须提供一个接收器对象以便接收这些通知,这是曾在第六章中介绍过的COM提供的通过接收器对象建立的通用的双向通信机制。而在统一数据传输机制中使用的通知接收器要简单一些,它是由客户程序实现的内部对象,只需实现IAdviseSink接口。
数据对象与客户程序之间的连接方式较第六章中的可连接对象机制简便得多。
客户程序通过IDataObject::DAdvise函数建立通报连接时,它除了要提供接收器对象的IAdciseSink接口指针,还要提供两个信息:格式信息和与通报连接有关的标志信息。
COM提供了“数据通报控制器”(data advise holder)的内部对象,数据通报控制器对象实现了IDataAdviseHolder接口。数据对象利用COM API函数CreateDataAdviseHolder创建一个数据通报控制器对象,该函数返回对象的IDataAdviseHolder接口指针,然后,数据对象把IDataObject接口的三个与变化通知有关的成员函数直接委托给数据通报控制器对象IDataAdviseHolder接口的相应成员函数。
9、数据对象
在实现数据对象时,不管是进程内组件程序,还是进程外组件程序,由于与数据对象有关的接口都是COM定义的标准接口,COM已经提供了这些接口的跨进程列集器,所以不用考虑跨进程的细节。进程模型只影响性能因素。
10、通过剪贴板传输数据
在剪贴板与数据对象结合起来之前,Win32中为支持剪贴板操作而提供了一组API函数:OpenClipboard、CloseClipboard、 EmptyClipboard、SetClipboardData、GetClipboardData、 IsClipboardFormatAvailable、EnumClipboardFormats。
因为剪贴板是Windows操作系统支持的特性,而COM是与平台无关的组件对象模型规范,所以剪贴板和数据对象结合之后的特性不属于COM范畴,严格来讲应该数OLE技术的一部分,称之为OLE剪贴板。OLE也提供了四个封装过的API函数:OleSetClipboard、 OleGetClipnoard、OleFlushClipboard、OleCurrentClipboard。
11、拖-放数据传输协议
与剪贴板传输协议不同,OLE的拖-放数据传输协议只能传输数据对象,而不能传输其他的数据。
拖-放操作是一个与界面有关的数据传输过程,通常涉及到源窗口和目标窗口。
OLE提供的API函数RegisterDragDrop把“放目标”对象与窗口联系起来。
12、MFC对剪贴板和拖-放的支持
MFC提供了两个类用于支持数据对象,分别为COleDataSource和COleDataObject类。这两个类直接继承于CCmdTarget,其中COleDataSource类用于源程序一方,COleDataObject用于客户程序一方。
COleDataSource类实现了IDataObject接口,但是不支持通报连接。COleDataSource类创建并管理了一组数据格式,这些数据格式被保存在对象内部(缓冲区中)。COleDataSource类实现了一个真正的COM对象,它有自己的引用计数。
文章出处:http://www.diybl.com/course/3_program/c++/cppxl/20081118/151930.html