Почему я не могу получить сообщение WM_DESTROY или WM_CLOSE вне оконной процедуры?

Я хотел зачитывать сообщения в моем цикле сообщений прямо перед отправкой их в свою оконную процедуру. Большинство сообщений, которые я пытался читать таким образом, были прочитаны правильно, но когда я закрывал окно, сообщение WM_CLOSE или WM_DESTROY не могло быть прочитано, так как казалось, что они никогда не были получены. Вот что я делаю:

void Framework::Run(){
while(running){

    MSG msg;
    while(PeakMessage(&msg, NULL, 0, 0)){
        TranslateMessage(&msg);
        switch(msg.message){
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            case WM_QUIT:
                running = false;
                break;
        //...other cases...
        }
        DispatchMessage(&msg);
    }
//...
}
}

Я ставлю точку останова в первом случае, но даже когда я закрываю окно (нажав «X»), точка останова никогда не срабатывает. Хотя, когда я проверяю WM_DESTROY в оконной процедуре, она считывается, и все идет нормально. Почему не вне его?

Отправляются ли такие сообщения непосредственно в оконный процесс? Как?


person The Light Spark    schedule 28.09.2014    source источник
comment
Где на самом деле работает этот цикл сообщений? В вашем экземпляре главного окна?   -  person πάντα ῥεῖ    schedule 28.09.2014
comment
Это не похоже на правильный цикл сообщений. Опубликуйте MCVE. GetMessage возвращает 0 на WM_QUIT, поэтому ваш цикл сообщений может вообще не оцениваться.   -  person Csq    schedule 28.09.2014
comment
Обычно вы обрабатываете сообщение внутри оконной процедуры, а не в цикле обработки сообщений. Преимущество этого заключается в том, что оно действительно относится к окну, в которое они отправляются.   -  person chris    schedule 28.09.2014
comment
@pάνταῥεῖ | мой цикл сообщений выполняется в экземпляре другого объекта, но этот же объект владеет оконной процедурой, в которой читается сообщение.   -  person The Light Spark    schedule 28.09.2014
comment
@TheLightSpark зарегистрирован как функция обратного вызова окна?   -  person Marco A.    schedule 28.09.2014
comment
@МаркоА. да очень хорошо.   -  person The Light Spark    schedule 28.09.2014
comment
На этом этапе отправьте код с MCVE.   -  person Marco A.    schedule 28.09.2014
comment
@ Марко, это нормально, что я только что отредактировал?   -  person The Light Spark    schedule 28.09.2014
comment
Наверное, контекст был бы лучше :)   -  person Marco A.    schedule 28.09.2014
comment
просто примечание: если вы на самом деле пишете свой собственный цикл сообщений, вы делаете что-то ужасно неправильное. Использование низкоуровневого API в Windows является ненужным и очень подверженным ошибкам, вы в настоящее время сталкиваетесь с результатами этой ошибки.   -  person specializt    schedule 28.09.2014
comment
Странно, что вы разместили поддельный код. PeakMessage нет. Это PeekMessage. Ваш цикл сообщений занят циклом. Я не знаю, почему вы отвергли GetMessage. Синхронные сообщения, такие как WM_DESTROY и WM_CLOSE, отправляются PeekMessage, GetMessage и т. д. PeekMessage, GetMessage возвращают асинхронные сообщения.   -  person David Heffernan    schedule 28.09.2014


Ответы (1)


Цикл сообщений видит только те сообщения, которые отправлены в очередь сообщений. Не все сообщения проходят через очередь сообщений. WM_DESTROY — одно из таких сообщений. Вместо этого вы должны обрабатывать сообщения в оконной процедуре, чтобы вы видели каждое сообщение, которое получает окно, независимо от того, прошло ли сообщение через очередь сообщений или нет.

Если вам нужно просмотреть сообщения для окна, которое вы не создаете сами, или для стандартного окна, имеющего системную оконную процедуру, вы можете подкласс окна с помощью SetWindowSubclass().

person Remy Lebeau    schedule 28.09.2014