Stop WndProc processing during shutdown of the app - windows

I have defined a WndProc which looks similar to below (the code is written in C++Builder, but it applies in similar form to Delphi as well):
#define WM_SETTINGS_UPDATE WM_APP + 1234
#define WM_GUI_UPDATE WM_APP + 1235
void __fastcall TForm1::WndProc(TMessage &fMessage)
{
switch (fMessage.Msg)
{
default: break;
case WM_SETTINGS_UPDATE: ProcessMySettingsUpdate();
fMessage.Result = 1;
return;
break; // I know this is not needed, I do this purely for aesthetics
case WM_GUI_UPDATE: ProcessMyGUIUpdate();
fMessage.Result = 1;
return;
break; // I know this is not needed, I do this purely for aesthetics
}
TForm::WndProc(fMessage);
}
So in essence this:
checks for my custom WM_APP range messages (WM_SETTINGS_UPDATE and WM_GUI_UPDATE) in this case.
processes those messages and then sets fMessage.Result to 1 indicating message was processed and returns (avoiding TForm:WndProc(fMessage), which I understand is the same as inherited in Delphi, and not needed if the message is processed).
if my messages are not processed, it just calls TForm:WndProc(fMessage) (or inherited) to do the default processing.
My concern is this - what if there is a situation where the application is shutting down, and there are still some messages being unprocessed (left in the message queue by PostMessage())?
What I'd like to do in such a situation is to avoid calling my own processing, as it might result in some uninitialized memory Access Violations or similar. Is this basically enough, or do I need to apply some special processing to avoid that kind of situation, or process some "application shutting down" code?
And also - do I need to call inherited / TForm:WndProc(fMessage) after I am done with my processing, or is it safe to do it like above (set Result to 1 and return)?
Note - this does not necessarily apply to the MainForm (the first Form being created).

what if there is a situation where the application is shutting down, and there are still some messages being unprocessed (left in the message queue by PostMessage())?
That is perfectly OK. Once a Form's HWND is destroyed, any remaining messages that were posted for that window will simply be discarded when dispatched by the main message loop. Your WndProc will not be called for them.
What I'd like to do in such a situation is to avoid calling my own processing, as it might result in some uninitialized memory Access Violations or similar.
That should not be a concern. One, because messages won't be dispatched to your Form's HWND after it is destroyed, and two, when the MainForm is closed, the main message loop is signaled to stop running, before any active Form HWNDs are destroyed. So, there won't be any further message dispatching anyway.
Is this basically enough, or do I need to apply some special processing to avoid that kind of situation
It should be enough. You typically do not need to handle this special (unless your custom messages are carrying pointers to objects that have to be freed).
or process some "application shutting down" code?
If you really want to detect when the app is being shut down, try having your WndProc handle the WM_CLOSE message (or you can use the Form's OnClose/Query events).
do I need to call inherited / TForm:WndProc(fMessage) after I am done with my processing, or is it safe to do it like above (set Result to 1 and return)?
That is perfectly OK for custom messages.

Related

How can you tell if SendMessage() was successful (message was delivered)?

is it possible to determine if a SendMessage() call was successful and delivered my message to the target window?
The SendMessage() description in the Windows API seems quiet on this and only says the following:
The return value specifies the result of the message processing; it depends on the message sent.
This obviously refers to the fact that the return code reflects the value returned by the wndproc of the target window.
But what will the return code be if the message wasn't delivered at all (e.g. due to access control, or due to the window having been destoroyed in the meantime)? How can I detect such situations?
There is no way to reliably tell, whether a call to SendMessage succeeded or failed. After all, it only has a single return value, and the entire range of values is used. There is no designated error value.
Playing tricks with the calling thread's last error code won't work either. The scheme proposed in this answer (clearing the last error code prior to the call and evaluating it after the call) is brittle. It's easy to see that it can fail, when sending a message to a window owned by the calling thread (as that window's window procedure is at liberty to change the last error any way it sees fit).
It's not quite as well known, that this can also fail when sending a message to a window owned by a different thread. The code suggests, that no intervening API call can happen in the calling thread. Yet in that scenario, SendMessage will also dispatch incoming cross-thread messages (see When can a thread receive window messages?), allowing the thread's last error code to change.
The only option then is to use SendMessageTimeoutW, as that API reports both the result of the call, as well as an error/success indicator. Passing the SMTO_NOTIMEOUTIFNOTHUNG flag makes sure that an arbitrarily chosen timeout will not adversely affect the outcome.
if SendMessage fail, it set last win32 error code, which we can get back via call GetLastError(). and returned error code, in case fail, never will be 0 (NOERROR) despite this is clear not documented. but how detect that SendMessage is fail ? here we can not base on return value. but we can SetLastError(NOERROR) before call SendMessage and check GetLastError() after:
if SendMessage fail - value returned by GetLastError() will be
not 0. (most common in this case ERROR_INVALID_WINDOW_HANDLE or
ERROR_ACCESS_DENIED).
if we still got 0 as last error - this mean that message was
delivered with no error.
however, possible case, when during SendMessage call, some window procedure
in current thread will be called and
code inside window procedure, set last error to non 0 value. so we
get finally not 0 last error, but not because SendMessage fail.
distinguish between these two cases very problematic
-
SetLastError(NOERROR);
LRESULT lr = SendMessageW(hwnd, *, *, *);
ULONG dwErrorCode = GetLastError();
if (dwErrorCode == NOERROR)
{
DbgPrint("message was delivered (%p)\n", lr);
}
else
{
DbgPrint("fail with %u error\n", dwErrorCode);
}

