【发布时间】:2011-03-10 12:08:16
【问题描述】:
我想知道 Windows 程序中的 WM_QUIT、WM_CLOSE 和 WM_DESTROY 消息有什么区别,本质上是:它们是什么时候发送的,除了程序定义的之外,它们是否有任何自动效果?
【问题讨论】:
-
非常好的任务
我想知道 Windows 程序中的 WM_QUIT、WM_CLOSE 和 WM_DESTROY 消息有什么区别,本质上是:它们是什么时候发送的,除了程序定义的之外,它们是否有任何自动效果?
【问题讨论】:
它们完全不同。
WM_CLOSE 在窗口关闭时被发送到窗口——当点击它的“X”按钮,或者从窗口的菜单中选择“关闭”,或者按下 Alt-F4当窗口有焦点时,等等。如果您收到此消息,这是您如何处理它的决定 - 忽略它,或者真正关闭窗口。默认情况下,WM_CLOSE 传递给 DefWindowProc() 会导致窗口被销毁。
WM_DESTROY 在窗口开始被销毁时被发送到窗口。在这个阶段,与WM_CLOSE相反,你不能停止进程,你只能做任何必要的清理。当你捕捉到WM_DESTROY 时,它的子窗口还没有被销毁。
WM_NCDESTROY 在完成销毁时发送到窗口。此时它的所有子窗口都已销毁。
WM_QUIT 与任何窗口都不相关(从GetMessage() 得到的hwnd 为NULL,不调用任何窗口过程)。此消息指示应停止消息循环并退出应用程序。当GetMessage() 读取WM_QUIT 时,它返回0 来表示。看看a typical message loop snippet - 当GetMessage() 返回非零时循环继续。
WM_QUIT 可以通过PostQuitMessage() 函数发送。该函数通常在主窗口收到WM_DESTROY时调用(见a typical window procedure snippet)。
【讨论】:
WM_ENDSESSION 到达时发生的情况。这会自动触发 WM_CLOSE / QUIT / DESTROY 吗?
WM_CLOSE/WM_DESTROY 消息发送给它们。他们有最后的机会通过处理WM_(QUERY)ENDSESSION 进行清理。毕竟,所有的赌注都没有了。见Windows doesn't close windows when a user logs off; that's your call
首先,WM_CLOSE 和WM_DESTROY 消息与特定窗口相关联,而WM_QUIT 消息适用于整个应用程序(井线程),并且消息永远不会通过窗口过程接收(@987654329 @routine),但只能通过 GetMessage 或 PeekMessage 函数。
在您的WndProc 例程中,DefWindowProc 函数负责处理这些消息的默认行为。 WM_CLOSE 消息请求关闭应用程序,默认行为是调用DestroyWindow 函数。当调用此DestroyWindow 函数时,将发送WM_DESTROY 消息。请注意,WM_CLOSE 只是一条要求您关闭的消息(如WM_QUIT) - 您实际上不必退出/退出。但是WM_DESTROY 消息告诉您,您的窗口IS 被关闭并销毁,因此您必须清理所有资源、句柄等。
【讨论】:
只是这样它就不会在 cmets 中丢失...不要忘记 WM_CANCEL。当您单击 MFC 对话框上的关闭 (x) 按钮时,它肯定会发送WM_CLOSE。然后默认的OnClose() 函数将调用默认的(基类)OnCancel() 函数。
但是,如果您只是键入 ESC 键,这将导致对话框关闭,但是(据我所知)不会生成 WM_CLOSE 事件 - 它直接转到 WM_CANCEL/OnCancel()机制。
我特此邀请社区对此进行详细说明...或将详细说明编辑为已接受的答案。
【讨论】:
首先让我们讨论一下 WM_QUIT - 与其他消息的不同之处在于它与窗口无关。它由应用程序使用。例如,这可以由不可见的独立 OLE 服务器(.exe,但不能在进程内作为 .dll)处理
WM_CLOSE - per msdn:“应用程序可以在销毁窗口之前提示用户确认” - 它用作关闭意图的通知(您可以拒绝此意图)。
WM_DESTROY - 窗口正在关闭,所有资源必须(!)被释放。
【讨论】:
我知道这是旧的,但只是想为任何人提供更清晰的答案。
// 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)函数,不过它只是将窗口最小化。
希望这对任何人都有帮助。
【讨论】: