7

在我的应用程序完成初始化并创建主窗体后,我有想要执行的功能。我在表单 OnShow 事件中确实有代码(称为 ProcedureX),但我刚刚注意到它被调用了两次,因为 OnShow 被触发了两次。它在主程序 DPR 调用时触发:

Application.CreateForm(TMainForm, MainForm) ;  

正如我所料。但在那之后,当我从一个包含屏幕位置表单的 INI 文件中读取内容时,我有一个电话:

MainForm.position := poScreenCenter ;

这似乎会再次触发 OnShow 事件。

我在哪里可以调用 ProcedureX,它只能调用一次,并且需要在执行之前创建主窗体?

4

6 回答 6

9

如果您的代码在每次创建表单时只需要运行一次(或每个应用程序并且每次应用程序运行只创建一次表单),请将代码放在表单的 OnCreate 处理程序中。这是它去的自然地方。

现在(我认为是从 D3 开始) OnCreate 在 AfterConstruction 方法的构建过程结束时触发。仅当您将 OldCreateOrder 设置为 True(默认为 False)时,您可能会遇到麻烦,因为这会使 OnCreate 在 Create 构造函数结束时触发。

于 2010-09-24T06:46:01.770 回答
6

表单的正常执行顺序是:

  • AfterConstruction:当表单和它的组件完全创建并具有它们的所有属性时。
  • OnShow:只要表格准备好显示(是的,任何导致 a 的更改CM_SHOWINGCHANGED都可以触发 a OnShow
  • Activate: 每当表单获得焦点时

因此,根据您在 ProcedureX 中的需要,AfterConstruction可能就足够了,并且只执行一次;只需覆盖它并在inherited. 以后会OnCreate

如果不是这种情况,您可以从 将自定义消息发布到您的表单AfterConstruction,它将排队并在处理其他消息后到达您的自定义处理程序。

在这两种情况下,您都不需要额外的布尔字段。

于 2010-09-24T03:12:40.907 回答
6

@Sertac,

确实不需要 FRUNOnce 字段;只需将 OnShow=NIL 作为 FormShow 方法的第一行。

仅供参考,“运行一次”习语——在事件处理程序的第一行将事件处理程序字段设置为 NIL——对于在表单完全初始化后启动并运行一些代码也非常有用。将您的代码放入 FormActivate 方法中,并在该方法的第一行设置 OnActivate=NIL。

于 2010-09-24T19:18:55.697 回答
4

首次调用该过程后,您可以测试并设置一个标志。像这样:

type
  TForm1 = class(TForm)
    procedure FormShow(Sender: TObject);
  private
    FRunOnce: Boolean;
  public
    [...]

[...]

procedure TForm1.FormShow(Sender: TObject);
begin
  if not FRunOnce then begin
    FRunOnce := True;
    ProcedureX;
  end;
end;
于 2010-09-24T01:45:04.280 回答
4

您可以在 DPR 文件中的 Application.CreateForm 之后添加一个过程。将您需要初始化的所有代码放入该过程中。当您的应用程序中有多个表单时效果最佳。

此外,如果初始化需要很多时间,让程序在屏幕上显示表单,以便用户知道应用程序正在加载。

例子:

PROGRAM MyProgram;
begin
    Application.Initialize;
    Application.CreateForm(TMyForm, MyForm);
    MyForm.Show;

    LateInitialize;        <----------- here

    Application.Run;
end. 
于 2012-09-13T17:34:42.900 回答
0

@Sertec,

如果您希望它为每个 unhide 事件运行(您没有输入任何代码来重置 frunonce 字段),您的代码也将不起作用。

所以你的方法需要重置 frunonce 字段,而我的需要设置 OnShow=FormShow。相同的区别,只是您需要一个附加字段。

于 2010-09-27T15:51:00.487 回答