【问题标题】:Window messages in windows application with no window没有窗口的 Windows 应用程序中的窗口消息
【发布时间】:2013-09-18 05:16:09
【问题描述】:

我有一个应用程序,我想在没有可见窗口或控制台的后台运行。为此,我创建了一个 Windows 应用程序,但我没有创建一个窗口。应用程序需要在请求关闭时(即用户注销时)进行一些清理。如何确定何时关闭?我可以简单地创建一个处理 WM_CLOSE 消息的消息循环吗?但是我没有 WndProc 来处理 WM_CLOSE 消息。

【问题讨论】:

  • 所以你并不是真的有一个 Windows 应用程序,而是一个在后台运行的程序,你想知道它正在被用户的注销请求杀死,对吧?
  • 像往常一样创建一个窗口,但使用 EnableWindow 隐藏它。

标签: c++ windows winapi


【解决方案1】:

不必费心创建一个虚拟窗口,在无窗口应用程序中处理关闭/退出控制事件有一种更简单的方法。为此,您需要使用一个鲜为人知的 Win API 函数:SetConsoleCtrlHandler (...)

这里是一个如何使用Control Handler的例子:

#include <windows.h> 

// You can fill-in your own behavior, this is just an example handler that
//   covers most of the most common events.
BOOL
ControlHandler (DWORD dwControlEvent) 
{ 
  switch (dwControlEvent) 
  { 
    // User wants to shutdown
    case CTRL_SHUTDOWN_EVENT: 
      return FALSE; 

    // User wants to logoff
    case CTRL_LOGOFF_EVENT: 
      return FALSE; 

    // Ctrl + C
    case CTRL_C_EVENT:
      return TRUE;

    // User wants to exit the "normal" way 
    case CTRL_CLOSE_EVENT:
      return TRUE;

    // Everything else, just ignore it...
    default:
      return FALSE; 
  } 
} 

int
main (void) 
{ 
  // Set the control handler so the app will be notified upon any special
  //   termination event.
  SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ControlHandler, TRUE); 

  //
  // Main Loop Here ...
  //

  return 0;
}

几年前我不得不了解这一点,因为当我的控制台应用程序被 Ctrl + C 终止时,一些中间件没有正确清理其资源。我在查看堆栈跟踪时偶然发现了它。值得一提的是,它取代了诸如 Ctrl + C 等事件的标准信号处理程序。

顺便说一句,即使它被称为“控制台控制处理程序”,它在使用WinMain (...) 而不是main (...) 的应用程序中也能正常工作。

【讨论】:

  • 是的,我以前一直在使用它,但我不希望用户看到任何东西,没有控制台,没有窗口。即使我在启动时隐藏控制台,它也会闪烁,这是不能接受的。
  • 你不需要控制台来工作,但服务方法肯定更优雅。
  • 服务不能满足所有需求,例如由于安全原因,无法访问用户输入或应用程序。因此,在用户帐户下运行的隐藏应用是解决方案。
【解决方案2】:

几个选项:

  1. 创建一个窗口,但不要设置 WS_VISIBLE 标志。
  2. 创建message-only window

区别在于不可见窗口接收广播消息,而仅消息窗口不接收。

【讨论】:

    【解决方案3】:

    要创建在后台运行的应用程序,请创建服务。服务可以响应ServiceMain 调用。

    如果您坚持创建前端应用程序,则应用程序尝试隐藏其主窗口基本上没有正当理由。您的可执行映像可以是 GUI (IMAGE_SUBSYSTEM_WINDOWS_GUI) 或控制台 (IMAGE_SUBSYSTEM_WINDOWS_CUI),您不能混合使用它们,请参阅 How do I write a program that can be run either as a console or a GUI application。如果您选择 GUI 应用程序,那么您应该创建一个消息泵。您可以选择创建一个隐藏窗口作为您的“主”窗口。您将在此隐藏窗口上看到WM_QUERYENDSESSIONWM_ENDSESSION(这是您感兴趣的消息,而不是WM_CLOSE)。

    另一方面,控制台应用程序必须处理信号,就像 Andon 已经向您展示的那样。

    选择你的毒药。我强烈建议走服务路线,因为这是“后台”应用程序的正确途径。

    【讨论】:

    • “应用程序试图隐藏其主窗口基本上没有正当理由”是一个相当不错的声明,显然也是错误的。在许多情况下,面向用户的窗口是没有意义的。做后台工作的子进程。仅通过通知栏交互的程序。两者都不是严格的服务,但仍然没有窗口。
    猜你喜欢
    • 1970-01-01
    • 2022-01-04
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    • 2021-04-30
    • 2012-06-30
    • 2021-10-02
    • 2010-09-18
    相关资源
    最近更新 更多