Хокинг TNotifyEvent / поиск правильного способа использования метода и процедурных указателей

Я ищу простой способ создания ловушки / оболочки 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 ответ

Это не сработает, потому что вы не можете хранить ссылку на само свойство события в переменной или параметре. NotifyEvent - это 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,

Другие вопросы по тегам