Ситуация такая: приложение можно "легально" завершить двумя способами- отправить окну WM_DESTROY "стандартными средствами"(alt+F4 или красный крестик вверху) или выбрать в меню соответствующий пункт. Пункт меню обрабатывается так: Код (Text): switch(uMsg) { case WM_COMMAND: { switch(LOWORD(wParam)) { case MENU_EXIT: { PostQuitMessage(0); MessageBox(g_hWnd,L"MENU_EXIT",L"",MB_OK); return 0; } ... } ... } ... } Тут всё выполняется корректно. А обработчик WM_DESTROY выглядит так: Код (Text): case WM_DESTROY: { MessageBox(g_hWnd,L"WM_DESTROY до",L"",MB_OK); PostQuitMessage(0); MessageBox(g_hWnd,L"WM_DESTROY после",L"",MB_OK); return 0; } А вот тут сообщение "WM_DESTROY до" появляется, а "WM_DESTROY после"- нет. И вообще весь код после этого PostQuitMessage игнорируется. Хотя встроенный отладчик VS2010 показывает, что этот код выполняется(прерывания срабатывают и трассировка внешне проходит нормально). Сам цикл выглядит так: Код (Text): Msg.message=0; SetTimer(NULL,0,1000,TimerFunction); while(Msg.message!=WM_QUIT) { if(PeekMessage(&Msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&Msg); DispatchMessage(&Msg); } if(!DoFrame()) break; } MessageBox(g_hWnd,L"",L"",MB_OK);//Сообщение не выводится. FreeMouse(); FreeDirect3D(); FreeWindow(); return Msg.wParam; Подскажите пожалуйста, в чём может быть дело?
Euler Долго медитировал над Вашим кодом, и тут внезапно вспомнил, что года полтора назад у меня была та же проблема. В некоторых местах программы в силу неведомых мне причин MessageBox отказывался выдавать сообщения. Но сейчас, помедитировав, подумал, что первый параметр, передаваемый в MessageBox некорректный.
красный крестик и alt+f4 это wm_close а не wm_destroy в ответ можно или вернуть 0 тогда приложение не закроется или отдать в defwindowproc что Вы и делаете defwindowproc на wm_close вызывает destroywindow и ставит в очередь wm_destroy когда после обработки wm_close вы обрабатываете wm_destroy окно уже разрушено и g_hWnd уже к этому времени не валидный
Код (Text): switch(LOWORD(wParam)) { case MENU_EXIT: { PostQuitMessage(0); MessageBox(g_hWnd,L"MENU_EXIT",L"",MB_OK); return 0; } ... } Вы выходите не освождая память и не разрушая окно лучше так Код (Text): switch(LOWORD(wParam)) { case MENU_EXIT: { SendMessage(hWnd, WM_CLOSE, 0, 0); MessageBox(g_hWnd,L"MENU_EXIT",L"",MB_OK); return 0; } ... } defwindowproc вызовет destroywindow поставит в очередь wm_destroy потом вернет вам управление у вас выведется messagebox следующим вы достанете wm_destroy и сделаете postquitmessage
В wm_destroy окно еще не разрушено, а просто скрыто - и дело не в этом, а в том, что после PostQuitMessage вызывать диалог бесполезно, т.к. он даже не появившись получит это самое сообщение WM_QUIT и закроется, повторно послав WM_QUIT в очередь
Euler а у вас при отладке в окне watch есть @err,hr ? а то он сразу выводит статус последней ошибки MessageBox(0x456, "", "", 0); @err,hr 0x00000578 Недопустимый дескриптор окна. unsigned long
Перечитай мсдн - wm_destroy посылается именно из DestroyWindow после сокрытия окна, но до его разрушения. И первый пост кстати тоже внимательно перечитай - первый MessageBox до PostQuitMessage отображается нормально, поэтому дело не в окне
osox Ну тебя, брат, понесло под аплодисменты Тогда получи ложечку критики. МСДН это конечно хорошо, но нужно и свою "соображалку включать" - сам подумай, как окно может быть уже разрушено, если wm_destroy шлется ни кому-нибудь, а самому этому окну ? И соотв-но в его WindowProc передается хэндл, который должен быть еще валидным, хотя бы для того, чтобы вызвать родительскую процедуру CallWindowProc или DefWindowProc. Да и wm_destroy для дочерних окон, вызываются после. И т.д. и т.п.
Всё понял, огромное спасибо за ваши ответы. leo, вам отдельная благодарность за развёрнутые ответы- очень часто ваши посты на этом форуме помогали мне решать свои задачи.