delphi - WM_COPYDATA 字符串未出现在目标应用程序中

标签 delphi delphi-2010 wm-copydata

我正在尝试在 Delphi 2010 中的两个应用程序之间传递信息。

我正在使用过去成功使用过的代码的简化版本(简化是因为我不需要发件人知道发送已成功)我已将收到的发送归结为一对示例应用程序,其本质如下

发送

procedure TMF.SendString;
var
   copyDataStruct: TCopyDataStruct;
   s: AnsiString;
begin
   s := ebFirm.Text;
   copyDataStruct.cbData := 1 + length(s);
   copyDataStruct.lpData := PAnsiChar(s);
   SendData(copyDataStruct);
end;

procedure TMF.SendData(copyDataStruct: TCopyDataStruct);
var
   rh: THandle;
   res: integer;
begin
   rh := FindWindow(PChar('TMF'), PChar('Get Phone'));
   if rh = 0 then
   begin
      // Launch the target application
      ShellExecute(Handle, 'open', GetPhone, nil, nil, SW_SHOWNORMAL);
      // Give time for the application to launch  
      Sleep(3000);
      SendData(copyDataStruct); // RECURSION!
   end;
   SendMessage(rh, WM_COPYDATA, Integer(Handle), Integer(@copyDataStruct));
end;

接收申请

procedure TMF.WMCopyData(var Msg: TWMCopyData);
var
   s : AnsiString;
begin
   s := PAnsiChar(Msg.CopyDataStruct.lpData) ;
   jobstatus.Panels[1].Text := s;
end;

工作测试应用程序和我添加代码的应用程序之间的主要区别是目标应用程序中正在进行很多额外的事件。尤其是在启动时。

关于为什么 WMCopyData 过程似乎根本没有触发有什么建议吗?

干杯

最佳答案

您的代码存在一些问题。

第一,您没有为消息分配唯一的 ID。 VCL 和各种第三方组件也使用 WM_COPYDATA,因此您必须确保您实际上正在处理您的消息,而不是其他人的消息。

第二,您可能没有等待足够长的时间来启动第二个应用程序。使用带有 SEE_MASK_WAITFORINPUTIDLE 标志的 ShellExecuteEx() 来代替 Sleep()(或者使用 CreateProcess()WaitForInputIdle())。

第三,当启动第二个应用程序时,您的递归逻辑将尝试第二次发送消息。如果失败,您将启动第三个应用程序,依此类推。您应该完全删除递归,您不需要它。

试试这个:

var
  GetPhoneMsg: DWORD = 0;

procedure TMF.SendString;
var
  copyDataStruct: TCopyDataStruct;
  s: AnsiString;
begin
  if GetPhoneMsg = 0 then Exit;
  s := ebFirm.Text;
  copyDataStruct.dwData := GetPhoneMsg;
  copyDataStruct.cbData := Length(s);
  copyDataStruct.lpData := PAnsiChar(s);
  SendData(copyDataStruct);
end;

procedure TMF.SendData(copyDataStruct: TCopyDataStruct);
var
  rh: HWND;
  si: TShellExecuteInfo;
  res: Integer;
begin
  rh := FindWindow(PChar('TMF'), PChar('Get Phone'));
  if rh = 0 then
  begin
    // Launch the target application and give time to start
    ZeroMemory(@si, SizeOf(si));
    si.cbSize := SizeOf(si);
    si.fMask := SEE_MASK_WAITFORINPUTIDLE;
    si.hwnd := Handle;
    si.lpVerb := 'open';
    si.lpFile := GetPhone;
    si.nShow := SW_SHOWNORMAL;
    if not ShellExecuteEx(@si) then Exit;
    rh := FindWindow(PChar('TMF'), PChar('Get Phone'));
    if rh = 0 then Exit;
  end;
  SendMessage(rh, WM_COPYDATA, WParam(Handle), LParam(@copyDataStruct));
end;

initialization
  GetPhoneMsg := RegisterWindowMessage('TMF_GetPhone');

接收申请

var
  GetPhoneMsg: DWORD = 0;

procedure TMF.WMCopyData(var Msg: TWMCopyData);
var
  s : AnsiString;
begin
  if (GetPhoneMsg <> 0) and (Msg.CopyDataStruct.dwData = GetPhoneMsg) then
  begin
    SetString(s, PAnsiChar(Msg.CopyDataStruct.lpData), Msg.CopyDataStruct.cbData);
    jobstatus.Panels[1].Text := s;
  end else
    inherited;
end;

initialization
  GetPhoneMsg := RegisterWindowMessage('TMF_GetPhone');

关于delphi - WM_COPYDATA 字符串未出现在目标应用程序中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7257719/

相关文章:

delphi - 在默认浏览器中打开 TWebBrowser 链接

delphi - Delphi 新 RTTI 的实际使用 - 属性、值

delphi - 释放的 TStringList 在 FastMM4 报告中算作内存泄漏的原因

delphi - TServerSocket Delphi 上的多字节字符支持

c++ - 使用 WM_COPYDATA 将结构从 C++ 发送到 WPF

forms - TForm.Close 和通过表单句柄关闭有什么区别?

delphi - 如何在 Delphi 7 中将一个接口(interface)转换为另一个接口(interface)?

delphi 通过 wm_copydata 将运行参数传递给其他实例在 Delphi XE2 中给出错误结果

delphi - 发送带有附件的电子邮件 与客户端无关

string - WM_COPYDATA SendMessage - 它可以发送大字符串吗?