【问题标题】:What's the logical difference between PostQuitMessage() and DestroyWindow()?PostQuitMessage() 和 DestroyWindow() 之间的逻辑区别是什么?
【发布时间】:2013-05-25 11:41:30
【问题描述】:

在我的演示应用中

case WM_CLOSE:
    DestroyWindow(hndl);
    return 0;

和

case WM_CLOSE:
    PostQuitMessage(0);
    return 0;

做同样的事情。每次打电话时,窗帘后面有什么不同? DestroyWindow 是否更直接,因为 PostQuitMessage 必须通过返回 false 的 getmessage 循环?

【问题讨论】:

  • 考虑在具有多个窗口的应用程序中可能发生的情况。 DestroyWindow 破坏一个窗口。 PostQuitMessage... 发布退出消息:即表示整个应用程序要退出。
  • @jalf,我只是将其编辑到我的答案中:p
  • @chris 和我刚刚对你的回答投了赞成票。 :)
  • 当您刚接触 Win32 API 时,“我的窗口”和“我的应用程序”之间的界线不是很明显。消息泵 API 在那里真的不是很清楚或没有帮助。但重要的是要认识到两者之间存在区别。您要关闭窗口,还是退出应用程序?

标签: c++ windows winapi


【解决方案1】:

DestroyWindow 破坏窗口(惊喜)并将WM_DESTROY(您还将获得WM_NCDESTROY)发布到消息队列。这是WM_CLOSE 的默认行为。然而,仅仅因为一个窗口被销毁并不意味着消息循环应该结束。如果有一个特定的窗口在关闭时结束应用程序,而其他窗口在关闭时对应用程序不做任何事情(例如,选项页面),就会出现这种情况。

PostQuitMessage 将WM_QUIT 发布到消息队列,通常会导致消息循环结束。例如,GetMessage 在拉出 WM_QUIT 时将返回 0。这通常会在主窗口的WM_DESTROY 处理程序中调用。这不是默认行为;你必须自己做。

【讨论】:

    【解决方案2】:

    sn-p 都不正确。第一个将执行默认窗口过程在处理 WM_CLOSE 消息时已经执行的操作,因此是多余的。但是不会以其他方式使应用程序退出,它应该继续运行,并且您通常必须使用 Debug + Stop Debugging 强制调试器停止。如果您在没有调试器的情况下运行它,那么您将保持进程运行但没有窗口,因此您无法判断它仍在运行。使用 Taskmgr.exe,进程选项卡查看那些僵尸进程。

    第二个 sn-p 将终止应用程序,但不会正确清理,因为您没有将 WM_CLOSE 消息传递给默认窗口过程。窗户不会被破坏。尽管操作系统会为您清理,所以这一切都结束了,只是没有任何优雅的加分。

    正确的方法是在主窗口被销毁时退出。您会从发生这种情况时发送的 WM_DESTROY 通知中了解它:

    case WM_DESTROY:
        PostQuitMessage(0);
        return 0;
    

    【讨论】:

    • 感谢您的回答!因此,根据我的理解,WM_CLOSE 中的 DestroyWindow() 函数检查它是否是应关闭的主应用程序窗口(父窗口),如果为真,它会发出 WM_DESTROY 消息。否则只有(子)窗口本身被关闭并且应用程序继续运行。
    • 不,任何窗口在被销毁时都会发送 WM_DESTROY。 Windows 本身对窗口没有特别的偏好,完全没有窗口的应用程序也可以。因此,您的工作就是对发送该消息的特定 窗口感兴趣。如果它是你的主窗口被破坏并且没有留下任何东西,那么你应该退出你的程序,因为用户不能再做任何有用的事情了。当您获得该窗口的 WM_DESTROY 时,您可以通过调用 PostQuitMessage 来执行此操作。
    • 如果我误解了我很抱歉,但是如果每次关闭窗口(例如孩子)时有效,它会发送一个 WM_DESTROY,这并不总是意味着你退出循环并退出应用程序?如果 WM_DESTROY 来自主窗口,那么专门发出 PostQuitMessage(0) 的逻辑在哪里?
    • 子窗口有自己的窗口过程,它不使用你的。
    • omg 当然,我是怎么混淆的。抱歉所有这些问题
    【解决方案3】:

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

    附带说明,如果您需要在消息循环之后执行更多代码行(例如进一步清理),PostQuitMessage 是一种更好的方法,因为 DestroyWindow 会在不经过消息循环的情况下销毁窗口,忽略消息循环后剩余的任何清理代码。有些人可能会说这是一种不太好的编码实践,但有时你无法避免这样的情况。

    【讨论】:

      猜你喜欢
      • 2019-06-08
      • 1970-01-01
      • 1970-01-01
      • 2016-03-18
      • 2020-09-07
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多