PostMessage (hwnd, WM_SETTEXT, ..) does not work while PostMessage (hwnd, WM_QUIT, ..) does

I have 2 applications, one is a hidden window ("hW"), the other is a console application ("CA"), from which, I believe, sends hW commands. In a console application, I get an hW descriptor, and here's the question: if I'm running:

PostMessage(hwnd, WM_QUIT, NULL, NULL); 

everything works fine, the message goes into hW and disables it. But if I send

 PostMessage(hwnd, WM_SETTEXT, NULL, (LPARAM)"texttext"); 

the message does not get into hW at all. Spy ++ also shows that the message does not fall into hW. Is there anything special about WM_SETTEXT that prevents it? Thanks in advance.

OK found the answer here http://cboard.cprogramming.com/windows-programming/72589-wm_settext-postmessage.html

  Turns out the API tries to protect me against scope issues;  PostMessage () 
 always fails with WM_SETTEXT, or any other system-defined message that has
 a pointer as a parameter.Which gets me to SendMessage (), which is not good,
 because i wanted asynchronous messaging .... 


PPS
It also looks like

 SendMessage(hwnd, WM_QUIT, NULL, NULL); 

doesn't do anything to the target application. Even in a simple test application, for example

  HWND hNote; if (!(hNote=FindWindow(L"Notepad",NULL))) exit(1); SendMessage(hNote, WM_QUIT, NULL, NULL); 

while

 PostMessage(hNote, WM_QUIT, NULL, NULL); 

works.
Everything that looks so illogical to me ... Is there any universal function that works correctly with any kind of message?

+6
source share
3 answers

Different messages have different requirements. Some of them must be sent to the queue. And some should be delivered synchronously. Thus, the system is designed to use both delivery mechanisms.

In the case of WM_SETTEXT it must always be delivered synchronously. This is because the window manager must be able to control the text data lifetime. Raymond Chen talked about this problem: Why can't I send a WM_COPYDATA message, but can I send a SendMessageTimeout with a tiny timeout?

There is a danger with calling SendMessage when the window is in another process. If another process freezes, your process will also not hang. Because SendMessage is synchronous.

The solution is to call SendMessageTimeout . This will force the string data into another process. And you can set a timeout to ensure that if another process freezes, your process can avoid this fate.

+8
source

Starting with your last question: there is no universal message function that will do what you want.

Analyze your cases:

  • WM_SETTEXT : This message accepts a pointer, so you cannot safely place it between processes, since they will have separate memory addresses, and a pointer from one process will be meaningless for another. You can use SendMessage() because Windows knows about the message, backs up the data, and makes an additional hack. But with PostMessage() there is no (cannot be) such magic.

  • WM_QUIT : This is a special message that causes interruption of message traversal. In short, all he does is GetMessage return FALSE to complete the standard message loop (1). But ah! this will only work if you are PostMessage() . When you send a message SendMessage() message, it is sent directly to the corresponding window function, without even stopping in the message queue. And windows don't do anything with WM_QUIT because they just don't expect it. In fact, even when you sent a message, this message will not reach the window, since a regular loop does not call DispatchMessage() for it. This is why it is usually sent to the stream, without a window, and therefore there are functions that do all this: PostQuitMessage() .

(1) Standard message loop:

 while (GetMessage(&msg, 0, 0, 0)) DispatchMessage(&msg); 

As a footnote, you can use several tricks to move data between processes:

  • Use WM_COPYDATA . AFAIK cannot be used with PostMessage() , but perhaps you can create two threads in the target process so that the first receives WM_COPYDATA and returns quickly and then queues it to the second thread.

  • Use shared memory (search CreateFileMapping() ) and PostMessage() offset into this memory. You should probably use a specific WM_APP + x user message, not a system one. However, beware of synchronization issues, you will need a mutex or something else.

  • Named pipes! (my favorite)

  • Sockets

    .

+1
source

What you are trying to do is pass two separate processes, regular messages will not work, but there is one that could do the trick: WM_COPYDATA message. A related question can be found here.

0
source

All Articles