消息后LParam截断 [英] Postmessage LParam truncation

查看:92
本文介绍了消息后LParam截断的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序有一个工作线程,我使用PostMessage将字符串发送到主线程.对于1条消息,该字符串在到达主线程中的消息处理程序时会被截断.

My app has a worker thread, and I use PostMessage to send a string to the main thread. For 1 message, the string is truncated when it gets to the message handler in the main thread.

在工作线程中由类似这样的原始数据字符串构造字符串.它以最后的"20"结尾.

The string is constructed in the worker thread from a string of raw data that is like this. It ends at the last '20'.

'01010000000030000102000008850008855343414E204544474520000000000000000000000000'

'01010000000030000102000008850008855343414E204544474520000000000000000000'

解码为我想要发送的字符串,如下所示,这是正确的:

Decoded into the string I want to send it looks like this, which is correct:

'0100 0.50000 LSB0288.588.5扫描边缘'

'0100 0.50000 LSB0288.588.5SCAN EDGE '

创建"SCAN EDGE"部分并将其发布的代码是: tmp和s_out是字符串

The code that creates the 'SCAN EDGE ' portion and posts it is: tmp and s_out are strings

x := 35;
for i := 1 to 10 do
begin
  tmp := '$' + copy(s,x,2);
  TryStrToInt(tmp,dec);
  s_out := s_out + chr(dec);
  x := x + 2;
end;
PostMessage(MainHandle,UM_CLONE, UM_756, Integer(PChar(s_out)));

主线程中的消息处理程序为: 我是一个字符串

The message handler in the main thread is: i is a string

i := pChar(msg.LParam);

当到达主线程时,我在调试器中看起来像这样:

when it gets to the main thread i looks like this in the debugger:

'0100 0.50000 LSB0288.588.5SCAN EDG'#0

'0100 0.50000 LSB0288.588.5SCAN EDG'#0

我该如何纠正?

推荐答案

您正在发布String变量的内容,该变量对于正在调用PostMessage()的线程过程是本地的.如果String超出范围并在主线程处理发布的消息之前被释放,则内存将为垃圾.

You are posting the contents of a String variable that is local to the thread procedure that is calling PostMessage(). If the String goes out of scope and gets freed before the main thread processes the posted message, the memory will be garbage.

您需要:

1)使用SendMessage()而不是PostMessage(),以便String保持作用域,直到消息处理程序退出:

1) use SendMessage() instead of PostMessage() so the String stays in scope until the message handler exits:

SendMessage(MainHandle, UM_CLONE, UM_756, LPARAM(PChar(s_out)));

2)动态地在内存中分配一个String,根据需要填充它,将其发布,然后在完成复制后让主消息处理程序释放它:

2) dynamically allocate a String in memory, fill it as needed, post it, and then let the main message handler free it when it is done copying it:

var
  s_out: PString;

New(s_out);
...
s_out^ := s_out^ + chr(dec);
...
if not PostMessage(MainHandle, UM_CLONE, UM_756, LPARAM(s_out)) then
  Dispose(s_out);

.

var
  ps: PString;
  i: String;

ps := PString(msg.LParam);
i := ps^;
Dispose(ps);

PS:注意,我也将您的Integer()演员表更改为LPARAM().如果您曾经升级到Delphi XE2或更高版本,这是非常重要的. PostMessage()SendMessage()使用LPARAM,而不是Integer.您可以在Delphi 7中使用它,因为在该版本中LPARAMInteger的别名,但是在现代Delphi版本中不再如此. LPARAM现在是NativeUInt的别名. LPARAM一直是Win32 API中的单一类型,Delphi在早期版本中只是搞错了,但是Embarcadero确实在RTL/VCL中一直在要求类型正确性,因为它增加了对64位和跨平台的支持.发展.如果您没有正确匹配正确的数据类型,则可能会导致范围检查错误等在运行时.

PS: notice I also changed your Integer() cast to LPARAM(). This is very important if you ever upgrade to Delphi XE2 or later. PostMessage() and SendMessage() use LPARAM, not Integer. You can get away with it in Delphi 7 because LPARAM is an alias for Integer in that version, but that is not the case anymore in modern Delphi versions. LPARAM is an alias for NativeUInt now. LPARAM has always been an unsinged type in the Win32 API, Delphi just got it wrong in the early versions, but Embarcadero has really been pushing for type-correctness in the RTL/VCL since adding support for 64-bit and cross-platform development. If you don't match the right data types correctly, you can cause range checks errors and such at runtime.

这篇关于消息后LParam截断的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