【问题标题】:Intercept WM_CLOSE for cleanup operations拦截 WM_CLOSE 进行清理操作
【发布时间】:2014-02-03 06:28:36
【问题描述】:

我有一个外部应用程序调用我的应用程序,并且应该在工作完成后结束它。这个外部应用程序的日志声称它在我的应用程序上使用了WM_CLOSE

如何在我的应用程序中拦截WM_CLOSE 消息以进行一些清理操作?我尝试了at_exit() 并将其包装在一个类中,但我认为我的方法有误。

【问题讨论】:

  • 你在你的应用程序中使用了某种框架吗?是否有要覆盖的 OnClose 函数?
  • 您的应用程序是否有一个消息循环来处理其他 Windows 消息?
  • 不,到目前为止它只是一个控制台应用程序。

标签: c++ winapi exit termination


【解决方案1】:

控制台应用的官方解决方案是HandlerRoutine,由SetConsoleCtrlHandler设置的回调。在WM_CLOSE 退出的情况下,Windows 将使用CTRL_CLOSE_EVENT 参数调用您的处理程序。

当您使用 SetConsoleCtrlHandler 的类方法时,它必须是 static 方法 - Windows 不会为您提供 this 指针。

【讨论】:

  • 感谢补充,不过我成功改成了winapi应用。如果它不能以这种方式解决,我可能会尝试你的方法。
【解决方案2】:

您可以只在消息循环中处理 WM_CLOSE 来进行任何必要的清理,甚至中止关闭(通过返回 1 而不是 0)。参见例如这个:http://cboard.cprogramming.com/windows-programming/141438-handling-wm_close-wm_destroy.html#post1056273

编辑:对于控制台应用程序,可能会感兴趣:http://support.microsoft.com/kb/178893

【讨论】:

  • 感谢您的链接,我有兴趣将其更改为隐藏的窗口应用程序。你有我的起始链接吗?
  • 这个比较旧,但是“消息处理”下的代码对于最小的应用程序应该足够了:functionx.com/win32/Lesson01b.htm
  • 好的,感谢您的支持。我找到了一个很好的教程:winprog.org/tutorial
  • 如果您的控制台应用程序是单线程的,您将不得不时不时地泵送您的窗口消息循环(调用 GetMessage,...),并且每次检查 WM_CLOSE 是否到达。其他解决方案是在单独的线程中创建窗口。
【解决方案3】:

您必须使用winapi创建隐藏窗口,并在其消息循环中处理WM_CLOSE消息。您的应用是否使用了任何 gui 元素?

【讨论】:

  • 不,它只是一个控制台应用程序。
【解决方案4】:

我认为最简单的方法是不时致电PeekMessage

BOOL IsCloseEventReceived()
{
    MSG msg;
    return PeekMessage(&msg, NULL, WM_CLOSE, WM_CLOSE, PM_NOREMOVE);
}

这个函数应该用来检查是否已经发布了 WM_CLOSE 消息。它不是阻塞的,您需要定期调用它。

我可能是错的,但我认为您不需要隐藏窗口来处理消息,当您第一次调用消息相关函数(如 PeekMessage)时,消息队列会附加到您的进程中。但是,如果您在第一次调用此函数之前收到 WM_CLOSE 消息,它可能会丢失。

【讨论】:

  • 好的,但是我需要创建一个循环,每 200 毫秒检查一次信号,对吧?
  • 是的,或者如果您的代码中已经有一个定期执行的循环,您可以将其插入其中(如果该位置执行过于频繁,您可能会添加一个计数器并每 1000 次检查一次或一些东西,这样你就不会过多地影响性能)。这样您就无需更改控制流。
  • 试过了。效果很好!我已经运行了一个循环,所以它只需要很少的改动。最重要的是,它不需要隐藏窗口。
猜你喜欢
  • 1970-01-01
  • 2012-12-26
  • 1970-01-01
  • 2018-03-31
  • 1970-01-01
  • 1970-01-01
  • 2010-11-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多