SendMessage and PostMessage which one is better to use? - visual-studio-2010

searching the web for the difference between these two function calls, I've found that:
The difference between these two API calls is the way that they return control to the calling application. With SendMessage control is not returned to the calling application until the window that the message was sent to has completed processing the sent message, however with PostMessage control is returned to the calling application immediately, regardless of weather or not the sent message has been processes.
postMessage: Sends a message in the message queue associated with the thread and returns without waiting for the thread to process that messaage.
SendMessage: calls the window procedure for the specified window and does not return until the window procedure has processed the message.
PostMessage is a Asynchronous function where as SendMessage is a synchronous function.
Now the question is for my application ( which needs high performance ) which function is better to be used?
Note that I'm using MFC in visual studio 2010 and for this code:
CWnd *pParentOfClass = CWnd::GetParent();
pParentOfClass ->
I just have these functions for sending messsages:
PostMessageW
SendMessage
SendMessageW
More questions:
Can you tell me the difference between SendMessage and SendMessageW?

You actually already answered your own question by describing SendMessage and PostMessage.
SendMessage: Sends a message and waits until the procedure which is responsible for the message finishes and returns.
PostMessage: Sends a message to the message queue and returns immediately. But you don't know when that message is actually being processed. Therefore, if you should be expecting an answer from that processed message, you will most likely get it through a message as well.
It really depends which one to use, but the end results are pretty much the same, it's just about timing. Also, PostMessage is especially useful in multi-threaded applications, which allows you to safely communicate between threads via their created windows.
PostMessage or SendMessage that end with A or W are just indicators how strings will be interpreted, i.e. single or multibyte, respectively. The ones without the A or W ending are preprocessor macros and will delegate to whatever you're application is set up to.

Related

Win32 API SendMessage with HWND_BROADCAST

