开发者

Using SendData results in a mangled string when received

I'm trying to send a string between two Delphi forms using code adapted from here: http://delphi.about.com/od/windowsshellapi/a/wm_copydata.htm.

The string that is displayed by the receiver is partially garbage. I suspect this is because of Unicode I issues when Delphi 2010 is communicating with the Windows API.

I want to be able to handle Unicode if possible.

I have been unable to figure out where in the code below a cast is wrong. Any help?

Sending form:

procedure TForm1.gridDetailsDblClick(Sender: TObject);
var
  StringToSend : String;
  CopyDataStruct : TCopyDataStruct;
begin
  StringToSend := StringGrid1.Cells[0, StringGrid1.Row];
  CopyDataStruct.dwData := 0;
  CopyDataStruct.cbData := 1 + Length(StringToSend) ;
  CopyDataStruct.lpData := PChar(StringToSend) ;
  SendDataToAppearanceForm(copyDataStruct) ;
end;

procedure TForm1.SendDataToAppearanceForm(const CopyDataStruct: TCopyDataStruct) ;
var
  ReceiverHandle : THandle;
begin
  ReceiverHandle := FindWindow(PChar('TForm2'), ni开发者_开发问答l);
  if (ReceiverHandle <> 0) then
    SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@CopyDataStruct)) ;
end;

Receiving form: (Which results in the edit box containing a part of the string, but then garbage.)

procedure TForm2.WMCopyData(var Msg: TWMCopyData);
var
  S: String;
begin
  edText.Text := PChar(Msg.CopyDataStruct.lpData);
end;  { WMCopyData }


Your problem is that you are setting cbData incorrectly. This is the number of bytes and not the number of characters.

The +1 is needed since your receiver is interpreting it as a null-terminated string. Therefore your code should read:

(1 + Length(StringToSend))*SizeOf(Char)

Alternatively you could, at the receiving end, make use of SetString() and cbdata to avoid the need for the +1.


I just tried

procedure TForm1.Button1Click(Sender: TObject); // Project1.exe
var
  CDS: TCopyDataStruct;
begin
  CDS.dwData := 0;
  CDS.cbData := (length(Edit1.Text) + 1) * sizeof(char);
  CDS.lpData := PChar(Edit1.Text);

  SendMessage(FindWindow(nil, 'RecForm'),
    WM_COPYDATA, Integer(Handle), Integer(@CDS));
end;

procedure TForm1.WndProc(var Message: TMessage); // Project2.exe
begin
  inherited;
  case Message.Msg of
    WM_COPYDATA:
      begin
        Edit1.Text := PChar(TWMCopyData(Message).CopyDataStruct.lpData);
        Message.Result := Integer(True);
      end;
  end;
end;

to copy and it works. The difference between this code and yours is that, since one Unicode character is two bytes long, the cbData member needs to be the number of characters in the string times two, that is, times sizeof(char). In addition, you need to add a whole character so that the null terminator is sent along with the string! Otherwise the receiver will not know when the string ends!

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