In similar situations, when I need to centralize the handling of certain events, I use the following approach, which works even if forms and controls are created at runtime.
procedure Form1.Hook(Root: TComponent);
var i: integer;
begin
if Root is TMemo then begin
TMemo(Root).OnClick := @CentralClick;
exit;
end;
if Root is TPanel then begin
TMemo(Root).OnClick := @PanelsClick;
end;
for i := 0 to Root.ComponentCount-1 do
Hook(Root.Components[i]);
end;
With the above, a form can call Hook(Self) and the above will go through every component and control, and there you will be able to assign different event handlers for different classes of controls, etc.
In the above example, I assign certain handlers to TMemo controls (and then I exit) and I assign other handlers to TPanel controls (and then I don't exit because panels may own children controls)
Note: Instead of Components/ComponentCount you may also use Controls/ControlCount, which follows the parent/child structure instead of the Owner structure.
Call Hook when the program starts, and if you dynamically create new controls, etc. at runtime then call again Hook(...) with the root of the changed controls.
The methods you assign, of course, will have to check who is the Sender object and operate accordingly.
I also use the above approach, for example, to change the captions and hints of different controls when the user changes language, or changes color scheme, and so on.