Delphi 10.3 在另一个FMX 窗体中创建FMX 窗体关闭错误

Delphi 10.3 Creating FMX forms inside another FMX form close error

我关注了这个:http://docwiki.embarcadero.com/CodeExamples/XE5/en/FMXEmbeddedForm_(Delphi)

还有这个:

还有这个:

我正在使用 Delphi 10.3

我的最终结果是:我创建了一个 parent 表单,里面有一个 TLayout,我希望 child 表单出现在其中。接下来,我所有的 child 表单都有一个包含表单所有其他组件的 TLayout。所有表单都是在运行时动态创建的,它们的内容也是如此。

出于测试目的,我在主窗体的按钮内创建了 child窗体:

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

到目前为止一切顺利,child 表单的所有组件都出现在 parent 表单上。问题是,之后如何 "clear" 他们。在 child 表单上的按钮上发送 self.Close 不会从主表单中删除布局组件,但会关闭 child 表单。在 child 窗体的按钮上执行 Layout1.Destroy 会清除布局,但我无法访问主窗体的 window 控制按钮(最大化、最小化、退出)以及获得该访问权限的唯一方法返回是重新创建 child 的布局。 我只想将此嵌入式功能用于 windows 和 macos OS',对于 android 则没有必要,因此我正在使用 defs 对其进行调整。

我觉得我这样做的方式不对:'(,有解决办法吗?我只想在主窗体的指定区域内动态创建一个 child 窗体的组件,并拥有在不再需要 child 表单后清除这些组件的安全方法

我自己做了一个MRE,因为你觉得你不需要提供。下面Form1是主窗体,Form2是子窗体

当您关闭一个不是主窗体的窗体(例如 Form2.Close;)时,它不一定会被销毁。窗体的默认关闭操作是 caHide,它只设置它的 属性 Visible = False,它保留在内存中,准备再次调用。

子窗体上的组件仍然是主窗体中 TLayout 的父级,因此隐藏子窗体不会影响组件的可见性。要更正此问题,您可以将组件从主窗体移回子窗体:

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

,可以在其OnClose()事件中销毁子窗体:

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

无需重新设置组件的父级即可工作,因为 Form2 仍然是组件的所有者,即使父级是 Form1。

/* 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();
}