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. POJ2771 Guardian of Decency

    Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5513   Accepted: 2319 Description Frank ...

  2. 百度云中有关IE浏览器的源码

    <!--[if lt IE 9]>   <div class="topbar">百度云控制台不支持当前所使用的浏览器,推荐安装 <a href=&qu ...

  3. linux中的vi编辑器(二)

    命令行模式删除命令 x:删除光标所处的字符 X:删除光标前面的字符 dd:删除光标所在的行 dG:删除光标所在行到末尾的内容 D:删除光标所在处到行结尾的内容 命令模式复制命令-> yy,Y:复 ...

  4. java-判断字符串是否为数字

    1.使用java自带的函数 public static boolean isNumeric1(String str){ int len=str.length(); if(len>1&&a ...

  5. 【Visual Studio】“rc.exe”已退出,代码为 5 ("rc.exe" exited with code 5.)

    [解决方案]找到 rc.exe 所在目录,然后 方法1:添加该目录到 VC++ Directories --> Executable Directories中 方法2:添加到系统变量中的Path ...

  6. 【字符集及字符编码】UTF-8、UTF-16和UTF-32

    UTF-32 用 4 个字节存储每一个字符,以保证能把 UCS 完全表达出来.但实际上 UCS 的字符数量根本不需要用 32 位表示,UTF-32 极大地浪费了空间.另外,由于组合字符的存在,定长表示 ...

  7. C语言中的基础知识变量探讨

    C语言中的变量是编程的基础,主要有四个要素:存储类型.存储大小.存储名称和存储地址. 一.变量的要素: 1.存储类型:主要表明名变量存储的特征,主要有auto.extern.static和regist ...

  8. linux mmap 详解【转】

    转自:http://blog.chinaunix.net/uid-20321537-id-3483405.html 一.前言mmap的具体实现以前在学习内核时学习过,但是对于其中的很多函数是一知半解的 ...

  9. java基础(1-50)-------->超级简单,不信你不会!!!

    1:java中的保留字:const&goto; 2:&和&&都可以做逻辑运算符,即运算符两边的表达式都为true,结果才为true,一方为false,则结果为false ...

  10. django 模型生成sql(多对多)

    模型如下: class Publisher(models.Model): name = models.CharField(max_length=30) address = models.CharFie ...