Wait for a specific key in a Win32 application - c++

At some point in my program, I want to wait for the user to either press [return] or [escape].
This is what I did:
while(1)
{
Sleep(100);
if( GetAsyncKeyState( VK_RETURN ) )
{
//do something
}
if( GetAsyncKeyState( VK_ESCAPE ) )
{
//do something else
}
}
But (only in the release build) after waiting for about 2 seconds, Windows says it's not responding, and it crashes.
What should I do?

Your application is a GUI subsystem application and its main thread must regularly pump its message queue. You are not doing that because you enter a tight loop looking for specific key state. Because you don't service your queue, the system concludes that your application is broken and ghosts your window.
Before we go on to how to do it right, your existing approach is broken in other ways. Suppose that the key is pressed and released during the Sleep(100). Then you miss that event. Or suppose your app is not in the foreground. Then it responds to key presses meant for other applications.
To solve the problem you simply need to let your normal message loop process and dispatch messages. When you get a WM_KEYDOWN message for the appropriate key you can react accordingly.
Using the message loop in the intended way not only fixes the behaviour you observe in the question, but also the issues I describe above.

Related

Is there a workaround for SetConsoleCtrlHandler() issue?

Windows 10, C++. I have a graphic app which opens a console, writes a few things, and waits until user clicks the close on the console. I only want for console to close, but the entire app exits. Yes, the handler is entered. I also see that this was an issue more than 10 years ago. So, is there another way around this?
// Graphic app makes following calls
...
AllocConsole();
SetConsoleCtrlHandler(ConsoleCloseHandler, TRUE);
...
The handler is defined as follows.
BOOL WINAPI ConsoleCloseHandler(DWORD signalType) {
switch (signalType) {
case CTRL_CLOSE_EVENT:
case CTRL_C_EVENT:
FreeConsole();
return TRUE;
default: return FALSE;
}
}
No matter which value your handler returns, Windows is going to kill your process after your or the last handler returns.
If your process is going to shut down soon after receiving this signal, notify your application to start shutting down and then sleep/wait forever in the handler.
If you want your application to continue to run as normal, you could perhaps call ExitThread(1337); in your handler. This is a giant hack and who knows if it works on all Windows versions.
If neither of the two methods are acceptable then I'm afraid you might have to use a child process as the console owner.

How to detect Windows shutdown or logoff in Qt

I am porting a Linux app to Windows written in Qt. The application needs to save some settings before closing. On Linux, we can do that by signal handlers for SIGTERM etc. How can I implement the same on Windows.
If you are using the Qt event loop, you can catch the following signal:
void QCoreApplication::aboutToQuit() [signal]
This signal is emitted when the application is about to quit the main event loop, e.g. when the event loop level drops to zero. This may happen either after a call to quit() from inside the application or when the users shuts down the entire desktop session.
The signal is particularly useful if your application has to do some last-second cleanup. Note that no user interaction is possible in this state.
Other than that, you may be looking for the following messages below if the aforementioned signal is not appropriate for your use case:
WM_QUIT: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632641(v=vs.85).aspx
WM_CLOSE: http://msdn.microsoft.com/en-us/library/windows/desktop/ms632617(v=vs.85).aspx
WM_QUERYENDSESSION: http://msdn.microsoft.com/en-US/library/windows/desktop/aa376890.aspx
WM_ENDSESSION: http://msdn.microsoft.com/en-US/library/windows/desktop/aa376889.aspx
I think the other answers completely miss the point: When you forcibly end an application, it's like SIGKILL on Unix. There's no way to handle it - except ahead of time. What I mean by handling it ahead of time is making sure that you save the settings every time they are changed. Of course you can optimize this behavior, for example save the settings every few seconds if they are dirty, if you want to minimize the number of disk accesses (think power consumption on mobile devices).
A lot of this is handled by QSettings for you. As long as you use QSettings, you'll get reasonable behavior. If you're saving files yourself, use QSaveFile as it deals with flushing the file and approximating atomic file replacement, so that you won't lose the settings if the kill (forced termination) comes in the middle of you doing the writing.
The aboutToQuit signal emitted by QCoreApplication is what you want to react to if you want to simply do something when the application being asked to quit. This is equivalent to handling the WM_QUIT message, or dealing with SIGTERM on Unix. So doing it in platform-specific way is pointless as Qt does it for you already. There's equally no point in handling WM_CLOSE since that's a message that only windows get, and again Qt already handles it for you.
You can also participate in the logoff/shutdown process by installing a QAbstractNativeEventFilter and processing the WM_ENDSESSION and WM_QUERYENDSESSION. This only makes sense if you want to know ahead of time that the application will be quit. Unless you explicitly want to stop the shutdown/logoff, you don't need to worry about it.
I think it might be better to handle the QApplication::commitDataRequest signal (or QGuiApplication::commitDataRequest in Qt5) instead of aboutToQuit. Just connect the signal to your function for saving settings.
Here are some related discussions: http://qt-project.org/forums/viewthread/33329
session logoff will emit aboutToQuit
case WM_ENDSESSION: {
sm_smActive = false;
sm_blockUserInput = false;
bool endsession = (bool) wParam;
// we receive the message for each toplevel window included internal hidden ones,
// but the aboutToQuit signal should be emitted only once.
QApplicationPrivate *qAppPriv = QApplicationPrivate::instance();
if (endsession && !qAppPriv->aboutToQuitEmitted) {
qAppPriv->aboutToQuitEmitted = true;
int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
// since the process will be killed immediately quit() has no real effect
QApplication::quit();
}
RETURN(0);
}
I do not know Qt. If you can afford to be Windows only WM_QUERYENDSESSION and WM_ENDSESSION messages might be the right thing to do.

