挂起TNotifyEvent /寻找使用方法和程序指针的正确方法

时间:2015-02-25 12:06:26

标签: delphi pointers methods event-hooking

我正在寻找创建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;

我真的很感激帮助......或者只是更好的想法?

1 个答案:

答案 0 :(得分:0)

这不会起作用,因为您无法在变量或参数中存储对事件属性本身的引用。 NotifyEvent ís OldProc / NewProc。换句话说:存储在事件属性中的事物是从对象内部触发属性时调用的事件处理程序。因此,有效的TNotifyEvent实例只会告诉调用哪个例程,而不是例程链接到哪个对象或属性。

如果您的问题仅限于一个特定事件,例如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