分享

COM编程技术基础概述之六

 昵称225033 2014-01-05
COM编程技术基础概述之六
在直接使用类型库时,应首先将类型库装载到内存,这可以通过多种方式进行。对于已注册到注册表中的类型库,可以使用LoadRegTypeLib()装载。如果知道类型库的准确路径也可以通过LoadTypeLib()函数直接从磁盘装载,并在装载成功后需要调用RegisterTypeLib()完成在注册表中的注册。有时为了发布、安装方便而将类型库文件作为资源打包进dll或exe文件中,对于这种情况,可以使用LoadTypeLibFromResource()函数。在类型库装载成功后,将得到一个ITypeLib接口指针,通过该指针调用GetTypeInfoOfGuid()并将所要使用的某组件或接口的CLSID或IID作为参数传入,可以得到相关的ITypeInfo指针。通过该指针即可获取类型库中组件、接口、方法和属性等对象的全部信息。


图1 OLE文档服务体系结构

  OLE文档是以结构存储方式保存对象的复合文档,它包含两方面的内容:OLE文档服务器和包容器。前者用来创建能够为包容器程序所使用的OLE文档对象,而包容器程序则采取链接或嵌入的方式将服务器合并到自己的文档。对于OLE文档服务器,可分为全服务器和小型服务器。全服务器即可以独立运行,也可以通过链接或嵌入在包容器程序中运行。小型服务器则不能独立运行,且不支持链接,只能以嵌入的方式在包容器程序中运行。包容器程序通过站点对象对这些链接或嵌入的每一个服务器对象进行管理。OLE文档主要包括现场激活、链接与嵌入等主要技术。为便于直观理解,在图1中给出了OLE文档服务体系结构的基本框架。其中主要用到了永久对象、结构化存储(structured storage)、拖放、统一数据传输以及命名与绑定等基本技术。

  结构化存储机制是COM的数据存储的基础,其核心思想是在一个文件内部建立一个类似于文件系统的完整的存储结构,并以存储对象或流对象构成了此类文件系统中树状结构的各个节点,这个包含了类似于文件系统的存储结构的文件也被称为复合文件。存储对象并不存储数据信息,只记录了子存储对象和子流对象的有关信息,其关键接口为IStorage接口,客户程序可以通过该接口对存储对象进行操作。流对象则是进行数据存取的基本对象,通过流对象可以存储各种类型的数据。
