delphi – 具有相同GUID的两个接口的相关性交互是什么
我以前认为Delphi中关于Interfaces的类型安全性是通过设置一个唯一的(可选的,但唯一的,如果填充的)GUID来维护的.
然后出现了这个问题:Unspecified error when calling Word CentimetersToPoints via OLE 我开始寻找现货Delphi TWordApplication组件(即Word200.pas单元).在那里,我看到: // *********************************************************************// // Interface: _Application // Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable // GUID: {00020970-0000-0000-C000-000000000046} // *********************************************************************// _Application = interface(IDispatch) ['{00020970-0000-0000-C000-000000000046}'] ... function CentimetersToPoints(Centimeters: Single): Single; safecall; // *********************************************************************// // DispIntf: _ApplicationDisp // Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable // GUID: {00020970-0000-0000-C000-000000000046} // *********************************************************************// _ApplicationDisp = dispinterface ['{00020970-0000-0000-C000-000000000046}'] ... function CentimetersToPoints(Centimeters: Single): Single; dispid 371; 或类似的: // *********************************************************************// // Interface: _Global // Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable // GUID: {000209B9-0000-0000-C000-000000000046} // *********************************************************************// _Global = interface(IDispatch) ['{000209B9-0000-0000-C000-000000000046}'] ... function CentimetersToPoints(Centimeters: Single): Single; safecall; // *********************************************************************// // DispIntf: _GlobalDisp // Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable // GUID: {000209B9-0000-0000-C000-000000000046} // *********************************************************************// _GlobalDisp = dispinterface ['{000209B9-0000-0000-C000-000000000046}'] ... function CentimetersToPoints(Centimeters: Single): Single; dispid 371; 我觉得这里完全迷失了. 我以前认为dispinterface是接口的“子类”,如TOERS的TPersistent是?如果是,那么如何在同一个项目中具有相同GUID的两个接口? 或者它们来自不同的不相关框架,如Delphi新类类继承TurboPascal对象类型? _GlobalDisp和_ApplicationDisp似乎都没有在Word200.pas中使用,所以它们就像附录,自动导入但从未实际使用过吗? 我使用_Application和_ApplicationDisp创建了该项目并进行编译.但后来我只想知道如果他们有相同的指南,Delphi如何打字呢? procedure TForm4.Button1Click(Sender: TObject); procedure show(const s: Single); begin ShowMessage(FloatToStr(s)); end; begin show( WordApplication1.CentimetersToPoints(1.0) ); show( WordApplication1.Application.CentimetersToPoints(2.0) ); show( WordApplication1.DefaultInterface.CentimetersToPoints(3.0) ); show( _ApplicationDisp(WordApplication1.Application).CentimetersToPoints(4.0) ); show( (WordApplication1.DefaultInterface as _ApplicationDisp).CentimetersToPoints(5.0) ); end; 解决方法
dispinterface实际上只是将IDispatch用于自动化接口的便捷方式.这就是他们拥有相同GUID的原因 – 它们在幕后完全相同.
使用IDispatch调用方法时,通常必须调用GetIdsOfNames以获取方法的调度ID.但由于这些是静态的,如果您知道调度ID,则可以通过跳过该步骤来节省时间.这就是dispinterface允许你做的事情. 当您在调度接口上调用方法时,您仍然最终在IDispatch上调用Invoke,但是您跳过对GetIdsOfNames的调用. 当您使用带接口的QueryInterface时,您将获得IDispatch.然后,您可以将其强制转换为相应的调度接口.它仍然是相同的接口,但是当您在dispinterface上调用方法时,您将保存对GetIdsOfNames的调用. 因此,如果您有Word应用程序对象的IDispatch,比如说,您可以编写如下代码: var WordApp: Variant; WordDisp: _ApplicationDisp; .... WordApp := CreateOleObject('Word.Application'); WordDisp := _ApplicationDisp(IDispatch(WordApp)); _ApplicationDisp()强制转换只不过是对IntfCopy的调用.反过来,这只不过是对_AddRef的调用.然后你可以写: Writeln(WordApp.ProductCode); Writeln(WordDisp.ProductCode); 两者都产生相同的输出.前者在调用Invoke之前首先调用GetIdsOfNames.后者直接进入Invoke. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |