4

I wrote a C++ console program that displays a menu with several options for the user, one of them goes into a continuous loop and the condition to exit the loop is !GetAsyncKeyState(VK_ESCAPE). So if a user presses ESC, on the next start of this loop it will exit and the main menu will be displayed again.

The problem happens when the user doesn't have my program on focus and presses the ESC key, the GetAsyncKeyState will still return that the ESC key was pressed and the loop will exit.

How can I implement a solution that will listen to the ESC key only when my program is on focus?

  • I can't use getline, getch or any line input methods because I will have the loop running and I can't ask for user input on every iteration.
  • The solution can be platform dependent since this will only be running on Windows.
  • I have to stick with C++ because I am using a library that the only "usable" implementation is the C++ version.

This could be useful to anyone else that would write a c++ console program that has a loop that exits when a key in pressed and the program is on focus.

Thanks in advance!

paulovitorjp
  • 538
  • 5
  • 14
  • So if I understand this right you display a menu and one of the options if selected will start running an infinite loop. You then want to allow the user to press a key which will terminate the loop and return the user to the main menu? – NathanOliver Apr 16 '15 at 15:51
  • @NathanOliver that is correct. This is already working, the problem is that the program will exit the loop even if the key is pressed when the user is doing something else, not with my program on focus. – paulovitorjp Apr 16 '15 at 15:55
  • 1
    Have you looked checking if the [windows is enabled](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646303(v=vs.85).aspx) before checking the key pressed? – NathanOliver Apr 16 '15 at 16:12
  • @nathan: Are you sure, you can get a window handle for a console program? – MikeMB Apr 16 '15 at 17:08
  • 2
    @MikeMB Sure. You can use [`GetConsoleWindow()`](https://msdn.microsoft.com/en-us/library/windows/desktop/ms683175(v=vs.85).aspx) – NathanOliver Apr 16 '15 at 17:13

1 Answers1

1

Problem was solved using GetForegroundWindow and comparing it to the Console window handler. Sample code below.

@NathanOliver using IsWindowEnabled didn't work because it returns true if the window is enabled for keyboard and mouse input, which it is even if it is minimized. I also tried IsWindowVisible, and both together and it didn't work either, it was still capturing the ESC input even when I was working on other windows. But thanks to your input, while researching some other related methods I came across GetForegroundWindow() which returns the handler for the current window the user is working on, then I just had to compare it to the console window handler that I retrived using GetConsoleWIndow() as you mentioned above, then if this condition was true as well as GetKeyState(VK_ESC) the loop would exit!

HWND hWnd = GetConsoleWIndow();
boolean leaveAuto = false;
while(!leaveAuto) {
  ...
  leaveAuto = (GetAsyncKeyState(VK_ESCAPE) && (GetForegroundWindow() == hWnd));
}

Obs: It is very important that you check whether the ESC key was pressed before you check the foreground window, because the GetAsyncKeyState will return true if the key was pressed after the last time this function was called, and if you check the current window first, an ESC key press that happened in another window sometime ago will exit the loop the next time you put the window in the foreground. Checking it befor ensures the you clean ESC key presses when the window was not on focus.

This solution addresses the question of only listening to an ESC key press when the windows is on focus.

paulovitorjp
  • 538
  • 5
  • 14