如何检测右键单击 WM_MENURBUTTONUP 的 TMenuItem?
How to detect right-click on a TMenuItem with WM_MENURBUTTONUP?
在 Windows 10 上的 32 位 Delphi 11 VCL 应用程序中,我使用 TApplicationEvents
组件来捕获 Windows 消息。不幸的是,当我右键单击 TPopupMenu
MenuItem:
时,TApplicationEvents
似乎对 WM_MENURBUTTONUP
消息没有反应
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
Winapi.Messages.WM_MENURBUTTONUP: CodeSite.Send('TForm1.ApplicationEvents1Message: WM_MENURBUTTONUP');
end;
end;
WM_MENURBUTTONUP message
Sent when the user releases the right mouse button while the cursor is on a menu item.
作为替代方案,WM_COMMAND
与左键和右键单击一起发送。但是,出于特定目的,我只需要在右键单击菜单项时做出反应。
documentation 中引用的部分解释了为什么您没有看到此消息:
Sent when the user [...]
TApplicationEvents.OnMessage
事件只能检测到已发布 条消息,不能检测到已发送 条消息。
TMainMenu
所以如果你想检测这个消息,你可以添加
protected
procedure WndProc(var Message: TMessage); override;
到你的表单class,实现如下:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
ShowMessage('rbu')
else
inherited
end;
尝试,例如:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
var MI := Menu.FindItem(Message.LParam, fkHandle);
if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
end
else
inherited
end;
TPopupMenu
对于TPopupMenu
,你需要写你自己的TPopupList
后代:
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage); override;
end;
{ TPopupListEx }
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
ShowMessage('rbu')
else
inherited
end;
initialization
FreeAndNil(PopupList);
PopupList := TPopupListEx.Create;
并确保将 TPopupMenu
的 TrackButton
设置为 tbLeftButton
。
如果您有多个弹出菜单,您可以尝试这样的操作(未完全测试):
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
for var X in PopupList do
if TObject(X) is TPopupMenu then
begin
OutputDebugString(PChar(TPopupMenu(X).Name));
var MI: TMenuItem;
if TPopupMenu(X).Handle = HMENU(Message.LParam) then
MI := TPopupMenu(X).Items
else
MI := TPopupMenu(X).FindItem(HMENU(Message.LParam), fkHandle);
if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
begin
ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
Break;
end;
end;
end
else
inherited
end;
在 Windows 10 上的 32 位 Delphi 11 VCL 应用程序中,我使用 TApplicationEvents
组件来捕获 Windows 消息。不幸的是,当我右键单击 TPopupMenu
MenuItem:
TApplicationEvents
似乎对 WM_MENURBUTTONUP
消息没有反应
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
Winapi.Messages.WM_MENURBUTTONUP: CodeSite.Send('TForm1.ApplicationEvents1Message: WM_MENURBUTTONUP');
end;
end;
WM_MENURBUTTONUP message
Sent when the user releases the right mouse button while the cursor is on a menu item.
作为替代方案,WM_COMMAND
与左键和右键单击一起发送。但是,出于特定目的,我只需要在右键单击菜单项时做出反应。
documentation 中引用的部分解释了为什么您没有看到此消息:
Sent when the user [...]
TApplicationEvents.OnMessage
事件只能检测到已发布 条消息,不能检测到已发送 条消息。
TMainMenu
所以如果你想检测这个消息,你可以添加
protected
procedure WndProc(var Message: TMessage); override;
到你的表单class,实现如下:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
ShowMessage('rbu')
else
inherited
end;
尝试,例如:
procedure TForm1.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
var MI := Menu.FindItem(Message.LParam, fkHandle);
if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
end
else
inherited
end;
TPopupMenu
对于TPopupMenu
,你需要写你自己的TPopupList
后代:
type
TPopupListEx = class(TPopupList)
protected
procedure WndProc(var Message: TMessage); override;
end;
{ TPopupListEx }
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
ShowMessage('rbu')
else
inherited
end;
initialization
FreeAndNil(PopupList);
PopupList := TPopupListEx.Create;
并确保将 TPopupMenu
的 TrackButton
设置为 tbLeftButton
。
如果您有多个弹出菜单,您可以尝试这样的操作(未完全测试):
procedure TPopupListEx.WndProc(var Message: TMessage);
begin
if Message.Msg = WM_MENURBUTTONUP then
begin
for var X in PopupList do
if TObject(X) is TPopupMenu then
begin
OutputDebugString(PChar(TPopupMenu(X).Name));
var MI: TMenuItem;
if TPopupMenu(X).Handle = HMENU(Message.LParam) then
MI := TPopupMenu(X).Items
else
MI := TPopupMenu(X).FindItem(HMENU(Message.LParam), fkHandle);
if Assigned(MI) and InRange(Message.WParam, 0, MI.Count - 1) then
begin
ShowMessageFmt('Menu item "%s" right clicked.', [MI.Items[Message.WParam].Caption]);
Break;
end;
end;
end
else
inherited
end;