PostQuitMessage()和DestroyWindow()之间的逻辑区别是什么?

20

在我的示范应用中

case WM_CLOSE:
    DestroyWindow(hndl);
    return 0;

case WM_CLOSE:
    PostQuitMessage(0);
    return 0;

执行相同的操作。当调用它们时,幕后有何不同之处?是DestroyWindow更直接,而PostQuitMessage必须通过getmessage循环返回false吗?


5
考虑一个具有多个窗口的应用程序可能会发生什么情况。DestroyWindow销毁一个窗口。PostQuitMessage会发布一个退出消息:即它表明整个应用程序想要退出。 - jalf
@jalf,我正在将它编辑到我的答案中:p - chris
@chris和我刚刚给你的回答点了赞。 :) - jalf
4
当你刚开始接触Win32 API时,很难立刻明确“我的窗口”和“我的应用程序”的区别。消息泵API在这方面并不是非常清晰或有帮助的。但是要意识到两者之间存在区别是很重要的。你想关闭窗口还是退出应用程序? - jalf
3个回答

25

DestroyWindow函数销毁窗口并在消息队列中发送WM_DESTROY(同时也会收到一个 WM_NCDESTROY)。这是WM_CLOSE的默认行为。但是,仅仅因为一个窗口被销毁了并不意味着消息循环应该结束。例如,在关闭特定窗口时结束应用程序而在关闭其他窗口时不影响应用程序(例如选项页面)。

PostQuitMessage函数向消息队列中发布WM_QUIT,通常会导致消息循环结束。例如,当获取到WM_QUIT时,GetMessage函数将返回0。通常在主窗口的WM_DESTROY处理程序中调用此函数。这不是默认行为,您需要自己执行。


17

两种代码片段都不正确。第一个片段将执行默认窗口过程在处理WM_CLOSE消息时所做的操作,因此是多余的。但它并不会使应用程序退出,应该继续运行,通常需要使用Debug + Stop Debugging强制停止调试器。如果你没有使用调试器运行它,那么进程将继续运行,但没有窗口,因此无法判断它是否仍在运行。使用任务管理器(Taskmgr.exe),进程选项卡可以查看这些僵尸进程。

第二个代码片段将终止应用程序,但由于没有将WM_CLOSE消息传递给默认窗口过程,因此不会正确清理。窗口不会被销毁,尽管操作系统会为您清理,但没有任何优雅的加分点。

正确的方法是在主窗口被销毁时退出。当发生这种情况时,您将收到发送的WM_DESTROY通知:

case WM_DESTROY:
    PostQuitMessage(0);
    return 0;

谢谢您的回答!据我所知,WM_CLOSE 中的 DestroyWindow() 函数会检查是否要关闭主应用程序窗口(父窗口),如果是,则发出 WM_DESTROY 消息。否则,只有(子)窗口本身被关闭,应用程序仍在运行。 - rails_has_elegance
3
任何一个窗口在被销毁时都会发送WM_DESTROY消息,Windows本身对一个窗口没有特别的偏好,即使一个应用程序没有窗口也可以。因此,你需要对发送该消息的特定窗口感兴趣。如果主窗口被销毁并且没有其他窗口存在,那么你应该退出程序,因为用户无法再进行任何有用的操作。当你收到该窗口的WM_DESTROY消息时,通过调用PostQuitMessage实现退出程序。 - Hans Passant
非常抱歉如果我误解了,但是如果每次窗口(例如子窗口)关闭时都会发送WM_DESTROY消息,那么这是否意味着您总是退出循环并退出应用程序?如果WM_DESTROY来自主窗口,哪里的逻辑会专门发出PostQuitMessage(0)命令? - rails_has_elegance
子窗口有自己的窗口过程,它不使用您的窗口过程。 - Hans Passant
天哪,当然是这样,我怎么会混淆呢。对于所有那些问题,抱歉了。 - rails_has_elegance

0

PostQuitMessage并不一定意味着应用程序的结束。它只是将WM_QUIT发布到消息循环并允许您退出消息循环,因此在大多数情况下,这意味着应用程序的结束。但是,在多线程应用程序中,如果为每个线程创建了消息循环,则PostQuitMessage仅关闭该线程。

作为副笔,如果您需要在消息循环之后执行更多行代码(例如进一步的清理),那么PostQuitMessage是更好的选择,因为DestroyWindow会在不经过消息循环的情况下销毁窗口,并忽略消息循环后剩余的任何清除代码。有些人可能认为这不是很好的编码实践,但有时您无法避免这种情况。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接