中国程序员联盟 正在重新改版中ing 不便之处还请见谅 改版后将内容涉及java delphi .net php
 
  首页 | 数据库开发 | 网络通讯 | 多线程 | 多媒体开发 | 图像处理 | 程序人生 | 系统函数 | 控件开发 | Web服务
 
  当前位置:笨鱼delphi技术网>数据库开发>开发应用>文章内容

delphi 关于使用COM对象的方法

来源:网络 关于:轶名 发布时间:2007-07-02   [收藏] [推荐]

  关于使用COM对象的方法,以Microsoft Word为例,作简要说明:


Step0: 从Word的类型库(Type Library)文件生成声明文件(xxx_TLB.pas),

 要使用自动对象,必须先读取相应的类型库文件(*.TLB),从其中得到自动对象的类型信息,

 方法:在Delphi IDE中打开......\Microsoft Office\Office\M$Word8.olb

 Delphi将根据类型库中的信息生成声明单元Word_TLB.pas,

 注意,Delphi在转换过程中将以下符号(symbol)进行了重命名(rename):
 --------------------------------------------------------
     类型库中的符号                重命名为
 --------------------------------------------------------
     Application                   WordApplication
     Document                      WordDocument
     Font                          WordFont
     ParagraphFormat               WordParagraphFormat
     OLEControl                    WordOLEControl
     LetterContent                 WordLetterContent
 --------------------------------------------------------
 这个问题后面会详细讨论

 

 Word_TLB.pas中包含的如下信息:
   ...
   ...
   const
     ...
    
//coClass "Application" 的ClassID
     CLASS_WordApplication: TGUID = '{000209FF-0000-0000-C000-000000000046}';
     ...
   ...
   ...
 我们也将在后面用到
 
 

 

Step1: 创建WordApplication对象,如下:

  函数CreateCOMObject将根据指定的ClassID创建对应的COM自动对象,声明如下:

  //unit COMObj
  function CreateCOMObject(const ClassID: TGUID): IUnknown;

  在本例中,我们创建WordApplication对象的代码如下:


  // 引用COMObj单元和Word_TLB单元
  uses
    ..., ..., ..., COMObj, Word_TLB;

  type
    TfmMain = class(TForm)
      ...
      ...
    private
      // 声明一个变量,保存WordApplication的引用
      // WordApplication在Word_TLB单元中声明
      WordApp: WordApplication;
    protected
      procedure StartWordApp;
      procedure TerminateWordApp;
    end;

    其中StartWordApp方法将分别创建一个WordApplication对象,
    实现如下:

    procedure TfmMain.StartWordApp;
    begin
      if not Assigned(WordApp) then
      try
        // 创建WordApplication对象
        WordApp:=CreateCOMObject(CLASS_WordApplication) as WordApplication;
        with WordApp do
        begin
          // 指定COM对象的属性
          Caption:='This copy of WinWord is launched by '+Forms.Application.ExeName;
          Visible:=True;
        end;
        ShowMsg('启动 Word Application 成功');
      except
        ShowError('启动 Word Application 失败');
      end;
    end;

    procedure TfmMain.btStartWordAppClick(Sender: TObject);
    begin
      StartWordApp;
    end;

Step2: 创建WordApplication对象后就可以使用其属性和方法了,如下:

    // 创建新文档
    procedure TfmMain.btNewDocClick(Sender: TObject);
    var
      DocTemplate,
      NewTemplate : OleVariant;
    begin
      StartWordApp;
      DocTemplate := UnAssigned;         // 打开新文档时使用的模板
      NewTemplate := False;              // 是否将文档作为模板打开
      WordApp.Documents.Add(DocTemplate,NewTemplate);
    end;

    // 关闭当前文档
    procedure TfmMain.btCloseDocClick(Sender: TObject);
    var
      SaveChanges,
      OriginalFormat,
      RouteDocument  : OleVariant;
    begin
      SaveChanges := WdDoNotSaveChanges;     // 不保存修改
      OriginalFormat := UnAssigned;          // 未赋值
      RouteDocument := UnAssigned;           // 未赋值
      WordApp.ActiveDocument.Close(SaveChanges,OriginalFormat,RouteDocument);
    end;
 
