分享

COM深入编程学习笔记3

 aaie_ 2012-10-16
类型库,它是一种与编程语言无关的方法,用于定义接口和说明COM服务器。
 
  1.定义类型库
   
   类型库提供了完全说明COM服务器的无确定编程语言的方法。类型库包含很多信息,例如哪个接口是由一个对象实现的、
   
哪个属性和方法是由接口定义的,以及每种方法的参数的数目和类型。

   通常,类型库可作为一种资源集成到COM服务器中,或可作为一个.tlb文件被分发。Delphi把类型库作为一种资源自动添加
   
到COM服务器中,并生成一个tlb文件。

   Delphi(以及大多数其它现代编译器)可以读取存储在类型库中的信息并自动创建一个用来编写一个客户应用程序的输入文件。
   
因此,通常只需要重新分发COM服务器给程序员来编写客户应用程序。如果遇到某人不能从COM服务器中提取类型库,那么也可以

重新分发.tlb文件。

   在delphi出现之前,很多语言被迫使用IDL语言手工编写类型库。进入Delphi编辑器后,可以用类型库编辑器。
   
   具体范例:
   FIle-->New-->Activx-->ActivX library
   FIle-->New-->Activx-->COM Object (选中Include Type Library)
   
    //下面范例是创建基于类型库支持的COM对象,具有跨多语言的通用性
    //注意是TTypedComObjectFactory作为类厂来创建COM对象的。
    //注意COM对象派生自TTypedComObject
    //另外对于COM接口和类的定义都是在类型库编辑器下完成,编辑器会自动创建接口和类的定义框架
    //注意:对于接口下的输入参数可以使用标准的COM数据类型[in],对于输出参数一律在函数[out] 定义下,要么使用指针,
    //要么使用Olevaraint类型,例如Delphi的字符串那是非标准类型就必须用OleVarant类型来输出。
    ///////////////////////////////////ActivX Library/////////////////////////////////////////
    library TIServer;

    uses
      ComServ,
      DCPTypeServer_TLB in 'DCPTypeServer_TLB.pas',
      AreaIntf in 'AreaIntf.pas' {UnitAuto: CoClass};
    
    exports
      DllGetClassObject,
      DllCanUnloadNow,
      DllRegisterServer,
      DllUnregisterServer;
    
    {$R *.TLB}
    
    {$R *.RES}
    
    begin
    end.
    
    /////////////////////////COM对象接口实现////////////////     
    unit AreaIntf;
    
    interface
    
    uses
      Windows, ActiveX, Classes, ComObj, DCPTypeServer_TLB, StdVcl;
    
    type
      TUnitAuto = class(TTypedComObject, IUnitAuto) //从类型库COM对象继承
      protected
        function Convert(Quantity: Double; InUnit, OutUnit: SYSINT): Double;stdcall; //标准API定义方式
        function Get_Name: WideString; stdcall;              //标准API定义方式
        procedure Set_Name(const Value: WideString); stdcall;//标准API定义方式
        {Declare IUnitAuto methods here}
      end;
    
    implementation
    
    uses ComServ;
    
    function TUnitAuto.Convert(Quantity: Double; InUnit,
      OutUnit: SYSINT): Double;
    begin
      { Stubbed out because we're only interested in the type library }
    end;
    
    function TUnitAuto.Get_Name: WideString;
    begin
      { Stubbed out because we're only interested in the type library }
    end;
    
    procedure TUnitAuto.Set_Name(const Value: WideString);
    begin
      { Stubbed out because we're only interested in the type library }
    end;
    
    initialization
         TTypedComObjectFactory.Create(ComServer, TUnitAuto, Class_UnitAuto,
          ciMultiInstance, tmApartment); //由类型库COM类工厂创建COM对象实例
    end.
      
///////////////////COM对象类型库申明(在定义COM对象时由向导自动生成)///////////////////
//类型库包含COM Server信息
//同时包含COM Object接口定义信息
//由类型库编辑器创建     
unit DCPTypeServer_TLB;


// Type Lib: D:\Book\Chap04\TIServer.tlb (1)
// IID\LCID: {91ADB6E6-4F4D-11D3-B84B-0040F67455FE}\0
// Helpfile:
// DepndLst:
//   (1) v2.0 stdole, (C:\WINNT\System32\STDOLE2.TLB)
//   (2) v4.0 StdVCL, (C:\WINNT\System32\STDVCL40.DLL)
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
interface

uses Windows, ActiveX, Classes, Graphics, OleServer, OleCtrls, StdVCL;

// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:        
//   Type Libraries     : LIBID_xxxx                                      
//   CoClasses          : CLASS_xxxx                                      
//   DISPInterfaces     : DIID_xxxx                                       
//   Non-DISP interfaces: IID_xxxx                                        
// *********************************************************************//
const
  // TypeLibrary Major and minor versions
  DCPTypeServerMajorVersion = 1;
  DCPTypeServerMinorVersion = 0;

  LIBID_DCPTypeServer: TGUID = '{91ADB6E6-4F4D-11D3-B84B-0040F67455FE}';

  IID_IUnitAuto: TGUID = '{91ADB6E7-4F4D-11D3-B84B-0040F67455FE}';
  CLASS_UnitAuto: TGUID = '{91ADB6E9-4F4D-11D3-B84B-0040F67455FE}';

// *********************************************************************//
// Declaration of Enumerations defined in Type Library                    
// *********************************************************************//
// Constants for enum AreaUnit
type
  AreaUnit = TOleEnum;
const
  auSquareMeters = $00000000;
  auSquareCentimeters = $00000001;
  auSquareYards = $00000002;
  auSquareFeet = $00000003;
  auSquareInches = $00000004;
  auSquareKilometers = $00000005;
  auSquareMiles = $00000006;
  auAcres = $00000007;

type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary                    
// *********************************************************************//
  IUnitAuto = interface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library                       
// (NOTE: Here we map each CoClass to its Default Interface)              
// *********************************************************************//
  UnitAuto = IUnitAuto;


// *********************************************************************//
// Interface: IUnitAuto
// Flags:     (256) OleAutomation
// GUID:      {91ADB6E7-4F4D-11D3-B84B-0040F67455FE}
// *********************************************************************//
  IUnitAuto = interface(IUnknown)
    ['{91ADB6E7-4F4D-11D3-B84B-0040F67455FE}']
    function  Convert(Quantity: Double; InUnit: SYSINT; OutUnit: SYSINT): Double; stdcall;
    function  Get_Name: WideString; stdcall;
    procedure Set_Name(const Param1: WideString); stdcall;
  end;

// *********************************************************************//
// The Class CoUnitAuto provides a Create and CreateRemote method to          
// create instances of the default interface IUnitAuto exposed by              
// the CoClass UnitAuto. The functions are intended to be used by             
// clients wishing to automate the CoClass objects exposed by the         
// server of this typelibrary.                                            
// *********************************************************************//
  CoUnitAuto = class
    class function Create: IUnitAuto;
    class function CreateRemote(const MachineName: string): IUnitAuto;
  end;


// *********************************************************************//
// OLE Server Proxy class declaration
// Server Object    : TUnitAuto
// Help String      : UnitAuto Object
// Default Interface: IUnitAuto
// Def. Intf. DISP? : No
// Event   Interface:
// TypeFlags        : (2) CanCreate
// *********************************************************************//
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  TUnitAutoProperties= class;
{$ENDIF}
  TUnitAuto = class(TOleServer)
  private
    FIntf:        IUnitAuto;
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    FProps:       TUnitAutoProperties;
    function      GetServerProperties: TUnitAutoProperties;
{$ENDIF}
    function      GetDefaultInterface: IUnitAuto;
  protected
    procedure InitServerData; override;
    function  Get_Name: WideString;
    procedure Set_Name(const Param1: WideString);
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure Connect; override;
    procedure ConnectTo(svrIntf: IUnitAuto);
    procedure Disconnect; override;
    function  Convert(Quantity: Double; InUnit: SYSINT; OutUnit: SYSINT): Double;
    property  DefaultInterface: IUnitAuto read GetDefaultInterface;
  published
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    property Server: TUnitAutoProperties read GetServerProperties;
{$ENDIF}
  end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
// *********************************************************************//
// OLE Server Properties Proxy Class
// Server Object    : TUnitAuto
// (This object is used by the IDE's Property Inspector to allow editing
//  of the properties of this server)
// *********************************************************************//
 TUnitAutoProperties = class(TPersistent)
  private
    FServer:    TUnitAuto;
    function    GetDefaultInterface: IUnitAuto;
    constructor Create(AServer: TUnitAuto);
  protected
    function  Get_Name: WideString;
    procedure Set_Name(const Param1: WideString);
  public
    property DefaultInterface: IUnitAuto read GetDefaultInterface;
  published
  end;
{$ENDIF}


procedure Register;

implementation

uses ComObj;

class function CoUnitAuto.Create: IUnitAuto;
begin
  Result := CreateComObject(CLASS_UnitAuto) as IUnitAuto;  //创建本地COM对象,并授权接口引用
end;

class function CoUnitAuto.CreateRemote(const MachineName: string): IUnitAuto;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_UnitAuto) as IUnitAuto; //创建远程COM对象,并授权接口引用
end;

procedure TUnitAuto.InitServerData;
const
  CServerData: TServerData = (
    ClassID:   '{91ADB6E9-4F4D-11D3-B84B-0040F67455FE}';
    IntfIID:   '{91ADB6E7-4F4D-11D3-B84B-0040F67455FE}';
    EventIID:  '';
    LicenseKey: nil;
    Version: 500);
begin
  ServerData := @CServerData;
end;

procedure TUnitAuto.Connect;
var
  punk: IUnknown;
begin
  if FIntf = nil then
  begin
    punk := GetServer;
    Fintf:= punk as IUnitAuto;
  end;
end;

procedure TUnitAuto.ConnectTo(svrIntf: IUnitAuto);
begin
  Disconnect;
  FIntf := svrIntf;
end;

procedure TUnitAuto.DisConnect;
begin
  if Fintf <> nil then
  begin
    FIntf := nil;
  end;
end;

function TUnitAuto.GetDefaultInterface: IUnitAuto;
begin
  if FIntf = nil then
    Connect;
  Assert(FIntf <> nil, 'DefaultInterface is NULL. Component is not connected to Server. You must call ''Connect'' or ''ConnectTo'' before this operation');
  Result := FIntf;
end;

constructor TUnitAuto.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps := TUnitAutoProperties.Create(Self);
{$ENDIF}
end;

destructor TUnitAuto.Destroy;
begin
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps.Free;
{$ENDIF}
  inherited Destroy;
end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
function TUnitAuto.GetServerProperties: TUnitAutoProperties;
begin
  Result := FProps;
end;
{$ENDIF}

function  TUnitAuto.Get_Name: WideString;
begin
  Result := DefaultInterface.Get_Name;
end;

procedure TUnitAuto.Set_Name(const Param1: WideString);
begin
  DefaultInterface.Set_Name(Param1);
end;

function  TUnitAuto.Convert(Quantity: Double; InUnit: SYSINT; OutUnit: SYSINT): Double;
begin
  Result := DefaultInterface.Convert(Quantity, InUnit, OutUnit);
end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
constructor TUnitAutoProperties.Create(AServer: TUnitAuto);
begin
  inherited Create;
  FServer := AServer;
end;

function TUnitAutoProperties.GetDefaultInterface: IUnitAuto;
begin
  Result := FServer.DefaultInterface;
end;

function  TUnitAutoProperties.Get_Name: WideString;
begin
  Result := DefaultInterface.Get_Name;
end;

procedure TUnitAutoProperties.Set_Name(const Param1: WideString);
begin
  DefaultInterface.Set_Name(Param1);
end;

{$ENDIF}

procedure Register;
begin
  RegisterComponents('Servers',[TUnitAuto]);
end;

end.


    //下面范例是创建基于类型库支持的COM对象,具有跨多语言的通用性
    //注意是TTypedComObjectFactory作为类厂来创建COM对象的。
    //注意COM对象派生自TTypedComObject
    //另外对于COM接口和类的定义都是在类型库编辑器下完成,编辑器会自动创建接口和类的定义框架
    //注意:对于接口下的输入参数可以使用标准的COM数据类型[in],对于输出参数一律在函数[out] 定义下,要么使用指针,
    //要么使用Olevaraint类型,例如Delphi的字符串那是非标准类型就必须用OleVarant类型来输出。
    ///////////////////////////////////ActivX Library/////////////////////////////////////////
library meterCovert;

uses
  ComServ,
  meterCovert_TLB in 'meterCovert_TLB.pas',
  meterInf in 'meterInf.pas' {TMeteCovert: CoClass};

exports
  DllGetClassObject,
  DllCanUnloadNow,
  DllRegisterServer,
  DllUnregisterServer;

{$R *.TLB}

{$R *.RES}

begin
end.

/////////////////////////COM对象接口实现和meterCovert_TLB同步////////////////
//完全由类型库编辑器编辑于meterCovert_TLB文件同步
unit meterInf;

{$WARN SYMBOL_PLATFORM OFF}

interface

uses
  Windows, ActiveX, Classes, ComObj, meterCovert_TLB, StdVcl;

type
  TTMeteCovert = class(TTypedComObject, ITMeteCovert)
  private
    FName : OleVariant;
    procedure Initialize; override; //覆盖初始化虚拟方法
  public
    function Conver(Aparam: Double; nStyle: CovertEnum;
      out AOut: OleVariant): HResult; stdcall;
    function Get_MeteName: OleVariant; stdcall;
    procedure Set_MeteName(Value: OleVariant); stdcall;

    {Declare ITMeteCovert methods here}
  end;

implementation

uses ComServ;

function TTMeteCovert.Conver(Aparam: Double; nStyle: CovertEnum;
  out AOut: OleVariant): HResult;
begin
   case nStyle of
      COV_CHINA:
       begin
         AOut := Aparam;
       end;
      COV_ENGLISH:
       begin
         AOut := Aparam * 0.8;
       end;
      else
       begin
         Result := S_FALSE;
       end;
   end;
   Result := S_OK;
end;

function TTMeteCovert.Get_MeteName: OleVariant;
begin
  Result := FName;
end;

procedure TTMeteCovert.Initialize;
begin
  inherited;
  FName := '我的表测试';
end;

procedure TTMeteCovert.Set_MeteName(Value: OleVariant);
begin
  FName := Value;
end;

initialization
  TTypedComObjectFactory.Create(ComServer, TTMeteCovert, Class_TMeteCovert,
    ciMultiInstance, tmApartment);
end.

///////////////////COM对象类型库申明(在定义COM对象时由向导自动生成)///////////////////
//类型库包含COM Server信息
//同时包含COM Object接口定义信息
//由类型库编辑器创建,客户端直接包含该类型库即可调用接口功能
unit meterCovert_TLB;

{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface

uses Windows, ActiveX, Classes, Graphics, StdVCL, Variants;
 

// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:       
//   Type Libraries     : LIBID_xxxx                                     
//   CoClasses          : CLASS_xxxx                                     
//   DISPInterfaces     : DIID_xxxx                                      
//   Non-DISP interfaces: IID_xxxx                                       
// *********************************************************************//
const
  // TypeLibrary Major and minor versions
  meterCovertMajorVersion = 1;
  meterCovertMinorVersion = 0;

  LIBID_meterCovert: TGUID = '{A5251101-97D1-49D1-886D-5EAB0773D4BA}';

  IID_ITMeteCovert: TGUID = '{41AF9106-9D39-4C43-9A93-3D1F174A337D}';
  CLASS_TMeteCovert: TGUID = '{4EE10370-5ED4-43B4-8681-17F7A05490B0}';

// *********************************************************************//
// Declaration of Enumerations defined in Type Library                   
// *********************************************************************//
// Constants for enum CovertEnum
type
  CovertEnum = TOleEnum;
const
  COV_CHINA = $00000000;
  COV_ENGLISH = $00000001;

type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary                   
// *********************************************************************//
  ITMeteCovert = interface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library                      
// (NOTE: Here we map each CoClass to its Default Interface)             
// *********************************************************************//
  TMeteCovert = ITMeteCovert;


// *********************************************************************//
// Interface: ITMeteCovert
// Flags:     (256) OleAutomation
// GUID:      {41AF9106-9D39-4C43-9A93-3D1F174A337D}
// *********************************************************************//
  ITMeteCovert = interface(IUnknown)
    ['{41AF9106-9D39-4C43-9A93-3D1F174A337D}']
    function Conver(Aparam: Double; nStyle: CovertEnum; out AOut: OleVariant): HResult; stdcall;
    function Get_MeteName: OleVariant; stdcall;
    procedure Set_MeteName(Value: OleVariant); stdcall;
  end;

// *********************************************************************//
// The Class CoTMeteCovert provides a Create and CreateRemote method to         
// create instances of the default interface ITMeteCovert exposed by             
// the CoClass TMeteCovert. The functions are intended to be used by            
// clients wishing to automate the CoClass objects exposed by the        
// server of this typelibrary.                                           
// *********************************************************************//
  CoTMeteCovert = class
    class function Create: ITMeteCovert;
    class function CreateRemote(const MachineName: string): ITMeteCovert;
  end;

implementation

uses ComObj;

class function CoTMeteCovert.Create: ITMeteCovert;
begin
  Result := CreateComObject(CLASS_TMeteCovert) as ITMeteCovert;
end;

class function CoTMeteCovert.CreateRemote(const MachineName: string): ITMeteCovert;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_TMeteCovert) as ITMeteCovert;
end;

end.

//////////////////////////////////////////////////////////////////////////////
//客户端调用基于类型库的COM对象,原理上和非类型库COM对象调用一样都是基于接口授权引用
//但是基于类型库的COM对象更为标准,可以跨越语言界限
//其他语言可以直接在系统中找到类型注册对象,并生成相应的类型库
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,meterCovert_TLB;

type
  TForm1 = class(TForm)
    btn1: TButton;
    mmo1: TMemo;
    procedure btn1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.btn1Click(Sender: TObject);
var
  MeteCovert:ITMeteCovert;
  Rt:OleVariant;
begin
  MeteCovert := CoTMeteCovert.Create;
  mmo1.Lines.Add(  MeteCovert.Get_MeteName );
  MeteCovert.Set_MeteName('改名啦');
  mmo1.Lines.Add(  MeteCovert.Get_MeteName );
  MeteCovert.Conver(899.9,COV_ENGLISH,Rt);
  mmo1.Lines.Add('Cov=' + FloatToStr(Rt));
end;

end.

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

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多