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;
2条答案
按热度按时间2w3rbyxf1#
您可以尝试各种选项。
方法1
在更简单的情况下,当您需要跟踪特定控件的上下文菜单时,可以手动处理其
WM_CONTEXTMENU
消息:其中(例如)
测试
ClientRect.Contains(ScreenToClient(Message.Pos))
是必要的,这样你就不会“覆盖”滚动条自己的上下文菜单。另外,你需要考虑上下文菜单是使用键盘打开的情况(例如,菜单键或Shift+F10)。方法2
如果这对您来说还不够,您可以创建自己的
TPopupMenu
子类并覆盖其Popup
方法,该方法是虚拟的。添加一个DoPopdown
方法并在最后调用它(遵循DoPopup
方法的设计)。要快速测试这种方法,可以使用interposer类:
实施为
当然,最好创建一个真正的子类(
TPopupMenuEx
)并在IDE中注册,添加一个FOnPopdown: TNotifyEvent
私有字段、一个DoPopdown
受保护函数和一个OnPopdown
发布属性,这样可以精确地模拟OnPopup
机制。不用说,这种方法也适用于
TTrayIcon
的菜单。klr1opcd2#
在较新版本(例如11.2 Alexandria)中,
TPopupMenu
具有内置OnClose
事件