2010-08-06 41 views
4

在Delphi 2007中可以使用接口方法作爲事件處理程序嗎?簡單的版本不工作:作爲事件處理程序的接口方法

type 
    TMyEvent = procedure of object; 

    IMyInterface = interface 
    procedure Handler; 
    end; 

    TMyClass = class(TInterfacedObject, IMyInterface) 
    public 
    procedure Handler; 
    end; 

var 
    ev: TMyEvent; 
    obj: TMyClass; 
    intf: IMyInterface; 
begin 
    obj := TMyClass.Create; 
    intf := obj; 
    ev := obj.Handler; // compiles 
    ev := intf.Handler; // <== Error E2010 (incompatible types) 
end. 

添加@Addr改變錯誤E2036(必需的變量)。

更新:

procedure IntRefToMethPtr(const IntRef; var MethPtr; MethNo: Integer); 
type 
    TVtable = array[0..999] of Pointer; 
    PVtable = ^TVtable; 
    PPVtable = ^PVtable; 
begin 
    //QI=0, AddRef=1, Release=2, etc 
    TMethod(MethPtr).Code := PPVtable(IntRef)^^[MethNo]; 
    TMethod(MethPtr).Data := Pointer(IntRef); 
end; 

var 
    ev: TMyEvent; 
    intf: IMyInterface; 
begin 
    intf := TMyClass.Create; 
    IntRefToMethPtr(intf, ev, 3); 
    ev; 
end. 

作品。不過我並不太喜歡那裏的魔法3。

+0

發佈後,我發現http://blog.barrkel.com/2010/01/using-anonymous-methods-in-method.html和http://sergworks.wordpress.com/2010/07/06/delphi-interfaces-on-binary-level /看起來很有前途。 – 2010-08-06 08:39:48

回答

2

更乾淨的解決方案是爲您的基類實現IInterfaceComponentReference或類似的東西,並使用它來獲取類參考。

上述代碼不適用於例如FPC和其他兼容產品。他們的VMT結構稍有不同。甚至在Delphi上,未來的語言擴展可能會導致這種情況。

一個完美的解決方案是爲此有一個完全獨立的「接口」methodvar類型,但我不知道這是否值得這個麻煩。

+0

聽起來合理。也許我會將其修改爲GetHandler方法而不是GetSelf。謝謝! – 2010-08-06 10:23:50

相關問題