gpt4 book ai didi

c++ - 向窗口应用程序发送 WM_CHANGEUISTATE 后,当使用鼠标访问菜单时,助记符不会显示在系统菜单上

转载 作者:可可西里 更新时间:2023-11-01 14:33:48 26 4
gpt4 key购买 nike

下面的代码向窗口过程本身发送一个 WM_CHANGEUISTATE,参数为:

LOWORD(wParam) = UIS_CLEAR

HIWORD(wParam) = UISF_HIDEACCEL

lParam = 0x00000000

当用鼠标左键单击窗口客户区时。

根据 this blog通过 Raymond Chen当使用鼠标访问菜单时,这应该会显示系统菜单中的助记符。以下段落摘自这篇文章:

Clearing a flag shows the corresponding indicator. For example, if you have a UIS_CLEAR for UISF_HIDE­FOCUS, that means that you want to show focus indicators.

在我的例子中,我有一个 UISF_HIDEACCEL 的 UIS_CLEAR,这意味着我想显示菜单加速器。

如果您运行下面的代码并在应用程序客户区上单击鼠标左键,您应该使加速器在系统菜单中可见,即使使用鼠标访问此菜单也是如此。但这不会发生,即,如果您通过左键单击窗口图标或右键单击窗口标题栏来激活系统菜单,系统菜单中的助记符将不会显示。我错过了什么?

#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
{
WNDCLASSEX wndclassx;
wchar_t szAppName[] = L"WM_CHANGEUISTATE";

wndclassx.cbSize = sizeof(WNDCLASSEX);
wndclassx.style = CS_HREDRAW | CS_VREDRAW;
wndclassx.lpfnWndProc = WndProc;
wndclassx.cbClsExtra = 0;
wndclassx.cbWndExtra = 0;
wndclassx.hInstance = hInstance;
wndclassx.hIcon = 0;
wndclassx.hCursor = LoadCursor(0, IDC_ARROW);
wndclassx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclassx.lpszClassName = szAppName;
wndclassx.lpszMenuName = nullptr;
wndclassx.hIconSm = 0;

if (!RegisterClassEx(&wndclassx)) return 0;

HWND hWnd = CreateWindow(szAppName, szAppName, WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0);

ShowWindow(hWnd, SW_MAXIMIZE);
UpdateWindow(hWnd);

MSG msg;
while (GetMessage(&msg, 0, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}

return (int)msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_LBUTTONUP:
{
BOOL b;

// Note that in my system (Windows 10) I have:
//
// Control Panel > Ease of Access > Ease of Access Center > Make the keyboard easier
//
// and the option "Underline keyboard shortcuts and access keys" unmarked (the default). Therefore, the value
// returned in b below will be 0x00000000 (FALSE).

SystemParametersInfo(SPI_GETKEYBOARDCUES, 0, &b, 0);

// If b = FALSE, the SendMessage() below should underline the accelerators in the System menu, when this menu is
// accessed with the mouse. But that doesn't work. Why?

if( !b ) SendMessage(hwnd, WM_CHANGEUISTATE, MAKEWPARAM(UIS_CLEAR, UISF_HIDEACCEL), NULL);
}
break;

// Setting a break in the return below, one can see that WM_CHANGEUISTATE message is being sent to the window and
// passed to DefWindowProc().

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


case WM_DESTROY:
PostQuitMessage(0);
break;

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

最佳答案

这似乎是 Windows 中的错误/疏忽。 DefWindowProc 在显示系统菜单之前不发送 WM_QUERYUISTATE。菜单实现直接检查最后一个输入事件,如果它来自键盘,它会显示下划线。

我尝试发送和发布 WM_CHANGEUISTATEWM_UPDATEUISTATE 以响应 WM_ENTERMENULOOPWM_INITMENUPOPUPWM_NCRBUTTONDOWN WM_SYSCOMMAND 没有任何运气。

我能想到的唯一解决方法是通过将 SC_MOUSEMENU 更改为 SC_KEYMENU 来破解 HTSYSMENU/icon 菜单:

case WM_SYSCOMMAND:
if ((wParam & 0xFFF0) == SC_MOUSEMENU)
{
return SendMessage(hwnd, WM_SYSCOMMAND, SC_KEYMENU, ' ');
}
return DefWindowProc(hwnd, message, wParam, lParam);

SC_KEYMENUDefWindowProc 中有特殊处理,并在适用时强制使用下划线。

这不处理右键单击图标、标题或任务栏...

关于c++ - 向窗口应用程序发送 WM_CHANGEUISTATE 后,当使用鼠标访问菜单时,助记符不会显示在系统菜单上,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47327246/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com