PostMessage () успешно, но мой код обработки сообщений никогда не получает сообщение - PullRequest
9 голосов
/ 26 июня 2011

В объекте GUI моего приложения C ++ у меня в главном окне есть следующее:

case WM_SIZE:
    {
        OutputDebugString(L"WM_SIZE received.\n");
        RECT rect = {0};
        GetWindowRect(hwnd, &rect);
        if (!PostMessage(0, GUI_MSG_SIZECHANGED, w, MAKELONG(rect.bottom - rect.top, rect.right - rect.left))) {
            OutputDebugString(L"PostMessage failed.\n"); // <--- never called
        }
    }

    return 0; // break;

Объект GUI также имеет следующий метод getMessage ():

int GUI::getMessage(MSG & msg) {
    BOOL result = 0;

    while ((result = GetMessage(&msg, 0, 0, 0)) > 0) {
        if (msg.message > (GUI_MSG_BASE-1) && msg.message < (GUI_MSG_LAST+1)) {
            OutputDebugString(L"GUI message received.\n");
            break;
        }
        else {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }

    return result;
}

Объект приложения вызывает этот метод следующим образом:

while ((result = _gui.getMessage(msg)) > 0) {
    switch (msg.message) {
        // TODO: Add gui message handlers
        case GUI_MSG_SIZECHANGED:
            OutputDebugString(L"GUI_MSG_SIZECHANGED received.\n");
            _cfg.setWndWidth(HIWORD(msg.lParam));
            _cfg.setWndHeight(LOWORD(msg.lParam));
            if (msg.wParam == SIZE_MAXIMIZED)
                _cfg.setWndShow(SW_MAXIMIZE);
            else if (msg.wParam == SIZE_MINIMIZED)
                _cfg.setWndShow(SW_MINIMIZE);
            else if (msg.wParam == SIZE_RESTORED)
                _cfg.setWndShow(SW_SHOWNORMAL);
            break;
    }
}

Объект приложения интересуется размером окна, поскольку хранит эту информацию в файле конфигурации.

Когда я запускаю это в отладчике Visual Studio, окно вывода выглядит после изменения размера окна:

WM_SIZE received.
GUI message received.
GUI_MSG_SIZECHANGED received.
WM_SIZE received.
WM_SIZE received.
WM_SIZE received.
WM_SIZE received.
...etc...

Функция PostMessage () никогда не завершается с ошибкой, но, похоже, она отправляет только GUI_MSG_SIZECHANGED (#defined as WM_APP + 0x000d) при первой обработке WM_SIZE, что происходит сразу после обработки WM_CREATE.

Я понятия не имею, что может быть причиной этого. Я пытался использовать SendMessage и PostThreadMessage, но результат тот же. Также прочитайте документацию MSDN по обработке сообщений, но не можете найти, что не так с моим кодом.

Может ли кто-нибудь помочь?

1 Ответ

6 голосов
/ 26 июня 2011

Взлом собственной петли сообщений - это то, о чем вы когда-нибудь пожалеете. Ты ударил это рано.

Не публикуйте сообщения с дескриптором окна NULL, они могут работать только в том случае, если вы можете гарантировать, что ваша программа только когда-либо качает вашу пользовательскую петлю сообщений. Вы не можете сделать такую ​​гарантию. Эти сообщения попадают в корзину, как только вы начинаете диалог, или Windows решает прокачать сам цикл сообщений. В этом случае пользователь изменяет размер окна, логика изменения размера является модальной. Windows прокачивает свой собственный цикл сообщений, WM_ENTERSIZEMOVE объявляет об этом. Это также причина того, что PostThreadMessage является злом , если поток способен отображать любое окно. Даже MessageBox смертелен. DispatchMessage не может доставить сообщение.

Создать скрытое окно, которое действует как контроллер. Теперь вы можете обнаружить GUI_MSG_SIZECHANGED в его оконной процедуре, и никаких хаков в цикл сообщений не требуется. Этот контроллер нередко является главным окном вашего приложения.

...