SendMessage函数功能描述:将指定的消息发送到一个或多个窗口。此函数为指定的窗口调用窗口过程,直到窗口过程处理完消息后才返回。
Postmessage函数则是将消息放入消息队列里,并立即返回。
PostThreadMessage函数:
BOOL PostThreadMessage( DWORD idThread,
UINT Msg,
WPARAM wParam,
LPARAM lParam
);
它可以用于线程之间的异步通讯,因为它不用等待调用者返回,
.常见问题
1)使用SendMessage来实现剪切、复制和粘贴
SendMessage(hwnd, WM_COPY, 0, 0);
SendMessage(hwnd, WM_CUT, 0, 0);
SendMessage(hwnd, WM_PASTE, 0, 0);
2)SendMessage与PostMessage的区别
PostMessage将消息放入消息队列后马上返回,而SendMessage直到窗口过程处理完消息后才返回,PostMessage 是异步的,SendMessage 是同步的。PostMessage 只把消息放入队列,不管消息是否被处理就返回,消息可能不被处理;而 SendMessage 等待消息被处理完了之后才返回,如果消息不被处理,发送消息的线程将一直被阻塞。
3、如果在同一个线程内,SendMessage 发送消息时,由 USER32.DLL 模块调用目标窗口的消息处理程序,并将结果返回。SendMessage 在同一线程中发送消息并不入线程消息队列。PostMessage 发送消息时,消息要先放入线程的消息队列,然后通过消息循环分派到目标窗口(DispatchMessage)。
如果在不同线程内,SendMessage 发送消息到目标窗口所属线程的消息队列,然后发送消息的线程在 USER32.DLL 模块内监视和等待消息处理,直到目标窗口处理完返回。SendMessage 在返回前还做了很多工作,比如,响应别的线程向它 SendMessage。Post 到别的线程时,最好用 PostThreadMessage 代替 PostMessage,PostMessage 的 hWnd 参数可以是 NULL,等效于 PostThreadMessage + GetCurrentThreadId。Post WM_QUIT 时,应使用 PostQuitMessage 代替。
4)SendMessage发送WM_COPYDATA消息在进程间传送数据
WM_COPYDATA消息主要目的是允许在进程间传递少量只读数据。SDK文档推荐用户使用SendMessage()函数,接收方在数据复制完成前不返回,这样发送方就不可能删除和修改数据。
例如:
std:string strData = "VC COM";
COPYDATASTRUCT cds;
cds.dwData = 0;
cds.cbData = strData.Length();
cds.lpData = strData.c_str();
::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之类的同步消息,否则会报错!
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);
PeekMessage
原型如下:
BOOL PeekMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax,
UINT wRemoveMsg
);
BOOL WaitMessage();
while(GetMessage(&msg, NULL, 0, 0))
{
if(!TranslateAccelerator(msg.hWnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
首先,GetMessage从进程的主线程的消息队列中获取一个消息并将它复制到MSG结构,如果队列中没有消息,则
GetMessage
函数将等待一个消息的到来以后才返回。如果你将一个窗口句柄作为第二个参数传入GetMessage,那么
只有指定窗口的的消息
可以从
队列
中获得。GetMessage也可以从
消息队列
中过滤消息
只接受消息队列中落在范围内的消息
。这时候就要利用
GetMessage/PeekMessage指定一个消息过滤器
。这个过滤器是一个
消息标识符的范围
或者是
一个窗体句柄
,或者两者同时指定。当应用程序要查找一个后入
消息队列
的消息是很有用。
WM_KEYFIRST
和
WM_KEYLAST
常量用于接受所有的键盘消息。
WM_MOUSEFIRST
和
WM_MOUSELAST
常量用于接受所有的鼠标消息。
if (::PeekMessage(&msg, m_hWnd, WM_KEYFIRST,WM_KEYLAST, PM_REMOVE))
{
if (msg.message == WM_KEYDOWN && msg.wParam == VK_ESCAPE)...
}