Answer the question
In order to leave comments, you need to log in
Independently attach multiple WindowProc handlers to an arbitrary TWinControl descendant?
There are at least three components that, having received a link to TWinControl, want to start adjusting their position when the position of that control changes, and somehow react to events that come to it.
All three, independently of each other, can be added and removed in any order. Both in runtime and design time.
All three, in principle, are in my source code - but a setup: they belong to different component packages and, accordingly, I cannot fix them so that they use some kind of auxiliary class that I have in common for them - the WindowProc replacement queue manager. In addition, perhaps someone else also uses the same method, but I have not yet discovered it.
Now all three of them use the same very popular approach to parasitize, thinking that each of them is unique:
procedure T***.PatchControl;
begin
FOldWndProc := FLinkedControl.WindowProc;
FLinkedControl.WindowProc := MyWndProc;
end;
procedure T***.UnpatchControl;
begin
FLinkedControl.WindowProc := FOldWndProc;
end;
procedure T***.UnpatchControl;
var
m: TWndMethod;
begin
m := MyWndProc;
Assert((TMethod(FLinkedControl.WindowProc).Code = TMethod(m).Code), 'unlink only own handler to prevent errors');
FLinkedControl.WindowProc := FOldWndProc;
end;
Answer the question
In order to leave comments, you need to log in
I would do this:
1) First of all, I checked if it is possible to implement the same without overriding WndProc, for example, using TAppEvents.OnMessage.
2) If not, then:
Created a separate package. I would make a separate component in it that allows you to organize a chain of calls to WinProc. Well, actually, you already have such a class in your code. T***(.UnpatchControl_. If there are many such classes, then it makes sense to make them a common successor. Or change the T*** class so that PatchControl delegates the call to an instance of TMyWndProcQueeHandler (proxy).
The class would look something like this:
type
TMyWndProcQueeHandler = class(TComponent)
private
FWndProcsList: array of TWndMethod; // или TList<TWndMethod>
public
// здесь присваиваем контролу MyWndProc в качестве WndProc
// а оригинальный добавлем в FWndProcsList
procedure PatchControl;
// здесь соответственно восстанавливаем оригинальный WndProc
procedure UnpatchControl;
// здесь вызываем WndProc-ы в нужном порядке. (начиная с последнего (кастомного) до 0-го (оригинального))
procedure MyWndProc(var Message: TMessage);
// тут просто добавляем aWndProc в список
procedure AddWndProc(const aWndProc: TWndProc);
// ну и конечно надо ещё сделать конструктор/деструктор. Опционально переопределить Notification, чтобы получать уведомления от освобожденных связанных компонентов.
// И добавить property LinkedControl с setter-ом.
end;
And if you make a proxy WinControl and slip it on them? And destroy everything in it.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question