就拿MSHTML来说吧,比如说有以下两个接口:
IHTMLElement = interface(IDispatch)
IHTMLImgElement = interface(IDispatch)THtmlImgElement = class(TAutoIntfObject, IHtmlElement, IHtmlImgElement)
// ...
constructor Create(...);
end;constructor THtmlImgElement.Create(...);
begin
inherited Create(ComServer.TypeLib, IHTMLImgElement);
// 实现的时候只能注册一个接口
end;这样的话,脚本语言调用的时候只能使用IHtmlImgElement接口而无法转换到IHtmlElement,因为脚本语言不能QueryInterface。请大家点拨一下,谢谢!
IHTMLElement = interface(IDispatch)
IHTMLImgElement = interface(IDispatch)THtmlImgElement = class(TAutoIntfObject, IHtmlElement, IHtmlImgElement)
// ...
constructor Create(...);
end;constructor THtmlImgElement.Create(...);
begin
inherited Create(ComServer.TypeLib, IHTMLImgElement);
// 实现的时候只能注册一个接口
end;这样的话,脚本语言调用的时候只能使用IHtmlImgElement接口而无法转换到IHtmlElement,因为脚本语言不能QueryInterface。请大家点拨一下,谢谢!
HTML元素都支持双接口。脚本语言用的是IDispatch接口
IApplication = interface(IDispatch)
//...
function GetSelection: IDispatch; safecall; // 当前选中的对象,可能是本例中的File/ImageFile
end;// IFile和IImageFile都继承自IDispatchIFile = interface(IDispatch)
// ...
property Created: TDateTime...
property Modified: TDateTime...
property Accessed: TDateTime...
property FileName: WideString...
end;IImageFile = interface(IDispatch)
// ...
property Width: Integer...
property Height: Integer...
end;以下是简单实现:
Unit Application;
// ...
TApplication = class(TAutoObject, IApplication)
// ...
funciton GetSelection: IDispatch; safecall;
end;funciton TApplication.GetSelection: IDispatch; safecall;
begin
Result := TImageFile.Create(Self, 'C:\Example.jpg'); // 假设选中的是个图片
end;initialization
TAutoObjectFactory.Create(ComServer, TApplication, Class_Application,
ciMultiInstance, tmApartment);
而File,Image则实现为如下:
TFile = class(TAutoIntfObject, IFile)
//...
constructor Create(const app: IApplication; const fileName: WideString); overload;
end;constructor TFile.Create(const app: IApplication; const fileName: WideString);
begin
inherited Create(ComServer.TypeLib, IFile);
//...
end;
TImageFile = class(TFile, IFolder) // "实现继承",共享了TFile的代码
//...
constructor Create(const app: IApplication; const fileName: WideString); overload;
end;constructor TImageFile.Create(const app: IApplication; const fileName: WideString);
begin
inherited Create(ComServer.TypeLib, IImageFile); // 这里只能注册一个接口
//...
end;由于TImageFile只能注册一个接口IImageFile, 那么在调用IFile的属性的时候就会出现错误:
<script language="javascript">
var app = new ActiveXObject("Example.Application");
var obj = app.GetSelection; // return TImageFile instance
alert(obj.Width); // OK
alert(obj.FileName); // Error
</script>
混淆Interface的GUID与 对象的GUID....
_IImageFile = interface(IDispatch) // 保持函数签名及DispID一致
//...
property Created: TDateTime...
property Modified: TDateTime...
property Accessed: TDateTime...
property FileName: WideString...
//...
property Width: Integer...
property Height: Integer...
end;然后更改TImageFile的构造函数为:
inherited Create(ComServer.TypeLib, _IImageFile);但这样太麻烦了,不知道有没有更好的方法?还是说一般只要声明IImageFile=interface(IFile)就好了?
IImageFile=interface(IFile) //同时记住把类型库对应作修改,一处是继承关系,另一处是方法的ID值....
Create(ComServer.TypeLib, IImageFile);
....这种方式我试过可行.