返回

WM_CHANGEUISTATE 导致系统菜单快捷键消失:如何解决?

windows

WM_CHANGEUISTATE 导致系统菜单快捷键消失:问题与解决方案

问题

在向窗口应用程序发送 WM_CHANGEUISTATE 消息后,当使用鼠标访问系统菜单时,快捷键将不会在菜单上显示。

问题背景

WM_CHANGEUISTATE 消息用于更新窗口的状态,例如禁用或隐藏系统菜单。通过设置 UISF_HIDEACCEL 标志,可以隐藏快捷键。当该标志设置后,即使使用鼠标访问菜单,也不会显示快捷键。

解决方案

要解决此问题,需要遵循以下步骤:

  1. 发送 WM_CHANGEUISTATE 消息清除 UISF_HIDEACCEL 标志:

    • 向窗口自身发送 WM_CHANGEUISTATE 消息,并使用 LOWORD(wParam) = UIS_CLEAR 和 HIWORD(wParam) = UISF_HIDEACCEL,以及 lParam = 0x00000000。
  2. 设置 WM_LBUTTONUP 事件处理程序:

    • 当左键单击窗口客户端区域时,会发送 WM_LBUTTONUP 消息。在该处理程序中,检查 UISF_HIDEACCEL 标志是否已清除,如果不是,则发送 WM_CHANGEUISTATE 消息以清除它。

代码示例

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case WM_LBUTTONUP:
        {
            BOOL b;
            SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &b, 0);
            if( !b ) SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL), NULL);
        }
        break;

        case WM_CHANGEUISTATE:
        return DefWindowProc(hwnd, message, wParam, lParam);

        case WM_DESTROY:
        PostQuitMessage(0);
        break;

        default:
        return DefWindowProc(hwnd, message, wParam, lParam);
    }
    return 0;
}

其他注意事项

  • 确保已将 UISF_HIDEACCEL 标志设置为 UIS_CLEAR 的值。
  • 检查系统参数 SPI_GETKEYBOARDCUES 以确保未设置“在快捷键和访问键上加下划线”选项。

结论

通过按照上述步骤,可以在发送 WM_CHANGEUISTATE 消息后继续在系统菜单上显示快捷键。这在需要隐藏或禁用菜单,但仍希望在使用鼠标时访问快捷键的情况下非常有用。

常见问题解答

Q1:为什么在发送 WM_CHANGEUISTATE 消息后快捷键消失?

A1:UISF_HIDEACCEL 标志已被设置为隐藏快捷键。

Q2:如何清除 UISF_HIDEACCEL 标志?

A2:使用 WM_CHANGEUISTATE 消息,设置 LOWORD(wParam) = UIS_CLEAR 和 HIWORD(wParam) = UISF_HIDEACCEL。

Q3:在 WM_CHANGEUISTATE 消息中设置的 lParam 参数有什么作用?

A3:lParam 参数未使用,因此可以设置为 0x00000000。

Q4:为什么在 WM_LBUTTONUP 事件处理程序中检查 UISF_HIDEACCEL 标志?

A4:如果在鼠标左键单击窗口时该标志未被清除,则再次发送 WM_CHANGEUISTATE 消息以清除它。

Q5:如何确保在菜单上显示快捷键?

A5:检查系统参数 SPI_GETKEYBOARDCUES 以确保未设置“在快捷键和访问键上加下划线”选项。