我偶然发现了这个页面Why shouldn’t I call Application.CreateForm。 现在我有一些像这样的代码:
SplashForm := TSplashForm.Create(Application);
SplashForm.Show;
SplashForm.Update; // force update
Application.Initialize;
Application.CreateForm(TClientData, ClientData);
SplashForm.Update; // force update
Application.CreateForm(TClientMainForm, ClientMainForm);
Application.ShowHint := True;
Application.Run;
ClientMainForm.ServerConnected := false;
FreeAndNil(ClientMainForm);
FreeAndNil(ClientData);
首先创建一个splashform,然后创建一个datamodule并最后一个主窗体。页面说不应该调用Application.CreateForm两次。上面的代码应该改变吗?
答案 0 :(得分:5)
多次使用Application.CreateForm没有任何问题。但是这会为每种形式引入全局变量,这些变量可能是代码气味。 不幸的是,IDE为每个表单创建一个。虽然你可以删除它们。
更好的方法是在需要时创建表单,并在准备就绪时将其释放。因此,您只能将Application.CreateForm用于主窗体。
主数据模块可以由主表单创建。但它也可以是全球性的,只是一种品味问题。
因此,要回答这个问题,您可以通过在本地创建和发布表单来避免Application.CreateForm。
文章提到Application.CreateForm的副作用(第一个完成的表单是主窗体)。 因此,如果主窗体使用Application.CreateForm创建其他窗体,则可能会出现意外的副作用。
所以为了避免任何讨厌,你应该将yoursef限制为一次通话。这只使用一种全局形式完成。
答案 1 :(得分:1)
如果TClientData是一个数据模块而TClientMainForm是一个表单,那么没有(除了最后两个FreeAndNil调用 - 不是真的需要)。但要小心。因为正如Rob Kennedy在帖子中所说的那样,Application.CreateForm会做其他事情(它设置 MainForm 变量),所以我建议根据以下规则设置项目文件: / p>
使用单次调用创建在启动时创建的所有表单到Application.CreateForm - 通常由IDE完成。
从项目文件中删除要在程序中动态(按需)创建的表单。 (在项目|选项|表单中...) - 将它们从“自动创建表单”移动到“可用表单”
使用 TmyForm.Create(所有者)(等)在 代码中创建表单,使用 不 Application.CreateForm(...)。顺便说一句,如果您确定要释放表单,那么最好(为了加快速度)调用 TmyForm.Create( nil ) - 没有任何所有者的情况。
如果你想在启动时进行某种初始化,你可以在项目文件中有一个与已经创建的表单/数据模块绑定的过程/方法,并在应用程序运行之前运行它。
例如:
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TdmoMain, dmoMain); //<--this is a data module
Application.CreateForm(TfrmMain, frmMain); //<--this will became the main form
Application.CreateForm(TfrmAbout, frmAbout);
//... other forms created here...
frmMain.InitEngine; //<--initialization code. You can put somewhere else, according with your app architecture
Application.Run;
end.
通过这种方式,您可以清理项目文件,并确切知道哪个是。
HTH
答案 2 :(得分:1)
当我写这篇文章时,我主要考虑的是代码在之外的DPR文件。人们在DPR文件中看到IDE生成的表单创建代码,并认为这是创建表单的最佳方式,因此他们在程序的其他地方使用它。他们有时在主窗体的OnCreate事件处理程序中使用它来创建程序需要的其他表单,然后它们遇到问题,因为程序的主要表单不是他们认为的那样。
在您提供的代码中,只需调用一次CreateForm即可。将它用于主表单,而不是其他任何内容。数据模块不是主要形式,因此您不需要CreateForm的魔力。
SplashForm := TSplashForm.Create(Application);
SplashForm.Show;
SplashForm.Update; // force update
Application.Initialize;
// Change to this.
ClientData := TClientData.Create(Application);
SplashForm.Update; // force update
Application.CreateForm(TClientMainForm, ClientMainForm);
Application.ShowHint := True;
Application.Run;
ClientMainForm.ServerConnected := false;
// Remove these.
FreeAndNil(ClientMainForm);
FreeAndNil(ClientData);
你真的不应该释放你在这里创建的对象,因为你没有拥有它们。它们由全局Application对象拥有,因此请让它们释放它们:删除对FreeAndNil的两个调用。
答案 3 :(得分:0)
您引用的文章不正确。您需要多次调用Application.CreateForm
的原因有很多1)数据模块:您可能希望所有这些都可用。最好的方法是Application.CreateForm。我知道有几个主题数据模块的应用程序,例如客户,发票,地址处理数据库的不同区域&amp;整齐地封装功能。所有这些都是在.dpr
中创建的2)大而缓慢的加载(这本身就是一个坏主意,但这些事情发生并且通常由支持程序员继承......)。将加载时间移动到应用程序启动中,与示例代码一样,同时更新启动画面。用户期待应用程序需要一段时间才能开始工作,这要归功于我们的同事在Microsoft Office上工作,以降低对我们其他人的期望:)
所以,总而言之,不要担心你的代码很好 - 但你可能会失去“FreeAndNil”的东西。然而,小型快速击中Dialog类型的东西最好由以下方式调用:
with TMyform.Create(nil) do
try
//Setup
case ShowModal of
// Whatever return values you care about (if any)
end;
finally
Free;
end;
简短,甜蜜,至关重要。最小化内存使用...