【问题标题】:Delphi: WM_COPYDATA work onceDelphi:WM_COPYDATA 工作一次
【发布时间】:2015-12-21 04:46:36
【问题描述】:

基于this post我写了一个简单的项目来沟通两个应用程序,但它只工作一次,也不完美。

如果我发送“stackoverflow”,我将在另一侧收到一次“stackov”。 WMGetData 过程似乎不再触发。

发件人代码:

procedure TForm1.Button1Click(Sender: TObject);
var
  CDS: TCopyDataStruct;
  receiverHandle : THandle;
  res : integer;
  S: string;
begin
  S:= Edit1.Text;
  CDS.dwData:= 0;   //Identify message
  CDS.cbData:= Length(S);
  CDS.lpData:= PChar(S);

  receiverHandle := FindWindow(PChar('TForm2'),PChar('Form2')) ;
  if receiverHandle <> 0 then
    res := SendMessage(receiverHandle, WM_COPYDATA, Integer(Handle), Integer(@CDS))
  else
    Caption:= 'Not Found';

  Caption:= IntToStr(Res);
  CloseHandle(receiverHandle);
end;

接收方代码:

  TForm2 = class(TForm)
    procedure WMGetData(var Msg : TWMCopyData) ; message WM_COPYDATA;

...

procedure TForm2.WMGetData(var Msg: TWMCopyData);
var
  S: string;
begin
  S:= PChar(Msg.CopyDataStruct.lpData);
  Caption := Caption + S;
  msg.Result := 2006;   //ACK for sender app.
end;

【问题讨论】:

  • 你为什么要投到Integer?切换到 64 位时会出现 32 位截断错误。这些参数是WPARAMLPARAM。永远不要在窗口句柄上调用CloseHandleCloseHandle 用于 kernel32 句柄而不是 user32 窗口句柄。你不需要做任何事情来整理你不拥有的窗口句柄。
  • @David 感谢您的提示。我不知道为什么它被铸造了。那是一个有名的。关于CloseHandle 我看到另一个demo 以try/finally 方式关闭句柄。
  • 我不知道该评论什么。我认为您的方法在这里不是很好。
  • 详细说明,您在这里接受了一个不正确且不完整的答案。您还指出了网络上一篇包含错误的无法署名的古老文章。不要相信你在网上读到的一切。检查并验证。

标签: delphi winapi delphi-xe


【解决方案1】:

正如documentation 指定的那样

CDS.cbData:= Length(S);

应该是

CDS.cbData:= Length(S) * SizeOf(S[1])

因为 cbData 成员应该包含您传输的字节数,而 delphi XE string 类型指的是 unicode 字符串(每个字符 2 个字节)

你的第二个问题

receiverHandle := FindWindow(PChar('TForm2'),PChar('Form2')) ;

我的最佳猜测是此调用第二次失败,因为您将第二个表单的标题更改为 Form2Stackov。

【讨论】:

  • 值得注意:cb 是匈牙利表示法前缀,count of bytes 的缩写。指定字符数的符号具有cch 前缀。
  • RTL在SysUtils单元中有一个ByteLength()函数,返回String的字符载荷占用的字节数,例如:CDS.cbData := ByteLength(S);
  • 这仍然是错误的,因为接收器依赖于空终止符。所以要么在接收器中使用字节数(更好),要么在发送器中使用Length()+1。正如我在对该问题的评论中提到的那样,还有更多错误。
  • 当心ByteLength。仅对原生 UTF-16 字符串有用。对于字节字符串,您会找到转换为 UTF-16 的字符串,然后是报告的字节长度。符合设计,但存在混淆范围。
  • @David,我不明白你说它更好的解决方案,混淆部分是它有一个“或”。 Length(S) 当 S 变成 AnsiString 时起作用了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-06
  • 2018-06-22
  • 2015-09-18
  • 2013-12-31
  • 1970-01-01
  • 2013-09-28
相关资源
最近更新 更多