读书人

急为啥PostMessage发送结构体会乱码

发布时间: 2012-12-17 09:31:40 作者: rapoo

急,,,为什么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;
}

接收端:

#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;看看
[其他解释]
先谢谢楼上各位提供的意见哈,几天没上来看帖子,发现热心的朋友还是挺多的……
闲话不多说了……

引用:
做了一个进程间发送接收例程
发送端:


C/C++ code?



123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828……
@mcmcmc 谢谢mcmcmc,朋友你的测试程序是同一编译器吧?我的不是哦,发送端是C++Builder程序,接收端是VS的MFC程序.

引用:
引用:
引用:跨进程还能用POSTMessage穿地址么?!
@ hushoubo 跨进程传地址无效的,那POSTMessage可不可以在进程间传数据呢?我的程序是这样的,发送端偶尔会给接收端发送一个消息,但是不需要回复收到消息的确认,只要把它丢在消息队列了就行了,这样可以减少延时,之前用的SendMessage+WM……

@sugar13 谢谢sugar13,我正在考虑用Postmessage+剪贴板通信的方法,基本能实现。至于你说的用户也用剪贴板的话,数据会不会被破坏.. 这个可以放心,我的界面程序是全屏仅限触摸屏使用的,其他用户用不了复制粘贴的操作。

引用:
检查一下工程设置中的结构体字节对齐问题:

@shine159111 谢谢shine159111 结构体的字节对齐也是个值得考虑的问题,这个我会抽空测试下。

引用:
是否是接收端和服务端的字节对齐问题导致的。

两个进程都使用

#pragam pack(1)

定义结构体
#pragma pack()
试试
@ bsnry 谢谢bsnry 你的建议,我测试一下再回帖哈,谢谢。

引用:
Student* stu=(Student *)lParam;
你这么接收是不是有点问题
能不能先new一个空间出来,然后强制转换为Student,然后再来赋值
这样直接接收,在进程中可能会有问题

@GLSC_CENA 谢谢GLSC_CENA 接收端也要new一块空间?我刚刚试了一下,传过来的是两个地址哦。

引用:
这么多人都没发现嘛, 跨进程的发送指针对嘛?

无论sendmessage,postmessae,都不对啊?


否则就多一种进程通信的方式了:发送消息。

所谓发送消息,根本就不能够发送数据出去的。

引用:
做了一个进程间发送接收例程
发送端:
C/C++ code?123456789101112131415161718192021222……

@liulin2025 谢谢liulin2025 众人皆醉你独醒哦,所以我在考虑用别的通讯方式,当然啦尽可能不Postmessage的特性也用上。
引用:
WM_COPYDATA
@VisualEleven 谢谢十一版主,WM_COPYDATA仅限Sendmessage哦,那个效率低我放弃了。

引用:
楼主没有调试的习惯,只看结果。如果调试以下,申请的时候看看stu,消息来的时候,在看一下参数,不至于看不到问题所在
@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穿地址么?!
@ hushoubo 跨进程传地址无效的,那POSTMessage可不可以在进程间传数据呢?我的程序是这样的,发送端偶尔会给接收端发送一个消息,但是不需要回复收到消息的确认,只要把它丢在消息队列了就行了,这样可以减少延时,之前用的SendMessage+WM_COPYDATA的方式……


用剪贴板通信的话,万一赶上用户也用剪贴板的话,会不会被破坏..
[其他解释]
跨进程还能用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数据流来发吧.
[其他解释]
引用:
不同编译器,二进制解释方法不同,做成xml数据流来发吧.

我试试,谢谢!
[其他解释]
该回复于2012-11-24 09:57:59被管理员删除
[其他解释]
不同的C++编译器对于类的二进制构造是不同的,比如有些exe调用其他编译器做的dll(class)会出乱子,只有c语言才是规范的
而且内存地址只在本进程中有效,跨了进程一点意义也没有.
[其他解释]
引用:

不同的C++编译器对于类的二进制构造是不同的,比如有些exe调用其他编译器做的dll(class)会出乱子,只有c语言才是规范的
而且内存地址只在本进程中有效,跨了进程一点意义也没有.

嗯嗯,我继续琢磨一下,实在不行只能用别的方法了,谢谢
[其他解释]
用SendMessage看看
[其他解释]
引用:
用SendMessage看看

不好意思呢,我现在用的就是SendMessage,不过效率实在不行,有延时
[其他解释]
引用:
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)stu);

把&去掉

这个我也试过了的,当执行到接收消息程序的int n = stu->age;赋值语句是程序会报错

[其他解释]
引用:
可能是‘对齐’问题 试试 1字节 对齐

朋友你说的一字节对齐是不是这样定义一个结构体

struct test
{
char Name[1];
char Sex[1];

};

这样也是乱码哦。
[其他解释]
windows采用的是进程独立地址空间制度,Post,Send之流只能传递DWORD,无法将整个结构穿过去.
好比上海有个电话62221111,北京也有一个电话62221111,号码一样,用户完全不同.

还是共享内存比较靠谱.
[其他解释]
最后一个方法了,你把stu放全局,保证其生命周期。
再用这个
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)stu);

[其他解释]
引用:
最后一个方法了,你把stu放全局,保证其生命周期。
再用这个
PostMessage(FindWindow(NULL,"Receive"),WM_SEND,0,(LPARAM)stu);


@tiger9991
按你的建议,跟踪了一下,发送前的stu的地址,和接收到的lParam地址一致,但是没有数据了呢
[其他解释]
引用:
跨进程还能用POSTMessage穿地址么?!

@ hushoubo 跨进程传地址无效的,那POSTMessage可不可以在进程间传数据呢?我的程序是这样的,发送端偶尔会给接收端发送一个消息,但是不需要回复收到消息的确认,只要把它丢在消息队列了就行了,这样可以减少延时,之前用的SendMessage+WM_COPYDATA的方式有点慢,所以考虑用POSTMessage。
进程间通讯还有剪贴板,管道,邮槽等。
[其他解释]
引用:
#pragma pack(push, 1)
struct Student { char Name[10]; int age; };
#pragma pack(pop)

进程间 用 WM_COPYDATA

谢谢,可是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,都不对啊?


否则就多一种进程通信的方式了:发送消息。

所谓发送消息,根本就不能够发送数据出去的。

引用:
做了一个进程间发送接收例程
发送端:
C/C++ code?12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182……


[其他解释]
PostMessage保证不了,数据的有效性。用SendMessage

读书人网 >VC/MFC

热点推荐