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

WM_HOTKEY消息未触发WinMain消息循环中的窗口大小调整

  •  0
  • xvymnp  · 技术社区  · 1 年前
    #ifndef UNICODE
    #define UNICODE
    #endif
    
    #define HOTKEY_REG_ERR -10
    
    #define HOTKEY_DEC_ID 1
    #define HOTKEY_INC_ID 2
    #define HOTKEY_CEN_ID 3
    
    #define WND_CHANGE_SIZE 50
    
    #include <windows.h>
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    LRESULT CALLBACK WindowProcAlt(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    SHORT            ResizeWindow(HWND hwnd, int widthChange, int heightChange);
    
    int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow) {
        // Register the window class.
        LPCWSTR mainWndClass = L"Sample Window Class ";
    
        WNDCLASS wc = {};
    
        wc.lpfnWndProc   = WindowProc;
        wc.hInstance     = hInstance;
        wc.lpszClassName = mainWndClass;
    
        RegisterClass(&wc);
    
        // Create the window.
    
        HWND hwnd = CreateWindowEx(
            0,                           // Optional window styles.
            mainWndClass,                // Window class
            L"Learn to Program Windows", // Window text
            WS_OVERLAPPEDWINDOW,         // Window style
    
            // Size and position
            CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
    
            NULL,      // Parent window
            NULL,      // Menu
            hInstance, // Instance handle
            NULL       // Additional application data
        );
    
        if (hwnd == NULL) {
            return 0;
        }
    
        ShowWindow(hwnd, nCmdShow);
    
        // Register hotkeys
    
        BOOL resultOne   = 0;
        BOOL resultTwo   = 0;
        BOOL resultThree = 0;
    
        if (!RegisterHotKey(NULL, HOTKEY_DEC_ID, MOD_CONTROL | MOD_SHIFT, '1')) {
            resultOne = -1;
        }
        if (!RegisterHotKey(NULL, HOTKEY_INC_ID, MOD_CONTROL | MOD_SHIFT, '2')) {
            resultTwo = -2;
        }
        if (!RegisterHotKey(NULL, HOTKEY_CEN_ID, MOD_CONTROL | MOD_SHIFT, '3')) {
            resultThree = -3;
        }
    
        // Run the message loop
    
        MSG msg = {};
    
        while (GetMessage(&msg, NULL, 0, 0) > 0) {
            UINT messageCode = msg.message;
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    
        return 0;
    }
    
    LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
        switch (uMsg) {
            case WM_DESTROY:
                PostQuitMessage(0);
                return 0;
    
            case WM_PAINT: {
                PAINTSTRUCT ps;
                HDC         hdc = BeginPaint(hwnd, &ps);
    
                // All painting occurs here, between BeginPaint and EndPaint.
    
                FillRect(hdc, &ps.rcPaint, (HBRUSH) (COLOR_WINDOW + 1));
    
                EndPaint(hwnd, &ps);
            }
                return 0;
    
            case WM_HOTKEY:
                switch (wParam) {
                    case HOTKEY_DEC_ID:
                        ResizeWindow(hwnd, -WND_CHANGE_SIZE, -WND_CHANGE_SIZE);
                        break;
    
                    case HOTKEY_INC_ID:
                        ResizeWindow(hwnd, WND_CHANGE_SIZE, WND_CHANGE_SIZE);
                        break;
    
                    case HOTKEY_CEN_ID:
                        break;
    
                    default:
                        break;
                }
                return 0;
        }
        return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    
    SHORT ResizeWindow(HWND hwnd, int widthChange, int heightChange) {
        if (hwnd == NULL) {
            return -1;
        }
        int  containerWidth, containerHeight, newWndWidth, newWndHeight, x, y;
        RECT rect;
        if (GetWindowRect(hwnd, &rect)) {
            RECT workArea = {};
    
            SystemParametersInfo(SPI_GETWORKAREA, NULL, &workArea, NULL);
    
            containerWidth  = workArea.right - workArea.left;
            containerHeight = workArea.bottom - workArea.top;
    
            newWndWidth  = rect.right - rect.left + widthChange;
            newWndHeight = rect.bottom - rect.top + heightChange;
    
            x = (containerWidth - newWndWidth) / 2;
            y = (containerHeight - newWndHeight) / 2;
    
            MoveWindow(hwnd, x, y, newWndWidth, newWndHeight, TRUE);
        } else {
            // std::cerr << "Failed to get window rect." << std::endl;
        }
    }
    
    

    起初,看起来WM_HOTKEY消息没有被发布。缺少窗口大小调整告诉了我这一点。我通过查看调试器中的resultOne、resultTwo和resultThree的值来确认我的密钥已正确注册,这些值都是0。然后我查看了消息循环,发现在消息循环中,msg.message成员是786=0x0312=WM_HOTKEY消息代码。也许我遗漏了一个线程问题?感谢您的帮助。

    1 回复  |  直到 1 年前
        1
  •  1
  •   Remy Lebeau    1 年前

    你的 WindowProc 未接收 WM_HOTKEY 消息,因为您没有在窗口中注册热键。

    这个 RegisterHotKey documentation 说:

    参数

    [in,可选]hWnd

    类型:HWND

    窗口的句柄,用于接收热键生成的WM_HOTKEY消息。 如果此参数为NULL,则WM_HOTKEY消息将被发布到调用线程的消息队列,并且必须在消息循环中进行处理。

    ...

    评论

    当按下某个键时,系统会查找与所有热键相匹配的项。找到匹配项后,系统将WM_HOTKEY消息发布到与热键相关联的窗口的消息队列。 如果热键与窗口不关联,则WM_HOTKEY消息将发布到与热键关联的线程。

    线程消息没有 HWND 分配给它,因此没有的窗口过程 DispatchMessage() 将消息发送到。

    因此,您必须处理 WM_HOTKEY 信息 直接地 在你的消息循环中(就像上面的文档所说的那样),例如:

    while (GetMessage(&msg, NULL, 0, 0)) {
        if (msg.message == WM_HOTKEY) {
            // do something ...
        }
        else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    

    否则,您将不得不执行以下操作之一,以便 WindowProc 可以接收 WM_HOTKEY 信息:

    • 只需通过您的 HWND RegisterHotKey() ,例如:

      RegisterHotKey(hwnd, ...)
      
    • 让您的消息循环转发消息到您的 HWND ,例如:

      while (GetMessage(&msg, NULL, 0, 0)) {
          if (msg.message == WM_HOTKEY) {
              SendMessage(hwnd, msg.message, msg.wParam, msg.lParam);
          }
          else {
              TranslateMessage(&msg);
              DispatchMessage(&msg);
          }
      }