After sending WM_CHANGEUISTATE to the window application, the mnemonics are not displayed in the system menu when the menu is accessed with the mouse

The code below sends WM_CHANGEUISTATE to the window procedure itself with arguments:

LOWORD (wParam) = UIS_CLEAR

HIWORD (wParam) = UISF_HIDEACCEL

lParam = 0x00000000

when the client window pane left clicked.

According to this blog post by Raymond Chen , this should do a mnemonic in the system menu, which will be displayed when the menu is accessed with the mouse. The following paragraph has been extracted from this article:

Deleting a flag shows the corresponding indicator. For example, if you have UIS_CLEAR for UISF_HIDEFOCUS, this means that you want to show focus indicators.

In my case, I have UIS_CLEAR for UISF_HIDEACCEL, which means that I want to show menu accelerators.

If you run the code below and left-click on the client area of ​​the application, you must make the accelerators visible in the System menu, even if this menu is accessible with the mouse. But this does not happen, i.e. If you activate the system menu by left-clicking on the window icon or by right-clicking on the window title bar, mnemonics in the system menu will not be displayed. What am I missing?

#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;
}
+4
source share
1 answer

/ Windows. DefWindowProc WM_QUERYUISTATE . , , .

WM_CHANGEUISTATE WM_UPDATEUISTATE WM_ENTERMENULOOP, WM_INITMENUPOPUP, WM_NCRBUTTONDOWN WM_SYSCOMMAND .

, , HTSYSMENU/icon, SC_MOUSEMENU SC_KEYMENU:

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

SC_KEYMENU DefWindowProc .

, ...

0

Source: https://habr.com/ru/post/1689371/


All Articles