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:
EnumWindows
uses an untyped pointer for the callback parameter. TThread.Queue
means that the enclosing stack frame can be finished before the call to EnumWindows
completes. 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.