导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2016/12/12 14:05:04
标题:
SendNotifyMessage从线程发送消息到主窗体时,主窗体收到的消息经常会出现乱码或收到的消息比发送时的少了,如何解决?谢谢!
浏览:1660
加入我的收藏
楼主:
使用SendNotifyMessage在线程中发送消息到主窗体时主窗体收到的消息经常会出现乱码或收到的消息比发送时的少了。 线程发送消息: strMsg := '对象不存在'; SendNotifyMessage(iHwnd, UM_SHOWREADWRITE, WParam(Length(strMsg)), Lparam(PChar(strMsg))); 主窗体收到消息: procedure TMainForm.ShowReadWrite(Var Msg: TMessage); //列:行索引列表=数据 var dwSize: DWORD; Smessage: String; begin try dwsize := DWORD(Msg.wParam); SetLength(Smessage, dwSize); Move(PChar(Msg.lParam)^, PChar(Smessage)^, dwsize); ...... except end; end; Smessage的值经常会是“对象不存”或“对象不?”之类的。 请教各位老师,有没有遇到上面的问题?如何解决?谢谢!
----------------------------------------------
不要等到孤独寂寞时才想起朋友,不要等到穷困潦倒时才想起发奋,不要等到疾病缠身时才想起健康。。。
作者:
2016/12/12 17:30:43
1楼:
不知道你的环境如何,我这里使用很正常。D7+WIN10
----------------------------------------------
Delphi爱好者。
作者:
2016/12/12 17:51:56
2楼:
把源代码存为UTF8试试 另外,Move命令好像只能以Byte为单位拷贝,所以你用PCHAR为单位好像是错的,改成PAnsiChar试试(不管你什么版本Delphi)
----------------------------------------------
只有偏执狂才能生存!
作者:
2016/12/12 19:18:37
3楼:
非常感谢nevergrief (孤独骑士)老师的回复,改成PAnsiChar结果是一样的。你是说在线程中把发送的消息存为UTF8格式的字符串?如何存成UTF8格式的字符串?请指教!谢谢!
----------------------------------------------
不要等到孤独寂寞时才想起朋友,不要等到穷困潦倒时才想起发奋,不要等到疾病缠身时才想起健康。。。
作者:
2016/12/12 20:44:48
4楼:
Smessage: ^String; 用指针试试,发送消息前,用堆变量别用栈变量,处理完消息后,再删除指针指向的内存。
----------------------------------------------
-上帝给我们的脑子编程,我们给电脑编程,可上帝却始终站在电脑一边...
作者:
2016/12/12 21:27:15
5楼:
右键设置源码格式为UTF8. 其实还是同一个问题,我假设你你使用2009以后的高版本Delphi,那么你的 WParam(Length(strMsg)) 计算字符串长度结果为5,但占了10个字节。 也就是此时你的dwsize=5 然而Move的单位是byte,这样拷贝5个byte,肯定内容不全啊。 修改办法,直接使用: dwsize := DWORD(Msg.wParam); SetLength(Smessage, dwSize); // 这样设置宽字符串,还是5 Move(PAnsiChar(Msg.lParam)^, PAnsiChar(Smessage)^, dwsize*2); // 对5个字符的宽字符串,拷贝的byte是10,而且指针类型理应是PAnsiChar 这样最简单明了。 下次提问记得说清楚你用哪个版本的Delphi,搞得一堆假设,不能有针对性解决问题。
----------------------------------------------
只有偏执狂才能生存!
作者:
bdl1 (bdl1)
▲▲▲▲▲
-
普通会员
2016/12/13 11:10:49
6楼:
用SizeOf计算长度,再试试...
----------------------------------------------
-我的博客
作者:
2016/12/14 9:58:36
7楼:
非常感谢各位老师的热情回复,我用的是Delphi7。使用PAnsiChar和PChar是一样的结果,使用dwsize*2会报错更不行。使用用SizeOf计算长度也会报错。Smessage: ^String;这种方式如何使用,能不能写出简单代码,谢谢!
----------------------------------------------
不要等到孤独寂寞时才想起朋友,不要等到穷困潦倒时才想起发奋,不要等到疾病缠身时才想起健康。。。
作者:
2016/12/14 10:28:33
8楼:
在线程里用SendNotifyMessage向主窗体发送消息后将会立即返回,也就是字符串马上会被释放掉,因为它们不在同一线程里,你这种情况建议用SendMessage; 当然,主窗体里的消息接收函数也可以简化一下: procedure TMainForm.ShowReadWrite(Var Msg: TMessage); //列:行索引列表=数据 var Smessage: String; begin Smessage := StrPas(PChar(Msg.LParam)); ...... end; 如果你一定要用SendNotifyMessage,那么请用GetMem/AllocMem之类的函数申请内存后传递字符串,在接收处释放内存,不过如果消息没送达,则可能会有内存泄漏,当然也可以用复杂些的内存管理。
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
2016/12/14 12:44:02
9楼:
楼上说的对的,SendNotifyMessage单线程类似SendMessage是同步的,多线程操作是异步的,类似POSTMessage。 题主SendNotifyMessage发完消息就继续往下执行了,这个时候你发送的字符串内容可能已经变了,甚至内存已经被回收了。所以接收方如果处理的比你后面的稍微慢的话,就会导致拿到的内容是错乱的,甚至会有访问不可读内存地址的问题。 改成SendMessage,同步执行就不会有问题了,或者像楼上说的,发送方分配内存,接收方释放就没问题了。
----------------------------------------------
武稀松http://www.raysoftware.cn
作者:
2016/12/14 13:19:30
10楼:
const UM_SHOWREADWRITE = WM_USER+1; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); procedure OnShowReadWrite(var message:TMessage);message UM_SHOWREADWRITE; private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var pStrMsg:^string; begin new(pStrMsg); pStrMsg^:='Hello,world'; SendNotifyMessage(Handle,UM_SHOWREADWRITE,0,LPARAM(pStrMsg)); end; procedure TForm1.OnShowReadWrite(var message: TMessage); var pStrMsg:^string; begin pStrMsg := Pointer(message.LParam); Memo1.Text := pStrMsg^; Dispose(pStrMsg); end;
----------------------------------------------
-上帝给我们的脑子编程,我们给电脑编程,可上帝却始终站在电脑一边...
作者:
2016/12/15 11:32:11
11楼:
非常感谢各位老师的热情回复,按照jccddd (jcd)老师的方法,已经OK了,谢谢!
----------------------------------------------
不要等到孤独寂寞时才想起朋友,不要等到穷困潦倒时才想起发奋,不要等到疾病缠身时才想起健康。。。
作者:
lab01 (lab01)
★☆☆☆☆
-
盒子活跃会员
2016/12/15 22:53:43
12楼:
LZ问的不是多线程的场景吗,怎么没看出jccddd老师的多线程?LZ你到底问的是什么?
----------------------------------------------
-
作者:
lab01 (lab01)
★☆☆☆☆
-
盒子活跃会员
2016/12/15 22:55:04
13楼:
iamdream才是正解!把var message:string设为全局的即可
----------------------------------------------
-
作者:
2016/12/16 14:55:25
14楼:
本示例不是要演示多线程,而是应楼主的要求,写个简单的代码演示如何在非堵塞式消息函数中传递对象,这也是多线程传递消息必需的,如果用全局变量,那是另一回事了。如果将SendNotifyMessage换成PostMessage,你就能理解这段代码的意思了。
----------------------------------------------
-上帝给我们的脑子编程,我们给电脑编程,可上帝却始终站在电脑一边...
作者:
2016/12/16 14:58:41
15楼:
当函数返回时,局部变量会被销毁,用全局变量是一种不被看好的编程风格。要想将string类的对象通过消息传递到另一个函数,在堆中创建对象是一种简单的方法,同时需要注意的是对象要在处理完后,别忘了销毁。
----------------------------------------------
-上帝给我们的脑子编程,我们给电脑编程,可上帝却始终站在电脑一边...