14

イベントハンドラーでクロージャーを使用しようとすると、コンパイラーは次のように文句を言います:

互換性のない型: 「メソッド ポインタと通常のプロシージャ」

私は理解しています..しかし、メソッドポインターでクローザーを使用する方法はありますか? できるかどうかを定義する方法は?

例:

Button1.Onclick = procedure( sender : tobject ) begin ... end;

ありがとう!

4

4 に答える 4

10
@Button1.OnClick := pPointer(Cardinal(pPointer( procedure (sender: tObject) 
begin 
  ((sender as TButton).Owner as TForm).Caption := 'Freedom to anonymous methods!' 

end )^ ) + $0C)^;

Delphi 2010で動作します

于 2011-04-13T10:13:15.553 に答える
5

素晴らしい質問です。

私の知る限り、現在のバージョンの Delphi では実行できません。オブジェクトのイベント ハンドラーをすばやくセットアップするためにこれらの匿名プロシージャがあれば、たとえば、xUnit の種類の自動テスト フレームワークでテスト フィクスチャをセットアップする場合に便利なので、これは非常に残念です。

CodeGear がこの機能を実装するには、次の 2 つの方法があります。

1: 匿名メソッドの作成を許可します。このようなもの:

Button1.OnClick := procedure( sender : tobject ) of object begin
  ...
end;

ここで問題となるのは、無名メソッドの自己ポインタを何にするかです。匿名メソッドが作成されたオブジェクトの自己ポインターを使用することもできますが、その場合、オブジェクト コンテキストからのみ匿名メソッドを作成できます。より良いアイデアは、舞台裏でダミー オブジェクトを作成して匿名メソッドを含めることです。

2: 別の方法として、定義されたシグネチャを共有する限り、イベント タイプがメソッドとプロシージャの両方を受け入れることができるようにすることもできます。そのようにして、必要な方法でイベント ハンドラーを作成できます。

Button1.OnClick := procedure( sender : tobject ) begin
  ...
end;

私の目には、これが最善の解決策です。

于 2008-12-23T11:45:54.777 に答える
4

Delphi の以前のバージョンでは、非表示の自己ポインタをパラメータに追加し、それをハード型キャストすることで、通常のプロシージャをイベント ハンドラとして使用できました。

procedure MyFakeMethod(_self: pointer; _Sender: TObject);
begin
  // do not access _self here! It is not valid
  ...
end;

...

var
  Meth: TMethod;
begin
  Meth.Data := nil;
  Meth.Code := @MyFakeMethod;
  Button1.OnClick := TNotifyEvent(Meth);
end;

上記が実際にコンパイルされるかどうかはわかりませんが、一般的なアイデアが得られるはずです。以前にこれを行ったことがありますが、通常の手順で機能しました。コンパイラーがクロージャーに対して生成するコードがわからないため、これがクロージャーに対して機能するかどうかはわかりません。

于 2009-01-04T09:35:39.483 に答える
2

以下を拡張して、より多くのフォームイベントタイプを処理するのは簡単です。

使用法

procedure TForm36.Button2Click(Sender: TObject);
var
  Win: TForm;
begin
  Win:= TForm.Create(Self);
  Win.OnClick:= TEventComponent.NotifyEvent(Win, procedure begin ShowMessage('Hello'); Win.Free; end);
  Win.Show;
end;

コード

unit AnonEvents;

interface
uses
  SysUtils, Classes;

type
  TEventComponent = class(TComponent)
  protected
    FAnon: TProc;
    procedure Notify(Sender: TObject);
    class function MakeComponent(const AOwner: TComponent; const AProc: TProc): TEventComponent;
  public
    class function NotifyEvent(const AOwner: TComponent; const AProc: TProc): TNotifyEvent;
  end;

implementation

{ TEventComponent }

class function TEventComponent.MakeComponent(const AOwner: TComponent;
  const AProc: TProc): TEventComponent;
begin
  Result:= TEventComponent.Create(AOwner);
  Result.FAnon:= AProc;
end;

procedure TEventComponent.Notify(Sender: TObject);
begin
  FAnon();
end;

class function TEventComponent.NotifyEvent(const AOwner: TComponent;
  const AProc: TProc): TNotifyEvent;
begin
  Result:= MakeComponent(AOwner, AProc).Notify;
end;

end.
于 2015-12-18T16:35:28.813 に答える