Question

I want to add a Tabsheet dynamically to a PageControl when a client connected to my IdCmdTCPServer same as this code:

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

Its OK, but when closing application i will get EOSError with message: "System Error. Code: 1400. Invalid window handle". I've been added this code block in a TButton's OnClick event, and application will close without any problem. Is there any safer way to do this?


After David Heffernan's help, I've Changed my methode this way:

....

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;

And command test result:

addtab Command Testing Result

but the mentioned problem is steel happening on application close!

Était-ce utile?

La solution

Your event handler, and therefore the VCL accessing code that it contains, executes on a thread other than the GUI thread. All code that accesses VCL objects must execute on the GUI thread. Hence, you will need to change your code to make sure that the VCL portions are marshalled on to the GUI thread.

Use TIdSync or TThread.Synchronize to marshal the VCL portions of your code onto the GUI thread. Remy gives an example of the former approach here: Indy synchronize ServerTCPExecute

Autres conseils

Final correct idea:

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;

Of course current connection must be closed before application close. If no, invalid pointer operation will occur!

Specially thanks to David Heffernan

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top