右键单击任何菜单项时如何获取 MenuItem 名称?
Posted
技术标签:
【中文标题】右键单击任何菜单项时如何获取 MenuItem 名称?【英文标题】:How to get the MenuItem name when right-clicking any menu item? 【发布时间】:2021-12-30 02:45:05 【问题描述】:在 Windows 10 上的 32 位 Delphi 11 VCL 应用程序中,当右键单击任何菜单项时,我需要获取单击的 MenuItem 的名称。
我使用TApplicationEvents
组件和此代码在我单击任何菜单项时收到通知:
procedure TformMain.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
Winapi.Messages.WM_COMMAND:
begin
CodeSite.Send('TformMain.ApplicationEvents1Message: WM_COMMAND');
end;
end;
end;
但是:
如何仅在右键单击菜单项时获得通知?
如何获取被点击的MenuItem的NAME?
【问题讨论】:
WM_COMMAND
在选择菜单项时发出(即左键单击)。要允许右键单击选择菜单项,必须使用 TPM_RIGHTBUTTON
标志(默认情况下不是)调用 TrackPopupMenu/Ex()
。要检测菜单项上的右键单击,您必须通过使用 TPM_RECURSE
标志调用 TrackPopupMenuEx()
来显示菜单,然后将 WM_MENURBUTTONUP
消息处理到菜单的所有者窗口。
相关/欺骗:Detect left/right mouse button on menu item click?
【参考方案1】:
每个TMenu(即TMainMenu或TPopupMenu)都提供了一个方法FindItem,它可以让你找到一个项目按不同的标准。在您的情况下,对表单主菜单的正确调用是
TheMenuItem := Menu.FindItem(Msg.wParam, fkCommand);
【讨论】:
感谢您的信息。但是如何获取 TMenu(即 TMainMenu 或 TPopupMenu)名称呢? @user1580348 为什么需要这个名字? Menu 是 TForm 的属性。 @user1580348 表单本身具有分配TMainMenu
或TPopupMenu
的属性 - 只需尝试其中一个。否则枚举所有控件。
检测当前打开了哪个菜单(TMainMenu 或 TPopupMenu)会很有用。可以使用EnumThreadWindows
来实现吗?【参考方案2】:
由于我的应用程序中有多个表单,并且每个表单上有多个(弹出)菜单,因此这里需要一个特殊的解决方案:
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG; var Handled: Boolean);
begin
case Msg.message of
Winapi.Messages.WM_COMMAND:
begin
// Todo: Check HERE for RightMouseButtonDown - BUT HOW? (Or how to check HERE for modifier keys?)
var ThisMenuItem := GetMenuItem(Msg.wParam);
if Assigned(ThisMenuItem) then
begin
CodeSite.Send('TForm1.ApplicationEvents1Message: Clicked MenuItem Name', ThisMenuItem.Name);
end;
end;
end;
end;
function TForm1.GetMenuItem(const aWParam: NativeUInt): TMenuItem;
var
ThisMenuItem: TMenuItem;
begin
Result := nil;
var ThisForm := Screen.ActiveForm; // works on any form in the application
for var i := 0 to ThisForm.ComponentCount - 1 do
begin
if ThisForm.Components[i] is TMenu then
begin
ThisMenuItem := TMenu(ThisForm.Components[i]).FindItem(aWParam, fkCommand);
if Assigned(ThisMenuItem) then
begin
Result := ThisMenuItem;
EXIT;
end;
end;
end;
end;
【讨论】:
是的:如果可以立即使用result
(在函数中),为什么还要使用单独的变量?
程序员经常使用单独的变量来让非程序员更容易理解代码。
否:The myth of increased readability。写if result<> nil then exit;
会更清楚。甚至ThisMenuItem
这个名字也是错误的,因为它与任何“this”都没有关系,如果不是Item
,最多应该命名为FoundItem
。反问:为什么不选择ThisFormMenuItem
?
你为什么对我的变量名感兴趣?
您的答案的早期版本包括“任何优化?”,因此是我的 cmets。此答案也仅重复 Uwe Raabe 根据您的问题已经回答的内容 - 您的后续请求不在原始问题中,但您选择了自己的“正确”。不要忽视其他人的贡献,不要忽视这是公共领域,而不是“你的”代码——现在每个人都可以使用它(就像每个人的帮助都对你可用一样)。以上是关于右键单击任何菜单项时如何获取 MenuItem 名称?的主要内容,如果未能解决你的问题,请参考以下文章