2012-11-16 69 views
3

我认为这必须是一个常见问题,但谷歌搜寻并没有真正的帮助。FormCreate()中可能做什么和不做什么?

我该做什么 - 可能不会 - 在FormCreate()

如果所有形式的子控件的完全创建并可供访问我在想,等

我想问的原因是,我偶然发现了一个旧的项目中,我FormCreate()只是由

Sleep(1000); 
PostMessage(Handle, UM_PROGRAM_START, 0, 0); 

看来,我想“稍等一下”,然后做一些初始化“当事情已经安定下来” ......

我一定有它的理由的时候(?),但是,在我缺乏启发性的评论无法回想为什么我觉得这是必要的。

任何人都可以陈述或引用一个链接,指出在FormCreate()中可以做什么的任何限制?


[更新]我想thta DavidHefferman找到了解决办法时,他写道:“在应用程序启动抽水消息。这时候,你在你的.dpr文件中调用Application.Run发生”。

我想我并不关心单一表格。例如,我的主表单想要在启动时对我的配置/选项表单进行一些操作,所以显然必须等到它创建完成。

下面是我的一个项目一个典型.DPR ...

Application.Initialize; 
Application.CreateForm(TGlobal, Global); 
Application.MainFormOnTaskbar := True; 
Application.CreateForm(TMainForm, MainForm); 

Application.CreateForm(TLoginForm, LoginForm); 
Application.CreateForm(TConfigurationForm, ConfigurationForm); 

//[snip] a bunch of other forms ... 

Application.Run(); 

因此,它是有道理的,我的应用程序的mainForm.CreateForm()UM_APPLICATION_START本身它不会处理,直到创建了所有形式&已初始化(或者,我可以在调用Application.Run()之后调用从.DPR触发的消息的fn();但我更喜欢消息,因为它更明显 - 我很少看到.DPR文件)。

+1

看看你在UM_PROGRAM_START到达时所做的事情,这会让你明白理由。 – jachguate

+2

创建ChildComponents后,OnCreate将被解雇。但取决于OldCreateOrder,它将在Create或AfterConstruction内部被触发。但是一些控件也可以使用PostMessage来执行它们的最终初始化,并且它们不能用于OnCreate事件。因此,您可能选择发布消息 - 是的,忘记睡眠:o) –

回答

7

没有明确的文件给出你可以做的所有事情的列表,并且不能在表单的OnCreate中做。

至于是否已处理.dfm文件并创建了所有表单的所有组件,是的。

我不会在你找到的代码中放置太多商店。在启动过程中调用Sleep以使主线程等待,这绝对不是好习惯。如果代码想要等待另一个线程,它可能会阻塞该线程,或者等待从该线程获取消息。这看起来像是一些不明白自己在做什么的代码。代码永远不会被删除。

代码的另一条线是合理的:

PostMessage(Handle, UM_PROGRAM_START, 0, 0); 

因为这个消息发布,它不会得到处理,直到应用程序启动抽水消息。当您在.dpr文件中调用Application.Run时会发生这种情况。这意味着与创建主表格相关的所有内容都是在该消息从队列中移出之前发生的。

+0

+1:“我知道,因为......我是那个编码器”(对Max Bygraves致歉,这应该是阶段我们的殖民表亲;-)是的,我同意,我可以跳过'睡眠()'(并经常这样做),但为什么我觉得有必要调用PostMessage()? – Mawg

+1

当一个窗口被创建时,它会发送很多消息。在SendMessage中发送同步传送。 PostMessage调用在主窗口完成所有初始化后触发的操作。也许这就是你做到这一点的原因。很难100%确定。你的应用做什么来回应这条消息? –

+0

+1您可能会在'FormCreate()' – Mawg

1

你可以在FormCreate中做任何你想做的事情。但是没有消息处理程序可以玩,就这些。一般来说,我会在FormCreate中创建依赖对象并将它们释放到FormDestroy中。我也会尽量避免耗时的初始化例程。

+0

的更新你的意思是什么,“没有消息处理程序”? –

+1

对不起,我的发言不清楚。在主窗体的FormCreate期间,应用程序的消息处理程序尚未初始化。我知道这个问题('在FormCreate中做什么'),从质疑如何使用MainForm.FormCreate初始化应用程序。 – alzaimar

+3

消息泵尚未启动。但消息可以发布。同步消息仍然直接传递给窗口过程。 –

4

我不会把得多初始化代码在FORMCREATE,而不是我把它放到一个独立的功能,如

fm := TForm.Create; 
fm.Init; 

的问题是,在FORMCREATE抛出异常()过程不重-thrown(只有一个MessageBox)。这意味着,您的代码会继续运行,但表单未正确初始化。

+1

'Init'的东西可能是PostMessage()所调用的动作。 –

+0

+1 LURD Max,我假设你从' .dpr'调用'fm.Init'?似乎发送消息 - 任何细微的差异?不确定异常位 - 是否要将'try ... except'添加到您的FornmCreate空白处? – Mawg

+0

我不是事件或消息的粉丝。他们总是更复杂的调试。你需要知道谁调用了它,它来自哪里。如果你只是调用一个函数,你完全知道它被调用的地方(当你只是看源代码)。 –