Послать сообщение с WM_COPYDATA из vb6 в delphi искажено
Я отправляю данные в приложение Delphi, используя WM_COPYDATA из приложения VB6. в моей системе, которая является английской, я получаю данные правильно, но в другой системе с голландским локальным, получаемый текст искажен.
принимающее приложение - 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 ответ
Строки VB основаны на COM BSTR
строковый тип, как у Delphi WideString
тип строки BSTR
является строкой Unicode в кодировке UTF-16. LenB()
возвращает количество байтов, которое занимает строка VB при преобразовании в текущий языковой стандарт локального компьютера. Вы не принимаете это во внимание. Вы неправильно копируете строковые байты в буфер и не устанавливаете cds.cbData
поле к правильному значению, либо. Len()
возвращает количество символов в кодировке UTF-16 в строке, тогда как LenB()
вместо этого возвращает количество байтов. Для английской строки Len()
а также LenB()
вернет то же значение, но для иностранного языка, который не гарантируется.
Я предлагаю вам отправить исходные данные в кодировке VB Unicode как есть, и изменить код Delphi, чтобы обрабатывать входящие данные как Unicode вместо Ansi, как это происходит в настоящее время (PChar
это Ansi в Delphi 7, но Unicode в Delphi 2009+).
Вам также необходимо присвоить уникальное значение cds.dwData
поле. WM_COPYDATA
используется VCL для некоторых собственных внутренних данных, поэтому вы должны различать 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');