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

标签 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;

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

我在 IdServerDisconnect 过程中调用 ClientRemove

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

谁能告诉我哪里出了问题吗?

最佳答案

这里有很多错误:

  • 您不得使用嵌套函数作为回调。这是语言所不允许的,您的代码只能编译,因为 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 自己的机制来枚举表单。

关于forms - Delphi - Indy关闭所有与客户相关的表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37904188/

相关文章:

javascript - Jquery 不允许在文本区域中换行

delphi - log4d 与 log4delphi

带登录/注销的 Delphi 应用程序 - 如何实现?

delphi - 如何使用 Delphi 2009 验证 SOAP 签名?

delphi - 如何在 Delphi 7 中通过 SSL 和 Indy 发送电子邮件

delphi - TIdHTTPProxyServer 引发 "Unknown Protocol"RSHTTPUnknownProtocol 异常

javascript - PHP 表单提交和 AJAX 验证

Python - 填写登录表单,然后填写只有登录后才能访问的另一个表单

Delphi IdHTTP服务器加载html

php - 如何在不刷新的情况下将数据插入字段?