WM_COPYDATA从vb6发送到delphi的sendmessage是乱码

时间:2012-09-25 06:58:21

标签: delphi vb6 delphi-7 sendmessage wm-copydata

我使用vb6 app中的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)

谁能告诉我出错了什么?

1 个答案:

答案 0 :(得分:3)

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

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

您还需要为cds.dwData字段指定唯一值。 VCL使用WM_COPYDATA作为其内部数据,因此您必须区分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');