1.新建两个对话框项目,分别在StdAfx.h中添加自定义消息
#define WM_CONTROLPRINT WM_USER+1001
2.发送端,获得其他窗口句柄的方法FindWindow();
void CAaDlg::OnButtonsend()
{
// TODO: Add your control notification handler code here
//通过窗体名称,获取其他进程窗口句柄
CWnd *pWnd=CWnd::FindWindow(NULL,_T("Bb"));
if(pWnd==NULL)
{
AfxMessageBox("接收程序没有运行!");
return ;
}
pWnd->SendMessage(WM_CONTROLPRINT,NULL,0);
}
3.接收端,接收其他进程发过来的消息。
//消息响应函数
void OnControlPrint(WPARAM wParam, LPARAM lParam);
void CBbDlg::OnControlPrint(WPARAM wParam, LPARAM lParam)
{
if(wParam==0 && lParam==0)
AfxMessageBox("HelloWorld!");
return ;
}
//添加消息映射
BEGIN_MESSAGE_MAP(CBbDlg, CDialog)
//{{AFX_MSG_MAP(CBbDlg)
ON_MESSAGE(WM_CONTROLPRINT, OnControlPrint)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
SendMessage 发送数据结构struct
发送
int SendLen = 100;
struct struct_SendPara
{
BYTE SendData[256];
CString Name;
}SendPara;
memcpy((unsigned char *)SendPara.SendData, (unsigned char *)SendData, SendLen);
SendPara.Name = Name;
::SendMessage(::AfxGetApp()->m_pMainWnd->m_hWnd,WM_DLG_ORDER,(WPARAM)SendLen,(LPARAM)&SendPara);
接收
struct struct_SendPara
{
BYTE SendData[256];
CString Name;
}*SendPara;
int SendLen = (int)wParam;
SendPara = (struct_SendPara*)lParam;
boost::thread编程实战(3)——通过PostThreadMessage和PeekMessage实现线程通信
包含PostThreadMessage和PeekMessage的介绍
1. PostThreadMessage和PeekMessage的介绍
① PostMessage 和SendMessage 的区别
PostMessage
是异步的,SendMessage
是同步的。PostMessage
只把消息放到队列,不管消息是不是被处理就返回,消息可能不被处理;SendMessage
等待消息被处理完了才返回,如果消息不被处理,发送消息的线程将一直处于阻塞状态,等待消息的返回。PostMessage
函数原型:
BOOL PostMessage(HWND hWnd,UINT Msg,WPARAM wParam,LPARAM lParam);
hWnd:
其窗口程序接收消息的窗口的句柄。可取有特定含义的两个值:HWND_BROADCAST:
消息被寄送到系统的所有顶层窗口,包括无效或不可见的非自身拥有的窗口、 被覆盖的窗口和弹出式窗口。消息不被寄送到子窗口。NULL:
此函数的操作和调用参数dwThread设置为当前线程的标识符PostThreadMessage函数一样
Msg:
指定被寄送的消息。
wParam:
指定附加的消息特定的信息。
lParam:
指定附加的消息特定的信息。
返回值:如果函数调用成功,返回非零,否则函数调用返回值为零
参考链接:
windows下多线程通信方法
消息队列和GetMessage/PeekMessage、SendMessage/Postmesage的详解
② PostThreadMessage
PostThreadMessage
方法可以将消息发送到指定线程。
函数原型:
BOOL PostThreadMessage(DWORD idThread,UINT Msg,WPARAM wParam, LPARAM lParam);
注意: PostThreadMessage
参数除了ThreadId
之外,基本和PostMessage
相同。
③ PeekMessage 和GetMessage的区别
GetMessage
是阻塞函数,它会在消息循环中会一直阻塞直到消息队列中出现了消息可以被获取;而PeekMessage
是非阻塞函数,不管有没有获取到消息队列中的消息,它都会返回。PeekMessage
:有消息时返回TRUE
,没有消息返回FALSE
。GetMessage
:有消息时且消息不为WM_QUIT
时返回TRUE
;如果有消息且为WM_QUIT
则返回FALSE
,没有消息时不返回PeekMessage
更多用来检测消息队里中是否有消息,它的最后一个参数可以用来指定获取到消息后要不要把消息从消息队列中移除。通常情况下通过PeekMessage
检测到消息队列有消息之后,再调用GetMessage
去获取。PeekMessage
函数原型:
BOOL PeekMessage(LPMSG IpMsg, HWND hWnd, UINT wMSGfilterMin, UINT wMsgFilterMax, UINT wRemoveMsg);
lpMsg:
接收消息信息的MSG结构指针。hWnd:
其消息被检查的窗口句柄。wMsgFilterMin:
指定被检查的消息范围里的第一个消息。wMsgFilterMax:
指定被检查的消息范围里的最后一个消息。wRemoveMsg:
确定消息如何被处理。此参数可取下列值之一:
值 | 意义 |
---|---|
PM_NOREMOVE | PeekMessage处理后,消息不从队列里除掉。 |
PM_REMOVE | PeekMessage处理后,消息从队列里除掉。 |
PM_NOYIELD | 此标志使系统不释放等待调用程序空闲的线程。可将PM_NOYIELD随意组合到PM_NOREMOVE或PM_REMOVE。 |
参考链接:
Windows消息传递机制详解
PeekMessage使用方法
2. 使用PostThreadMessage和PeekMessage实现线程间通信
程序思路:
- 首先创建一个server线程,获取该线程的ID。
- 接着创建一个client线程,将server线程的ID通过函数参数传递给client线程。
- client线程主动向server线程发送自己的线程ID,之后再发送实际数据。
- server线程循环接收消息,通过消息ID过滤得到client线程的消息。
- server线程在收到client线程之后,发送接收的消息数给client线程。
- 如果server线程收到
WM_QUIT
消息,表示client与其断开通信,自己也结束循环,不在接收消息。
#include <iostream>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <Windows.h>
#include <string.h>
#include <boost/lexical_cast.hpp>
using namespace boost;
DWORD getThreadId(boost::thread::id id){
std::string threadId = boost::lexical_cast<std::string>(id);
DWORD threadNumber = 0;
sscanf(threadId.c_str(), "%lx", &threadNumber);
return threadNumber;
}
void thread1(DWORD threadID){
//向对方线程发送自己的线程id
PostThreadMessage(threadID, WM_USER + 101, GetCurrentThreadId(), 0);
Sleep(500);
//发送自定义消息
for (size_t i = 0; i < 4; i++)
{
std::cout << "Send: " << i * 10 << " , " << i << std::endl;
PostThreadMessage(threadID, WM_USER + 102, i * 10, i);
Sleep(1000);
MSG msg;//在Windows程序中,消息是由MSG结构体来表示的。第二个成员变量message指定了消息的标识符
DWORD id = 0;
//PeekMessage函数,param1(lpMsg):接收消息信息的MSG结构指针;param4(wRemoveMsg):PM_REMOVE指PeekMessage处理后,消息从队列里除掉。
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_USER + 201://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive from " << threadID << ": "<< msg.wParam<< std::endl;
break;
default:
break;
}
}
}
std::cout << "Send Quit" << std::endl;
//发送关闭消息,WM_QUIT:关闭消息循环
PostThreadMessage(threadID, WM_QUIT, 0, 0);
}
void thread2(int x){
MSG msg;
DWORD id = 0;
int count = 0;
bool flag = true;
//发送自定义消息
while (flag){
//PeekMessage函数,param1(lpMsg):接收消息信息的MSG结构指针;param4(wRemoveMsg):PM_REMOVE指PeekMessage处理后,消息从队列里除掉。
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_USER + 101://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive threadID:" << msg.wParam << std::endl;
id = msg.wParam;
PostThreadMessage(id, WM_USER + 201, ++count, 0);
break;
case WM_USER + 102://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive from " << id << ":" << msg.wParam << ", " << msg.lParam << std::endl;
PostThreadMessage(id, WM_USER + 201, ++count, 0);
break;
case WM_QUIT:
std::cout << "Receive from " << id << ": I quit, bye bye!" << std::endl;
flag= false;
break;
default:
break;
}
}
}
}
int main(){
boost::thread thrd2(boost::bind(&thread2, 2));
DWORD id = getThreadId(thrd2.get_id());
boost::thread thrd1(boost::bind(&thread1, id));
thrd1.join();
thrd2.join();
return 0;
}
运行结果如下:
3. 使用PostThreadMessage和PeekMessage实现线程间字符串的传递
现在能实现线程间的通信了,值传递数值是不能满足自己的需求的。自己想要传递字符串,因此查阅了一些资料。
解决方法: 传送字符串地址(字符串得是CString
类型,如果是string类型,需要使用c_str
进行转化),可以将想要传送的数据强制转化为WPARAM
或LPARAM
类型。
程序实例:
#include <iostream>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <Windows.h>
#include <string.h>
#include <boost/lexical_cast.hpp>
using namespace boost;
DWORD getThreadId(boost::thread::id id){
std::string threadId = boost::lexical_cast<std::string>(id);
DWORD threadNumber = 0;
//threadNumber = std::stoul(threadId, nullptr, 16);
sscanf(threadId.c_str(), "%lx", &threadNumber);
return threadNumber;
}
void thread1(DWORD threadID){
//向对方线程发送自己的线程id
PostThreadMessage(threadID, WM_USER + 101, GetCurrentThreadId(), 0);
Sleep(500);
//发送自定义消息
for (size_t i = 0; i < 4; i++)
{
std::string str = "hello, send message to you";
std::cout << "Send: " << str << std::endl;
PostThreadMessage(threadID, WM_USER + 102, (WPARAM)str.length(), (LPARAM)str.c_str());
Sleep(1000);
MSG msg;//在Windows程序中,消息是由MSG结构体来表示的。第二个成员变量message指定了消息的标识符
DWORD id = 0;
//PeekMessage函数,param1(lpMsg):接收消息信息的MSG结构指针;param4(wRemoveMsg):PM_REMOVE指PeekMessage处理后,消息从队列里除掉。
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_USER + 201://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive from " << threadID << ": "<< msg.wParam<< std::endl;
break;
default:
break;
}
}
}
std::cout << "Send Quit" << std::endl;
//发送关闭消息,WM_QUIT:关闭消息循环
PostThreadMessage(threadID, WM_QUIT, 0, 0);
}
void thread2(int x){
MSG msg;
DWORD id = 0;
int count = 0;
bool flag = true;
//发送自定义消息
while (flag){
//PeekMessage函数,param1(lpMsg):接收消息信息的MSG结构指针;param4(wRemoveMsg):PM_REMOVE指PeekMessage处理后,消息从队列里除掉。
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
switch (msg.message)
{
case WM_USER + 101://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive threadID:" << msg.wParam << std::endl;
id = msg.wParam;
PostThreadMessage(id, WM_USER + 201, ++count, 0);
break;
case WM_USER + 102://WM_USER + 101是Fortrain发来的消息id
std::cout << "Receive from " << id << ":" << (int)msg.wParam << ", " << (const char*)msg.lParam << std::endl;
PostThreadMessage(id, WM_USER + 201, ++count, 0);
break;
case WM_QUIT:
std::cout << "Receive from " << id << ": I quit, bye bye!" << std::endl;
flag= false;
break;
default:
break;
}
}
}
}
int main(){
boost::thread thrd2(boost::bind(&thread2, 2));
DWORD id = getThreadId(thrd2.get_id());
boost::thread thrd1(boost::bind(&thread1, id));
thrd1.join();
thrd2.join();
return 0;
}
原文地址:http://www.manongjc.com/article/64482.html