据说dispinterface就是纯分发接口,未实现IUnknown的
在用连接点的时候,需要给它一个dispinterface的接口,通常就是给它IDispatch接口,但是因为不能实现dispinterface接口,弄得每次QueryInterface的时候要比较GUID,如果是某个dispinterface,就返回对应的IDispatch,而不能使用QueryInterface的默认实现。大家在自己手动使用事件连接点的时候一般怎么干的啊?还有,有没有好一点的办法能够直接将Invoke调用映射到一系列方法上去?Delphi编译器有没有对它的默认实现?

解决方案 »

  1.   

    Delphi帮助就有:
    type
            IStringsDisp = dispinterface
            ['{EE05DFE2-5549-11D0-9EA9-0020AF3D82DA}']
             property ControlDefault[Index: Integer]: OleVariant dispid 0; default;
             function Count: Integer; dispid 1;
          property Item[Index: Integer]: OleVariant dispid 2;
          procedure Remove(Index: Integer); dispid 3;
          procedure Clear; dispid 4;
          function Add(Item: OleVariant): Integer; dispid 5;
             function _NewEnum: IUnknown; dispid -4;
         end;
      

  2.   

    http://www.informit.com/articles/article.aspx?p=130494&seqNum=5
      

  3.   

    楼上,非常感谢,我想问的就是,我如何写一个类实现IStringsDisp接口?
    或许是我语法不懂,貌似TMyObject = class(TObject, IStringsDisp)不行?
      

  4.   

    这个我当然清楚,但是编译时delphi说IStringsDisp不是个接口
      

  5.   

    那就看你是否有声明IStringsDisp.uses
    Stdvcl;
      

  6.   

    楼主理解有点不对IUnkonwn 是最底的带 GUID 接口 等价于 IInterface, 派生于 interface 用于 COM 实现时转义为 IUnknown, delphi 接口有一个广意性, 它不一定非要是 COM 对像IDispatch 叫调度接口, 定义为
      IDispatch = interface(IUnknown)
        ['{00020400-0000-0000-C000-000000000046}']
        function GetTypeInfoCount(out Count: Integer): HResult; stdcall;
        function GetTypeInfo(Index, LocaleID: Integer; out TypeInfo): HResult; stdcall;
        function GetIDsOfNames(const IID: TGUID; Names: Pointer;
          NameCount, LocaleID: Integer; DispIDs: Pointer): HResult; stdcall;
        function Invoke(DispID: Integer; const IID: TGUID; LocaleID: Integer;
          Flags: Word; var Params; VarResult, ExcepInfo, ArgErr: Pointer): HResult; stdcall;
      end;
    其中 2 个方法最为重要, GetIDsOfNames和 Invoke注意 GetIdsOfNames 中参数 
    Names 是一个 c 数组
    DispIDs 实际是一个整形数组
    这里面的内容就是 函数名 <--> Disp id 之间的关系现在是 Invoke 参数, 跟上面很有关系
      DispId 是用 name 查出来的 Id, 并不支持 Name 调用
      ... 下面是参数之类换句话说你如果直接知道 DispID 就可以直接调用 Invoke 而不必用 GetIDsOfNames(用函数名称取得 id)
      

  7.   

    现在我们再来看 dispinterface 是什么
      IStringsDisp = dispinterface
        ['{EE05DFE2-5549-11D0-9EA9-0020AF3D82DA}']
        property ControlDefault[Index: Integer]: OleVariant dispid 0; default;
        function Count: Integer; dispid 1;
        property Item[Index: Integer]: OleVariant dispid 2;
        procedure Remove(Index: Integer); dispid 3;
        procedure Clear; dispid 4;
        function Add(Item: OleVariant): Integer; dispid 5;    function _NewEnum: IUnknown; dispid -4;
      end;
    注意看后面的 dispid xx, 这个实际就是用于调用 Invoke 中 DispId 的参数
    很显然, 没实现 IDispatch 的接口是不能用 dispinterface 的
    不是很显然的是, dispinterface 实际上并不是接口, 它不能用于实现, dispinterface 只是一个对接口的描述表, 知道了上面的原理后得出, 任何实现了 IDispatch 的接口都可以定义一个 dispinterface 纯描述文件, 任何 IDispatch 实现类都可以 as 成 dispinterface(是不是相同就你自已认定了)实现一个可远程的 stringlist 类只要自已申明并实现一个 IStringList = IDispatch, delphi 实现为 IStringsAdapter, 而不是 IStringsDisp, IStringsDisp 只是描述了 IStringsAdaper 的函数的 disp id