WM_CHANGEUISTATE 导致系统菜单快捷键消失:如何解决?
2024-03-26 17:04:33
WM_CHANGEUISTATE 导致系统菜单快捷键消失:问题与解决方案
问题
在向窗口应用程序发送 WM_CHANGEUISTATE 消息后,当使用鼠标访问系统菜单时,快捷键将不会在菜单上显示。
问题背景
WM_CHANGEUISTATE 消息用于更新窗口的状态,例如禁用或隐藏系统菜单。通过设置 UISF_HIDEACCEL 标志,可以隐藏快捷键。当该标志设置后,即使使用鼠标访问菜单,也不会显示快捷键。
解决方案
要解决此问题,需要遵循以下步骤:
-
发送 WM_CHANGEUISTATE 消息清除 UISF_HIDEACCEL 标志:
- 向窗口自身发送 WM_CHANGEUISTATE 消息,并使用 LOWORD(wParam) = UIS_CLEAR 和 HIWORD(wParam) = UISF_HIDEACCEL,以及 lParam = 0x00000000。
-
设置 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 以确保未设置“在快捷键和访问键上加下划线”选项。