这是我为重现该问题而做的测试应用程序:

请查看以下测试代码:
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage(radioGroup1.Items[0]);
ShowMessage(BoolToStr(radioGroup1.Buttons[0].Enabled));
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
ShowMessage(radioGroup1.Items[0]);
ShowMessage(BoolToStr(radioGroup1.Buttons[0].Enabled)); //<- Fails!!!
end;
Run Code Online (Sandbox Code Playgroud)
将显示FormCreate中的第一个ShowMessage,并显示正确的文本(Item1).
FormCreate中的第二个代码行抛出一个异常,该索引超出范围.
如果我在按钮单击事件中运行相同的代码,如代码中所示(在表单加载后)一切正常.
问题1: 在FormCreate中执行第二个代码行时,似乎没有加载按钮.为什么会出现这样的情况,当项目本身似乎已经加载?
问题2: 在将现有(运行良好)项目从Delphi 2006升级到XE6时,我注意到了这个问题.由于此问题,此项目现在在不同的单元中引发了几个异常.在这方面发生了什么变化?
提前感谢您的帮助!
当流式传输.dfm文件时,将填充这些项目.这种情况很早就会发生,当然在OnCreate事件发生之前就已经发生了.通常在创建窗口时创建窗口控件的按钮.当表单的OnCreate事件执行时,窗口尚未创建.
你问为什么项目存在,但按钮不存在.嗯,按钮是从项目创建的.但不是马上.在表单流式传输过程中,按钮创建被禁止,这意味着首先填充项目,然后在某个时间点创建按钮.
我不确定从旧版本的Delphi到现代Delphi究竟发生了什么变化.如果你回到Delphi 6,你可以看到创建的按钮TCustomRadioGroup.ReadState,它们在表单流式传输过程中执行.但最新版本的Delphi抑制了按钮的创建ReadState.我猜测为什么进行此更改是因为它会阻止您设置在窗口重新创建期间丢失的按钮属性.
但是,太多细节可能没有什么意义.重要的事实是你不能指望按钮存在期间OnCreate.您应该将需要按钮的任何代码移动到其他位置.一些明显的候选人将是形式的OnShow事件,或被重写的CreateWnd方法.