【问题标题】:Correct way to destroy a form and show another in Delphi在 Delphi 中销毁表单并显示另一个表单的正确方法
【发布时间】:2012-03-05 04:27:51
【问题描述】:

目前在我的程序中,我有一个启动表单和一个主表单。启动表单会显示一两秒钟。

现在,我在计时器中有以下代码:

  frmStartup.Destroy;

  frmMain := TfrmMain.Create(Self);
  frmMain.Show;

现在,我不确定这是否是正确的方法。它有效,但是当调用 application.Terminate(); 时 我收到一条访问冲突消息,导致我认为我在破坏启动表单时做错了..

如果有人可以展示做我想做的事情的正确程序(非模态),将不胜感激。

提前致谢,

编辑:

感谢所有反馈,我通过简单地添加代码修复了我的访问冲突:

  Action := caFree;

进入frmStartup.formClose方法。

【问题讨论】:

  • frmStartup.Destroy 应该是 frmStartup.Free 甚至是 frmStartup.Release FWIW

标签: forms delphi procedure creation destruction


【解决方案1】:

不要使用Application.CreateForm 创建frmStartup。在那里创建的第一个表单成为您应用程序的主表单,如果那是 frmStartup,那么您将在 Application 知识之外销毁它。

改为在您的项目源 (.dpr) 文件中使用普通的 Form.Create:

var
  frmStartup: TfrmStartup;

begin
  Application.Initialize;
  Application.MainFormOnTaskBar := True;
  frmStartup := TfrmStartup.Create(nil);  // No owner assigned here!
  frmStartup.Show;
  frmStartup.Update;

  Application.CreateForm(TfrmMain, frmMain); // Let Application have this for main form
  // Delay here if needed
  frmfrmStartup.Free;
  Application.Run;
end.

【讨论】:

  • 为了使过程尽可能紧凑,定义一个 Windows 消息并在您的启动表单中放置一个消息处理程序,以便在收到消息时释放它。然后从主窗体的 OnShow 方法发送该消息。
  • 我在我的应用程序中使用启动画面。然而,这似乎超出了这个问题的范围。
【解决方案2】:

TFrmMain.Create(Self)???什么是“自我”?你是从 frmStartup 内部做的吗?如果是这样,不要。使用 TFrmMain.Create(NIL)。

使用frmStartup.Release释放frmStartup,如果你发送的所有代码都在frmStartup的一个方法中,你需要把那行放在方法的底部

【讨论】:

  • 使用我当前的解决方案,TFrmMain.Create(nil) 在应用程序终止时给我一个访问冲突.. :/
【解决方案3】:

您可能希望尽早显示您的启动画面,因此理想情况下应该在初始化阶段完成,然后仅在 MainForm 准备好接管时才会消失。

这正是我们在应用程序中所做的,我们将 About 对话框重用为启动屏幕,然后在 MainForm 窃取焦点时释放它。

在 dpr 中,在所需的 VCL/RTL 单元之后的 uses 子句中尽可能高:

  f_adtDlgAbout in 'f_adtDlgAbout.pas' {frmDlgAbout}, // ASAP to be used as a Splash screen

关于单位(仅供参考,FormStylefsStayOnTopPositionpoScreenCenter):

unit f_adtDlgAbout;

[...]

type
  TfrmDlgAbout = class(TForm)

[...]

procedure TfrmDlgAbout.SplashFormDeactivate(Sender: TObject);
begin
  Release;
end;

initialization
  // Use it as a Splash screen
  with TfrmDlgAbout.Create(nil) do begin
    AlphaBlend := True;
    AlphaBlendValue := 208;
    BorderStyle := bsNone;
    btnOK.Visible := False;
    OnDeactivate := SplashFormDeactivate;
    Show;
    Update;
  end;
end.

【讨论】:

    【解决方案4】:

    将frmMain设置为主窗体

    在 frmMain.FormCreate 上

    frmStartup := TfrmStartup.Create(nil);
    try
      frmStartup.ShowModal;
    finally
      frmStartup.Free;
    end;
    

    【讨论】:

      猜你喜欢
      • 2020-09-14
      • 2015-06-27
      • 1970-01-01
      • 1970-01-01
      • 2012-04-16
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 2015-09-07
      相关资源
      最近更新 更多