迁移Lazarus应用至Delphi10.4:WM_COPYDATA字符串接收异常问题咨询
解决WM_COPYDATA在VB.Net与Delphi 10.4之间的编码不匹配问题
问题根源
你的代码存在两个关键问题:
- VB.Net端逻辑错误:明明将字符串转成了ANSI字节数组,但
cds.lpData却直接赋值原字符串msg,导致实际发送的是.Net字符串内部的Unicode指针,而非预期的ANSI字节数据。 - 编码不匹配:Delphi 10.4默认使用Unicode(
PCHAR等价于PWideChar),若VB.Net发送ANSI编码数据,直接用StrPas(PCHAR)解析会将单字节ANSI字符当作双字节宽字符处理,必然导致内容损坏。
方案一:统一使用ANSI编码(兼容旧逻辑)
VB.Net端调整
修正lpData赋值,指向ANSI字节数组首地址,同时确保cbData传递正确的字节长度(包含终止符):
Dim sarr As Byte() = System.Text.Encoding.Default.GetBytes(msg & vbNullChar) ' 手动添加ANSI终止符 Dim cds As COPYDATASTRUCT cds.dwData = CType(wParam, IntPtr) cds.lpData = sarr ' 指向ANSI字节数组 cds.cbData = sarr.Length ' 字节数组长度(已包含终止符) SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
Delphi端调整
明确使用ANSI字符指针解析数据:
WM_COPYDATA : begin recvdata := PCopyDataStruct(Message.LParam); msgtype := recvdata^.dwData; msglen := recvdata^.cbData; str := StrPas(PAnsiChar(Recvdata^.lpData)); // 用PAnsiChar而非默认PCHAR end;
方案二:统一使用Unicode编码(推荐,适配Delphi 10.4原生Unicode环境)
VB.Net端调整
直接发送Unicode字节数据,无需转ANSI:
Dim sarr As Byte() = System.Text.Encoding.Unicode.GetBytes(msg & vbNullChar) ' Unicode终止符为两个空字节 Dim cds As COPYDATASTRUCT cds.dwData = CType(wParam, IntPtr) cds.lpData = sarr cds.cbData = sarr.Length SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
Delphi端调整
直接使用默认的PWideChar解析(Unicode Delphi中PCHAR等价于PWideChar):
WM_COPYDATA : begin recvdata := PCopyDataStruct(Message.LParam); msgtype := recvdata^.dwData; msglen := recvdata^.cbData; str := StrPas(PCHAR(Recvdata^.lpData)); // 直接使用PCHAR即可 end;
额外注意事项
确保两端的COPYDATASTRUCT定义严格匹配Windows原生结构:
- VB.Net定义:
<StructLayout(LayoutKind.Sequential)> Public Structure COPYDATASTRUCT Public dwData As IntPtr Public cbData As Integer Public lpData As IntPtr ' 直接传字节数组时,.Net会自动封送为指针 End Structure - Delphi定义:
type PCopyDataStruct = ^TCopyDataStruct; TCopyDataStruct = packed record dwData: DWORD_PTR; cbData: DWORD; lpData: Pointer; end;
内容的提问来源于stack exchange,提问作者Steve London
相关产品推荐
相关产品推荐

