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实例只告诉调用哪个例程,而不是例程链接到哪个对象或属性。

如果您的问题仅限于一个特定事件,例如TControl.OnClick,那么以下工作。否则,我建议您使用多播事件模型,例如 like TApplicationEventsdoes。

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 回答