许多Windows程序开发者喜欢使用WM_COPYDATA来实现一些进程间的简单通信(笔者也正在学习共享内存的一些知识来实现一些更高级的通信),这篇文章描述了笔者在使用这项技术时候的一些总结以及所遇到的一个问题回顾和分析。
在Windows程序中,各个进程之间常常需要交换数据,进行数据通讯。常用的方法有
比起前两种的复杂实现来,WM_COPYDATA消息无疑是一种经济实惠的一种方法
1
2
3
4
5 |
typedef
struct tagCOPYDATASTRUCT { ULONG_PTR
dwData; //用户定义数据 DWORD
cbData; //用户定义数据的长度 __field_bcount(cbData) PVOID
lpData; //指向用户定义数据的指针 } COPYDATASTRUCT, *PCOPYDATASTRUCT; |
COPYDATASTRUCT结构是WM_COPYDATA的参数,在这里可以指定对象的内存地址,对象的长度,data可以是子进程和父进程都认识的对象
一个简单的发送方和接收方的代码(C++实现):
发送端
1
2
3
4
5
6
7
8
9
10
11 |
void
CSendDlg::OnDataSend() { CWnd *pWnd = CWnd::FindWindow(NULL, "接收窗口的标题" ); CString sCopyData = "HELLO" ; COPYDATASTRUCT cpd; cpd.dwData = 0; cpd.cbData = sCopyData.GetLength() + 1; //多加一个长度,防止乱码 cpd.lpData = ( void *)sCopyData.GetBuffer(cpd.cbData); pWnd->SendMessage(WM_COPYDATA,NULL,( LPARAM )&cpd); } |
接收端(需要根据实际情况做一些修改,下面的文章会更新)
1
2
3
4
5
6
7 |
// 声明 afx_msg void
OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct); <br> // 添加消息映射 BEGIN_MESSAGE_MAP(CMainFrame, CCJMDIFrameWnd)<br>...<br>...<br>ON_MESSAGE(WM_COPYDATA, OnCopyData)<br>...<br>...<br>END_MESSAGE_MAP()<br><br> //函数实现<br>BOOL CReceiveDlg::OnCopyData( CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct ) { AfxMessageBox(( LPCSTR )(pCopyDataStruct->lpData)); } |
在使用了类似上述代码时,笔者遇到一个问题,如果使用CString类型传递数据时,在接受方的窗体内,始终只能接受到第一个字母,既如果发送端发送“HELLO”,接收端只能收到“H”。
原因:
单步调试的时候发现传进去的其实是L"HELLO",这表示“HelloWorld”将以unicode形式编码,Visual Studio默认默认采用unicode编码
客户端读取的方式是LPTSTR,LPSTR被定义成是一个指向以NULL(‘\0’)结尾的16位ANSI字符数组指针,而接受到的数据是一个以Unicode编码的32位双字节字符数组指针。这必然将产生的阶段的问题
Unicode使用两个字节表示一个字符,字符‘H‘的Unicode编码就是0x0072,此时“HELLO”在内存中的表现形式是:
72 00 - ‘H’
69 00 - ‘E‘
76 00 - ‘E‘
76 00 - ‘E‘
79 00 - ‘O‘
(注:基于X86平台的PC是基于Little Endian既将低字节存储在起始地址,故有如上地址分布)
因为x86CPU是little-endian,值0x0072在内存中的存储形式是72 00。你能看出如果这个字符串被传给strlen()函数会出现什么问题吗?它将先看到第一个字节42,然后是00,而00是字符串结束的标志,于是 strlen()将会返回1。所以如果用LPTSTR既8个字节对齐的方式去读取数据,只能得到首字母H
解决方法:
遇到类似的问题,一定需要了解字符的编码方式,然后用正确的方式去读取,在这里应该用微软所提供的LPWSTR既指向宽字符的指针去读取该字符串方可以得到正确的输出:
1 |
CString sCopyData = ( LPWSTR )(pCopyDataStruct->lpData); |
注:LPWSTR可使用上述方式显示转换为CString
字符的编码方式一定要理解清楚,否则将会带来难以发现的bug
以上是笔者粗略的理解,如果有不当之处欢迎指正。
WM_COPYDATA消息回顾和总结,以及如何解决WM_COPYDATA 发送CString消息的过程中,UNICODE字符不能被正确解析的错误,布布扣,bubuko.com
WM_COPYDATA消息回顾和总结,以及如何解决WM_COPYDATA 发送CString消息的过程中,UNICODE字符不能被正确解析的错误
原文:http://www.cnblogs.com/amsun/p/3619774.html