В чем разница между WM_QUIT, WM_CLOSE и WM_DESTROY в программе Windows?

Мне было интересно, в чем разница между сообщениями WM_QUIT, WM_CLOSE и WM_DESTROY в программе Windows, по сути: когда они отправляются и имеют ли они какие-либо автоматические эффекты, кроме того, что определено программой?


person Community    schedule 01.07.2010    source источник
comment
очень хороший квест   -  person bvs    schedule 12.05.2018


Ответы (5)


Они совершенно разные.

WM_CLOSE отправляется в окно, когда оно закрывается - когда нажата его кнопка X, или когда выбрано Close из меню окна, или Alt-F4 нажата, когда окно находится в фокусе, и т. Д. вы поймали это сообщение, это ваше решение, как с ним обращаться - игнорировать его или действительно закрыть окно. По умолчанию WM_CLOSE, переданный в DefWindowProc(), приводит к разрушению окна.

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

WM_NCDESTROY отправляется окну, когда оно завершает уничтожение. К этому времени все его дочерние окна были уничтожены.

WM_QUIT не имеет отношения к какому-либо окну (hwnd, полученный от GetMessage(), равен NULL, и никакая оконная процедура не вызывается). Это сообщение указывает на то, что цикл обработки сообщений должен быть остановлен, а приложение должно выйти. Когда GetMessage() читает WM_QUIT, он возвращает 0, чтобы указать на это. Взгляните на типичный фрагмент цикла сообщений - цикл продолжается, пока GetMessage() возвращает ненулевое значение.

WM_QUIT может быть отправлен функцией PostQuitMessage(). Эта функция обычно вызывается, когда главное окно получает WM_DESTROY (см. типичный фрагмент оконной процедуры).

person adf88    schedule 01.07.2010
comment
@ ad88 было бы здорово добавить, что происходит при выходе пользователя / WM_ENDSESSION. Это автоматически вызывает WM_CLOSE / QUIT / DESTROY? - person Basj; 22.07.2017
comment
Когда сеанс завершается, все оставшиеся окна, которые все еще существуют, просто уничтожаются ОС, им не отправляются сообщения _1 _ / _ 2_. У них есть последний шанс навести порядок, обработав WM_(QUERY)ENDSESSION. В конце концов, все ставки сняты. См. Windows не закрывает окна, когда пользователь выходит из системы; это ваш звонок - person Remy Lebeau; 17.12.2020

Прежде всего, WM_CLOSE и WM_DESTROY сообщения связаны с определенными окнами, тогда как WM_QUIT применимо ко всему приложению (поток скважины), и сообщение никогда не принимается через оконную процедуру (процедура WndProc), а только с помощью функций GetMessage или PeekMessage.

В вашей WndProc программе функция DefWindowProc заботится о поведении этих сообщений по умолчанию. Сообщения WM_CLOSE запрашивают, что приложение должно быть закрыто, и поведение по умолчанию для этого заключается в вызове функции DestroyWindow. Когда вызывается эта DestroyWindow функция, отправляется сообщение WM_DESTROY. Обратите внимание, что WM_CLOSE - это всего лишь сообщение с просьбой закрыть (например, WM_QUIT) - на самом деле вам не нужно выходить / выходить. Но сообщение WM_DESTROY сообщает вам, что ваше окно IS закрывается и уничтожается, поэтому вы должны очистить все ресурсы, дескрипторы и т. д.

person user353297    schedule 01.07.2010
comment
Не для всего приложения, а для конкретного цикла сообщений. Каждый поток может иметь свой собственный цикл сообщений, поэтому приложение может иметь несколько циклов сообщений. - person 0xC0000022L; 25.01.2018

Чтобы в комментариях не потерялось ... не забываем про WM_CANCEL. Когда вы нажимаете кнопку закрытия (x) в диалоговом окне MFC, он обязательно отправляет WM_CLOSE. Затем функция по умолчанию OnClose() вызовет функцию по умолчанию (базовый класс) OnCancel().

Однако, если вы просто наберете клавишу ESC, это приведет к закрытию диалога, но (насколько я могу судить) без генерации события WM_CLOSE - он перейдет непосредственно к механизму WM_CANCEL/OnCancel().

Настоящим я предлагаю сообществу подробно остановиться на этом ... или отредактировать это уточнение в принятом ответе.

person omatai    schedule 10.06.2015

Сначала обсудим WM_QUIT - отличие от других сообщений в том, что это не связано с окном. Используется приложением. Например, это может обрабатываться невидимым автономным сервером OLE (.exe, но не внутрипроцессным, как .dll)

WM_CLOSE - на msdn: «Приложение может запрашивать у пользователя подтверждение перед разрушением окна» - оно используется как уведомление о намерении закрыть (вы можете отклонить это намерение).

WM_DESTROY - это факт, что окно закрывается и все ресурсы должны (!) Быть освобождены.

person Dewfy    schedule 01.07.2010
comment
@atzz да, ты прав. Говоря в целом, это сообщение уведомляет цикл событий о прекращении обработки вообще, независимо от всего приложения или автономного потока. - person Dewfy; 01.07.2010

Я знаю, что это устарело, но просто пытаюсь дать более ясный ответ для всех.

// What causes each message?
WM_CLOSE:       // Pressed Close Button (X) / Alt+F4 / "Close" in context menu
WM_DESTROY:     // Called DestroyWindow(hwnd)
WM_QUIT:        // Called PostQuitMessage(exit)

// What do they do by default?
case WM_CLOSE: DestroyWindow(hwnd); return 0; // pressed close? destroy window.
case WM_DESTROY: PostQuitMessage(0); return 0; // destroyed window? quit message loop.
// WM_QUIT isn't associated with a window, so isn't sent to the window procedure

Итак, WM_CLOSE просто для того, чтобы мы могли запросить уничтожение окна. Однако вы можете захотеть, чтобы в вашей игре отображалось всплывающее окно с вопросом, уверены ли вы. (и если вы хотите сначала сэкономить)

И WM_DESTROY фактически не отправляет сообщение о выходе по умолчанию, поскольку у вас может быть несколько окон. Это обычное событие, после которого мы бросаем курить. Вы могли бы WM_CLOSE вызвать PostQuitMessage(exit) и уничтожить ваши окна после цикла сообщений, если хотите.

Если вам нужна пользовательская кнопка закрытия в вашей игре, она должна делать то, что делает WM_CLOSE.

Также есть функция CloseWindow(hwnd), но она просто минимизирует окно.

Надеюсь, это кому-нибудь поможет.

person Puddle    schedule 17.02.2021