-2

我正在尝试在 Delphi XE6 中创建具有 2 个表单的应用程序。根据ParamStr设置,Form2 可能会或可能不会在 Form1 之前显示。

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

procedure TForm1.FormShow(Sender: TObject);
begin
  if ParamStr(1) = 'foo' then
      Form2.FooShow;
end;

procedure TForm2.FooShow;
begin
   ShowModal;
end;

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

在这种情况下Form1.Show,一旦被调用就会Application.CreateForm(TForm1, Form1)被调用。这是创建 Form2 之前,这会导致问题,因为 Form2 在需要时不存在。

任何解释为什么行为会有所不同?我是否错过了隐藏在项目>选项中的某个设置

4

1 回答 1

3

如果您的表单被Visible设置为 True,那么它会在创建后立即显示。

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

编辑

PS:以防万一有类似问题的人在Visible设置为 时意外显示其主窗体False。发生这种情况是因为默认情况下,应用程序将显示主窗体,而不管其Visible在调用中的属性如何Application.Run
如果是这样,以下问题应该会有所帮助:如何使用隐藏的主窗体启动 Delphi 应用程序?

编辑2

为了完整起见,还有其他一些事情可能会导致表单在创建后立即显示。但是,这些可能不适用于这个特定问题。

  • 任何在创建时显式显示表单的代码(例如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;
于 2014-06-30T10:53:56.157 回答