C++: How do I check if my window is about to close

2019-05-25 05:00发布

问题:

I'm trying to make a Win32/*nix console-based ASCII game. I want to use no libraries whatsoever that aren't standard C++ or on *nix/windows(.h).

I want it to be structured like a game loop. Aka:

while (!WIN_CLOSE_FUNCTION()) {
  //Do crap
}
//Do other shutdown crap
return 0;

Can anyone point me to what function this would be? If it is platform dependent, give me one example on Windows and *nix.

回答1:

Similar question that might help you What happens when you close a c++ console application

The accepted answer is: Closing a c++ console app with the "x" in the top corner throws an CTRL_CLOSE_EVENT which you could catch and process if you set a control handler using the SetConsoleCtrlHandler function.

Useful links:

  • Console Event Handling
  • SetConsoleCtrlHandler

On *nix:

On Linux and other Unix systems, the console runs as a separate process. As you close the shell, it sends the SIGHUP signal to the currently active process or processes that are not executed in the background. If the programmer does not handle it, the process simply terminates. The same signal is sent if you close the SSH session with a terminal and an active process.

answer provided by @Zyx in the question linked above



回答2:

For the Unix/Linux console, there is no such function. The closest you can do is to catch the signal SIGHUP which is sent when losing the terminal. However be aware that the things you can do in a signal handler are quite limited. Probably the closest to your loop would be (note: untested code):

#include <signal.h>

volatile sig_atomic_t hupflag = 0;

extern "C" void hangup(int)
{
  hupflag = 1;
}

int main()
{
  sigaction act;
  act.sa_handler = hangup;
  act.sa_mask = 0;
  act.sa_flags = 0;
  if (sigaction(SIGHUP, &act, 0) < 0)
  {
    std::cerr << "could not install signal handler\n";
    return 1;
  }

  while (!hupflag)
  {
    // ...
  }
  // shutdown
  return 0;
}


回答3:

There isn't such a function per se, but both Unix and Windows will send a signal (SIGHUP under Unix, SIGBREAK under Windows) to all processes in the process group when the window on which the process group depends is closed. So all you have to do is catch the signal and set a flag, which you test in the loop:

#ifdef _WIN32
int const sigClosed = SIGBREAK;
#else
int const sigClosed = SIGHUP;
#endif

volatile sig_atomic_t windowClosed = 0;

void signalHandler( int )
{
    windowClosed = 1;
}

//  ...
signal( sigClosed, signalHandler );
while ( windowClosed == 0 ) {
    //  ...
}

If you're doing any input from the console in the loop, you'll have the be prepared for the input to fail (which you should be anyway).