How to design cleaner PostMessage chain in WinApi/MFC

I have a MFC GUI app that has multiple frames (sort of like Outlook'ish behavior with main window, and message/appointment windows being created in new frames, or Skype like multi frame syncronization), and I need to PostMessage malloc'ed data through the window hierarchy.
Say, I get the string, _wcsdup it, PostMessage(WM_NEWSTRING, ...), and, the control somewhere deep down the hierarchy processes it, or if there are no subscribers, the message get's cleaned.
What I am looking into now, is that all messages are posted to application thread, thread finds the active frame or best fit frame, passes the message to it, frame passes the message to it's view, the view passes message to subview and so on, if there is no view to process the message, it get's free'd.
The problem is that these chaining commands are pretty tiring to write, as I have to duplicate the message forwarding code in each CWnd class I have. At the same time, resource cleanup is pretty unpleasant, because if there is no window to catch the message, someone has to call the free. Therefore simply posting the message to the main message pump without extra handling, hoping that someone will always catch it, is not a valid approach. PostMessage returns S_OK, no one sees the message as processable, and it's left dangling.
Is there a better, correct approach for what I'm looking for?
I would never use PostMessage as you describe. My solution often involves a hand-shake:
// From CNotifierBlah
PostMesssage(hWnd, UWM_NEW_DATA, 0, 0);
//
LRESULT CDestinationWnd::OnNewData(WPARAM wParam, LPARAM lParam)
{
CNewData newData = GetNotifierBlah().GetNewData(); // Thread-safe getter!
}
Pretty much the same as Observer pattern.

Why are "TranslateMessage" and "DispatchMessage" separate calls?

Most of the Win32 main loops I've seen are all structured like:
while (GetMessage(&message, NULL, 0, 0) > 0) {
TranslateMessage(&message);
DispatchMessage(&message);
}
It was pointed out to me that MsgWaitForMultipleObjects may be used to add some variety to a main loop. But is there a scenario where doing something between GetMessage, TranslateMessage and DispatchMessage is actually useful?
The more traditional message loop looks like this:
while (GetMessage(&msg, 0, 0, 0))
{
if (!TranslateAccelerator(hwndMain, haccel, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
It is a pretty big hint to what you'd want to do before dispatching the message: catch messages that ought to be intercepted and treated specially before the window sees them. Keyboard shortcuts are a classic example, they need to be detected no matter what window has the focus.
Any GUI class library exposes it with a virtual method named something like App.PreProcessMessage, a virtual function that can be overridden so your program can implement its own shortcuts and whatnot.
They are different beasts.
For TranslateMessage function
Translates virtual-key messages into
character messages. The character
messages are posted to the calling
thread's message queue, to be read the
next time the thread calls the
GetMessage or PeekMessage function.
[...]
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
DispatchMessage, on the other hand, dispatches a message to a window procedure.
So DispatchMessage does the actual work of processing the message. TranslateMessage MAY or MAY NOT post a new message to the thread queue. If the message is translated then a character message is posted to the thread's message queue.
The TranslateMessage function does not
modify the message pointed to by the
lpMsg parameter.
They are separate calls so you, the programmer, can have a chance to avoid the message translation provided by TranslateMessage.
Well to quote an example from the MSDN:
You can modify a message loop in a variety of ways. For example, you can retrieve messages from the queue without dispatching them to a window. This is useful for applications that post messages not specifying a window. You can also direct GetMessage to search for specific messages, leaving other messages in the queue. This is useful if you must temporarily bypass the usual FIFO order of the message queue.
You can also possibly avoid calls to Translate message if you don't need to convert keyboard input control codes.
TranslateMessage() converts virtual keys messages to character input messages.
It is a separate call for the remote chance that under certain circumstances you would want to not produce character input messages for certain virtual keys.

Best way to close and wait for a child frame window using Win32/MFC

There are a few options here, probably, but what would you suggest to be the safest way to accomplish the following:
I've got a child CFrameWnd with a parent = NULL (so that it can live a separate life from the main application, while the app is running, at least). I've got all those windows stored in a list. When the main app is closing (MainFrame getting an OnClose), I go through the array and issue a PostMessage(WM_CLOSE) to all. However, the problem is that each of them has to do stuff before closing down. So, I need to wait for them. But we're all on the same thread... So, how can I wait for the children to close, without blocking their own processing in a single-threaded application?
Or should I launch a worker thread to take care of that? Would it be easier?
Thanks in advance!
Use SendMessage() instead of PostMessage().
Edit: Another option might be to simply handle WM_DESTROY in your child windows (depending on your code of course).
Well you certainly can't just wait for them to close, you need to at least pump messages so that they would receive and handle the WM_CLOSE. How you do that is up to you I guess. But I see you are doing PostMessage. Why not do SendMessage instead - this will run the close synchronously in the window procedure for the window. Or are you trying to quit the app? Then you should really use PostQuitMessage then pump messages in the normal fashion until GetMessage returns 0. Lots of options.
Pumping messages means to have a loop in your code that looks like this. You don't have to call AfxPumpMessages, but that would probably do something similar. There are in fact many different ways to pump messages depending on what you want to do. In addition there are quite a few functions that pump messages for you.
BOOL bRet;
// note that GetMessage returns 0 when WM_QUIT is received - this is how PostQuitMessage
// would work to get us to shut down
// We are passing NULL for the hWnd parameter - this means receive all window and
// thread messages for this thread
while( (bRet = GetMessage( &msg, NULL /* hWnd */, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
If you post the message to a window or windows, then you need to pump messages. What happens is that the message goes into a queue for the thread associated with that window (this thread) - the message pump extracts them out and dispatches them off to the correct window procedure.
If you had sent the message instead of posting it, then the window procedure for the window is called directly - rather than going into a queue. You wouldn't need to pump messages because once SendMessage returns the message is fully handled.
The way PostQuitMessage works is by setting a flag on the message queue indicating that the application should quit. The WM_QUIT message isn't really a window message that you would send - what happens is that GetMessage will check this flag after all the other posted window messages are processed and returns 0 if it is set. This will cause all windows to correctly close, and you don't need to send it to the windows themselves.

How can I update a win32 app gui while it is waiting for another program to finish?

I am currently using CreateProcess/WaitForSingleObject from within a win32 GUI app to launch a small GUI app that deals with software licensing issues. This all works fine, but it essentially hangs the "parent" app while it waits for the licensing app to finish its work. During this time, updates to the parent app do not occur and it ends up with ugly white squares if the utility app window is moved.
Also, for some strange reason, while the utility app is running, if I copy something from within that app to the clipboard, it HANGS. I haven't figured out why yet, but it only happens if I am waiting for the app to finish from within the parent app.
So I'm thinking that if I can cause the parent app to handle its events while waiting for my other app to finish, it might solve both problems.
So, is there a replacement for CreateProcess/WaitForSingleObject that also handles UI updates?
Your parent process appears to hang because the WaitForSingleObject() call blocks your thread until the handle you pass into the call is signaled.
Your child process likely hangs during the copy-to-clipboard operation because it is, as a part of that operation, sending a message either specifically to the parent process's window or to all top-level windows. The message loop in your parent process's thread is not running, because it is blocked waiting until the child process exits, so the message is never processed and the child process remains blocked.
Instead of calling WaitForSingleObject(), you can call MsgWaitForMultipleObjects(). If you specifiy QS_ALLINPUT for the dwWaitMask parameter, MsgWaitForMultipleObjects will return either when your event is signaled or when there is input in the thread's message queue. If MsgWaitForMultipleObjects() returned because a message is available, you can process it and resume waiting:
MSG msg;
DWORD reason = WAIT_TIMEOUT;
while (WAIT_OBJECT_0 != reason) {
reason = MsgWaitForMultipleObjects(1, &hChildProcess, FALSE, INFINITE, QS_ALLINPUT);
switch (reason) {
case WAIT_OBJECT_0:
// Your child process is finished.
break;
case (WAIT_OBJECT_0 + 1):
// A message is available in the message queue.
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
// Note that if your main message loop does additional processing
// (such as calling IsDialogMessage() for modeless dialogs)
// you will want to do those things here, too.
}
break;
}
}
You could put the WaitForSingleObject call in a loop and use a relatively small value for the dwMilliseconds parameter.
The condition to exit the loop is when the WaitForSingleObject call returns WAIT_OBJECT_0.
In the loop you have to examine the message queue to see if there are any that you must process. How you handle this is really up to you an it depends on your typical needs.
// Assuming hYourWaitHandle is the handle that you're waiting on
// and hwnd is your window's handle, msg is a MSG variable and
// result is a DWORD variable
//
// Give the process 33 ms (you can use a different value here depending on
// how responsive you wish your app to be)
while((result = WaitForSingleObject(hYourWaitHAndle, 33)) == WAIT_TIMEOUT)
{
// if after 33 ms the object's handle is not signaled..
// we examine the message queue and if ther eare any waiting..
// Note: see PeekMessage documentation for details on how to limit
// the types of messages to look for
while(PeekMessage(&msg, hwnd, 0, 0, PM_NOREMOVE))
{
// we process them..
if(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
// if you're here it means WaitForSingleObject returned WAIT_OBJECT_0, so you're done
// (but you should always check and make sure it really is WAIT_OBJECT_0)
if(result != WAIT_OBJECT_0)
{
// This should not be.. so react!
}
I suggest you can handle this as follows:
Parent application does CreateProcess, and then returns immediately instead of waiting for a response or for the utility app to finish
Because the parent applicatin has returned, it can handle other Window messages (e.g. WM_PAINT)
When the utility app finishes, it notifies the parent application (e.g. using PostMessage and RegisterWindowMessage APIs)
Parent application handles positive notification received via PostMessage
Parent application may also have a Windows timer (WM_TIMER) running, so that it knows if the utility app is killed before it send its notification
You can get a hanging problem if the app you are spawning causes a sendmessage broadcast, either explicit or implicit. This is clipped from my website:
The problem arises because your application has a window but isn't pumping messages. If the spawned application invokes SendMessage with one of the broadcast targets (HWND_BROADCAST or HWND_TOPMOST), then the SendMessage won't return to the new application until all applications have handled the message - but your app can't handle the message because it isn't pumping messages.... so the new app locks up, so your wait never succeeds.... DEADLOCK.
I don't do clipboard code, but if that causes the situation above (believeable), then you'll deadlock. You can:
put the launch of the secondary application into a little thread
use a timeout and spin around a PeekMessage loop (yuck)
use the MsgWaitForMultipleObjects API.
No preference is implied by that ordering... I'm assuming you don't create the spawned application yourself, in which case you could use IPC to get around this issue, as ChrisW suggested.
You should create a thread that does only the following:
call CreateProcess() to run the other app
call WaitForSingleObject() to wait for the process to finish - since this is a background thread your app will not block
call CloseHandle() on the process handle
call PostMessage() with a notification message for your main thread
Now you only need to make sure that your main application has its GUI disabled to prevent reentrancy problems, possible by showing a modal dialog that informs the user that the other app is running and needs to be dealt with first. Make sure that the dialog can not be closed manually, and that it closes itself when it receives the posted notification message from the background thread. You can put the whole thread creation into this dialog as well, and wrap everything in a single function that creates, shows and destroys the dialog and returns the result your external application produces.

Resources