2

我正在使用来自 vb6 应用程序的 WM_COPYDATA 将数据发送到 delphi 应用程序。在我本地为英语的系统中,我正确接收数据,但在另一个使用荷兰语本地的系统上,接收文本是乱码。

接收应用程序是delphi,代码是

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData);
var
  copyDataType: TCopyDataType;
begin
  copyDataType := TCopyDataType(Msg.CopyDataStruct.dwData);

  //Handle of the Sender
  mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From]));

  case copyDataType of
    cdtString: HandleCopyDataString(Msg.CopyDataStruct);
  end;

  //Send something back
  msg.Result := mmoResult.Lines.Count;
end;

procedure TReceiverMainForm.HandleCopyDataString(
  copyDataStruct: PCopyDataStruct);
var
  s: string;
begin
  s := PChar(copyDataStruct.lpData);
  mmoResult.Lines.Add(s);
end;

编辑

这是发送数据的vb6代码,发送的数据是字符串

Dim buf() As Byte
ReDim buf(1 To LenB(Message))
Call CopyMemory(buf(1), ByVal Message, Len(Message))
cds.dwData = 0
cds.cbData = Len(Message) + 1
cds.lpData = VarPtr(buf(1))
' Send the string.
Dim i As Long
i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds)

谁能告诉我做错了什么?

4

1 回答 1

3

VB 字符串是基于 COMBSTR字符串类型的,就像 Delphi 的WideString字符串类型一样。ABSTR是 UTF-16 编码的 Unicode 字符串。 LenB()返回转换为本地机器的当前语言环境时 VB 字符串占用的字节数。你没有考虑到这一点。您没有将字符串字节正确复制到缓冲区中,也没有将cds.cbData字段设置为正确的值。 Len()返回字符串中 UTF-16 编码字符LenB()的数量,而返回字节数。对于英文字符串,Len()并且LenB()将返回相同的值,但不能保证对于外语。

我建议您按原样发送原始的 VB Unicode 编码数据,并更改您的 Delphi 代码以将传入数据视为 Unicode,而不是像当前那样处理 Ansi(PChar在 Delphi 7 中是 Ansi,但在 Delphi 2009+ 中是 Unicode)。

您还需要为该cds.dwData字段分配一个唯一值。 WM_COPYDATAVCL 将其用于一些自己的内部数据,因此您必须区分您的WM_COPYDATA消息和 VCL 的消息。

试试这个:

cds.dwData = RegisterWindowMessage("MyWMCopyData")
If cds.dwData <> 0 Then
  cds.cbData = Len(Message) * 2 ' characters are 2-bytes each
  cds.lpData = StrPtr(Message) ' access the string's character buffer directly
  ' Send the string. 
  Dim i As Long 
  i = SendMessage(lHwnd, WM_COPYDATA, MainForm.hwnd, cds) 
End If

.

var
  uMyWMCopyDataMsg: UINT = 0;

procedure TReceiverMainForm.WMCopyData(var Msg: TWMCopyData); 
var 
  s: WideString; // you can use UnicodeString in D2009+ 
begin 
  if (uMyWMCopyDataMsg = 0) or (Msg.CopyDataStruct.dwData <> uMyWMCopyDataMsg) then
  begin
    inherited;
    Exit;
  end;

  mmoResult.Lines.Add(Format('WM_CopyData from: %d', [msg.From])); 

  SetString(s, PWideChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData div SizeOf(WideChar)); 
  mmoResult.Lines.Add(s); 

  msg.Result := mmoResult.Lines.Count; 
end; 

initialization
  uMyWMCopyDataMsg := RegisterWindowMessage('MyWMCopyData');
于 2012-09-25T17:28:52.117 回答