如何在关闭打开的控制台窗口时阻止我的程序关闭?

Eva*_*ake 3 c++ console winapi

我试图从我的主程序(Win32)打开控制台.我找到了一些代码,但它确实有效,但我不明白.我正在发生的问题是,当我在控制台上单击X时,它也会关闭程序.

我大概有这个:

int APIENTRY WinMain (HINSTANCE hThisInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int nFunsterStil) {

  // create the main program window, classes registered, etc...
  hwnd = CreateWindowEx(0, csClassName, "theNewTimer", WS_POPUP | WS_CLIPCHILDREN, 300, 0, WINDOW_WIDTH, WINDOW_HEIGHT, HWND_DESKTOP, NULL, hThisInstance, NULL);
  ShowWindow (hwnd, nFunsterStil);

  // and now the console
  AllocConsole();
  HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
  int hCrt = _open_osfhandle((long) handle_out, _O_TEXT);
  FILE* hf_out = _fdopen(hCrt, "w");
  setvbuf(hf_out, NULL, _IONBF, 1);
  *stdout = *hf_out;

  HANDLE handle_in = GetStdHandle(STD_INPUT_HANDLE);
  hCrt = _open_osfhandle((long) handle_in, _O_TEXT);
  FILE* hf_in = _fdopen(hCrt, "r");
  setvbuf(hf_in, NULL, _IONBF, 128);
  *stdin = *hf_in;


// and then the message loop concluding
Run Code Online (Sandbox Code Playgroud)

我用谷歌搜索了一些,但不知道我在读什么.

chw*_*arr 5

我不认为这是可能的。从 a 的 MSDN 文档中HandlerRoutine,有这句话。

CTRL_CLOSE_EVENTCTRL_LOGOFF_EVENTCTRL_SHUTDOWN_EVENT信号给进程一个机会终止前进行清理。

我读这句话是说CTRL_CLOSE_EVENT是建议性的,无论如何该进程都会退出。我的猜测是,当系统发送CTRL_CLOSE_EVENT 时,它会启动一个计时器。该进程被允许继续运行一段时间,但最终,操作系统将单方面终止该进程。

这是我注册的处理程序

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) {
   switch (dwCtrlType) {
       case CTRL_C_EVENT:
       case CTRL_CLOSE_EVENT:
           return TRUE; // breakpoint set here

       default:
           return FALSE;
   }
}
Run Code Online (Sandbox Code Playgroud)

这是我在调用后注册处理程序的方式AllocConsole

BOOL result = SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE /* Add */);
assert(result);
Run Code Online (Sandbox Code Playgroud)

我在标记为 的行上设置了一个断点//breakpoint set here。然后,我在 Visual Studio 调试器下运行该过程。当控制台窗口聚焦时,我按下了 Ctrl+C。我的断点被击中,我能够通过我的处理程序并返回KernelBase.dll!CtrlRoutine等等。当我让进程恢复正常执行时,进程继续运行。

然而,当我关闭控制台窗口时,我的处理程序确实被调用了,但我无法跟踪它的执行很远。我能够单步执行几次,但随后该过程就退出了。Visual Studio 报告“程序 '[10644] Win32Project.exe' 已退出,代码为 -1073741510 (0xc000013a)。”

0xc000013a 是 STATUS_CONTROL_C_EXIT:

BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType) {
   switch (dwCtrlType) {
       case CTRL_C_EVENT:
       case CTRL_CLOSE_EVENT:
           return TRUE; // breakpoint set here

       default:
           return FALSE;
   }
}
Run Code Online (Sandbox Code Playgroud)


Jon*_*ter 5

您可以做的一件事是禁用控制台窗口上的关闭按钮:

HWND hwnd = ::GetConsoleWindow();
if (hwnd != NULL)
{
   HMENU hMenu = ::GetSystemMenu(hwnd, FALSE);
   if (hMenu != NULL) DeleteMenu(hMenu, SC_CLOSE, MF_BYCOMMAND);
}
Run Code Online (Sandbox Code Playgroud)