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);
}
Related
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.
I have an application which uses a three helper threads to read from a database (3 different tables, ~160,000 rows in total), create objects from those rows, then add the objects to one of two lists, depending on what type of object was created. The helper threads add objects to the list through a SendMessage call so that the main thread is the only object adding/removing to/from the list.
The odd thing is that SendMessage doesn't always succeed, I'll frequently get these two errors ERROR_ALREADY_EXISTS (183) and ERROR_TRUSTED_DOMAIN_FAILURE (1788). The function that SendMessage calls just adds an object to the list, and this function always returns success (0). There's no creating files (as ERROR_ALREADY_EXISTS seems to suggest) and there's no network calls so I'm not sure why I'm getting ERROR_TRUSTED_DOMAIN_FAILURE errors.
Any ideas on what might be causing these errors or any way to debug these errors?
As a note, before it was SendMessage I was using PostMessage and would get lots of ERROR_NOT_ENOUGH_QUOTA errors; SendMessage makes the utility work a lot better.
SendMessage() returns the result of the message that is sent. It is up to the message handler to decide what value is actually returned by SendMessage() to the sending code. GetLastError() is only meaningful if SendMessage() itself fails, and you have to use SetLastError() to detect that, eg:
SetLastError(0);
LRESULT res = SendMessage(...);
if ((res == 0) && (GetLastError() != 0))
{
// send failed, for example GetLastError()=ERROR_ACCESS_DENIED if UIPI blocked the message ...
}
else
{
// send succeeded, res is whatever value the message handler returned ...
}
This only works reliably if the target HWND is owned by a different thread than the one that is calling SendMessage(). GetLastError() cannot be influenced across thread boundaries. Any call to SetLastError() within the message handler affects the error code of the HWND's owning thread, not the error code of the sending thread.
However, if the target HWND is owned by the same thread that is calling SendMessage(), and the message handler happens to call SetLastError() (directly, or indirectly via a failed API call) to set a non-zero error code, and happens to return 0 as its result value for SendMessage() to return to the sender, then the only way I can think of for the sender to differentiate whether the error code returned by GetLastError() was set by SendMessage() itself on failure, or set by the message handler, is to use a thread-locale message hook via SetWindowsHookEx() to detect whether the message handler was actually called or not (the only condition I can think of for that happening is if the target HWND is invalid so SendMessage() cannot find its window procedure).
You can use GetWindowThreadProcessId() and GetCurrentThreadId() to check if the target HWND is owned by the calling thread or not.
What exactly is going on inside this Win32 messaging loop? I understand that TranslateMessage is converting keycodes to UTF char codes and sending the WM_CHAR event, but what is the call to PeekMessage doing exactly? Is it filtering out a certain type of message and only translating those?
// Application / Player message loop.
MSG msg;
ZeroMemory(&msg, sizeof(msg));
while(msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// work happens here...
}
Normally the message loop will use GetMessage instead of PeekMessage. The difference is that PeekMessage returns immediately. Returning either TRUE if a message was removed, or FALSE if no message was fetched. On the other hand if the queue is empty, GetMessage blocks until a message arrives.
The point is the comment stating work happens here. Presumably the author had some reason why the normal blocking message loop would not suffice. The down side of the non-blocking message loop code in the question is that it is a busy loop. It will not idle and so it will fully consume the CPU, unless there is a call to Sleep() or similar that you have excised.
In a comment you say that you actually want to pull off keyboard messages only, and just messages for a specific window. You need to call PeekMessage like this:
PeekMessage(&msg, hwnd, WM_KEYFIRST, WM_KEYLAST, PM_REMOVE)
All it is is a nonblocking way to get messages. It checks to see if there is a message, and if there is, it takes it out of the queue and puts it in &msg.
Check the docs.
The second parameter says which window to look in. In this case, it's "all windows in the thread."
The third and fourth parameter do let you specify whether you want keyboard or mouse events, but currently is set to "all".
In MSDN's Win32-Api documentation (at http://msdn.microsoft.com/en-us/library/ms633573%28VS.85%29.aspx) on the WindowProc, it states: The return value is the result of the message processing and depends on the message sent.
Since I have to implement this (callback) procedure, I'd like to know what it depends on, and what I have to return. Can someone shed some light on this?
It is dependent on the exact message you are processing. You need to refer to the documentation for that message to see the expected values and meanings of the return value.
For instance, for WM_CREATE, you should return zero to continue window creation, and -1 to fail and destroy the window. For WM_GETICON, you should return a handle to the icon for your window.
For messages that you do not explictly handle, you should call DefWindowProc, passing to it all the parameters to your window proc, and return its return value to the caller.
Michael's answer answers the question perfectly, but just for reference, the usual return value will always be 0.
For most messages it means that your application has processed the message. But always consult the MSDN page for the actual message to know for sure.
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.