【问题标题】: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() 从客户端坐标转换。

标签: c++ winapi


【解决方案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
猜你喜欢
  • 2010-11-01
  • 2014-06-17
  • 1970-01-01
  • 2010-11-26
  • 1970-01-01
  • 2021-09-02
  • 1970-01-01
  • 2021-03-03
  • 1970-01-01
相关资源
最近更新 更多