Delphi - Indy 关闭所有与客户相关的表格
Delphi - Indy close all the forms that related to client
一旦客户端与服务器断开连接,我将尝试关闭与客户端相关的所有表单
此操作将在服务器端进行。
我有(我在 运行 时间知道的)例如每个客户的部分唯一标题
表单标题 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
总是空的。
我在 IdServerDisconnect
过程中调用 ClientRemove
procedure TIdServer.IdServerDisconnect(AContext: TIdContext);
begin
TMyContext(AContext).Queue.Clear;
........
ClientRemove(AContext);
end;
谁能告诉我哪里错了?
这里有很多错误:
- 您不得使用嵌套函数作为回调。语言不允许这样做,您的代码只能编译,因为
EnumWindows
的 RTL 声明使用回调参数的无类型指针。
- 与
TThread.Queue
的异步执行意味着封闭堆栈帧可以在对 EnumWindows
的调用完成之前完成。
- 您有关闭不属于您进程的 windows 的危险。
如果我遇到这个问题,我会使用 Screen.Forms[]
来解决它。像这样:
for i := Screen.FormCount-1 downto 0 do
if CaptionMatches(Screen.Forms[i]) then
Screen.Forms[i].Close;
这只是一个大纲。我相信你能理解这个概念。关键是不要使用 EnumWindows
而是使用 VCL 自己的机制来枚举您的表单。
一旦客户端与服务器断开连接,我将尝试关闭与客户端相关的所有表单
此操作将在服务器端进行。
我有(我在 运行 时间知道的)例如每个客户的部分唯一标题
表单标题 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
总是空的。
我在 IdServerDisconnect
过程中调用 ClientRemove
procedure TIdServer.IdServerDisconnect(AContext: TIdContext);
begin
TMyContext(AContext).Queue.Clear;
........
ClientRemove(AContext);
end;
谁能告诉我哪里错了?
这里有很多错误:
- 您不得使用嵌套函数作为回调。语言不允许这样做,您的代码只能编译,因为
EnumWindows
的 RTL 声明使用回调参数的无类型指针。 - 与
TThread.Queue
的异步执行意味着封闭堆栈帧可以在对EnumWindows
的调用完成之前完成。 - 您有关闭不属于您进程的 windows 的危险。
如果我遇到这个问题,我会使用 Screen.Forms[]
来解决它。像这样:
for i := Screen.FormCount-1 downto 0 do
if CaptionMatches(Screen.Forms[i]) then
Screen.Forms[i].Close;
这只是一个大纲。我相信你能理解这个概念。关键是不要使用 EnumWindows
而是使用 VCL 自己的机制来枚举您的表单。