代码之家  ›  专栏  ›  技术社区  ›  Ayrosa

我正在测试WM_MENUCHAR,但代码没有按预期工作

  •  3
  • Ayrosa  · 技术社区  · 8 年前

    下面的示例使用了一个只有系统菜单的应用程序窗口,我试图理解消息是如何显示的 WM_MENUCHAR 应该使用。这个 MSDN doc 因为信息上写着:

    当菜单处于活动状态且用户按下的键与任何助记符键或加速器键不对应时发送。此消息将发送到拥有菜单的窗口。

    Alt + A , Alt + B ,或者随便什么 发送到窗口过程。

    我假设Alt键激活系统菜单,因为所有WM\u MENUCHAR消息都发送到 WndProc() HIWORD(wParam) = MF_SYSMENU 消息被发送到窗口的原因是,程序没有加速器表,系统菜单也不包含任何助记符。

    这是我不清楚的一点:对 WM_MENUCHAR公司 MAKELPARAM(5, MNC_SELECT) 但是这个返回值不会调用 Close

    #include <windows.h>
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR pszCmdLine, int nCmdShow)
    {
        WNDCLASSEX  wndclassx;
    
        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 = L"WndProc";
        wndclassx.lpszMenuName = nullptr;
        wndclassx.hIconSm = 0;
    
        if (!RegisterClassEx(&wndclassx)) return 0;
    
        HWND hWnd = CreateWindow(L"WndProc", L"WM_MENUCHAR", 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_MENUCHAR:
            return MAKELPARAM(5, MNC_SELECT);
    
            case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
            default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   mnistic    8 年前

    MNC_SELECT仅“选择”低位词指定的菜单项,即如果您可以看到菜单,则该菜单项将突出显示。似乎毫无意义,不确定用例是什么。如果您想实际调用菜单项,可以使用MNC_EXECUTE。

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int count = 0;
        switch (message)
        {
        case WM_MENUCHAR:
            count = GetMenuItemCount((HMENU)lParam);
            if (count == 1)
                return MAKELRESULT(0, MNC_EXECUTE);
            else
                return MAKELRESULT(6, MNC_EXECUTE);
    
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }
    

    我相信以下内容显示了消息的全部预期用途,包括MNC\U SELECT和MNC\U EXECUTE。如果按住Alt键并继续按A,它将弹出系统菜单,并从上到下高亮显示其中的每个项目,直到到达最后一个项目(通常为“关闭”),然后执行。请注意,当它“选择”分隔符时,高亮显示“maximize”和高亮显示“close”之间有一个奇怪的节点。

    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
        int count = 0;
        static int selected = 1;
        switch (message)
        {
        case WM_MENUCHAR:
            count = GetMenuItemCount((HMENU)lParam);
            if (count == 1)
                return MAKELRESULT(0, MNC_EXECUTE);
            else
            {
                if (selected < count)
                    return MAKELRESULT(selected++, MNC_SELECT);
                else
                    return MAKELRESULT(count - 1, MNC_EXECUTE);
            }
    
        case WM_DESTROY:
            PostQuitMessage(0);
            break;
    
        default:
            return DefWindowProc(hwnd, message, wParam, lParam);
        }
        return 0;
    }