Click to See Complete Forum and Search --> : DispatchMessage return value


Runt888
May 24th, 2006, 03:58 PM
If I use SendMessage to send a message to a window in a different process, how does the return value get passed back to my process?

Here's what I think happens (in very broad steps):
1. I call SendMessage.
2. Windows puts the message in the message queue for the specified window, and puts my process's thread to sleep.
3. The other process's message loop eventually calls DispatchMessage with my message.
4. Some window procedure handles the message and returns a value.
5. ???
6. Windows sets the return value for the SendMessage call and wakes up my process's thread.

How does Windows deal with step 5?

You may be wondering why I need to know. I'm building an app that only allows a single instance to run at one time. When my app starts up, it calls RegisterWindowMessage to register a system wide message. If it detects that another instance is running, it sends this message to every window in the system (using SendMessageTimeout). If the return value from SendMessageTimeout is equal to my system wide message, then I know that I've found the correct window handle, and I call SetForegroundWindow to show the first instance of my app.

This works great, assuming that my window procedure handles the message correctly. However, in my windowing framework, I allow the message processing to be overridden, so there's no guarantee that the message will be handled correctly (in theory if the message processing is overridden, the default message processing will be called eventually, but it's not enforced).

So I'm trying to handle this message in my message loop, before it gets passed to the window procedure for processing. Testing for the message in the message loop is trivial. However, I don't know how to handle the return value.

Any ideas?

Thanks!

Kelly

Brenton S.
May 24th, 2006, 08:20 PM
Hi Runt888,

Well, if you want a single instance to run at a time, I suggest you use the CreateMutex (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/base/createmutex.asp) function. Here's an example program that checks if any other instances of the current application is running:

BOOL IsAppAlreadyRunning()
{
if(CreateMutex(NULL, TRUE, "AppAlreadyRunningMutex"))
{
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
return TRUE;
}
}
return FALSE;
}

int main()
{
if(IsAppAlreadyRunning())
{
return 0; // exit; another instance is already running
}

while(TRUE)
;

return 0;

}

Runt888
May 24th, 2006, 08:40 PM
Thanks for the reply. I've already got that part working. I just need to know how the return value from SendMessage works when sending a message to a window in a different process.

kirants
May 25th, 2006, 12:08 AM
Interesting. I don't have an answer to your question. However, I feel there is still no way you will be able to make it fool-proof. Problems.


Even if you were to change your message loop to handle it, there is no stopping an implementor from implementing another message loop on top of the main loop for the same thread.
If you did implement such a thing in your main message loop, it would be misleading for anyone who is gonna implement the window procedure since no matter what they did, what they did won't take effect.


Anyways, why can't you do something like this: Check for the message in message loop and in addition to doing the normal, why don't you bring the window to top right there , instead of having the app that does the SendMessageTimeout do that ?

Also, are you doing a SendMessageTimeout on all windows or only on top-level-windows ?

Runt888
May 25th, 2006, 12:27 AM
Hi Kirants. Thanks for the reply. At first I thought it wouldn't really be a problem, since my framework provides support for modal dialogs, so there's not much reason for the user to run their own loop. However, it wouldn't work if a message box was showing, which is a large problem (I pass other messages to the window also). As far as it being misleading, if the user implemented their own message processing for a window, they would receive all messages to the window except for the special system wide message that I would check for in the message loop.

If it wasn't for the problem above, I like your idea of processing the message in the message loop instead of relying on the return value. The best solution I can think of is to require the user to pass all unprocessed messages to my message handler (kind of like Windows and DefWindowProc, and something they should be doing anyway). If they don't pass it along, then things won't work correctly.

I'm using SendMessageTimeout in conjunction with EnumWindows, so it only sends messages to the top-level windows.

Kelly

philkr
May 25th, 2006, 07:56 AM
Here's what I think happens (in very broad steps):
1. I call SendMessage.
2. Windows puts the message in the message queue for the specified window...
This is the behaviour for PostMessage(). Instead SendMessage() calls the target window procedure directly and blocks until it returns a value. No message queue involved here.

Runt888
May 25th, 2006, 11:03 AM
Ah...that makes more sense. I knew I was missing something there... :blush:

Thanks for the reply!!

Kelly