Link to home
Start Free TrialLog in
Avatar of termination
termination

asked on

PostMessage or SendMessage?

What is the difference?  I have used both functions extensively but have never found a difference.  Can someone please explain the difference?

e.g.  PostMessage( hwnd,WM_CLOSE,0,0 );
yields the same effect as:
      SendMessage( hwnd,WM_CLOSE,0,0 );

Please explain?
ASKER CERTIFIED SOLUTION
Avatar of thresher_shark
thresher_shark

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of nietod
nietod

One small point that is not quite clear is that sendmessage() completely bypasses the queue.  the message does not go in the queue.  Instead the window procedure is called with the message directly from the SendMessage() procedure.   This is important because the it means that a message sent with SendMessage will be processed before any messages that are waiting in the queue.

Also it is usually best to use SendMessages for messages that must be handled within a thread and PostMessage for message that must be handled across threads.  Those aren't absolute rules, but often good guidelines.
SendMessage bypasses the queue?  Really.  Gee, I never knew that.  I always thought it sat there until it was processed.  Learning something new every day! :-)
Though the difference seems to be subtle, sometimes they make completely different results, especially in some message handlers. You have to use PostMessage instead of SendMessage in some message handlers if you want to do next step after current message is completely processed. Otherwise, current message handler might override what you are going to do.

Personally, I would prefer to use PostMessage whenever possible. Some messages must be used with SendMessage, such as WM_COPYDATA.

And there are some other functions similar to PostMessage and SendMessage, such as PostThreadMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessage, etc.
Nietod or Chensu: Please correct me if i am wrong.

If i use SendMessage (and since it by passes the Queue), another program with a Message Hook will not be able to identify the message.  

I assume this happens because SetWindowsHookEx(WH_MESSAGE, ..) call backs only when a new message is added to the queue.


Sorry, but SendMessages are hooked as well.  There are 3 hooks directly related to window messages.

The WH_GETMESSAGE hook is called whenever GetMessage() retrieves a message.  This will get only the messages sent with PostMessage() that is, the ones in the queue (or that appear to be in the queue, so don't actually get stored inthe queue.)

The WH_CALLWINDOWPROC hook is called before the window procedure is called to handle a message.  This will hook every message.  First of all it will hook the SendMessage() messages since they call thw window procedure directly.  It will also hook the messages that are posted (ussually), because when the posted messages are retreived with GetMessage() they are usually sent to the window procedure with DispatchMessage().  Needless to say, DispatchMessage just calls the window procedure with SendMessage().  

Similarly, the WH_CALLWINDOWPROCRET is called after the window procedure handles a message.  This will also be for all messages.

Thanks for your comment.

i am a little confused. I understand that WH_CALLWINDOWPROC  and WH_CALLWINDOWPROCRET  hooks will capture all messages.  

But what about WH_GETMESSAGE hook ?  
1).  This hook is called only when GetMessage retrieves a message
2).  GetMessage is used to retrives messages from the Queue.
3).  SendMessage does NOT put the message in the Queue

so, how can my hook procedure (hooked with WH_GETMESSAGE) be called when the app receives a message via SendMessage ?

In my programs if i use a WH_GETMESSAGE hook then i do not receive WM_PAINT (&several other) messages. But i receive all of them with WH_CALLWINDOWPROC.


a WH_GETMESSAGE hook is used it will not be notified of messages that are sent with SendMessage().  the other two hooks will be notified for all messages.


The WM_GETMESSAGE might not detect WM_PAINT messages.  These messages (as I said above) are a little special.  (so are WM_TIMER)  They are never really placed in the queue.  They are returned with the queue is empty and a window has non-empty invalid region.
Thanks for the clarification nietod.
Avatar of termination

ASKER

Thank you everyone.  I have learned a great deal from these discussions.
Thank you!  You really should award some points to nietod though.  He contributed much more than me.
Hello Sir's

 Really had lot of good solutions were here for lot of practical problems in this thread.

I was struggling with Wh_getmessage hook with this problem.

I used Wh_getmessge hook and used postmessge to send additional characters in my application.


the problem i have is this

if i use this in notepad or photoshop

say i press 'a' and and 'a' get printed
now if i presss 'b' then what i am doing is changing 'b' into backspace and then posting two new characters

msg->message=WM_KEYDOWN;
msg->wParam = VK_BACK;

if i use this alone without sending postmessage
then it works in all application where it removes 'a'when i pressed 'b'

but if i use postmessage with this message

msg->message=WM_KEYDOWN;
msg->wParam = VK_BACK;
PostMessage(C,D);

Then what happens is 'a' remains there while first character of postmessage is there while the second character is removed

a , b -> backspace ,postmessage (c and d)

desired result cd

actual output coming = ac ( d is removed.)

But it works as desired (desired result cd) in all other applications.

so what i have did is
Changed
B->NULL
PostMessage(BackSpace,C.D)

desired result cd

in notepad and photoshop i get the desired output
but in all the other applicaiton i get

outpu ->acd

backspace which i send dont seem to work

please help me in this.

Thanks in advance
with regards
vimal