Step3:COM对象使用完毕后,注意释放

    TerminateWordApp方法将释放WordApp指向的COM对象,
    实现如下:

    procedure TfmMain.TerminateWordApp;
    var
      SaveChanges,
      OriginalFormat,
      RouteDocument  : OleVariant;
    begin
      if Assigned(WordApp) then
      begin
        SaveChanges := WdDoNotSaveChanges;  // 不保存修改
        OriginalFormat := UnAssigned;       // 未赋值
        RouteDocument := UnAssigned;        // 未赋值
        try
          // 调用COM对象方法
          WordApp.Quit(SaveChanges,OriginalFormat,RouteDocument);
          ShowMsg('关闭 Word Application 成功');
        except
          ErrorMsg('关闭 Word Application 失败');
        end;
        // 将WordApp赋值为Nil,则原来指向的COM对象的引用记数减1
        // 当引用记数为0时,COM对象将被释放
        WordApp := Nil;
      end;
    end;

    procedure TfmMain.FormDestroy(Sender: TObject);
    begin
      TerminateWordApp;
    end;

后记:
  1、以上所述方法是完全通过编程直接调用COM实现的,
     所有使用COM的地方都可以通过上面的方法实现,
     步骤为:
       (0)根据类型库文件生成声明单元
       (1)得到需要的ClassID后使用CreateCOMObject函数创建COM对象
       (2)使用COM对象的属性和方法完成操作
       (3)释放COM对象

  2、我们的目的不仅仅是为了控制Word,而是为了说明使用COM的根本方法,
     选择Word作为例子,是因为大家都比较熟悉,
     对Word的控制,Delphi已经提供了一些支持,包括:
     ......\Delphi5\Ocx\Servers\Word97.pas
        等于前面所说的Word_TLB.pas,

     ......\Delphi5\Demos\Activex\Oleauto\Word8\autoimpl.pas
        将以上对COM对象的操作封装成了一个Delphi类

     还可以参考两个示例:
     ......\Delphi5\Demos\Activex\Oleauto\Word8\word8auto.dpr
     和
     ......\Delphi5\Demos\Activex\Oleauto\SrvCOMp\Word\pwordCOMp.dpr


  3、一般情况下会同时提供很多COM Server,
     应该使用什么对象、使用什么方法、使用什么属性
     需要参考帮助文件,上面的例子中M$Word8.olb的帮助文件为:
       ....\Microsoft Office\Office\VBAWRD8.HLP
     在没有帮助文件的情况下就需要研究类型库中的信息了


  4、关于类型库本身
     类型库包含非常丰富的信息,包括:

       Interface、DispInterface、CoClass、Enumeration、
       Alias、Record、Union、Module等等

       这些是类型库的基本信息,此外还包括:
         指定的帮助文件、所依赖的其它类型库等等

     类型库一般以单独的类型库文件(*.TLB)提供,或包含在Server程序中(*.EXE、*.DLL)
     类型库信息包含在EXE中的例子有:
         ....\Delphi5\Demos\Activex\Oleauto\Autoserv\memoedit.dpr
     在DLL中的例子有:
         ....\Delphi5\Bin\StdVcl40.DLL
     这两种情况下,实际上类型库信息都包含在EXE/DLL中的名为"TypeLib"的资源中

     查看M$Word8.OLB可以看到,它实际上是一个DLL格式文件

  5、关于类型库的Register和Unregister
     Windows下有注册类型库的程序RegSvr32.exe,Borland自己也有TRegSvr.exe
     除此之外,在Delphi IDE中打开类型库后,可以使用菜单Run|Register ActiveX Server
     或Run|Unregister ActiveX Server
     那么类型库的Register和Unregister具体是怎么实现的呢,

     打开....\Delphi5\Demos\Activex\TRegSvr\TRegSvr.dpr,查看源代码,我们可以看到:
     (1)对于*.tlb:
          调用OleAut32.DLL中的LoadLibrary函数,得到一个ITypeLib接口,
          调用ITypeLib的GetLibAttr方法,得到tagTLibAttr结构,其中包括
                 GUID、LCID、Major Version、Minor Version、SysKind信息
        Register的方法是:
          调用OleAut32.DLL中RegisterTypeLib函数
        Unregister的方法是:
          调用OleAut32.DLL中UnregisterTypeLib函数,参数由前面的tagTLibAttr结构中各域指定

        详见TRegSvr.dpr中的RegisterTLB过程

     (2)对于*.dll:
          调用LoadLibrary函数载入dll
        Register的方法是:
          调用DLL中的DllRegisterServer函数
        Unregister的方法是:
          调用DLL中的DllUnregisterServer函数
     (3)对于*.exe
        Register的方法是:
          调用EXE,命令行参数为"/RegServer"
        Unregister的方法是:
          调用EXE,命令行参数为"/UnregServer"
     也就是说,对于DLL和EXE,应该实现自注册(Self Register),
     即ActiveX Server本身完成Register和Unregister动作。

     对于Delphi编写的ActiveX Server,这些工作都在COMServ.pas完成,
     详细的过程比较罗嗦,有兴趣可以去看看,
     主要的代码在RegisterTypeLibrary和UnregisterTypeLibrary过程中
     和上面的TRegSvr.dpr中对TLB的注册过程大致一样

     经过上面的分析可以看到,最终都是通过OleAut32.DLL中的
        RegisterTypeLib和UnregisterTypeLib完成的,

     我们注意到一点奇怪的现象:
        上面提到的源代码在调用RegisterTypeLib时都是直接调用,
          该函数的声明在ActiveX.pas中,指定到OleAut32.DLL中的RegisterTypeLib函数
          就在相同的地方,我们也看到了UnregisterTypeLib的声明,
        但是,上面提到的源代码在调用UnregisterTypeLib时都没有直接调用,
          而是先GetModuleHandle('OLEAut32.DLL'),然后用GetProcAddress查找UnregisterTypeLib,
          再根据查找的结果进行调用
        而且所有相关的地方都是这样进行,估计不是失误,这样看来,
          似乎Borland在写这段程序时考虑到了OLEAut32.DLL中不包括UnregisterTypeLib函数的情况,
        难道OLEAut32.DLL的早期版本中的确不包括UnregisterTypeLib函数??
        但M$DN对UnregisterTypeLib的说明没有提到

  6、关于打开类型库时符号重命名(symbol rename)
     类型库中某些符号在生成声明单元时被重命名,
     大部分是因为符号名与Pascal关键字重名,因此Delphi必须重命名

     但前面说到的几个符号的重命名显然不是这个原因,我们注意到:
     (1)这几个符号都是CoClass,而且是类型库中几乎全部的CoClass,
        只有一个CoClass:"Global"不在其中
     (2)这几个符号被重命名后都加上了"Word"前缀,
        而这个类型库的名称正好就是"Word"
     其中是否存在联系??

  7、对于任意的一个CoClass,从类型库中可以得到其中的interface信息,
     因此创建和释放COM对象的代码可以自动生成,
     对于所有的interface,也可以从类型库中得到其属性、方法信息,
     因此访问这些属性、方法的代码也可以自动生成

     由此,Delphi 5 将在声明单元中为所有的CoClass
     创建相应的代理类(OLE Server Proxy class),
     这些代理类以Delphi类的形式提供封装,而内部实现了对COM对象的全部操作,
     包括创建、释放以及访问各种属性和方法
     另外,Delphi 5还会将这些代理类作为组件注册到组件板的'Server'页面上
     详情请在xxx_TLB.pas中查找"OLE Server Proxy class"

     通过这些代理类,我们可以很方便地使用COM对象,
     而不必向上面所说的那样一切都通过自己实现,
     当然,前面所说的是一切的基础,应该作为原理了解


[浏览: 次]   
上一篇:delphi 汉字转拼音码(下)   下一篇:delphi 在delphi中使用flash控件
[收藏] [推荐] [返回顶部] [打印本页] [关闭窗口]  
    评论加载中…
google adsense热点文章
·delphi Delphi_三谈多态——善用virtua
·delphi 条形码处理
·delphi Delphi_三层开发基本概念介绍
·delphi 汉字转拼音码(上)
·delphi CS构架下的客户端自动更新程序
·delphi Olevariant
·delphi 在Dephi中使用TStream读写数据
·delphi 汉字转拼音码(下)
·delphi delphi处理流
·delphi MTS组件——从理论到实践
·delphi 汉字转拼音码(中3)
·delphi 创建纯资源的DLL
     delphi技术网 | firefox 下载 | Avant Browser下载 | dedecms 技术网 | drupal 爱好者 | php 技术网
  Copyright@www.delphichm.com,2006-2009.All Rights Reserved.
 
程序员联盟 | delphi Java .net|QQ:707102932