现在的位置: 首页 > 自动控制 > 工业·编程 > 正文

VC中使用自定义消息在进程间通讯

2012-09-09 22:10 工业·编程 ⁄ 共 3260字 ⁄ 字号 暂无评论

WINDOWS中进程间通讯的方式很多,如:消息机制,共享内存机制,SOCKET,COM,RPC等等,
需要时可以根据具体情况来选择使用的方式。
我在这本文中仅介绍进程间的自定义消息通讯机制。
1,WINDOWS中自定义消息的定义和使用; 在WNDOWS中消息分系统消息和自定义消息。
系统消息定义从0到0x3FF,使用0x400到0x7FFF定义自己的消息。
Windows把0x400定义为WM_USER。如果想定义自己的一个消息,可以在WM_USER上加上
一个值: #define WM_CONTROLPRINT WM_USER+1001
另一种自定义窗口消息的方法是用RegisterWindowsMessage()函数来注册这个消息。
与在WM_USER上加上某个数相比,它的好处是不必考虑所表示的消息标识符是否超出
工程的允许范围。如: const UINT WM_CONTROLPRINT=RegisterWindowMessage("reg_data");
在接收消息的程序中,需要对添加对应消息的响应处理函数,并将消息和消息处理函数关联,
要不它不知道消息发给谁:
//函数定义,在//AFX_MSG中
afx_msg LRESULT OnControlPrint(WPARAM wParam,LPARAM lParam);
//函数实现 LRESULT CSendDlg::OnControlPrint(WPARAM wParam,LPARAM lParam) { }
//关联映射,在BEGIN_MESSAGE_MAP中 ON_MESSAGE(WM_CONTROLPRINT,OnControlPrint)
//使用WM_USER+1001定义的消息 ON_REGISTERED_MESSAGE(WM_CONTROLPRINT,OnControlPrint)
//使用RegisterWindowMessage定义的消息 消 息如何传递呢?我们需要发送消息时,
可以使用PostMessage和SendMessage。这两个消息发送函数不一样的地方就是 SendMessage
发送完消息后会等待消息处理函数处理完成后返回,PostMessage则不等待。所以,可以说
PostMessage是不可靠 的,实际运用中可以根据具体情况来确定用那一个。
这两个函数的具体使用请查看MSDN。 如我向主窗体发送一个消息(
第一个参数是接收消息的窗体句柄,第二个参数是要发送的消息,
后边两个为随消息发送的参数信息):
::SendMessage(AfxGetApp()->GetMainWnd()->m_hWnd,WM_CONTROLPRINT,NULL,0);

2,使用自定义消息在进程间通讯; 我们可以用VC60建立两个基于对话框的工程,
一个命名为Send,一个命名为Revice。 在Send对话框中添加一个名成为IDC_BUTTONSEND的按钮。
在SendDlg.h和ReviceDlg.g中都添加自定义消息。消息实现进程间通信,需要在
这两个程序中定义或注册相同的消息,才能保证数据通信顺利进行:
#define WM_CONTROLPRINT WM_USER+1001 在Send工程中添加IDC_BUTTONSEND
按钮的单击处理事件,并添加代码:
void CSendDlg::OnButtonsend() {
//获取窗口句柄 CWnd *pWnd=CWnd::FindWindow(NULL,_T("Revice"));
if(pWnd==NULL) { AfxMessageBox("接收程序没有运行!");
return ;
}
//发送消息 pWnd->SendMessage(WM_SENDYKDISABLE,NULL,0); }
在Revice工程中添加WM_CONTROLPRINT 的处理函数,关联映射,和上边描述的过程一样,
在处理函数中添加相应的处理代码。这里就不多说了!

------------------------------------------ 关于进程间互发信息

想一想,在平时的处理程序的时候,我们都是在一个进程中进行处理,所以,在处理字符串
的时候,我们都不用考虑太多的问题,处理什么样的数据和数据的发送都会在同一个
进程中进行。 但是,假如要你负责一个程序要在两个不同的进程中交换数据,
你会怎么办,你要想怎样做,一般的做法是这样,自定义一个消息,然后你就把这个数据
放在这个消息附带的参数WPARAM wParam 与 LPARAM lParam 中,不过这样只能限
于非字符串的传递,只能传递数字,或者你更聪明一点,把字符编码,然后在另一个
进程中解码,这样可以做成伪字符的数据传递。 不过,这样的方法都不错!
我在开始的时候,使用了字符地址作为消息参数进行传递,可是由于进程间都是独立的4GB
内存空间,当接到我的字符消息的时候,就程序就误以为是自已的进程空间的地址,所以
就把读取了这个地址,一般结果来看,不是乱码就是空字符串。 那么我们有什么方法可
以在消息中进行字符串的传递呢? 我们可以使用两个Windows的消息分别进行一个字符
串的两个进程间的传递, 一个消息是WM_SETTEXT。 一个消息是WM_COPYDATA。 以下我
来分析这两个消息怎么实现, 最简单的是使用WM_SETTEXT的消息了,这个方法只是使用
一个字符串的地址作为一个消息参数就可以实现了两个不同进程间的消息的互发了。
原因是因为这个消息会为这个字符串分配一个内存空间,在接收方就可以根据这个地址
把这个字符串读取保存了 CString str = _T( "Hello" );
HWND hWndReceived = FindWindow( "Receiver", NULL );
SendMessage( hWndReceived, WM_SETTEXT, 0, (LPARAM) str );
在接收方这样处理消息: 加入消息映射宏:
BEGIN_MESSAGE_MAP(CMyWnd, CWnd)
//{{AFX_MSG_MAP(CMyWnd)...
ON_MESSAGE( WM_SETTEXT, OnSetTextMsg )
...//}}
AFX_MSG_MAPEND_MESSAGE_MAP()
... 加入消息映射函数:
afx_msg void OnSetTextMsg( WPARAM wParam, LPARAM lParam)
OnSetTextMsg( WPARAM wParam, LPARAM lParam )
{
char str[ 256 ];
wsprintf( str, "%s", (char*) lParam
); // 加入处理这个字符串的语句 .....}
使用WM_COPYDATA:CString str = _T( "Hello" );
HWND hWndReceived = FindWindow( "Receiver", NULL );
COPYDATASTRUCT cpd;
cpd.dwData = 0;
cpd.cbData = strDataToSend.GetLength();
cpd.lpData = (void*)str.GetBuffer(cpd.cbData);
SendMessage( hWndReceived, WM_COPYDATA, 0, (LPARAM) & cpd );
str.ReleaseBuffer();
加入映射宏: B
EGIN_MESSAGE_MAP(CMyWnd, CWnd)
//{{AFX_MSG_MAP(CMyWnd) ...
ON_WM_COPYDATA()
... //}}
AFX_MSG_MAP END_MESSAGE_MAP() ...
映射函数:
BOOL CMyWnd::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
  {
  CString strRecievedText = (LPCSTR) (pCopyDataStruct->lpData);
  return CMyWnd::OnCopyData(pWnd, pCopyDataStruct);
  }
  这样就可以实现了不同进程间两个字符串之间的互发!

给我留言

留言无头像?