除了这个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;


Owner中的AnonProc2NotifyEvent参数是为了可以管理包装对象的生存期。没有类似的东西,您将泄漏TNotifyEventWrapper的实例。

Owner的形式传递事件所要连接到的组件。例如:

Button1.OnClick := AnonProc2NotifyEvent(
  Button1,
  procedure(Sender: TObject)
  begin
    (Sender as TButton).Caption := 'Clicked';
  end
);


因此,当按钮被销毁时,TNotifyEventWrapper也将被销毁。包装对象必须至少与与其事件关联的对象一样长。因此,选择Button1作为拥有者是自然而明显的选择。

10-08 14:47