2016-06-19 4 views
1

に関連するすべてのフォームを閉じます。デルファイ - インディは、私は彼がこのアクションは、サーバー側になり、サーバーに</p> <p>を形成する切断後、クライアントに関連するすべてのフォームを閉じますしようとしているクライアント

私は例えば、各クライアントのための(実行時に私のために知られている)部分のユニークなキャプション

フォームのキャプション1持っている:

ServiceA - ClientABC 

フォームのキャプション2:

ServiceB - ClientABC 

何を私はすでに知っているのは- ClientABC部分だけです。

したがって、クライアントClientABCが私のサーバから切断された場合、サーバ側で関連する開いているフォームをすべて閉じたいと思っています。

procedure TIdServer.ClientRemove(const AContext: TIdContext); 
var 
    sTitle: string; 
    function CloseChildForm(Wnd: HWND; Param: LPARAM): BOOL; stdcall; 
    begin 
     if Pos(sTitle, _GetWindowTitle(Wnd)) <> 0 then 
      PostMessage(Wnd, WM_CLOSE, 0, 0); 
     Result := True; 
    end; 
begin 
    sTitle := TMyContext(AContext).Uniquename {ClientABC} 
    if Assigned(FListView) then begin 
     TThread.Queue(nil, 
      procedure 
      var 
      i: Integer; 
      begin 
       EnumWindows(@CloseChildForm, 0); 

       ....... 

       end; 

      end 
     ); 
    end; 
end; 

私の問題は常に空CloseChildForm関数内の文字列sTitleです。

私は誰が何を間違った私にしてください教えてください。
procedure TIdServer.IdServerDisconnect(AContext: TIdContext); 
begin 
    TMyContext(AContext).Queue.Clear; 
    ........ 
    ClientRemove(AContext); 
end; 

IdServerDisconnect手順に ClientRemoveを呼び出す

+2

「TMyContext」に関連付けられたウィンドウのリストを与えるだけではどうですか?ウィンドウが開いたら、それをクライアントのリストに追加します。ウィンドウが閉じられたら、クライアントのリストからウィンドウを削除します。クライアントが接続を切断すると、まだ開いているウィンドウを閉じるリストをループします。 **あなたの窓を追跡する** **それらのための**狩猟ではありません。 –

答えて

4

は間違ってここにかなりの数のものがあります。

  • はあなたがあなたのコールバックとしてネストされた関数を使用しないでください。 RTL宣言EnumWindowsは、コールバックパラメータに型なしポインタを使用するため、言語では許可されていません。コードはコンパイルのみです。
  • TThread.Queueを使用した非同期実行は、EnumWindowsの呼び出しが完了する前に、囲みスタックフレームを終了できることを意味します。
  • プロセスに属していないウィンドウを閉じる危険があります。

私はこの問題に直面しましたが、Screen.Forms[]を使用して解決しました。このようなもの:

for i := Screen.FormCount-1 downto 0 do 
    if CaptionMatches(Screen.Forms[i]) then 
    Screen.Forms[i].Close; 

これは単なる概要です。私はあなたがそのコンセプトを理解できると確信しています。重要な点は、EnumWindowsを使用せず、代わりにフォームを列挙するためにVCLの独自のメカニズムを使用することです。

関連する問題

 関連する問題