4

Delphi2010の2つのアプリケーション間で情報を渡そうとしています。

過去に正常に使用したコードの簡略化されたバージョンを使用しています(送信者が送信が成功したことを知る必要がないため簡略化されています)受信した送信を2つの例に要約しました本質的に次のようなアプリケーション

送信

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プロシージャがまったく起動していないように見える理由について何か提案はありますか?

乾杯

ダン

4

4 に答える 4

6

コードにはいくつかの問題があります。

1 つは、メッセージに一意の ID を割り当てていないことです。VCL およびさまざまなサードパーティ コンポーネントも を使用するWM_COPYDATAため、他の誰かのメッセージではなく、実際に自分のメッセージを処理していることを確認する必要があります。

2 つ目は、2 つ目のアプリが起動するまで十分に待機していない可能性があることです。の代わりに、フラグとともにSleep()使用します (または と を使用します)。ShellExecuteEx()SEE_MASK_WAITFORINPUTIDLECreateProcess()WaitForInputIdle()

3 番目に、2 番目のアプリを開始するときに、再帰ロジックがメッセージを 2 回送信しようとしています。それがたまたま失敗した場合は、3 つ目のアプリを起動します。再帰を完全に削除する必要があります。必要ありません。

これを試して:

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');
于 2011-08-31T18:35:43.830 に答える
3

追加するのは良い習慣だと思います

  copyDataStruct.dwData := Handle; 

in procedure TMF.SendString;- カスタム識別子を持っていない場合、ソース HWND 値を配置すると、宛先でのデバッグに役立ちます (反対側でこの値を確認できるため、ブロードキャストされた WMCOPY_DATA の誤解を避けることができます。 、しかし私はいくつか見た!)。

    procedure WMCopyData(var Msg : TWMCopyData); message WM_COPYDATA;

クライアントクラスのTMF定義ですよね?

入れ子になった呼び出しの後に行方不明exitまたは後にあるはずです。elseSendData

procedure TMF.SendData(copyDataStruct: TCopyDataStruct);
  (...)
      Sleep(3000);
      SendData(copyDataStruct);
   end else
     SendMessage(rh, WM_COPYDATA, NativeInt(Handle), NativeInt(@copyDataStruct));
end;

しかし、これはあまり変わりません。

rh := FindWindow()返されたハンドルを確認します。それはTMFクライアント フォームのハンドルですか、それとも Application.Handle ですか?

于 2011-08-31T14:26:39.883 に答える
0

Windows 7 を使用している場合は、もう機能しません。使用している場合は、このページをチェックして、例外を追加する方法を確認してください: http://msdn.microsoft.com/en-us/library/ms649011%28v= vs.85%29.aspx

于 2011-08-31T13:55:15.107 に答える
0

アプリを起動する必要がある場合、呼び出すときに (rh) ハンドルが 0 になることに問題があると思いました。しかし、SendData が自分自身を再帰的に呼び出していることがわかりました。自明ではないため、コードにコメントを追加しました。しかし今、別の問題があります。SendData の 2 番目のインスタンスには、正しいハンドルがあります。しかし、その後、ハンドルがまだ 0 である最初のインスタンスに戻り、今度は 0 ハンドルで SendMessage を再度呼び出します。これはおそらく問題の原因ではありませんが、意図的ではなく、不必要であり、まったく悪いことです. IMO、これは巧妙になりすぎて事態を複雑にしているケースです。

于 2011-08-31T15:32:19.220 に答える