delphifiremonkeytformtpanel

How can I use a form's global variable to put it in a panel?


This is a continuation of my question: How can I display a Delphi form in a panel?

I want to use a forms global variable to embed it in a panel to display it now, but it only creates the form to embed, without it's buttons.

In the code of the executable I'm creating the form to embed first and the form that I want to embed it in second, like so:

program Project1;

uses
  System.StartUpCopy,
  FMX.Forms,
  Unit1 in 'Unit1.pas' {Form1},
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm2, Form2);
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

The main form's code is:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls;

type
  TForm1 = class(TForm)
    Label1: TLabel;
    Panel1: TPanel;
    procedure EmbedForm(ArgParent : TControl; ArgForm : TCustomForm);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

uses Unit2;



procedure TForm1.FormCreate(Sender: TObject);
begin
  EmbedForm(Panel1, Form2);
end;

procedure TForm1.EmbedForm(ArgParent: TControl; ArgForm: TCustomForm);
begin
  while ArgForm.ChildrenCount>0 do
  begin
    ArgForm.Children[0].Parent:= ArgParent;
  end;
end;

end.

The code of the form to embed is:

unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls;

type
  TForm2 = class(TForm)
    Button2: TButton;
    Button1: TButton;
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form2: TForm2;

implementation

{$R *.fmx}

end.

Solution

  • The way I've done this before to avoid having to iterate through all you ArgForm's children is by having a "master container" of sorts on the ArgForm that has all the children you need. How I set this up is by

    1. first placing a TLayout, aligned to Client on the ArgForm
    2. Next, I added all my children controls to the TLayout of ArgForm (buttons etc..)
    3. Next add a panel to the form we want this embedded in
    4. After that form was setup, I assign the layout of ArgForm to the Parent form's panel on ParentForm's OnShow rather than the OnCreate ( ArgForm.Children[0].Parent:=Self.Panel1;)

    Project Source:

    program Project1;
    
    uses
      System.StartUpCopy,
      FMX.Forms,
      Unit1 in 'Unit1.pas' {ParentForm},
      Unit2 in 'Unit2.pas' {ArgForm};
    
    {$R *.res}
    
    begin
      Application.Initialize;
      Application.CreateForm(TParentForm, ParentForm);
      Application.CreateForm(TArgForm, ArgForm);
      Application.Run;
    end.
    

    Parent Form Code:

    unit Unit1;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,unit2,
      FMX.StdCtrls;
    
    type
      TParentForm = class(TForm)
        Panel1: TPanel;
        procedure FormShow(Sender: TObject);
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      ParentForm: TParentForm;
    
    implementation
    
    {$R *.fmx}
    
    procedure TParentForm.FormShow(Sender: TObject);
    begin
      ArgForm.Children[0].Parent:=Self.Panel1;
    end;
    
    end.
    

    ArgForm Code:

    unit Unit2;
    
    interface
    
    uses
      System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
      FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.StdCtrls,
      FMX.Layouts;
    
    type
      TArgForm = class(TForm)
        Layout1: TLayout;
        Button1: TButton;
        Button2: TButton;
      private
        { Private declarations }
      public
        { Public declarations }
      end;
    
    var
      ArgForm: TArgForm;
    
    implementation
    
    {$R *.fmx}
    
    end.
    

    Maybe someone else could answer, but it just seemed to me the reason why the buttons weren't showing on the create, was that the controls hadn't been created at that time?