激活系统菜单
Posted
技术标签:
【中文标题】激活系统菜单【英文标题】:Activating the system menu 【发布时间】:2020-10-21 22:39:23 【问题描述】:我创建了一个没有标题/标题栏的自定义窗口。我在自定义菜单栏中添加了一个系统菜单图标/按钮。这是处理来自该按钮的命令的代码,我尝试访问系统菜单:
case ID_MENUBAR_SYS:
HMENU hSysMenu = GetSystemMenu(hWnd, FALSE);
TrackPopupMenu(hSysMenu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_LEFTBUTTON, 0, cyMenu, 0, hWnd, NULL);
按钮起作用,并显示系统菜单。但是,没有任何菜单项处于活动状态。我只是听到哔哔声,表示命令无效。假设GetSystemMenu()
只返回一个副本。如何访问到实际的系统菜单?
作为临时措施,我使用SendInput()
模拟Alt + Space。虽然这样可行,但实现需要一堆丑陋的代码。另外,这似乎是一种过于暴力的方法。
另外一个问题,为什么TrackPopupMenu()
使用屏幕坐标,而不是窗口坐标?我需要设置一个标志吗?
【问题讨论】:
当您说菜单项处于非活动状态时,您的意思是它们被禁用/重影吗?或者你可以选择它们吗?TrackPopupMenu()
使用屏幕坐标,因为它……就是这样。您可以使用ClientToScreen()
从客户端坐标转换。
【参考方案1】:
根据document:
hWnd
拥有快捷菜单的窗口句柄。此窗口接收来自菜单的所有消息。在函数返回之前,窗口不会收到来自菜单的 WM_COMMAND 消息。如果在 uFlags 参数中指定 TPM_NONOTIFY,则该函数不会向 hWnd 标识的窗口发送消息。但是,您仍然必须在 hWnd 中传递一个窗口句柄。它可以是您应用程序中的任何窗口句柄。
所以当你点击菜单选项时,你没有处理WM_COMMAND
中的消息。并且您可以在WM_COMMAND
中单独处理GetSystemMenu()
返回的副本,如下代码:
case WM_COMMAND:
if (wParam == SC_MINIMIZE)
ShowWindow(hwnd, SW_MINIMIZE);
return 0;
当然,您也可以将消息转发至WM_SYSCOMMAND
进行系统默认处理。可以参考以下代码:
case WM_COMMAND:
SendMessage(hwnd, WM_SYSCOMMAND, wParam, lParam);
return 0;
最后TrackPopupMenu
的文档说明弹出菜单可以在屏幕的任何位置,所以原来是这样设置的。
在指定位置显示快捷菜单并跟踪菜单上项目的选择。快捷菜单可以出现在屏幕的任何位置。
【讨论】:
谢谢朱松。通过SendMessage()
转发命令似乎是最好的解决方案。我不知道命令被发送到WM_COMMAND
,而不是WM_SYSCOMMAND
。以上是关于激活系统菜单的主要内容,如果未能解决你的问题,请参考以下文章