急,,,为什么PostMessage发送结构体会乱码
//结构体
struct Student
{
char Name[10];
int age;
};
//发送端@bcb工程
Student *stu =new Student;
strcpy(stu->Name,"date");
stu->age = 18;
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)&stu); //已发送成功
//接收端@VS MFC工程
LRESULT CReceiveDlg::OnMyMessage(WPARAM wParam, LPARAM lParam)
{
// TODO: 处理用户自定义消息
Student* stu=(Student *)lParam;
int n = stu->age; //数据不对
char nam[10];
strcpy(nam, stu->Name); //乱码
delete stu;
return 0;
}
如上,PostMessage给其他程序发送结构体接收到的数据会乱码,SendMessage的WM_COPYDATA不考虑,效率偏低,也不考虑共享内存的方法,只想通过PostMessage给其他程序发送结构体。请问各位有什么解决方法呢?
[最优解释]
而且不同进程之间最好用共享内存.
[其他解释]
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)stu);
把&去掉
[其他解释]
FILE_MAP_WRITE,0,0,0);
if(pv!=NULL){
memcpy(pv,ss.str().c_str(),sz);
memset((char*)pv+sz,0,256-sz);
UnmapViewOfFile(pv);
}
//send to target process
DWORD idProcess;
GetWindowThreadProcessId(hwnd,&idProcess);
HANDLE hProcess= OpenProcess(PROCESS_DUP_HANDLE,FALSE,idProcess);
HANDLE hDup=0;
DuplicateHandle(GetCurrentProcess(),hFile,hProcess,&hDup,NULL,FALSE,DUPLICATE_SAME_ACCESS);
PostMessage(hwnd,WM_MSG_SEND,0,(LPARAM)hDup);
CloseHandle(hFile);
/*
if(pStream->Write(ss.str().c_str(),ss.str().size(),NULL)!=S_OK){
cout<<"stream write fail"<<endl;
}
HGLOBAL hgb=NULL;
//PostMessage(hwnd,WM_MSG_SEND,0,(LPARAM)hgb);
GetHGlobalFromStream(pStream,&hgb);
pStream->Release();
ULONG sz=GlobalSize(hgb);
*/
cout<<"item posted, bytes ="<<sz<<endl<<endl;
CoUninitialize();
}else{
break;
}
} while (1);
return 0;
}
接收端:
@mcmcmc 谢谢mcmcmc,朋友你的测试程序是同一编译器吧?我的不是哦,发送端是C++Builder程序,接收端是VS的MFC程序.
#include <windows.h>
#include <stdio.h>
#include <sstream>
using namespace std;
struct Stu{
char name[10];
int m_nAge;
};
istream& operator>>(istream& is,Stu& x)
{
is>>x.name;
is>>x.m_nAge;
return is;
}
ostream& operator<<(ostream& os,Stu& x)
{
os<<x.name;
os<<x.m_nAge;
return os;
}
#define WM_MSG_SEND WM_USER+125
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("RecvData") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW
[其他解释]
检查一下工程设置中的结构体字节对齐问题:
[其他解释]
楼主没有调试的习惯,只看结果。如果调试以下,申请的时候看看stu,消息来的时候,在看一下参数,不至于看不到问题所在
[其他解释]
Student *stu =new Student;
改成student stu;看看
[其他解释]
先谢谢楼上各位提供的意见哈,几天没上来看帖子,发现热心的朋友还是挺多的……
闲话不多说了……
@sugar13 谢谢sugar13,我正在考虑用Postmessage+剪贴板通信的方法,基本能实现。至于你说的用户也用剪贴板的话,数据会不会被破坏.. 这个可以放心,我的界面程序是全屏仅限触摸屏使用的,其他用户用不了复制粘贴的操作。
@shine159111 谢谢shine159111 结构体的字节对齐也是个值得考虑的问题,这个我会抽空测试下。
@ bsnry 谢谢bsnry 你的建议,我测试一下再回帖哈,谢谢。
@GLSC_CENA 谢谢GLSC_CENA 接收端也要new一块空间?我刚刚试了一下,传过来的是两个地址哦。
@liulin2025 谢谢liulin2025 众人皆醉你独醒哦,所以我在考虑用别的通讯方式,当然啦尽可能不Postmessage的特性也用上。
@VisualEleven 谢谢十一版主,WM_COPYDATA仅限Sendmessage哦,那个效率低我放弃了。
@pengyw 谢谢pengyw 朋友你可以看我11 16楼的回帖啦,我有调试的。tiger9991 朋友10楼的建议把&去掉其实是可行的,不过限于同一编译器同一工程里。
这几天工作忙,可能不能及时回帖,迟些问题解决了再结贴哈,衷心感谢楼上各位的热心帮助!
[其他解释]
FILE_MAP_READ,0,0,0);
char* buf=(char*)pv;
stringstream ss(buf);
ss>>item;
char str[30]={0};
sprintf(str,"SZ=%d,name=%s,age=%d",strlen(buf),item.name,item.m_nAge);
MessageBox(NULL,str,"recv",MB_OK);
CloseHandle(hFile);
}
return 0;
case WM_DESTROY :
PostQuitMessage (0) ;
return 0 ;
}
return DefWindowProc (hwnd, message, wParam, lParam) ;
}
效果:
------其他解决方案--------------------
可能是‘对齐’问题 试试 1字节 对齐
[其他解释]
用剪贴板通信的话,万一赶上用户也用剪贴板的话,会不会被破坏..
[其他解释]
跨进程还能用POSTMessage穿地址么?!
[其他解释]
CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MB_ICONERROR) ;
return 0 ;
}
hwnd = CreateWindow (szAppName, TEXT ("recv data"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
200, 200,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_MSG_SEND:
{
Stu item;
HANDLE hFile=(HANDLE)lParam;
PVOID pv=MapViewOfFile(hFile,FILE_MAP_WRITE
[其他解释]
是否是接收端和服务端的字节对齐问题导致的。
两个进程都使用
#pragam pack(1)
定义结构体
#pragma pack()
试试
[其他解释]
Student* stu=(Student *)lParam;
你这么接收是不是有点问题
能不能先new一个空间出来,然后强制转换为Student,然后再来赋值
这样直接接收,在进程中可能会有问题
[其他解释]
WM_COPYDATA
[其他解释]
不同编译器,二进制解释方法不同,做成xml数据流来发吧.
[其他解释]
我试试,谢谢!
[其他解释]
该回复于2012-11-24 09:57:59被管理员删除
[其他解释]
不同的C++编译器对于类的二进制构造是不同的,比如有些exe调用其他编译器做的dll(class)会出乱子,只有c语言才是规范的
而且内存地址只在本进程中有效,跨了进程一点意义也没有.
[其他解释]
嗯嗯,我继续琢磨一下,实在不行只能用别的方法了,谢谢
[其他解释]
用SendMessage看看
[其他解释]
不好意思呢,我现在用的就是SendMessage,不过效率实在不行,有延时
[其他解释]
这个我也试过了的,当执行到接收消息程序的int n = stu->age;赋值语句是程序会报错
[其他解释]
朋友你说的一字节对齐是不是这样定义一个结构体
struct test
{
char Name[1];
char Sex[1];
};
这样也是乱码哦。
[其他解释]
windows采用的是进程独立地址空间制度,Post,Send之流只能传递DWORD,无法将整个结构穿过去.
好比上海有个电话62221111,北京也有一个电话62221111,号码一样,用户完全不同.
还是共享内存比较靠谱.
[其他解释]
最后一个方法了,你把stu放全局,保证其生命周期。
再用这个
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)stu);
[其他解释]
@tiger9991
按你的建议,跟踪了一下,发送前的stu的地址,和接收到的lParam地址一致,但是没有数据了呢
[其他解释]
@ hushoubo 跨进程传地址无效的,那POSTMessage可不可以在进程间传数据呢?我的程序是这样的,发送端偶尔会给接收端发送一个消息,但是不需要回复收到消息的确认,只要把它丢在消息队列了就行了,这样可以减少延时,之前用的SendMessage+WM_COPYDATA的方式有点慢,所以考虑用POSTMessage。
进程间通讯还有剪贴板,管道,邮槽等。
[其他解释]
谢谢,可是POSTMessage发送不了WM_COPYDATA消息的哦
引述资料书上的:
你必须使用 SendMessage() 传送 WM_COPYDATA , 不能够使用PostMessage() 或任何其他变种函数如 PostThreadMessage() 之流。这是因为系统必须管理用以传递数据的缓冲区的生命期。如果你使用PostMessage(),数据缓冲区会在接收端(线程)有机会处理该数据之前,被系统清除并摧毁。
[其他解释]
#pragma pack(push, 1)
struct Student { char Name[10]; int age; };
#pragma pack(pop)
进程间 用 WM_COPYDATA
[其他解释]
做了一个进程间发送接收例程
发送端:
#include <windows.h>
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
struct Stu{
char name[10];
int m_nAge;
};
istream& operator>>(istream& is,Stu& x)
{
is>>x.name;
is>>x.m_nAge;
return is;
}
ostream& operator<<(ostream& os,Stu& x)
{
os<<x.name;
os<<" ";
os<<x.m_nAge;
return os;
}
#define WM_MSG_SEND WM_USER+125
int main(int, char **, char **)
{
Stu item;
string strcmd;
do
{
cout<<"enter name:";
cin>>item.name;
cout<<"enter age:";
cin>>item.m_nAge;
cout<<"enter s to send, e to exit: ";
cin>>strcmd;
if(strcmd=="s"){ //post message
HWND hwnd=FindWindow(NULL,TEXT("recv data"));
if(hwnd==NULL){
cout<<"can't find target recv window!"<<endl<<endl;
continue;
}
stringstream ss;
ss<<item;
size_t sz=ss.str().size();
HANDLE hFile=CreateFileMapping(INVALID_HANDLE_VALUE,NULL,
PAGE_READWRITE,0,256,NULL);
//write data
PVOID pv=MapViewOfFile(hFile,FILE_MAP_READ
[其他解释]
postmessage 可以送 2*4 个字节的值。
看看 能不能分2次 post 出去
student 14 个 字节
[其他解释]
这么多人都没发现嘛, 跨进程的发送指针对嘛?
无论sendmessage,postmessae,都不对啊?
否则就多一种进程通信的方式了:发送消息。
所谓发送消息,根本就不能够发送数据出去的。
[其他解释]
PostMessage保证不了,数据的有效性。用SendMessage