BOOL WINAPI PostThreadMessage(
_In_ DWORD idThread,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Parameters
idThread [in]
Type: DWORD
The identifier of the thread to which the message is to be posted.
The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the User or GDI functions. For more information, see the Remarks section.
Message posting is subject to UIPI. The thread of a process can post messages only to posted-message queues of threads in processes of lesser or equal integrity level.
This thread must have the SE_TCB_NAME privilege to post a message to a thread that belongs to a process with the same locally unique identifier (LUID) but is in a different desktop. Otherwise, the function fails and returnsERROR_INVALID_THREAD_ID.
This thread must either belong to the same desktop as the calling thread or to a process with the same LUID. Otherwise, the function fails and returnsERROR_INVALID_THREAD_ID.
Msg [in]
Type: UINT
The type of message to be posted.
wParam [in]
Type: WPARAM
Additional message-specific information.
lParam [in]
Type: LPARAM
Additional message-specific information.
Return value
Type:
Type: BOOL
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, callGetLastError. GetLastError returns ERROR_INVALID_THREAD_ID if idThread is not a valid thread identifier, or if the thread specified byidThread does not have a message queue. GetLastError returnsERROR_NOT_ENOUGH_QUOTA when the message limit is hit.
Remarks
When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).
The thread to which the message is posted must have created a message queue, or else the call toPostThreadMessage fails. Use the following method to handle this situation.
Create an event object, then create the thread.
Use the WaitForSingleObject function to wait for the event to be set to the signaled state before callingPostThreadMessage.
In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
Set the event, to indicate that the thread is ready to receive posted messages.
The thread to which the message is posted retrieves the message by calling theGetMessage or PeekMessage function. The hwnd member of the returnedMSG structure is NULL.
Messages sent by PostThreadMessage are not associated with a window. As a general rule, messages that are not associated with a window cannot be dispatched by theDispatchMessage function. Therefore, if the recipient thread is in a modal loop (as used byMessageBox or DialogBox), the messages will be lost. To intercept thread messages while in a modal loop, use a thread-specific hook.
The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >=WM_USER) to another process, you must do custom marshalling.
There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the following registry key.
Above Text From MSDN
Example:
#include <windows.h>
#include <cstdio>
#include <process.h>
#define MY_MSG WM_USER+100
const int MAX_INFO_SIZE = 20;
HANDLE hStartEvent; // thread start event
// thread function
unsigned __stdcall fun(void *param)
{
printf("thread fun start\n");
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent)) //set thread start event
{
printf("set start event failed,errno:%d\n",::GetLastError());
return 1;
}
while(true)
{
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s\n",pInfo);
delete[] pInfo;
break;
}
}
};
return 0;
}
int main()
{
HANDLE hThread;
unsigned nThreadID;
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
if(hStartEvent == 0)
{
printf("create start event failed,errno:%d\n",::GetLastError());
return 1;
}
//start thread
hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID );
if(hThread == 0)
{
printf("start thread failed,errno:%d\n",::GetLastError());
CloseHandle(hStartEvent);
return 1;
}
//wait thread start event to avoid PostThreadMessage return errno:1444
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
int count = 0;
while(true)
{
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
sprintf(pInfo,"msg_%d",++count);
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//post thread msg
{
printf("post message failed,errno:%d\n",::GetLastError());
delete[] pInfo;
}
::Sleep(1000);
}
CloseHandle(hThread);
return 0;
}
_In_ DWORD idThread,
_In_ UINT Msg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
Parameters
idThread [in]
Type: DWORD
The identifier of the thread to which the message is to be posted.
The function fails if the specified thread does not have a message queue. The system creates a thread's message queue when the thread makes its first call to one of the User or GDI functions. For more information, see the Remarks section.
Message posting is subject to UIPI. The thread of a process can post messages only to posted-message queues of threads in processes of lesser or equal integrity level.
This thread must have the SE_TCB_NAME privilege to post a message to a thread that belongs to a process with the same locally unique identifier (LUID) but is in a different desktop. Otherwise, the function fails and returnsERROR_INVALID_THREAD_ID.
This thread must either belong to the same desktop as the calling thread or to a process with the same LUID. Otherwise, the function fails and returnsERROR_INVALID_THREAD_ID.
Msg [in]
Type: UINT
The type of message to be posted.
wParam [in]
Type: WPARAM
Additional message-specific information.
lParam [in]
Type: LPARAM
Additional message-specific information.
Return value
Type:
Type: BOOL
If the function succeeds, the return value is nonzero.
If the function fails, the return value is zero. To get extended error information, callGetLastError. GetLastError returns ERROR_INVALID_THREAD_ID if idThread is not a valid thread identifier, or if the thread specified byidThread does not have a message queue. GetLastError returnsERROR_NOT_ENOUGH_QUOTA when the message limit is hit.
Remarks
When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).
The thread to which the message is posted must have created a message queue, or else the call toPostThreadMessage fails. Use the following method to handle this situation.
Create an event object, then create the thread.
Use the WaitForSingleObject function to wait for the event to be set to the signaled state before callingPostThreadMessage.
In the thread to which the message will be posted, call PeekMessage as shown here to force the system to create the message queue.
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE)
Set the event, to indicate that the thread is ready to receive posted messages.
The thread to which the message is posted retrieves the message by calling theGetMessage or PeekMessage function. The hwnd member of the returnedMSG structure is NULL.
Messages sent by PostThreadMessage are not associated with a window. As a general rule, messages that are not associated with a window cannot be dispatched by theDispatchMessage function. Therefore, if the recipient thread is in a modal loop (as used byMessageBox or DialogBox), the messages will be lost. To intercept thread messages while in a modal loop, use a thread-specific hook.
The system only does marshalling for system messages (those in the range 0 to (WM_USER-1)). To send other messages (those >=WM_USER) to another process, you must do custom marshalling.
There is a limit of 10,000 posted messages per message queue. This limit should be sufficiently large. If your application exceeds the limit, it should be redesigned to avoid consuming so many system resources. To adjust this limit, modify the following registry key.
Above Text From MSDN
Example:
#include <windows.h>
#include <cstdio>
#include <process.h>
#define MY_MSG WM_USER+100
const int MAX_INFO_SIZE = 20;
HANDLE hStartEvent; // thread start event
// thread function
unsigned __stdcall fun(void *param)
{
printf("thread fun start\n");
MSG msg;
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
if(!SetEvent(hStartEvent)) //set thread start event
{
printf("set start event failed,errno:%d\n",::GetLastError());
return 1;
}
while(true)
{
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case MY_MSG:
char * pInfo = (char *)msg.wParam;
printf("recv %s\n",pInfo);
delete[] pInfo;
break;
}
}
};
return 0;
}
int main()
{
HANDLE hThread;
unsigned nThreadID;
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); //create thread start event
if(hStartEvent == 0)
{
printf("create start event failed,errno:%d\n",::GetLastError());
return 1;
}
//start thread
hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID );
if(hThread == 0)
{
printf("start thread failed,errno:%d\n",::GetLastError());
CloseHandle(hStartEvent);
return 1;
}
//wait thread start event to avoid PostThreadMessage return errno:1444
::WaitForSingleObject(hStartEvent,INFINITE);
CloseHandle(hStartEvent);
int count = 0;
while(true)
{
char* pInfo = new char[MAX_INFO_SIZE]; //create dynamic msg
sprintf(pInfo,"msg_%d",++count);
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0))//post thread msg
{
printf("post message failed,errno:%d\n",::GetLastError());
delete[] pInfo;
}
::Sleep(1000);
}
CloseHandle(hThread);
return 0;
}