Хокинг 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
,