如何在 Delphi 个应用程序中检测 TPopupMenu 的 OnClose (OnPopDown) 事件
How to Detect a TPopupMenu's OnClose (OnPopDown) Event in Delphi applications
我可以在 TPopupMenu 的 OnPopUp 事件中编写一些代码。但我还需要 OnPopDown 的另一个事件。有什么方法可以使用 Delphi 10.3.3 吗?
您可以尝试多种选择。
方法一
在更简单的情况下,当您有一个需要跟踪其上下文菜单的特定控件时,您可以手动处理其 WM_CONTEXTMENU
消息:
protected
procedure WMContextMenu(var Message: TWMContextMenu);
message WM_CONTEXTMENU;
其中(例如)
procedure TForm1.WMContextMenu(var Message: TWMContextMenu);
begin
if
Assigned(PopupMenu)
and
(ClientRect.Contains(ScreenToClient(Message.Pos)) or (Message.Pos = Point(-1, -1)))
then
begin
Windows.Beep(200, 500); // pre-popup code
if (Message.XPos = -1) and (Message.YPos = -1) then // Menu key or Shift+F10
with ClientToScreen(Point(0, 0)) do
PopupMenu.Popup(X, Y)
else
PopupMenu.Popup(Message.XPos, Message.YPos);
Windows.Beep(400, 500); // post-popup code
end
else
inherited;
end;
测试 ClientRect.Contains(ScreenToClient(Message.Pos))
是必要的,这样您就不会“覆盖”滚动条自己的上下文菜单。此外,您需要考虑使用键盘(例如菜单键或 Shift+F10)打开上下文菜单的情况。
方法二
如果这对您来说还不够,您可以创建自己的 TPopupMenu
子 class 并覆盖它的 Popup
方法,这是虚拟的。添加一个DoPopdown
方法,在最后调用(按照DoPopup
方法的设计)。
要快速测试此方法,您可以使用插入器 class:
type
TPopupMenu = class(Vcl.Menus.TPopupMenu)
procedure Popup(X, Y: Integer); override;
end;
实现为
{ TPopupMenu }
procedure TPopupMenu.Popup(X, Y: Integer);
begin
inherited;
Windows.Beep(400, 500); // post-popup code
end;
当然,创建一个您在 IDE 中注册的真正后代 class(TPopupMenuEx
,或许?)会更好。添加一个 FOnPopdown: TNotifyEvent
私有字段、一个 DoPopdown
受保护函数和一个 OnPopdown
已发布 属性。这精确地模仿了 OnPopup
机制。
不用说,这种方法也适用于 TTrayIcon
的菜单。
我可以在 TPopupMenu 的 OnPopUp 事件中编写一些代码。但我还需要 OnPopDown 的另一个事件。有什么方法可以使用 Delphi 10.3.3 吗?
您可以尝试多种选择。
方法一
在更简单的情况下,当您有一个需要跟踪其上下文菜单的特定控件时,您可以手动处理其 WM_CONTEXTMENU
消息:
protected
procedure WMContextMenu(var Message: TWMContextMenu);
message WM_CONTEXTMENU;
其中(例如)
procedure TForm1.WMContextMenu(var Message: TWMContextMenu);
begin
if
Assigned(PopupMenu)
and
(ClientRect.Contains(ScreenToClient(Message.Pos)) or (Message.Pos = Point(-1, -1)))
then
begin
Windows.Beep(200, 500); // pre-popup code
if (Message.XPos = -1) and (Message.YPos = -1) then // Menu key or Shift+F10
with ClientToScreen(Point(0, 0)) do
PopupMenu.Popup(X, Y)
else
PopupMenu.Popup(Message.XPos, Message.YPos);
Windows.Beep(400, 500); // post-popup code
end
else
inherited;
end;
测试 ClientRect.Contains(ScreenToClient(Message.Pos))
是必要的,这样您就不会“覆盖”滚动条自己的上下文菜单。此外,您需要考虑使用键盘(例如菜单键或 Shift+F10)打开上下文菜单的情况。
方法二
如果这对您来说还不够,您可以创建自己的 TPopupMenu
子 class 并覆盖它的 Popup
方法,这是虚拟的。添加一个DoPopdown
方法,在最后调用(按照DoPopup
方法的设计)。
要快速测试此方法,您可以使用插入器 class:
type
TPopupMenu = class(Vcl.Menus.TPopupMenu)
procedure Popup(X, Y: Integer); override;
end;
实现为
{ TPopupMenu }
procedure TPopupMenu.Popup(X, Y: Integer);
begin
inherited;
Windows.Beep(400, 500); // post-popup code
end;
当然,创建一个您在 IDE 中注册的真正后代 class(TPopupMenuEx
,或许?)会更好。添加一个 FOnPopdown: TNotifyEvent
私有字段、一个 DoPopdown
受保护函数和一个 OnPopdown
已发布 属性。这精确地模仿了 OnPopup
机制。
不用说,这种方法也适用于 TTrayIcon
的菜单。