如何在MainForm之前创建一个窗体?

How to create a form before the MainForm?

我想创建一个显示 x 秒的启动画面(在主窗体之前),但是我不想延迟主窗体的创建x 秒。

因此,我创建了闪屏表单,创建了主表单,然后在 x 秒后关闭了闪屏表单。
据我了解,使用 CreateForm 创建的第一个表单是主表单。这是正确的吗?

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := FALSE;
  Application.Title := AppName;
  frmSplash:= TfrmSplash.Create(NIL);         <----- not main form??
  Application.CreateForm(TfrmMain, frmMain);  <----- main form??
  frmMain.LateInitialization;
  frmMain.show;
  Application.Run;
end.

关闭启动画面
初始屏幕有一个 TTimer。计时器以飞溅形式执行一些动画,并在 x 秒后关闭表单:

procedure TfrmSplash.CloseSplashForm;
begin
 Timer.Enabled:= FALSE;
 Close;        <-- I do see the program reaching this point
end;

但是,应用程序在关闭时泄漏内存:

5 - 12 bytes: TMoveArrayManager<System.Classes.TComponent> x 4, Unknown x 2
13 - 20 bytes: TObservers x 1, TList x 3, Unknown x 3
21 - 36 bytes: TComponent.GetObservers2$ActRec x 1, TPen x 2, TIconImage x 1, TPadding x 1, TBrush x 3, TTouchManager x 2, TMargins x 2, TSizeConstraints x 2, TList<System.Classes.TComponent> x 4, UnicodeString x 3, Unknown x 6
37 - 52 bytes: TDictionary<System.Integer,System.Classes.IInterfaceList> x 1, TPicture x 1, TGlassFrame x 1, TFont x 4
53 - 68 bytes: TIcon x 1
69 - 84 bytes: TControlScrollBar x 2
85 - 100 bytes: TTimer x 1
101 - 116 bytes: TControlCanvas x 2
149 - 164 bytes: Unknown x 2
437 - 484 bytes: TImage x 1
917 - 1012 bytes: TfrmSplash x 1

看起来 frmSplash 并没有真正被释放。

OnClose 事件添加到初始表单并设置

Action := caFree;

飞溅形式泄漏,因为没有破坏它。部分选项:

  • 在创建初始表单时将 Application 对象作为初始表单的所有者传递。
  • 手动销毁它。
  • 忽略泄漏。这并不重要,因为您只创建了一个飞溅形式,因此未能销毁它不会导致大量资源消耗。

对于第一个选项,启动窗体在应用程序结束之前不会被销毁。这与故意泄露表格没有什么不同。

选择手动销毁表单有点棘手。您希望在关闭启动窗体时执行此操作,但您不能从其自身的事件处理程序之一中销毁对象。因此,您可以调用表单的 Release 方法并将表单的销毁排队。如果你这样做,你需要确保表单被销毁,即使计时器永远不会过期。使表单由 Application 对象拥有即可完成此操作。

多年来我一直使用这个结构:

program MyProg;
uses
  Vcl.Forms,
  MainFrm in 'MainFrm.pas' {Zentrale},
  // Your Forms are here
  SplashFrm in 'SplashFrm.pas' {Splash};

{$R *.res}

var
  Sp: TSplash;

begin
  Application.Initialize;
  Application.MainFormOnTaskbar := True;
  Application.Title := 'XXXXXX';

{$IFDEF RELEASE}
  SP := TSplash.Create(nil);
  SP.Show;
  SP.Update;
{$ENDIF}

  Application.CreateForm(TZentrale, Zentrale);
  // ... and more Forms 

{$IFDEF RELEASE}
  SP.Hide;
  SP.free;
{$ENDIF}

  Application.Run;