从VB.Net到 Delphi 的WM_COPYDATA

xeufq47z  于 2022-12-23  发布在  .NET
关注(0)|答案(1)|浏览(146)

我试图将一个应用程序从Lazarus移动到Delphi 10.4。我遇到的问题是WM_COPYDATA。
在VB. Net应用程序上:

Dim sarr As Byte() = System.Text.Encoding.[Default].GetBytes(msg)
        Dim len As Integer = sarr.Length
        Dim cds As COPYDATASTRUCT
        cds.dwData = CType(wParam, IntPtr)
        cds.lpData = msg
        cds.cbData = len + 1
        SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)

在德尔福方面:

WM_COPYDATA :
       begin
            recvdata := PCopyDataStruct(Message.LParam);
            msgtype := recvdata^.dwData;
            msglen := recvdata^.cbData;
            str := StrPas(PCHAR(Recvdata^.lpData));

msgtype和msglen看起来很好,但是str(lpdata)被损坏了。我认为这与Delphi使用widechar或ANSI有关。
我需要在VB.Net和Delphi10.4端做些什么才能让它们对齐?
谢谢!

3ks5zfa0

3ks5zfa01#

在Delphi2009及以后版本中,PCharPWideChar(16位UTF-16)的别名,但VB.NET代码发送的是8位ANSI编码字节,因此,在Delphi端需要使用PAnsiChar而不是PChar(除非您更改VB.NET代码,使用Encoding.Unicode而不是Encoding.Default)。
顺便说一句,有一个VB.NET代码中的(潜在)错误。DotNet字符串不是以空结尾的,因此如果msgString,则Encoding.GetBytes(msg)将不输出空终止符字节(如果msg是存在空终止符的Char[]数组,则会出现这种情况)。代码将cds.cbData = len + 1设置为存在空终止符。它应该设置cds.cbData = len,然后,在Delphi端,您可以使用SetString()而不是StrPas()PAnsiChar数据放入一个AnsiString,然后您可以将其分配给一个原生string
试试这个:

Dim sarr As Byte() = System.Text.Encoding.[Default].GetBytes(msg)
Dim len As Integer = sarr.Length
Dim cds As COPYDATASTRUCT
cds.dwData = CType(wParam, IntPtr)
cds.lpData = msg
cds.cbData = len
SendMessage(CInt(hWnd), WM_COPYDATA, 0, cds)
var
  ...
  astr: AnsiString;
  str: String;
...
  WM_COPYDATA :
  begin
    recvdata := PCopyDataStruct(Message.LParam);
    msgtype := recvdata^.dwData;
    msglen := recvdata^.cbData;
    SetString(astr, PAnsiChar(Recvdata^.lpData), msglen);
    str := string(astr);
    ...
  end;

一旦这样做了,考虑使用Encoding.UTF8而不是Encoding.Default来避免任何非ASCII字符的潜在数据丢失,因为Encoding.Default是一个特定于语言环境的转换,可能会有丢失,而UTF-8是一个无损转换:
一个二个一个一个

相关问题