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()的更多相关文章

  1. 深度解析VC中的消息传递机制

    摘要:Windows编程和Dos编程,一个很大的区别就是,Windows编程是事件驱动,消息传递的.所以,要学好Windows编程,必须 对消息机制有一个清楚的认识,本文希望能够对消息的传递做一个全面 ...

  2. Unity的3种消息传递方法(SendMessage等)

    为了方便多个物体间的消息传达与接收,Unity中包含了几种消息推送机制 : 分别为SendMessage.SendMessageUpwards.BroadcastMessage. 我们首先以SendM ...

  3. android log 学习

    一,Bug出现了, 需要“干掉”它 bug一听挺吓人的,但是只要你懂了,android里的bug是很好解决的,因为android里提供了LOG机制,具体的底层代码,以后在来分析,只要你会看bug, a ...

  4. [深入学习Redis]RedisAPI的原子性分析

    在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...

  5. Redis API的原子性分析

    在学习Redis的常用操作时,经常看到介绍说,Redis的set.get以及hset等等命令的执行都是原子性的,但是令自己百思不得其解的是,为什么这些操作是原子性的? 原子性 原子性是数据库的事务中的 ...

  6. 知其所以然~redis的原子性

    原子性 原子性是数据库的事务中的特性.在数据库事务的情景下,原子性指的是:一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节. 对于Redis而言,命 ...

  7. [OS] 操作系统常考知识点

    转自:http://jennica.space/2017/03/21/os-principle/ 大纲如下: 1.操作系统概述2.操作系统运行环境3.进程线程模型4.处理器调度5.同步机制6.存储模型 ...

  8. MFC 监控界面上所有文本框值的变化

    //控件消息,菜单,按钮等 BOOL CXXDlg::OnCommand(WPARAM wParam, LPARAM lParam) { // TODO: 在此添加专用代码和/或调用基类 int wm ...

  9. iOS App Crash原理分析

    预备知识:OS X系统分析 1.内核XNU是Darwin的核心,也是整个OS X的核心.XNU本身由以下几个组件构成: Mach微核心 BSD层 libKern I/O Kit 此外,内核是模块化的, ...

随机推荐

  1. hdu 1423 最长上升递增子序列

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; ; in ...

  2. HTML 文档之 Head 最佳实践

    语言 在 html 标签中通过 lang 属性进行明确的语言声明,将会有助于翻译,英文.简体中文和繁体中文网页所属性值如下: <html lang="en"> < ...

  3. 【jetty】Jetty与Tomcat的区别

    Jetty 的架构从前面的分析可知,它的所有组件都是基于 Handler 来实现,当然它也支持 JMX.但是主要的功能扩展都可以用 Handler 来实现.可以说 Jetty 是面向 Handler ...

  4. 对/proc和/sys的一些理解

    一切皆文件,设备(文件)可以通过读写来操作:/proc procfs:/sys sysfs: 个人的理解(不知对不对,感觉有些片面)/proc是内存中有关系统进程的实时信息:/sys是有关系统内核以及 ...

  5. hdu 4857(好题,反向拓扑排序)

    逃生 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submissi ...

  6. hdu 2824(欧拉函数)

    The Euler function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Other ...

  7. LeetCode OJ-- Balanced Binary Tree ***

    https://oj.leetcode.com/problems/balanced-binary-tree/ 判断一个二叉树,是否为平衡的.如果是平衡的,则它的每个子树的左右子树高度差不大于1. 递归 ...

  8. springBoot AOP切面编程

    AOP 为 Aspect Oriented Programming 的缩写,意为 面向切面编程.AOP 为spring 中的一个重要内容,它是通过对既有程序定义一个切入点,然后在其前后切入不同的执行内 ...

  9. C++ 找不到方法标识符

    其实原因是这个CPP并没有面向对象的结构. 所以进行编译时是“顺序编译”的,而main函数的定义又在A的定义之前.自然找不到标识符了.

  10. Codeforces 782B The Meeting Place Cannot Be Changed(二分答案)

    题目链接 The Meeting Place Cannot Be Changed 二分答案即可. check的时候先算出每个点可到达的范围的区间,然后求并集.判断一下是否满足l <= r就好了. ...