Delphi表单创建和显示

时间:2014-06-27 16:23:00

标签: forms delphi delphi-xe6

我正在尝试在Delphi XE6中创建一个包含2个表单的应用程序。根据{{​​1}}设置,Form2可能会或可能不会在Form1之前显示。

在快速测试应用程序中,两个表单都是在调用ParamStr之前创建的 - 在此期间显示Form2

Form1.Show

然而在“真正的”应用程序中,我看到了不同的行为。

在这种情况下,只要调用procedure TForm1.FormShow(Sender: TObject); begin if ParamStr(1) = 'foo' then Form2.FooShow; end; procedure TForm2.FooShow; begin ShowModal; end; ,就会调用Form1.Show。在创建Form2之前,这是,这会导致问题,因为Form2在需要时不存在。

任何解释为什么行为会有所不同?我错过了隐藏在 Project> Options

中某处的设置

1 个答案:

答案 0 :(得分:2)

如果您的表单保持Visible设置为True,则会在创建后立即显示。

将属性设置为False可以解决您的问题。

修改

PS:即使Visible被设置为False,以防万一有类似问题的人的主要表单也会意外显示。发生这种情况是因为默认情况下,无论Visible调用中的Application.Run属性如何,应用程序都会显示主窗体。
如果是这样,以下问题应该有所帮助:How can I start Delphi application with the hidden main form?

<强> EDIT2

为了完整起见,还有一些其他因素可能会导致表单一旦创建就显示出来。但是,这些可能不适用于这个特定问题。

  • 任何在创建表单时明确显示表单的代码(例如OnCreate事件)显然会导致表单显示。但是,人们希望这些行为不会导致这些问题。
  • 永远不会隐藏MDI子表单。充其量可以最小化。

提示

找到这些问题答案的最快方法通常只是一点点调试。

  • FormShow方法中设置断点。
  • 转到编译器设置,并启用使用调试DCU构建的选项。 (您将要查看VCL代码。)
  • 重建并运行您的应用程序。
  • 当您到达断点时,打开“调用堆栈”调试窗口。
  • 导航调用堆栈以查找触发器。

在这种情况下,您应该在Forms.pas中找到以下代码。

procedure TCustomForm.DoCreate;
begin
  //...
  if fsVisible in FFormState then Visible := True; //<-- The trigger
end;

fsVisible进行更多投资可以揭示根本原因:Visible属性设置为True


那就是说,你不想以这种方式编码,因为你通过全局变量创建了依赖关系。这很容易出错;而你的小实验显示只是可能导致问题的许多微妙事物之一。

相反,避免使用类似DPR中的以下更改的全局变量:

begin
  Application.Initialize;
  ShowForms;
end;

ShowForms实施为:

procedure ShowForms;
var
  LForm1: TForm1;
  LForm2: TForm2;
begin
  Application.CreateForm(TFrom1, LForm1);
  Application.CreateForm(TFrom2, LForm2);

  if (ParamStr(1) = 'foo') then
    LForm2.Show
  else
   LForm1.Show;
end;

如果您在表单之间没有任何依赖关系,则上述内容就足够了。 如果您确实有依赖关系,例如Form2使用Form1:然后您可以在创建表单后显式传递引用,然后再开始对它们执行任何操作。

//Define a property on TForm2 E.g.
property MainForm: TForm1 read FMainForm write SetMainForm;

//Immediately after creating both forms tell form2 which to use as its main form.
LForm2.MainForm := LForm1;