1
votes

I've followed this: http://docwiki.embarcadero.com/CodeExamples/XE5/en/FMXEmbeddedForm_(Delphi)

and this: https://stackoverflow.com/a/2475810

and this: https://stackoverflow.com/a/26508888

I'm using Delphi 10.3

My final result was: I've created a parent form with a TLayout inside of it where I want the child forms to appear. Next, all my child forms have a TLayout containing all the other components of the form. All forms are dynamically created in runtime and their contents are as well.

For testing purposes I've created the childform inside a button on the main form:

procedure TForm1.Button1Click(Sender: TObject);
begin
  Application.CreateForm(TfChild, fChild);
  fChild.Layout1.Parent := self.Layout1;
end;

So far so good, all the components of the childform appears on the parent form. Problem is, how to "clear" them afterwards. Sending a self.Close, on a button on the child form doesn't remove the Layout components from the main form but it closes the child form. Doing a Layout1.Destroy on the child form's button clears the layout, but I lose acess to my main form's window control buttons (maximize, minimize, exit) and the only way to get that access back is to recreate the child's layout. This embedded feature I only wanna use for windows and macos OS', for android it won't be necessary so I'm using defs to adjust that.

I feel like I'm not doing this the right way :'(, is there a solution? I just want to dynamically create the components of a child form inside the main form's designated area and have a safe way of clearing those components after that child form is no longer necessary

2
Please provide a minimal reproducible example, including .pas and .fmx files. Emphasize on minimalTom Brunberg

2 Answers

1
votes

I made an MRE myself, since you felt you don't need to provide one. In the following Form1 is the main form and Form2 is the child form

When you close a form (e.g. Form2.Close;), that is NOT the main form, it is not necessarily destroyed. The default close action for a form is caHide, which only sets its property Visible = False, which leaves it existing in memory, ready to be called up again.

The components on your child form are still parented to the TLayout in your main form, so therefore hiding the child form has no influence on the visibility of the components. To correct this you can move the components back from the mainform to the child form:

procedure TForm2.Button1Click(Sender: TObject);
begin
  Layout1.Parent := Self; // add this
  Self.Close;
end;

Or, you can destroy the child form in its OnClose() event:

procedure TForm2.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree;
end;

This works without reparenting the components, because Form2 is still the owner of the components, even though the parent is Form1.

0
votes
/* It works on C++ Builder 
  the main form has a layout component called LayoutContainer
  and the child form has a main LayoutClient which contains all objects*/

//code in main form 
#include "UChild.h"
void __fastcall TFmMain::Item1Click(TObject *Sender)
{
  TFmChild *FmChild;
  TLayout  *LyChild; 

  FmChild = new TFmChild(Application);

  LyChild = dynamic_cast<TLayout *> (FmChild->FindComponent("LayoutClient"));
  LayoutContainer->AddObject(LyChild);

}
//---------------------------------------------------------------------------

//child form has a button bnBack1
//this code is in child form

void __fastcall TFmBoletos::bnBack1Click(TObject *Sender) 
{
   LayoutClient->Parent = this;
   this->Close();
}