Delphi:应用程序初始化 - 最佳实践/方法

发布于 2024-07-10 05:53:19 字数 479 浏览 8 评论 0原文

我经常遇到这个问题,我只是在寻找最佳实践/方法。 我有一个包含数据库/数据模块的应用程序,并且希望在启动时启动数据库/数据集,而无需在设计时将“运行时活动”设置为 true(数据库位置不同)。 当应用程序启动时,还运行网络“检查更新”例程。

给定 TForm 事件序列以及各种试验和错误的结果,我目前正在使用这种方法:

我使用主窗体中设置的“Globals”记录来存储所有全局变量,其中有一个元素称为 Globals.AppInitialized ( boolean),并在主窗体的初始化部分将其设置为 False。

在主窗体的 OnShow 事件中(此时所有窗体均已创建),我测试 Globals.AppInitialized; 如果它是 false,我运行我的“初始化”内容,然后通过设置 Globals.AppInitialized := True 来完成。

这似乎很有效,但这是最好的方法吗? 从他人的经验、想法和意见中寻找见解。 蒂亚..

I run into this regularly, and am just looking for best practice/approach. I have a database / datamodule-containing app, and want to fire up the database/datasets on startup w/o having "active at runtime" set to true at design time (database location varies). Also run a web "check for updates" routine when the app starts up.

Given TForm event sequences, and results from various trial and error, I'm currently using this approach:

I use a "Globals" record set up in the main form to store all global vars, have one element of that called Globals.AppInitialized (boolean), and set it to False in the Initialization section of the main form.

At the main form's OnShow event (all forms are created by then), I test Globals.AppInitialized; if it's false, I run my "Initialization" stuff, and then finish by setting Globals.AppInitialized := True.

This seems to work pretty well, but is it the best approach? Looking for insight from others' experience, ideas and opinions. TIA..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

海拔太高太耀眼 2024-07-17 05:53:20

我通常总是关闭所有表单的自动创建,除了主表单和可能的主数据模块。

我了解到您可以做的一个技巧是将数据模块添加到您的项目中,允许它在主表单之前自动创建和创建。 然后,当创建主表单时,数据模块的 onCreate 将已经运行。

如果您的应用程序有一些代码要说,请设置控件的焦点(您不能在创建时执行此操作,因为它“尚不可见”),然后创建一条用户消息并将其发布到 oncreate 中的表单中。 一旦处理表单消息循环,消息就应该(不保证)被处理。 例如:

const
  wm_AppStarted = wm_User + 101;


type
  Form1 = class(tForm)
    :
    procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted;
  end; 

// in your oncreate event add the following, which should result in your wmAppStarted event firing.
PostMessage(handle,wm_AppStarted,0,0);

我想不出有一次这条消息从未被处理过,但调用的本质是它被添加到消息队列中,如果队列已满,那么它就会被“丢弃”。 请注意存在边缘情况。

I generally always turn off auto creation of all forms EXCEPT for the main form and possibly the primary datamodule.

One trick that I learned you can do, is add your datamodule to your project, allow it to auto-create and create BEFORE your main form. Then, when your main form is created, the onCreate for the datamodule will have already been run.

