应恢弘之约,写了一个对其发布的匿名函数动态绑定到事件的封装,代码如下:
type TAnonEvent=class public class function Wrap<T1,T2>(OnEvent:T1):T2; end; { TAnonEvent } class function TAnonEvent.Wrap<T1,T2>(OnEvent: T1):T2; var Addr:Pointer; AMethod:PMethod; begin Addr:=PPointer(@OnEvent)^; AMethod:=@Result; AMethod.Code:=PPointer(IntPtr(PPointer(Addr)^)+SizeOf(Pointer)*3)^;//QueryInterface/AddRef/Release/Invoke AMethod.Data:=Pointer(Addr); end; type TNotifyEventA=reference to procedure(ASender:TObject); procedure TForm3.Button1Click(Sender: TObject); begin Button2.OnClick:=TAnonEvent.Wrap<TNotifyEventA,TNotifyEvent>(procedure (sender: tObject) begin Button2.Caption:=DateTimeToStr(Now); ShowMessage('OK'); end); Button2.OnClick(Sender); end;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | type TAnonEvent=class public class function Wrap<T1,T2>(OnEvent:T1):T2; end; { TAnonEvent } class function TAnonEvent.Wrap<T1,T2>(OnEvent: T1):T2; var Addr:Pointer; AMethod:PMethod; begin Addr:=PPointer(@OnEvent)^; AMethod:=@Result; AMethod.Code:=PPointer(IntPtr(PPointer(Addr)^)+SizeOf(Pointer)*3)^;//QueryInterface/AddRef/Release/Invoke AMethod.Data:=Pointer(Addr); end;
type TNotifyEventA=reference to procedure(ASender:TObject); procedure TForm3.Button1Click(Sender: TObject); begin Button2.OnClick:=TAnonEvent.Wrap<TNotifyEventA,TNotifyEvent>(procedure (sender: tObject) begin Button2.Caption:=DateTimeToStr(Now); ShowMessage('OK'); end); Button2.OnClick(Sender); end; |
【注意】
由于匿名函数中,我将TMethod.Data指向了匿名函数对应的接口对象,所以在匿名函数中,不要使用Self来代表当前对象。如果非要使用的话,那么自己修改下Wrap的代码,将AMethod.Data:=Pointer(Addr)改为指向当前函数所隶属对象的Self即可。