2

I'm looking for easy way to create TNotifyEvent hook/wrapper So I got an idea to create it as object to make stuff easier

But I have no idea how to attach / swap method pointers correctly... :/

Maybe anyone of You has done similar things before?

Here is the skeleton of my class

  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;

I'd be really grateful for help... Or maybe just better ideas?

Mad Scientist
  • 331
  • 2
  • 15
  • I dont realy Understanc what you are trying to do? Do you want to add an extra event to sat Button.OnClick? – Jens Borrisholt Feb 25 '15 at 12:36
  • *".. how to attach .."* - Attach to where? You're passing a method to the constructor that is attached to a property of some object. That method does not know which object, if there is one, it is attached to, and to which event handler. – Sertac Akyuz Feb 25 '15 at 16:26

1 Answers1

0

This is not gonna work because you cannot store the reference to an event property itself in a variable or parameter. The NotifyEvent ís the OldProc/NewProc. In other words: the thing that is stored in an event property is the event handler which get called when the property is fired from within the objects internals. So a valid TNotifyEvent instance only tells which routine gets called, not to which object nor property the routine is linked to.

If your question would be limited to one specific event, e.g. TControl.OnClick, then the following works. Otherwise, I suggest you use a multi-cast event model, for example like TApplicationEvents does.

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;

Copy this for each specific event you would like to intercept. Beware that this code example does not safeguard the possibility that FControl does not exist anymore at this object's destruction. Therefore it would be best to descend from TComponent and use FreeNotification.

NGLN
  • 43,011
  • 8
  • 105
  • 200
  • Regarding multicasting, have a look at Allen Bauer's blog for his implementation: [Multicast events using generics](http://blogs.embarcadero.com/abauer/2008/08/15/38865) – Remy Lebeau Feb 26 '15 at 00:40
  • Blog post has moved to [Multicast events using generics](https://blogs.embarcadero.com/multicast-events-using-generics/) – vav Jul 12 '23 at 20:52