SendMessage函数功能描述:将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口过程,直到窗口过程处理完消息后才返回。
Postmessage函数则是将消息放入消息队列里,并立即返回。
PostThreadMessage函数:
1 |
BOOL PostThreadMessage( DWORD idThread, |
2 |
UINT Msg, |
3 |
WPARAM wParam, |
4 |
LPARAM lParam |
5 |
); |
它可以用于线程之间的异步通讯,因为它不用等待调用者返回。
常见问题
1)使用SendMessage来实现剪切、复制和粘贴
1 |
SendMessage(hwnd, WM_COPY, 0, 0); |
2 |
SendMessage(hwnd, WM_CUT, 0, 0); |
3 |
SendMessage(hwnd, WM_PASTE, 0, 0); |
2)SendMessage与PostMessage的区别
PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回。
3)SendMessage发送WM_COPYDATA消息在进程间传送数据
WM_COPYDATA消息主要目的是允许在进程间传递少量只读数据。SDK文档推荐用户使用SendMessage()函数,接收方在数据复制完成前不返回,这样发送方就不可能删除和修改数据。
例如:
1 |
std:string strData = "VC知识库 VCKBASE.COM"; |
2 |
COPYDATASTRUCT cds; |
3 |
cds.dwData = 0; |
4 |
cds.cbData = strData.Length(); |
5 |
cds.lpData = strData.c_str(); |
6 |
::SendMessage(hwnd, WM_COPYDATA, NULL, (LPARAM)&cds); |
3、PostThreadMessage有时会失败,报1444错误(Invalid thread identifier. ),其实这不一定是线程不存在的原因,也有可能是线程不存在消息队列(message queue)造成的。事实上,并不是每个thread都有message queue,那如何让thread具有呢? 答案是,至少调用message相关的function一次,比如GetMessage,PeekMessage。
4、如果是postthreadmessage动态分配的memory给另外一个thread,要注意内存的正确释放。并且PostThreadMessage不能够post WM_COPYDATE之类的同步消息,否则会报错!
5、最好不要使用PostThreadMessage post message给一个窗口,使用PostMessage替代。
example:
1 |
#include <windows.h> |
2 |
#include <cstdio> |
3 |
#include <process.h> |
4 |
#define MY_MSG WM_USER+100 |
5 |
const int MAX_INFO_SIZE = 20; |
6 |
HANDLE hStartEvent; |
7 |
|
8 |
unsigned __stdcall fun(void *param) |
9 |
{ |
10 |
printf("thread fun start |
11 |
|
12 |
|
13 |
\n"); |
14 |
MSG msg; |
15 |
PeekMessage(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE); |
16 |
if(!SetEvent(hStartEvent)) |
17 |
{ |
18 |
printf("set start event failed,errno:%d\n",::GetLastError()); |
19 |
return 1; |
20 |
} |
21 |
|
22 |
while(true) |
23 |
{ |
24 |
if(GetMessage(&msg,0,0,0)) |
25 |
{ |
26 |
switch(msg.message) |
27 |
{ |
28 |
case MY_MSG: |
29 |
char * pInfo = (char *)msg.wParam; |
30 |
printf("recv %s\n",pInfo); |
31 |
delete[] pInfo; |
32 |
break; |
33 |
} |
34 |
} |
35 |
}; |
36 |
return 0; |
37 |
} |
38 |
int main() |
39 |
{ |
40 |
HANDLE hThread; |
41 |
unsigned nThreadID; |
42 |
hStartEvent = ::CreateEvent(0,FALSE,FALSE,0); |
43 |
if(hStartEvent == 0) |
44 |
{ |
45 |
printf("create start event failed,errno:%d\n",::GetLastError()); |
46 |
return 1; |
47 |
} |
48 |
|
49 |
hThread = (HANDLE)_beginthreadex( NULL, 0, &fun, NULL, 0, &nThreadID ); |
50 |
if(hThread == 0) |
51 |
{ |
52 |
printf("start thread failed,errno:%d\n",::GetLastError()); |
53 |
CloseHandle(hStartEvent); |
54 |
return 1; |
55 |
} |
56 |
|
57 |
::WaitForSingleObject(hStartEvent,INFINITE); |
58 |
CloseHandle(hStartEvent); |
59 |
int count = 0; |
60 |
while(true) |
61 |
{ |
62 |
char* pInfo = new char[MAX_INFO_SIZE]; |
63 |
sprintf(pInfo,"msg_%d",++count); |
64 |
if(!PostThreadMessage(nThreadID,MY_MSG,(WPARAM)pInfo,0)) |
65 |
{ |
66 |
printf("post message failed,errno:%d\n",::GetLastError()); |
67 |
delete[] pInfo; |
68 |
} |
69 |
::Sleep(1000); |
70 |
} |
71 |
CloseHandle(hThread); |
72 |
return 0; |
73 |
} |
|