If your application has some code to say, set the focus of a control (something you can't do on creation, since its "not visible yet") then create a user message and post it to the form in your oncreate. The message SHOULD (no guarantee) be processed as soon as the forms message loop is processed. For example:

const
  wm_AppStarted = wm_User + 101;


type
  Form1 = class(tForm)
    :
    procedure wmAppStarted(var Msg:tMessage); message wm_AppStarted;
  end; 

// in your oncreate event add the following, which should result in your wmAppStarted event firing.
PostMessage(handle,wm_AppStarted,0,0);

I can't think of a single time that this message was never processed, but the nature of the call is that it is added to the message queue, and if the queue is full then it is "dropped". Just be aware that edge case exists.

与之呼应 2024-07-17 05:53:20

您可能希望在表单创建调用之后、Application.Run 之前直接干扰项目源(.dpr 文件)。 (或者甚至更早,以防万一。)

这就是我通常处理此类初始化内容的方式:

...
Application.CreateForm(TMainForm, MainForm);    
...
MainForm.ApplicationLoaded; // loads options, etc..
Application.Run;
...

You may want to directly interfere with the project source (.dpr file) after the form creation calls and before the Application.Run. (Or even earlier in case.)

This is how I usually handle such initialization stuff:

...
Application.CreateForm(TMainForm, MainForm);    
...
MainForm.ApplicationLoaded; // loads options, etc..
Application.Run;
...
記柔刀 2024-07-17 05:53:20

我不知道这是否有帮助,但我的一些应用程序没有自动创建任何表单,即它们在 IDE 中没有主表单。

以 Application 对象作为其所有者创建的第一个窗体将自动成为主窗体。 因此,我只自动创建一个数据模块作为加载程序,并让该数据模块决定何时创建哪些数据模块以及以什么顺序创建哪些表单。 该数据模块有一个 StartUp 和 ShutDown 方法,它们在 dpr 中的 Application.Run 周围被称为“括号”。 ShutDown 方法对关闭过程提供了更多的控制。

当您为应用程序的不同用例设计不同的“主窗体”或者您可以使用一些配置文件来选择不同的主窗体时,这可能很有用。

I don't know if this is helpful, but some of my applications don't have any form auto created, i.e. they have no mainform in the IDE.

The first form created with the Application object as its owner will automatically become the mainform. Thus I only autocreate one datamodule as a loader and let this one decide which datamodules to create when and which forms to create in what order. This datamodule has a StartUp and ShutDown method, which are called as "brackets" around Application.Run in the dpr. The ShutDown method gives a little more control over the shutdown process.

This can be useful when you have designed different "mainforms" for different use cases of your application or you can use some configuration files to select different mainforms.

九八野马 2024-07-17 05:53:20

Delphi中实际上没有“全局变量”这样的概念。 所有变量的范围仅限于它们所在的单元以及使用该单元的其他单元。

只需将AppInitialized初始化内容作为数据模块的一部分即可。 基本上有一个类(或数据模块)来统治所有非 UI 的东西(有点像 One-Ring,除了不是所有邪恶之类的。)

或者你可以:

  • 从你的启动屏幕调用它。
  • 在登录期间
  • 执行此操作在后台线程中运行“检查更新” - 不要强迫他们立即更新。 像 Firefox 那样做。

There actually isn't such a concept as a "global variable" in Delphi. All variables are scoped to the unit they are in and other units that use that unit.

Just make the AppInitialized and Initialization stuff as part of your data module. Basically have one class (or datamodule) to rule all your non-UI stuff (kind of like the One-Ring, except not all evil and such.)

Alternatively you can:

  • Call it from your splash screen.
  • Do it during log in
  • Run the "check for update" in a background thread - don't force them to update right now. Do it kind of like Firefox does.
山川志 2024-07-17 05:53:20

我不确定我理解为什么需要全局变量? 如今,我编写的所有 Delphi 应用程序都没有使用单个全局变量。 即使我确实使用了它们,每个应用程序也从来没有超过几个。

因此,也许您需要首先思考为什么您真正需要它们。

I'm not sure I understand why you need the global variables? Nowadays I write ALL my Delphi apps without a single global variable. Even when I did use them, I never had more than a couple per application.

So maybe you need to first think why you actually need them.

傲世九天 2024-07-17 05:53:20

我使用主数据模块来检查数据库连接是否正常,如果没有,则显示自定义组件表单来设置数据库连接,然后加载主表单:

Application.CreateForm(TDmMain, DmMain);

  if DmMain.isDBConnected then
    begin
      Application.CreateForm(TDmVisualUtils, DmVisualUtils);
      Application.CreateForm(TfrmMain, frmMain);
    end;

  Application.Run;

I use a primary Data Module to check if the DB connection is OK and if it doesn't, show a custom component form to setup the db connection and then loads the main form:

Application.CreateForm(TDmMain, DmMain);

  if DmMain.isDBConnected then
    begin
      Application.CreateForm(TDmVisualUtils, DmVisualUtils);
      Application.CreateForm(TfrmMain, frmMain);
    end;

  Application.Run;
丑疤怪 2024-07-17 05:53:20

我使用的一个技巧是在主窗体上放置一个 TTimer,将时间设置为 300 毫秒,然后执行任何初始化(数据库登录、网络文件复制等)。 启动应用程序会立即调出主窗体,并允许进行任何初始化“操作”。 用户不会在启动多个实例时想着“哦..我没有双击...我会再做一次..”

One trick I use is to place a TTimer on the main form, set the time to something like 300ms, and perform any initialization (db login, network file copies, etc). Starting the application brings up the main form immediately and allows any initialization 'stuff' to happen. Users don't startup multiple instances thinking "Oh..I didn't dbl-click...I'll do it again.."

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文