VC进程间通信之消息传递PostMessge()或SendMessage()
1. 进程内消息:
(1). 仅仅传消息码
(2). 传送消息串
发送端:
void CTestDlg::OnBnClickedButtonSend()
{
CString* msg = new CString("发送的字符串");
::SendMessage(m_hWnd,WM_USER+1,0,(LPARAM)msg);
delete msg;
} 接收端:
afx_msg HRESULT OnClickBtn(WPARAM,LPARAM); BEGIN_MESSAGE_MAP
ON_MESSAGE(WM_USER+1,OnClickBtn)
END_MESSAGE_MAP() HRESULT CSendMessageDlg::OnClickBtn1(WPARAM wParam,LPARAM lParam)
{
CString* rmsg = (CString*)lParam;
MessageBox(*rmsg);
return TRUE;
}
2. 进程间通讯:
PostMessge或者SendMessage()实现进程间通讯
(1)两个不同的进程不能用上面的方法。当然仅仅发送消息不发内容是能够的。
(2)两个进程因为使用的是相互独立的两个虚拟内存空间,同一地址对不同的进程来说并不一定指向同一物理内存,内容也就不一定一样。因此不同进程无法通过传地址的方式传递字符串(可是同一进程下的不同线程是能够的)
2.解决的方法
发送WM_COPYDATA消息在进程间传送数据
(1)发送消息
The exchange of data is performed by finding the other application (using FindWindow) and sending a WM_COPYDATA message to that window
使用FindWindow找到窗体。然后发送WM_COPYDATA消息。字符串附加到COPYDATASTRUCT 结构体
LRESULT copyDataResult; //copyDataResult has value returned by other app
CWnd *pOtherWnd = CWnd::FindWindow(NULL, strWindowTitle); if (pOtherWnd)
{
COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = strDataToSend.GetLength(); //data length
cpd.lpData = (void*)strDataToSend.GetBuffer(cpd.cbData); //data buffer
copyDataResult = pOtherWnd->SendMessage(WM_COPYDATA,(WPARAM)AfxGetApp()->m_pMainWnd->GetSafeHwnd(),(LPARAM)&cpd);
strDataToSend.ReleaseBuffer();
}
else
{
AfxMessageBox("Unable to find other app.");
}
(2)加入消息
The other app should handle the WM_COPYDATA message in the following manner
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
...
ON_WM_COPYDATA()
...
END_MESSAGE_MAP()
(3)消息处理
BOOL CMyWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
CString strRecievedText = (LPCSTR) (pCopyDataStruct->lpData);
return CMyWnd::OnCopyData(pWnd, pCopyDataStruct);
}
五、PostMessage 和SendMessage的差别
(1). PostMessage 和SendMessage的差别主要在于是否等待其它程序消息处理完毕。
PostMessage仅仅是把消息放入队列,无论其它程序是否处理都返回,然后继续运行。
而SendMessage则必须等待其它程序处理消息完毕后才返回继续运行。因为SendMessage消息不放进消息队列, 所以PreTranslateMessage里无法收到其消息。
(2). 这两个函数的返回值也不同
原型:
BOOL PostMessage(HWND hWnd。UINT Msg,WPARAM wParam,LPARAM lParam);
LRESULT SendMessage(HWND hWnd。UINT Msg。WPARAM wParam。LPARAM IParam);
SendMessage的返回值表示其它程序消息处理函数的返回值(如return 10, 则long nRet = SendMessage(...) = 12)。
PostMessage的返回值仅表示PostMessage函数运行是否成功,成功返回非零,否则返回零。
举比例如以下(仅仅传消息码):
方法1: PostMessge或者SendMessage()消息机制
项目1中发送消息:
#define WM_MYMESSAGE WM_USER + 1 //目标进程的窗体类名(可通过Spy++工具查看)和窗体名
CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest");
if (NULL != pWnd)
{
pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL);
} 或者:
HWND hWnd = ::FindWindow("#32770", "MfcTest");
if (NULL != hWnd)
{
::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL);
}
项目2中接收消息:
.h中声明:
afx_msg LRESULT OnMyMessage(WPARAM wp, LPARAM lp);
.cpp中定义:
BEGIN_MESSAGE_MAP(CMainFrame, CFrameWnd)
...
ON_MESSAGE(WM_MYMESSAGE, OnMyMessage)
...
END_MESSAGE_MAP()
LRESULT CMfcTestDlg::OnMyMessage(WPARAM wp, LPARAM lp)
{
AfxMessageBox("Hello World");
return 0;
}
说明:
使用PostMessage或SendMessage均可,差别在于SendMessage堵塞,直到目标窗体程序处理完消息再返回,而PostMessage是将一个消息寄送到一个线程的消息队列后就马上返回。通常使用PostMessage,假设为了探測目标进程是否存在,则用SendMessage比較好。
方法2: 消息接收端採用PreTranslateMessage()来处理
发送端代码:
#define WM_MYMESSAGE WM_USER + 1 //目标进程的窗体类名(可通过Spy++工具查看)和窗体名
CWnd *pWnd = CWnd::FindWindow("#32770", "MfcTest");
if (NULL != pWnd)
{
pWnd->PostMessage(WM_MYMESSAGE, NULL, NULL);
} 或者:
HWND hWnd = ::FindWindow("#32770", "MfcTest");
if (NULL != hWnd)
{
::PostMessage(hWnd, WM_MYMESSAGE, NULL, NULL);
}
接收端代码:
.h声明
BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg);
.cpp定义
#define WM_MYMESSAGE WM_USER + 1 BOOL CMfcTestDlg::PreTranslateMessage(MSG* pMsg)
{
if (pMsg->message == WM_USER + 1)
{
AfxMessageBox("Hello World");
} return CDialog::PreTranslateMessage(pMsg);
}
说明:
这里将接收端处理放在PreTranslateMessage 中, 因此发送端必须选择 PostMessage, 由于SendMessage消息不放进消息队列, PreTranslateMessage里不能收到这个消息。
VC进程间通信之消息传递PostMessge()或SendMessage()的更多相关文章
- 深度解析VC中的消息传递机制
摘要:Windows编程和Dos编程,一个很大的区别就是,Windows编程是事件驱动,消息传递的.所以,要学好Windows编程,必须 对消息机制有一个清楚的认识,本文希望能够对消息的传递做一个全面 ...
- Unity的3种消息传递方法(SendMessage等)
为了方便多个物体间的消息传达与接收,Unity中包含了几种消息推送机制 : 分别为SendMessage.SendMessageUpwards.BroadcastMessage. 我们首先以SendM ...
- android log 学习
一,Bug出现了, 需要“干掉”它 bug一听挺吓人的,但是只要你懂了,android里的bug是很好解决的,因为android里提供了LOG机制,具体的底层代码,以后在来分析,只要你会看bug, a ...
- [深入学习Redis]RedisAPI的原子性分析
在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...
- Redis API的原子性分析
在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...
- 知其所以然~redis的原子性
原子性 原子性是数据库的事务中的特性.在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节. 对于Redis而言,命 ...
- [OS] 操作系统常考知识点
转自:http://jennica.space/2017/03/21/os-principle/ 大纲如下: 1.操作系统概述2.操作系统运行环境3.进程线程模型4.处理器调度5.同步机制6.存储模型 ...
- MFC 监控界面上所有文本框值的变化
//控件消息,菜单,按钮等 BOOL CXXDlg::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: 在此添加专用代码和/或调用基类 int wm ...
- iOS App Crash原理分析
预备知识:OS X系统分析 1.内核XNU是Darwin的核心,也是整个OS X的核心.XNU本身由以下几个组件构成: Mach微核心 BSD层 libKern I/O Kit 此外,内核是模块化的, ...
随机推荐
- Activity启动创建 (AcitivtyManageService,ActivityThread,Activity)
ActivityThead,ActivityManagerService,Activity <<Android内核剖析>>中有一章节专门介绍 Activity框架和管理结构A ...
- vuemock数据
http://www.jianshu.com/p/ccd53488a61b dev.server.js 61 行 app.use('/mock',express.static('./mock'))
- Java EE 学习(9):IDEA + maven + spring 搭建 web(5)- 博客文章管理
转载:Gaussic(一个致力于AI研究却不得不兼顾项目的研究生) . 注:在阅读本文前,请先阅读: Java EE 学习(5):IDEA + maven + spring 搭建 web(1) Jav ...
- Vue.js笔记 — vue-router路由懒加载
用vue.js写单页面应用时,会出现打包后的JavaScript包非常大,影响页面加载,我们可以利用路由的懒加载去优化这个问题,当我们用到某个路由后,才去加载对应的组件,这样就会更加高效,实现代码如下 ...
- 写一个Foreach帮助类,在razor中使用
原文发布时间为:2011-05-05 -- 来源于本人的百度文章 [由搬家工具导入] A Better Razor Foreach Loop(razor delegate extension) htt ...
- soc与cpu区别
soc(System on Chip)片上系统cpu只包括运算器和控制器.早期 的系统是指在PCB上有cpu和Nand控制器,LCD控制器之类的控制器,构成一个系统. cpu和这些控制器之间用pcb板 ...
- FTP上传文件服务器python实现
总结 使用Python的socket和socketserver模块实现ftp文件服务器.不是很难,但在粘包的问题上纠缠了不少时间.解决办法是发送文件信息之后等待一段时间. #!/usr/bin/pyt ...
- LeetCode OJ-- Binary Tree Maximum Path Sum ***
https://oj.leetcode.com/problems/binary-tree-maximum-path-sum/ 给一棵二叉树,路径可以从任一点起,到任一点结束,但是可以连成一个路径的.求 ...
- 2017 ACM-ICPC EC-Final 记录
北京赛区结束后就以为自己的赛季结束了……但是还是保持着做题量 那天突然接到通知,去打EC-Final 但是这是一个临时组起来的队伍,另外两位队友原来一起组的比较熟,我就需要适应一下. 于是我们临时训练 ...
- java 两个int类型的数据相除并输出百分号保留两位有效数字
java代码: public void IntA(int a , int b){ //首先判断分母不能为0 if(b!=0){ folat num = (float) a*100/b; Decimal ...