2

TNotifyEvent フック/ラッパーを作成する簡単な方法を探しているので、簡単にするためにオブジェクトとして作成するというアイデアを得ました

しかし、メソッドポインターを正しくアタッチ/スワップする方法がわかりません... :/

多分あなたの誰かが以前に同様のことをしたことがありますか?

これが私のクラスのスケルトンです

  TNotifyEventHook = class
  private
    NotifyEvent: ???????;
    OldProc, NewProc: ???????;

    FContinueEventChain: Boolean;
    procedure Wrapper(Sender: TObject);
  public
    constructor Create(OriginalNotifyEvent: ???????; ChainNotifyEvent???????);
    destructor Destroy; override;
    property ContinueEventChain: Boolean read FContinueEventChain write FContinueEventChain default True;
  end;



constructor TNotifyEventHook.Create(OriginalNotifyEvent: ???????; ChainNotifyEvent: ???????);
begin
  NotifyEvent := ???????   // save
  OldProc := ???????
  NewProc := ???????

  NotifyEvent := ??????? // redirect NotifyEvent to Wrapper
end;

destructor TNotifyEventHook.Destroy;
begin                                 
  ???????   // detach chain
end;

procedure TNotifyEventHook.Wrapper(Sender: TObject);
begin
  if Assigned(NewProc) then
    NewProc(Sender);
  if FContinueEvenChain and Assigned(OldProc) then
    OldProc(Sender);
end;

私は助けに本当に感謝しています...それとももっと良いアイデアですか?

4

1 に答える 1

0

イベント プロパティ自体への参照を変数またはパラメーターに格納できないため、これは機能しません。NotifyEventはOldProc /NewProc です。つまり、イベント プロパティに格納されるのは、オブジェクト内部からプロパティが起動されたときに呼び出されるイベント ハンドラです。したがって、有効なTNotifyEventインスタンスは、ルーチンがどのオブジェクトまたはプロパティにリンクされているかではなく、どのルーチンが呼び出されるかを示すだけです。

質問が 1 つの特定のイベントに限定される場合、たとえばTControl.OnClick、次のようになります。それ以外の場合は、マルチキャスト イベント モデルを使用することをお勧めしますTApplicationEvents

type
  TOnClickRedirector = class
  private
    FControl: TControl;
    FFireOriginalToo: Boolean;
    FOriginal: TNotifyEvent;
    FRedirect: TNotifyEvent;
    procedure Fire(Sender: TObject);
  public
    constructor Create(Control: TControl; OnClick: TNotifyEvent);
    destructor Destroy; override;
    property FireOriginalToo: Boolean read FFireOriginalToo
      write FFireOriginalToo default True;
  end;

  TControlAccess = class(TControl);

{ TOnClickRedirector }

constructor TOnClickRedirector.Create(Control: TControl; OnClick: TNotifyEvent);
begin
  FControl := Control;
  FOriginal := TControlAccess(FControl).OnClick;
  FRedirect := OnClick;
  TControlAccess(FControl).OnClick := Fire;
  FFireOriginalToo := True;
end;

destructor TOnClickRedirector.Destroy;
begin
  TControlAccess(FControl).OnClick := FOriginal;
  inherited Destroy;
end;

procedure TOnClickRedirector.Fire(Sender: TObject);
begin
  if Assigned(FRedirect) then
    FRedirect(Sender);
  if FFireOriginalToo and Assigned(FOriginal) then
    FOriginal(Sender);
end;

傍受したい特定のイベントごとにこれをコピーします。FControlこのコード例は、このオブジェクトの破棄時に存在しなくなる可能性を保護しないことに注意してください。TComponentしたがって、 から派生して使用するのが最善FreeNotificationです。

于 2015-02-25T12:38:36.330 に答える