Das scheint in der Tat ein Designfehler zu sein. Das angeklickte Control gibt in
TWinControl.DefaultHandler erstmal an den jeweiligen Parent weiter (Panel10, Panel9, ... Panel1, Form2).
Delphi-Quellcode:
if (Msg = WM_CONTEXTMENU) and (Parent <> nil) then
begin
Result := Parent.Perform(Msg, WParam, LParam);
if Result <> 0 then Exit;
end;
Bis auf Form2, bei dem es ja keinen Parent gibt, wird danach aber noch ein CallWindowProc-Aufuf durchgeführt, der aber am Ende wiederum im WMContextMenu des Controls landet und dort wieder die Leiter der Controls hinaufklettert, was dann zu diesem exponentiellen Wachstum der Durchläufe führt.
Delphi-Quellcode:
Result := CallWindowProc(FDefWndProc, WindowHandle, Msg, WParam, LParam);
Beispielhaft hier mal die Liste der Aufrufe für einen Klick in Panel3:
Panel3, Panel2, Panel1, Form2, Form2, Panel1, Form2, Form2, Panel2, Panel1, Form2, Form2, Panel1, Form2, Form2
Eigentlich sollte das anfängliche Hochhängeln zum Form ausreichen und die Überprüfung auf Result <> 0 vor dem Exit entfallen. Mit dieser Code-Änderung in TWinControl.DefaultHandler wird das Laufzeitverhalten auch wieder akzeptabel.
Delphi-Quellcode:
if (Msg = WM_CONTEXTMENU) and (Parent <> nil) then
begin
Result := Parent.Perform(Msg, WParam, LParam);
Exit;
end;
Als Workaround kannst du z.B. im Form die WM_CONTEXTMENU Message abfangen und den Result auf 1 setzen.
Delphi-Quellcode:
procedure WMContextMenu(var Message: TWMContextMenu); message WM_CONTEXTMENU;
...
procedure TForm2.WMContextMenu(var Message: TWMContextMenu);
begin
inherited;
Message.Result := 1;
end;