在这个
post的接受答案仍然是非常神秘的:
@Button1.OnClick := pPointer(Cardinal(pPointer( procedure (sender: tObject) begin ((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' end )^ ) + $0C)^;
我想知道有可能设计一个简单和优雅的方式类似于:
Button.OnClick := AnonProc2NotifyEvent ( procedure (Sender: TObject) begin ((Sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' end );
以达到相同的目的,而AnonProc2NotifyEvent是Button的所有者的一种方法,具有以下签名:
TOwnerOfButton = class(TForm) Button: TButton; ... private ... protected function AnonProc2NotifyEvent(aProc: TProc<TObject>): TNotifyEvent; public ... end;
这是可行的,如果是这样实现呢?
解决方法
这样做就足够了:
type TNotifyEventWrapper = class(TComponent) private FProc: TProc<TObject>; public constructor Create(Owner: TComponent; Proc: TProc<TObject>); published procedure Event(Sender: TObject); end; constructor TNotifyEventWrapper.Create(Owner: TComponent; Proc: TProc<TObject>); begin inherited Create(Owner); FProc := Proc; end; procedure TNotifyEventWrapper.Event(Sender: TObject); begin FProc(Sender); end; function AnonProc2NotifyEvent(Owner: TComponent; Proc: TProc<TObject>): TNotifyEvent; begin Result := TNotifyEventWrapper.Create(Owner,Proc).Event; end;
AnonProc2NotifyEvent中的Owner参数使得可以管理包装器对象的生命周期.没有这样的东西,你会泄露TNotifyEventWrapper的实例.
作为所有者传递作为连接事件的组件.例如:
Button1.OnClick := AnonProc2NotifyEvent( Button1,procedure(Sender: TObject) begin (Sender as TButton).Caption := 'Clicked'; end );
因此,当按钮被破坏时,TNotifyEventWrapper也将被销毁.包装对象必须至少与其所关联事件的对象一样长.所以Button1作为主人的选择是自然而又明显的.