Сообщение WM_HOTKEY не вызывает изменение размера окна в цикле сообщений WinMain

#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.
Возможно, есть проблема с потоками, которую я упускаю? Любая помощь приветствуется, спасибо.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
78
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ваш WindowProc не получает сообщения WM_HOTKEY, потому что вы не зарегистрировали горячие клавиши в своем окне.

В документации RegisterHotKey говорится:

Параметры

[in, необязательно] 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:

  • просто передайте свой HWNDRegisterHotKey(), например:

    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);
        }
    }
    

Я чувствую себя невероятно глупо. Большое спасибо. +1 за Гамбит.

xvymnp 25.06.2024 03:08

@xvymnp Это тоже часть ответа на этот вопрос . Вторая часть головоломки такова: Сообщения тредов съедаются модальными циклами (MessageBox() раскручивает модальный цикл сообщений). На этот вопрос вполне можно ответить, даже если трое разработчиков, не использующих Windows, не согласны с этим.

IInspectable 28.06.2024 19:53

Другие вопросы по теме