简体   繁体   中英

Delphi - Indy close all the forms that related to client

I'm trying to close all the forms that related to client once he disconnected form the server

This action will be on the server side.

I have ( the known for me at run time ) partial unique caption for each client for example

Form caption 1:

ServiceA - ClientABC

Form caption 2:

ServiceB - ClientABC

What i already know is the - ClientABC part only.

So when the client ClientABC disconnected form my server i want to close all the related opened form in the server side.

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;

My problem is the string sTitle inside the CloseChildForm function always empty.

I call ClientRemove on the IdServerDisconnect procedure

procedure TIdServer.IdServerDisconnect(AContext: TIdContext);
begin
     TMyContext(AContext).Queue.Clear;
     ........
     ClientRemove(AContext);
end;

Can anyone tell me what wrong please ?

There are quite a few things wrong here:

  • You must not use a nested function as your callback. That is not allowed by the language and your code only compiles because the RTL declaration of EnumWindows uses an untyped pointer for the callback parameter.
  • Asynchronous execution with TThread.Queue means that the enclosing stack frame can be finished before the call to EnumWindows completes.
  • You are in danger of closing windows that do not belong in your process.

Were I faced with this problem I would solve it using Screen.Forms[] . Something like this:

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

This is just an outline. I'm sure you can understand the concept. The key point is not to use EnumWindows and instead use the VCL's own mechanism to enumerate your forms.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM