【问题标题】:Where should I put code to execute once after my Delphi app has finished initialising?在我的 Delphi 应用程序完成初始化后,我应该在哪里执行一次代码?
【发布时间】:2010-09-23 22:32:48
【问题描述】:

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

Application.CreateForm(TMainForm, MainForm) ;  

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

MainForm.position := poScreenCenter ;

这样,它会再次触发 OnShow 事件。

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

【问题讨论】:

    标签: delphi events forms show delphi-2006


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      Form 的正常执行顺序是:

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

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

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

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

      【讨论】:

      • 那么使用 OnCreate 怎么样?
      • 应该没问题。但是 AfterConstruction 允许在 OnCreate 中的任何内容之后始终执行 ProcedureX...
      【解决方案3】:

      @Sertac,

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

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

      【讨论】:

      • 只有在事件处理程序中没有其他事情可做时才有可能。但是,如果您在处理程序中有代码,您希望它在您 f.i. 时运行。取消隐藏您的表单,您不能取消处理程序。
      【解决方案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;
      

      【讨论】:

      • 我遵循“前缀字段带有 F”的约定,所以 FRunOnce 对我来说听起来更标准。不是规则,只是约定,就像类名前加T一样。只是让别人的代码更容易阅读。
      • @jachguate - 当有“F”时,我觉得它应该有一个 getter/setter。但那是我的问题我猜...编辑了答案,感谢您指出。
      • 好的,我曾想过这样做,但这似乎是治标不治本。我想我正在寻找其他仅触发一次的事件(例如“OnEverythingFinished”)。我听到的是没有!谢谢你的帮助。 FRunOnce 它是。
      • 这可能是最好的方法,但是,我会在 TForm1.OnCreate.. 中添加 fRunOnce:= false 以确保它一开始是错误的。
      • @sergeant - 哦,别担心它是假的,构造函数总是将对象将要使用的内存归零,所有字段的初始值都是 nil、0、false 等。 .
      【解决方案5】:

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

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

      例子:

      PROGRAM MyProgram;
      begin
          Application.Initialize;
          Application.CreateForm(TMyForm, MyForm);
          MyForm.Show;
      
          LateInitialize;        <----------- here
      
          Application.Run;
      end. 
      

      【讨论】:

        【解决方案6】:

        @Sertec,

        如果您希望它为每个取消隐藏事件运行(您没有输入任何代码来重置 frunonce 字段),您的代码也将无法工作。

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

        【讨论】:

        • 如果我要重置标志,我为什么要拥有它?示例:在表单第一次可见后,我必须在OnShow 上运行过程ShowJustOnce。每次用户在OnShow 上重新显示表单时,我都必须运行UpdateInfo。我不能 nil 处理程序,因为“UpdateInfo”不会运行。我必须使用该标志,否则每次重新显示表单时都会运行“ShowJustOnce”。
        • 如果您需要 FormSHow 中的一些代码运行一次而一些运行多次,那么是的,您需要一个标志。这与我们俩都回答的问题并不真正相关,这只是“我如何让某些东西在最初显示我的表单时只执行一次”。所以,再次...把它放在 FormActivate 方法中,并且,作为方法的第一行,放入“OnActivate := NIL ;”。如果您希望每次显示表单时都运行一些东西,并且每次实际可见性更改只运行一次,那是一个不同的问题。
        • 它是相关的,它不是一个不同的问题。我不建议任何人取消他的事件处理程序,因为我不知道是否已经存在代码,并且将来也不会......就像在“OnShow”中一样,一个人可能在“OnActivate”中有代码' 也是如此。例如,我 代码重新显示以前隐藏在“OnDeactivate”上的表单。如果我没有“OnActivate”,你会建议我在哪里再次显示它们?
        猜你喜欢
        • 1970-01-01
        • 2011-02-12
        • 1970-01-01
        • 2016-03-26
        • 1970-01-01
        • 2018-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多