激活系统菜单

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

以上是关于激活系统菜单的主要内容,如果未能解决你的问题,请参考以下文章

win10怎么激活

如何在 Windows 中取消“系统键关闭”状态

永久免费Win10企业版激活密钥大全系统天地

电脑系统windows10激活

如何使用最快速的方式激活windows10所有版本

无法使用 Angular.js 激活菜单栏