Window message WM_SIZING sending incessantly when window resizing

I make small game and have some problem with low priority window messages, that incessantly sending from system and block running game logic's code.
I create my message loop something like this:
bool Window::SystemRoutineAndCheckQuit() {
::MSG msg;
while( ::PeekMessage( &msg, nullptr, 0, 0, PM_REMOVE ) ) {
if( msg.message == WM_QUIT ) {
::UnregisterClass( registeredClassName, ::GetModuleHandle( nullptr ) );
DLOG( lg ) << "Exit from system loop" << DLOG_END;
return false;
}
::TranslateMessage( &msg );
::DispatchMessage( &msg );
}
return true;
}
//....
while( window.SystemRoutineAndCheckQuit() ) {
// do all render and logic
}
I.e. before every frame I wanna process all messages from windows and then, when queue will empty do all logic. I notice when window resizing I get same message WM_SIZING again and again and queue never will empty when mouse button still press (even when size of window don't change from previos call I receive message with same window coordinates). So it block execute my code.
Is there any other messages, that keep windows message queue don't empty and what is the best way to process all messages without some low priority, like WM_SIZING?
I test it on Windows 8.
PS: I need resize window, so I don't wanna disallow it by change style.
EDIT: sorry for incorrect description problem, but found what real happened (and why my previously attempt to fix it by limit number of processed messages, or by break message process when get same message two times in sequence will not success). From PeekMessage I get message WM_NCLBUTTONDOWN and after this message program don't return from ::DispatchMessage and block continue execution of thread until mouse will be released. And when program in DispatchMessage, my handler get repeatly WM_SIZING or WM_MOVING (independently what return from message handler function (result of DefWindowProc, TRUE (message was processed) or 0).
You could just process N messages before each frame.. where N is a limit you set between 1-10. That way you can process a reasonable number of events, then get onto your actual game logic.
It's conceivable that Windows may just generate the 'window sizing' message continually when the queue is empty, to make sure applications are aware the window is being resized.
(Maybe MS think applications might not know, maybe there's nothing else the user can do.. so MS want to hammer that single message.)
When DefWindowProc handles WM_SYSCOMMAND with either SC_MOVE or SC_SIZE in the wParam, it enters a loop until the user stops it by releasing the mouse button, or pressing either enter or escape. It does this because it allows the program to render both the client area (where your widgets or game or whatever is drawn) and the borders and caption area by handling WM_PAINT and WM_NCPAINT messages (you should still receive these events in your Window Procedure).
It works fine for normal Windows apps, which do most of their processing inside of their Window Procedure as a result of receiving messages. It only effects programs which do processing outside of the Window Procedure, such as games (which are usually fullscreen and not affected anyway).
However, there is a way around it: handle WM_SYSCOMMAND yourself, resize or move yourself. This requires a good deal of effort, but may prove to be worth it. Alternatively, you could use setjmp/longjmp to escape from the Window Procedure when WM_SIZING is sent, or Windows Fibers along the same lines; these are hackish solutions though.
I solved it (using the first method) this past weekend, if you're interested I have released the code to the public domain on sourceforge. Just make sure to read the README, especially the caveat section. Here it is: https://sourceforge.net/projects/win32loopl/

Basic pause/resume functionality in C++

I am making a primitive time keeper that I would like to pause and resume with the simple press of a key. I've been told that
system("pause>null")
pauses the program until a key is hit, but how is the conditional written to pause to begin with?
Preferred structure in pseudo-code:
if (certain_key_pressed)
{
pause_program_until_any_key_hit;
}
There are 2 idioms to choose from here. Polling or event driven programming.
Polling is the more simple but often less elegant solution where the program would periodically check to see if the pause button has been hit within a loop.
While(not_quit)
{
if(key_pressed)
Etc...
In event driven programming, you would register the pauseButtonPressed event with an event handler. When the pause button is pressed, a special function assigned the task of handling the event would call the pause function.
if ( certain_key_pressed )
while ( true )
{
if ( any_key_hit )
break;
}
Something like this would suspend any loop it is placed in (presumably your program loop) when the particular key is pressed. It would then keep it suspended until any key is hit.

Avoiding "(Not Responding)" label in windows while processing lots of data in one lump

I occasionally need to process a large amount of data from one package off the network, which takes sufficiently long that when the user tries to interact with the application windows adds the "(Not Responding)" string to the window title. I am aware this is because the processing is being done within a call to handle a message (some way up the stack) and therefore is blocking the message pump. I'm also aware the ideal way to deal with this is to process the data asynchronously in a separate thread so the pump can continue running, however this is a LARGE desktop application which is single threaded from top to toe and safely spinning this processing off is not feasible in our time frame.
So with that in mind, is there by any chance a way I can at least avoid the "not responding" moniker (which to most users reads as "has crashed") by telling windows my application is about to be busy before I begin the work? I believe there is something along these lines when responding to a request to close, one can keep asking windows for more time to avoid it proclaiming that your not "closing in a timely fashion"
I should add this is a C++ MFC application.
I don't think the Windows API can help you here.
Alternatively, how about showing a dialog box with a progress bar and make it run in a separate thread?
A text like "This operation may take half an hour" on the dialog box may be appropriate too.
Ok, firstly I upvoted Frederick's post because like it or not, the second thread is probably the best way to go.
However, if you really don't want to go down this road, you could manually pump the message queue within your apps inner loop. Something like this;
int Refresh()
{
MSG msg;
if (PeekMessage (&msg, NULL, 0, 0,PM_NOREMOVE))
if ((msg.message == WM_QUIT)
||(msg.message == WM_CLOSE)
||(msg.message == WM_DESTROY)
||(msg.message == WM_NCDESTROY)
||(msg.message == WM_HSCROLL)
||(msg.message == WM_VSCROLL)
)
return(1);
if (PeekMessage (&msg, NULL, 0, 0,PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
return(0);
}
This is actually a piece of code I used prior to rewriting something similar as a seperate thread. Basically I have a look at the queue, filter out unwanted messages, and post on the rest. It works to an extent, but caused some occasional nasty side effects, hence the rewrite.
You don't have to actually do anything with the messages from PeekMessage. Just call PeekMessage, you don't even have to remove anything from the queue or process it. As long as it is called every 5 seconds or so, it will cause windows to think the process is still responsive.
An alternative idea is to have a separate process/thread that will appear in the notification tray and inform the user that the process is busy waiting for an internal operation to complete. You'll see these in the later versions of Visual Studio, SQL Server Management Studio, etc.
Win32 has a method for this in user32.dll.
DisableProcessWindowsGhosting()
Disables the window ghosting feature for the calling GUI process. Window ghosting is a Windows Manager feature that lets the user minimize, move, or close the main window of an application that is not responding.
In addition to the above documented behavior, I also verified here (in a C# application) that this Win32 call also prevents the Not Responding label from appearing on the window as desired.
I found this via the C# answer to similar question here: https://stackoverflow.com/a/15380821/29152.
If you fork off a thread you're most likely worried about some other user action happening which may depend on the result of the long running operation (yeah, concurrency). So expanding on what Fredrick said, if you do spin off a new thread and put up a progress bar, you could lock the focus onto the progress bar to stop a user from interacting with the rest of the application. That should be enough to implement a really simple second thread without really having to worry about concurrency because you're essentially locking out the rest of the app by disabling user interation.
You'll need to interleave the processing with message handling somehow. If threads are out of the question, you might want to look at splitting the processing into multiple phases. One way to do this is to do some processing when you first receive the packet, then post a message to the application saying "continue processing here". When the application receives the "continue processing here" message, it will do some more processing, and either send another "continue processing here" message or finish up.
There are a couple of considerations though:
You need to make sure that the state of the application is consistent every time you post a message to yourself and defer to the message loop, as other message handling might happen in the mean-time. This can be done e.g. by only changing the state in the final processing phase.
Another packet might arrive while you are still processing the first packet. If changing the order of processing would be bad for the application, you could handle this by e.g. posting a "remind me to process this packet later" message when this happens.
I don't know whether this would be feasible within the design of your application, but it would be one way to solve the problem.
If you are unwilling to spawn a worker thread, but you can break the long-running task down into smaller parts, you can do the processing in MFC's CWinApp::OnIdle. This function gets called from within the message pump loop whenever there are no Windows messages waiting. As long as the work you do in each OnIdle call is sufficiently short, you keep your app responsive.
Assuming that it is the processing of the data that is taking up all the time and not the receiving (and you're serious about avoiding a thread - which is fine IMOHO) of the data you could:
In the function that you are currently handling the message, create a modal dialog that shows a "please wait" message (or make it hidden, small, whatever...). Copy (or send a pointer, etc...) the data you're processing to a member variable of that dialog.
In the modal dialog post a user-defined message to yourself to process the data.
In the dialog's message handler, handle one "unit" of work. Keep track what the next "unit" of work is. Post the same message again.
Repeat this post-message "loop" until done. Close your dialog.
The nature of the modal dialog will keep you're application "responsive", with minimal interruption or change to how the application worked previously. Reentrancy can be a problem with modal loops, especially if any of this is involved with a WM_PAINT message. (anyone ever assert inside painting code? good times, good times...)
The dialog could even have a cancel button if you'd like.
I encountered the exact same problem.
Since I dont consider the other answers appealing/straightforward I decided to post this.
Short description and some context:
I am saving data from a grid into a database, and this process can take a while. So I changed the saving method to an asynchronous method and had the same problem.
Then I came up with a simple solution:
//__ENABLE OR DISABLE MAIN DIALOG
void CMFCApplication1Dlg::enableMainDlg(bool enable)
{
this->EnableWindow(enable);
}
When starting the asynchronous method, I disable the main dialog.
This prevents the user from interacting with the main dialog (like starting another saving process which could result in thousands of SQL error messages if I wouldn't check if the saving process is already running...)
When the saving process is finished, I re-enable the main dialog.
Works like a charm, I hope this helps
One way to overcome your application from becoming unresponsive you need to tell the application to process messages from windows. When you are in your loop you can call
Application->ProcessMessages();
I had a similar issue with a win32 app that was waiting on a response from webservice using cpprest (Casablanca) api. My solution was to create a event and thread that does nothing but wait for the cpprest api and then release the thread once it recieves the signal:
DWORD WINAPI WaitForCasablanca(LPVOID n)
{
// Get the handler to the event for which we need to wait in
// this thread.
HANDLE hEvent = OpenEvent(EVENT_ALL_ACCESS, false, "MyEvent");
if (!hEvent) { return -1; }
// Loop through and wait for an event to occur
// Wait for the Event
WaitForSingleObject(hEvent, INFINITE);
// No need to Reset the event as its become non signaled as soon as
// some thread catches the event.
CloseHandle(hEvent);
return 0;}
BOOL WINAPI DlgProc(HWND hDlg, UINT message, WPARAM,wParam, LPARAM lParam) ...
HANDLE hEvent = CreateEvent(NULL, false, false, "MyEvent");//create an event that will wait for casablanca ro authenticate
if (!hEvent) return -1;
// Create a Thread Which will wait for the events to occur
DWORD Id;
HANDLE hThrd = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WaitForCasablanca, 0, 0, &Id);
if (!hThrd) { CloseHandle(hEvent); return -1; }
makeCasablancaRequest(...);
SetEvent(hEvent); //casablanca has finished signal the event to terminate
WaitForSingleObject(hThrd, INFINITE); //wait for thread to die
CloseHandle(hThrd);
CloseHandle(hEvent);
...}
That got rid of the "program not responding" message for me. I believe the problem is the code that is getting the data is running in a thread too- only the main program doesn't know this- so as far as the system is concerned the main program is idling. You need an event and a thread that waits for the event to tell the system the program is waiting on data. I got the code from this tutorial: How to use WIN32 Event Kernel Object