SendMessage函数只将消息的第一个字符从VC ++ app发送到reciever(Delphi App)?

时间:2013-09-06 15:54:22

标签: delphi visual-c++ sendmessage

SendMessage只发送VC ++消息的第一个章程,你能帮忙吗? 只收到第一份包机。

实际上这是我的完整发件人应用代码(VC ++)

   // notification->FileName is UCHAR[255]

        HWND app = FindWindow(NULL,TEXT("Message Receiver"));
        COPYDATASTRUCT cds;
    cds.dwData = 0; // can be anything
    cds.cbData = sizeof(notification->FileName) - sizeof(UCHAR);
    cds.lpData = (void*)notification->FileName;
     SendMessageA(app, WM_COPYDATA, (WPARAM)app, (LPARAM)&cds);

我的收件人代码(Delphi)

 procedure TfrmReceiver.WMCopyData(var Msg: TWMCopyData);
    var
      sText: array[0..255] of Char;
      s: string;
      ms: TMemoryStream;
    begin
      case Msg.CopyDataStruct.dwData of
        0: { Receive Text, Text empfangen}
          begin
            StrLCopy(sText, Msg.CopyDataStruct.lpData,Min(Length(sText), Msg.CopyDataStruct.cbData));
            label1.Caption := sText;
          end;
         1: { Receive Image, Bild empfangen}
         {
          begin
            ms := TMemoryStream.Create;
            try
              with Msg.CopyDataStruct^ do
               ms.Write(lpdata^, cbdata);
               ms.Position := 0;
              image1.Picture.Bitmap.LoadFromStream(ms);
            finally
              ms.Free;
            end;
          end; }
      end;
    end;

2 个答案:

答案 0 :(得分:1)

您将数据作为8位Ansi发送。但是,如果您使用的是Delphi 2009或更高版本(您没有说),StringChar是Unicode,那么您将遇到问题。

将您的Delphi代码更改为以下版本,该代码适用于所有版本:

procedure TfrmReceiver.WMCopyData(var Msg: TWMCopyData);
var
  sText: AnsiString;
  ms: TMemoryStream;
begin
  case Msg.CopyDataStruct.dwData of
    0: { Receive Text, Text empfangen}
    begin
      SetString(sText, PAnsiChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
      Label1.Caption := Trim(sText);
    end;
    1: { Receive Image, Bild empfangen}
    {
    begin
      ms := TMemoryStream.Create;
      try
        with Msg.CopyDataStruct^ do
          ms.Write(lpData^, cbData);
        ms.Position := 0;
        Image1.Picture.Bitmap.LoadFromStream(ms);
      finally
        ms.Free;
      end;
    end;
    }
  end;
end;

如果您更改C ++代码以发送实际的FileName长度而不是盲目地发送255,那么您可以从Delphi代码中删除Trim()

此代码的另一个问题是0和1是dwData值的非常差的选择。您应该在双方使用RegisterWindowMessage()来生成更多唯一值,这些值不太可能与其他人使用WM_COPYDATA冲突(例如,即使VCL在内部使用WM_COPYDATA也是如此)。例如:

const UINT MyTextMsg = RegisterWindowMessage(TEXT("MyTextMsg"));
// ...
if (MyTextMsg != 0)
{
    COPYDATASTRUCT cds;
    cds.dwData = MyTextMsg;
    // ...
}

var
  MyTextMsg: UINT = 0;
  MyImageMsg: UINT = 0;

procedure TfrmReceiver.WMCopyData(var Msg: TWMCopyData);
var
  sText: AnsiString;
  ms: TMemoryStream;
begin
  if (Msg.CopyDataStruct.dwData = MyTextMsg) and (MyTextMsg <> 0) then
  begin
    // ...
  end
  else if (Msg.CopyDataStruct.dwData = MyImageMsg) and (MyImageMsg <> 0) then
  begin
    // ...
  end;
end;

initialization
  MyTextMsg := RegisterWindowMessage('MyTextMsg');
  MyImageMsg := RegisterWindowMessage('MyImageMsg');

此外,只是优化 - 如果您从TCustomMemoryStream派生一个类而不是TMemoryStream,您可以将lpData指针传递给TCustomMemoryStream.SetPointer(),以便{{1}将能够直接读取消息数据,您不必在内存中单独复制它。

答案 1 :(得分:0)

好像你正在混合unicode和ansi字符串。在第一种情况下不要使用TEXT宏,使用纯ansi字符串。 片段sizeof(TEXT(“消息接收者”)) - sizeof(UCHAR)将计算unicode字符串的无效大小

Unicode字符串TEXT(“消息接收器”)将被读取为“M”,当您将其读取到delphi char数组时,因为unicode中的“M”是两个字符 - “M”和零。