0

当客户端连接到我的代码时,我想Tabsheet动态添加一个:PageControlIdCmdTCPServer

procedure TForm1.IdCmdTCPServer1Connect(AContext: TIdContext);
var
  ATabSheet: TTabSheet;
begin
  ATabSheet := TTabSheet.Create(PageControl1);
  ATabSheet.PageControl := PageControl1;
  ATabSheet.Caption := 'Hello!';
  {...}
end;

没问题,但是当关闭应用程序时,我会收到带有消息的 EOSError:“系统错误。代码:1400。无效的窗口句柄”。我已经在TButton'sOnClick事件中添加了这个代码块,应用程序将毫无问题地关闭。有没有更安全的方法来做到这一点?


David Heffernan的帮助下,我改变了我的方法:

....

type
  TMyThrd = class(TThread)
    protected
      procedure Execute; override;
  end;

...

procedure TMyThrd.Execute;
begin
  with TTabsheet.Create(Form1.PageControl1) do
    PageControl := Form1.PageControl1;
end;

...

procedure TForm1.cmdAddTabCommand(ASender: TIdCommand);
begin
  with TMyThrd.Create(True) do
  begin
    FreeOnTerminate := True;
    Resume;
  end;
end;

并命令测试结果:

addtab 命令测试结果

但提到的问题是钢铁在应用程序关闭时发生!

4

2 回答 2

1

您的事件处理程序以及它所包含的 VCL 访问代码在 GUI 线程以外的线程上执行。所有访问 VCL 对象的代码都必须在 GUI 线程上执行。因此,您需要更改代码以确保将 VCL 部分编组到 GUI 线程。

使用 TIdSync 或 TThread.Synchronize 将代码的 VCL 部分编组到 GUI 线程上。雷米在这里给出了前一种方法的一个例子:Indy synchronize ServerTCPExecute

于 2013-05-30T08:46:20.243 回答
0

最终正确的想法:

uses
..., IdSync, ...
...

type
  TSyncThrd = class(TIdSync)
  protected
    procedure DoSynchronize; override;
end;

...

procedure TForm1.cmdAddTabCommand(ASender: TIdCommand);
begin
  with TSyncThrd.Create do
  begin
    try
      Synchronize;
    finally
      Free;
    end;
  end;
end;

...


procedure TSyncThrd.DoSynchronize;
begin
  with TTabsheet.Create(Form1.PageControl1) do
    PageControl := Form1.PageControl1;
end;

当然,当前连接必须在应用程序关闭之前关闭。如果没有,invalid pointer operation就会发生!

特别感谢大卫赫弗南

于 2013-05-30T09:54:25.740 回答