闲着无聊,想整个进程间通信的C++小东西,美其名曰:技术储备。
其中一个要实现的功能可以精简概述为:A对话框向B对话框发送一个结构体,B收到后蹦个提示框显示收到的部分内容。
略去非重点,直奔主题:A框打算用发送WM_COPYDATA的方式发送结构体,但之前要先用FindWindow函数找到B框的句柄。以下是遇到的一系列问题……
问题一:找不到B框!
描述:调试程序,使用类名和窗口名作参数、单用类名作为参数,始终找不到B框句柄;改为只用窗口名,却可以找到。使用Spy++查看,发现A框和B框的类名都为“#32770 (对话框)”,看来问题出这,函数找到了两个,不好辨别了。两个参数的方式,似乎后一个参数是摆设~
解决办法:修改对话框默认类名。改起来还挺麻烦的,要改两处:
主类文件,在启动对话框前添加如下代码:
WNDCLASS wndMyClass;
::GetClassInfo(AfxGetInstanceHandle(), _T("#32770"), &wndMyClass); //取得原来对话框的窗口类属性
wndMyClass.lpszClassName= _T("Ctest2Dlg");//将类名改成自定义的类名
AfxRegisterClass(&wndMyClass);
.rc文件:
IDD_TEST2_DIALOG DIALOGEX 0, 0, 320, 200
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
EXSTYLE WS_EX_APPWINDOW
CAPTION "CH372模拟器"
CLASS "Ctest2Dlg" ///////////////这行是要添加的内容,显然就是这里改了自定义类名,这个类名要和类文件里的相同!
FONT 9, "宋体", 0, 0, 0x1
问题二:SendMessage函数不能接受四参数
描述:根据MSDN里的实例,添加找到的窗口句柄作为第一参数,WM_COPYDATA作为第二参数,外加两个参数,结果调试报错。
解决办法:原来是个小问题,示例中的函数是系统函数,要调用得加::,否则默认调用的是Cwn::SendMessage,它只有三个参数。
问题三:B框响应函数收不到WM_COPYDATA消息
描述:现象就是B框没反应~
解决办法:COPYDATASTRUCT结构体没有正确设置,一定要给结构体里每一个参数都赋值。
问题四:B框的响应函数解析不了收到的结构体
描述:首先描述下我的结构体,我是将一个含有LPCTSTR类型参数的结构体嵌入到COPYDATASTRUCT结构体中去的。B的函数可以收到COPYDATASTRUCT结构体,但无法解析出LPCTSTR参数的内容,总是乱码。步调发现,在A端嵌入结构体的时候就出问题了,使用sizeof算出的结构体长度不对。我赋的字符串至少30个字符,它却只算出20个字节!
解决办法:看来不能用LPCTSTR参数,换了定长的TCHAR数组,问题解决了。至于原理还不怎么明白,有空研究下。
问题五:为什么不能用自定义的消息传递数据
解决办法:这是C++对内存的管理机制问题了,进程间的内存是不能互相访问的,而WM_COPYDATA消息在底层用了共享内存的机制,传递的是物理内存地址映射,而不是普通消息的虚拟映射。
众里寻他千百度,我的A框终于找到了它的B框了……