Delphi - Indy关闭与客户相关的所有表格

时间:2016-06-19 05:21:37

标签: forms delphi indy

我试图在与服务器断开连接后关闭与客户端相关的所有表单

此操作将在服务器端。

我(在运行时为我所知)每个客户端的部分唯一标题,例如

表格标题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;

我的问题是sTitle函数中的字符串CloseChildForm始终为空。

我在ClientRemove程序

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

有谁能告诉我有什么不对吗?

1 个答案:

答案 0 :(得分:4)

这里有很多不妥之处:

  • 您不得使用嵌套函数作为回调。语言不允许这样做,并且您的代码仅编译,因为EnumWindows的RTL声明使用无类型指针作为回调参数。
  • 使用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自己的机制来枚举表单。