I am trying to send a message using myresult=SendMessage(hWnd,...). As I understand it, SendMessage sends a Windows message to the specified target hWnd; the target's WndProc returns a long value; that value is returned by SendMessage (myresult). Am I right so far?
Ok, now if the SendMessage hWnd is HWND_BROADCAST, it is sent to all top-level windows. So which window's WndProc determines the return value?
UPDATE: 02-10-20
Just to clear up what I hoped to do...
My app consists of a small constellation of windows apps that need to communicate via Windows Messages. My plan was to broadcast a registered message, e.g., WM_IDENTIFYMYAPP, and identify all siblings by responses. That won't for the reason explained in the answer by Adrian Mole.
The return value will be that from whatever is the last of the receiving windows to process the message and return; which window this is is difficult (if not impossible) for the sending application to determine.
Generally, when you want to use HWND_BROADCAST to notify multiple windows (or to communicate with a window to which you don't have a handle), you should use the (asynchronous) PostMessage function (which returns immediately) rather than SendMessage (which waits for all receiving windows to process the message).
Using the (synchronous) SendMessage with HWND_BROADCAST as the target can cause many undesirable effects, as discussed here on Stack Overflow. But note, there are some message that cannot be sent asynchronously (via PostMessage) - WM_COPYDATA is one that I know of.

Windows messages and their deterministic properties

I'd like to confirm what I think to be true. When I use Windows SendMessage(), this is a deterministic call in that it will execute immediately (will not return until the message is processed) as opposed to PostMessage() which is non-deterministic as it can be preempted by any other message that happens to be in the queue at that moment in time (in fact it will not be executed until it hits the message loop).
Is this a fair assessment, or am I missing something?
That is essentially true for in-process calls. Cross-process SendMessage works similar, but processing of the message doesn't begin until the receiver process calls GetMessage (or its kin).
Your UI thread has a message pump that looks something like:
while (GetMessage(&msg))
DispatchMessage(&msg);
PostMessage causes the message to be put onto the message queue. GetMessage removes the oldest message from the queue (FIFO*).
DispatchMessage causes the WndProc associated with the message's target window to be called with the message.
SendMessage basically bypasses this chain and calls the WndProc directly (more or less).
A lot of standard window messages result in a chain of SendMessage calls where sending one message sends another which sends another. That chain is often referred to as "the current dispatch". If you need your message to be processed inside the chain, use SendMessage. If you need it to be processed after the current dispatch has completed, use PostMessage.
You can use a tool like Spy++ to see Windows messaging in action, or to debug problems you're having with message order of operations.
[*] It's not strictly a FIFO queue because certain kinds of messages (i.e. timer, mouse, keyboard) are not actually posted to the queue, but rather generated on the fly. For the sake of simplicity, you can think of it as a FIFO.

Using GetWindowText synchronously

I don't quite understand how GetWindowText can work for a window on the same thread as the caller. If GetWindowText blocks until the message is processed, how can the thread call DispatchMessage? It's been blocked inside GetWindowText. Does this mean that GetWindowText must always be called from a separate thread from the one operating the message loop?
GetWindowText is just a thin wrapper for SendMessage(WM_GETTEXT).
Messages sent to a window are always processed in the thread which created the window (windows have "thread affinity"). Sent messages do not go through DispatchMessage, rather GetMessage (or PeekMessage or MsgWaitForMultipleObjects) will call the window procedure directly, for messages sent from another thread. If the message is sent from the same thread, SendMessage will call the window procedure.
The SendMessage documentation says:
The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
And the GetMessage documentation says:
Retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.
From the PeekMessage docs:
Dispatches incoming sent messages, checks the thread message queue for a posted message, and retrieves the message (if any exist).
The behavior of sending messages has previously been highlighted on Raymond Chen's excellent blog, The Old New Thing, which all Win32 developers ought to subscribe to:
If you use any of the above send-type functions to send a message to a window that belongs to the sending thread, the call is made synchronously.
http://blogs.msdn.com/b/oldnewthing/archive/2004/11/19/266664.aspx
Recall that SendMessage delivers the message directly to the window procedure; the message pump never sees it.
http://blogs.msdn.com/b/oldnewthing/archive/2008/12/23/9248851.aspx
And of course, there are related questions found here on StackOverflow:
SendMessage vs PostMessage + WaitForSingleObject

Sending and receiving Windows messages

Windows messages seems a good way to notify an application on Windows OSes. It actually works well, but few question comes up to my mind:
How to specify structured data to the lparam of the SendMessage routines (like many message codes does)? I mean... of course the parameter is a pointer, but how the process access to it? Maybe is it allocated by a DLL loaded by the processes sending/receiving the message?
Is it possible to share message structured parameters (between sender and receiver)? They are marshalled between the send operation and the peeking operation? If this is the case, it is possible to return data from the caller by modifying the structured parameter? This could be usefull with SendMessage, since it is executed synchronously, instead the PostMessage routine.
Other doubts...
What the differences from PostMessage and SendNotifyMessage?
Is it possible to cause a deadlock in the case an application calls SendMessage to itself while processing the message pump?
If the message is one of the standard window's messages - usually with a message id between 0 and WM_USER, then the systems window message dispatching logic contains code to marshal the struct to the any processes the message is dispatched to.
Messages above WM_USER get no such treatment - and this includes all the common control messages introduced with Windows 95 - you cannot end any of the LVM_* (list view messages) or other new control messages to a control in a different process and get a result back.
WM_COPYDATA was specifically introduced as a general purpose mechanism for user code to marshal arbitrary data between processes - outside of WM_COPYDATA (or reusing other windows standard messages) there is no way to get windows to automatically marshal structured data using the message queue mechanism into another process.
If it is your own code doing the sending AND receiving of messages, you could use a dll to define a shared memory section, instead of sending pointers (the dll might be based differently in each process) sends offsets to the shared memory block.
If you want to exchange structured data with external applications that do not marshal their data (for example to extract data from a list or tree view) then you need to perform dll injection so you can send and process the message from "in-process".
SendNofityMessage is different to PostMessage because PostMessage always puts the message in the message queue, whereas SendNotifyMessage acts like SendMessage for windows in the same process. Then, even if the target window is in another process, the message is dispatched DIRECTLY to the window proc not placed in the posted message queue for retreivel via GetMessage or PeekMessage.
Lastly it is possible to cause a deadlock - however while in a "blocking" sendmessage waiting for another thread to reply, SendMessage will dispatch messages sent (not posted) from other threads - to prevent deadlocks. This mitigates most potential deadlocks, but its still possible to create deadlocks by calling other blocking apis, or going into modal message processing loops.
Your concerns apply primarily in the case of messages sent between processes -- within a process, you can just send a pointer, and the sender just has to ensure the data remains valid until the receiver is finished using it.
Some interprocess messages require you to work with an HGLOBAL (e.g., the clipboard messages). Others require an explicit block size (e.g., with WM_COPYDATA). Still others send data in a pre-specified structure (e.g., a zero-terminated string) to support marshalling.
Generally speaking you can't return a value by modifying the block you received. To return a value, you need to (for example) send a reply message.
SendMessage has some (fairly complex) logic to prevent deadlocks, but you still need to be careful.

How is executed a SendMessage from a different thread?

When we send a message, "if the specified window was created by the calling thread, the window procedure is called immediately as a subroutine".
But "if the specified window was created by a different thread, the system switches to that thread and calls the appropriate window procedure. Messages sent between threads are processed only when the receiving thread executes message retrieval code." (taken from MSDN documentation for SendMessage).
Now, I don't understand how (or, more appropriately, when) the target windows procedure is called. Of course the target thread will not be preempted (the program counter is not changed). I presume that the call will happen during some wait function (like GetMessage or PeekMessage), it is true? That process is documented in detail somewhere?
Update: the rationale behind it is explained by the QS_SENDMESSAGE flag of GetQueueStatus() and MsgWaitForMultipleObjects():
QS_SENDMESSAGE
A message sent by another thread or application is in the queue.
This, along with additional remarks in MSDN documentation, means that a message sent by another thread is actually posted to the queue. Then, as soon as GetMessage or PeekMessage are called, it will be processed before any other posted message by being sent directly to the window procedure.
I see some confusion here.
According to the MSDN docs, when you touch the message queue of the current thread with the intent of message processing (e.g. if you call PeekMessage or GetMessage), all pending sent (i.e. non-queued) messages from other threads are handled - passed to the WndProc - and then the message queue is checked, so:
sent messages never go through DispatchMessage and are handled as soon as possible:
in the current thread, they are simply passed to WndProc
in another thread, they are handled before any posted message processing
to be able to handle sent messages, the target thread still needs a message pump
PostThreadMessage does just what it states - posts a message in a threads queue - such messages are not directed to any window and must be handled explixitly
the only messages handled by DispatchMessage are those created by PostMessage or some system facility (timers, events, user input, etc.)
to avoid deadlocks, use SendNotifyMessage, SendMessageTimeout or SendMessageCallback instead of plain SendMessage between different threads
For further reference, study the Remarks section of the MSDN PeekMessage entry.
Short answer: When the target thread calls GetMessage (or PeekMessage) followed by DispatchMessage, then the SendMessage from the other thread is received and handled.
I am not certain if the received SendMessage preempts other messages in the queue or not. Either way, a SendMessage from one thread to another is like saying: "Post this message to the other thread's message queue. Return when that thread has finished processing it".
An now for an answer you didn't ask for:
In general, when I program interactions between the main UI thread and a worker thread, I try to avoid using SendMessage. If you aren't careful, you can get into a situation where both threads are deadlocked on each other. (Think of the case where the main thread is calling WaitForSingleObject to wait for the worker thread to complete, but the worker thread is blocked on SendMessage back to the UI thread).
Every windows is associated with a thread. You can use GetWindowThreadProcessId to retrieves the thread of every window. If you send a message to a windows from the other thread with respect of PostThreadMessage the message will be placed in the thread's message queue. The thread must have a get-message loop (with GetMessage for example) to get the messages and dispatch there to the window procedure of the window.
It you call SendMessage instead of PostThreadMessage you call the Windows Procedure directly without placing it in the message queue. Some nonqueued messages are sent also immediately to the destination window procedure, bypassing the system message queue and thread message queue. (see http://msdn.microsoft.com/en-us/library/ms644927(VS.85).aspx#nonqueued_messages). The main reason to use SendMessage instead of PostThreadMessage if you want to give some information from another windows (control) like read a text from an another control during processing of another message. You should do this only if it really needed. So if you use SendMessage to send a message to a windows from another thread your current thread must be blocked for some time.
It can be a good idea to use PostThreadMessage or SendMessageCallback instead of SendMessage if it is possible.

Resources