流对象的关键接口为IStream接口,通过该接口可以访问流对象并对其存储的数据进行操作。与复合文件建立了连接的COM对象也就是上面所说的永久对象。这种对象可以将状态信息保存到存储对象、流对象或是文件等存储介质中,并能由此重建对象。在客户程序中通过永久对象提供的永久接口对这些永久对象的状态信息进行维护管理。COM定义的常用的永久接口有IPersistStorage、IPersistStream、IPersistStreamInit和IPersistFile。包括以上四个永久接口在内的所有永久接口都包含IsDirty()、Load()和Save()这三个基本成员函数(对于不同的永久接口这几个函数的参数可能有所区别)。IsDirty()函数可以检查自上次保存状态操作后对象的状态信息是否被修改过。Load()和Save()分别用于从存储介质装入状态数据和将状态数据写入到存储介质。

  命名与绑定技术主要为客户程序提供了一种通过名字对象(moniker)创建COM对象的方法。名字对象是命名与绑定技术的核心,在COM中已经实现了包括文件名字对象、复合名字对象和指针名字对象等多种不同类型的名字对象。在客户程序中,可以创建相应的名字对象并通过名字对象的绑定功能而得到组件对象。名字对象封装了组件对象的所有状态处理过程,并提供了标准接口Imoniker,在客户程序中可以通过使用该接口的成员函数来使用名字对象的所有功能。

  统一数据传输是COM建立在结构化存储基础上的一种通用的数据交换方法,通过一个实现了IDataObject接口的数据对象作为信息传递的实体。这个IDataObject接口将能够使数据交换操作独立于具体的传输协议。OLE拖放即是统一数据传输的一种典型传输协议。这种数据传输协议可以把一个数据对象从提供方拖动到接收方。对于数据传输双方,除了提供必要的数据对象外,还需要在数据对象的提供方和接收方分别提供实现了IDropSource和IDropTarget接口的拖源对象和放目标对象。

  链接与嵌入技术是OLE用来合并其他程序数据的两种重要方法,通过使用粘贴或粘贴链接命令可以在OLE包容器程序中创建一个OLE嵌入组件/对象或OLE链接组件/对象。在嵌入方式下,嵌入对象的源数据本身被合并到OLE包容器程序的文档中。而在链接方式下,链接对象的内容只是一个包含了对象源数据的路径的简单链接。被合并的对象源数据通常以文件的形式独立存在。

  在OLE包容器程序中,以站点对象负责管理链接或嵌入到文档中的服务器对象。这就需要在包容器的站点对象和服务器对象中分别实现相应的必要接口,以完成相互的通信。对于任何一个站点对象,其必须提供的接口是IOleClientSite,服务器对象所必须实现的接口为IOleObject。 IOleObject接口通常与IDataObject 和IPersistStorage等接口共同使用,虽然该接口提供了21种方法,但只有DoVerb()、SetHostNames()和Close()这三个方法是必须被实现的。调用IOleObject接口提供的方法将能够使包容器程序与嵌入对象进行通信。任何包容器程序都必须调用DoVerb()方法以激活嵌入对象,并可通过使用不同的动词让嵌入对象执行相应的动作。SetHostNames()方法则允许嵌入对象能够在其窗口标题上显示包容器程序名。

  包容器程序可以通过调用Close()方法来终止嵌入对象的激活状态。由包容器的站点对象实现的IOleClientSite接口是嵌入对象获取由包容器程序提供的诸如显示位置、名字、用户界面、以及其他一些本地或外部资源信息的主要手段。在组件服务器中使用IOleClientSite接口可以请求到包容器提供的服务。在包容器程序必须为其所包含的每一个复合文档对象提供一个IOleClientSite接口的实现。IOleClientSite接口的实现比较简单,只包含以下六个方法:

IOleClientSite方法 方法说明
SaveObject() 保存嵌入对象
GetMoniker() 请求组件名
GetContainer() 请求组件包容器指针
ShowObject() 要求包容器显示对象
OnShowWindow() 在组件变为可视或不可视时通知包容器
RequestNewObjectLayout() 要求包容器更改显示位置

  现场激活(in-place activation)技术能够使用户在不离开包容器程序文档的情况下同嵌入对象进行交互操作。在用户激活对象后,一个由包容器程序和服务器程序菜单组成的复合菜单条将替换包容器程序原有的主菜单条。此时,用户将能使用包容器程序和服务器程序提供的所有命令和特性。如果用户开始对文档中的非对象部分进行操作,那么对象将处于非激活状态,同时包容器程序将以原先的主菜单去替换激活对象时出现的复合菜单。现场激活将在对象响应从包容器程序发出的对IOleObject::DoVerb()方法的调用后启动。这种调用通常是在用户双击对象或是在包容器程序的编辑菜单中选择了一个命令(动词)时发生。

  在嵌入的对象处于激活状态时,现场(in-place)窗口将接受键盘和鼠标输入。对复合菜单上的菜单项的调用将根据当前菜单项的归属而把命令或相关的菜单消息发送给包容器程序或是服务器对象。一个现场激活的嵌入对象在包容器程序响应用户输入而使其无效或是服务器对象自动放弃活动状态之前将一直是活动。

  用户在点击另一个对象或包容器文档中的非现场激活区域时将能够使当前处于激活状态的服务器对象无效。但是在点击包容器程序的标题、滚动条或是菜单条等区域时则不会改变现场激活对象的状态。现场激活对象除了要实现IOleObject、IDataObject和IPersistStorage等OLE对象的接口外,还必须实现IOleInPlaceObject接口。而且在嵌入对象处于现场激活状态时,还必须提供一个实现了IOleInPlaceActiveObject接口的对象。包容器程序将通过此接口完成对对象的取消激活、再次激活以及设置矩形区域等操作。除此之外,在包容器程序中还必须实现一个IOleInPlaceSite接口和一个实现了IOleInPlaceFrame框架对象。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多