这是我为重现此问题而做的测试应用程序:
请查看以下测试代码:
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;
显示FormCreate中的第一个ShowMessage,并显示正确的文本(Item1)。
FormCreate中的第二个代码行抛出异常,该索引超出范围。
如果我在代码中显示的按钮单击事件中运行相同的代码(在表单加载后),一切正常。
问题1: 在FormCreate中执行第二个代码行时,似乎没有加载按钮。 为什么会这样,当项目本身似乎已经加载?
问题2: 在将现有(运行良好)项目从Delphi 2006升级到XE6时,我注意到了这个问题。 由于此问题,此项目现在在不同的单元中引发了几个异常。 在这方面发生了什么变化?
提前感谢您的帮助!
答案 0 :(得分:5)
当流式传输.dfm文件时,会填充这些项目。这种情况很早就会发生,当然在OnCreate
事件触发之前。通常在创建窗口时创建窗口控件的按钮。当表单的OnCreate
事件执行时,窗口尚未创建。
您问为什么项目存在,但按钮不存在。嗯,按钮是从项目创建的。但不是马上。在表单流式传输过程中,按钮创建被禁止,这意味着首先填充项目,然后在某个时间点创建按钮。
我不确定从旧版本的Delphi到现代Delphi究竟发生了什么变化。如果你回到Delphi 6,你可以看到按钮是在TCustomRadioGroup.ReadState
中创建的,它在表单流式传输过程中执行。但最新版本的Delphi会在ReadState
中禁止创建按钮。我猜测为什么要进行此更改是因为它会阻止您设置在窗口重新创建过程中丢失的按钮属性。
但是,太多细节可能没有什么意义。重要的事实是你不能指望按钮在OnCreate
期间存在。您应该将需要按钮的任何代码移动到其他位置。一些明显的候选人将是表单的OnShow
事件或被覆盖的CreateWnd
方法。
答案 1 :(得分:1)
编辑:在您访问RadioGroup之前,RadioGroup.ControlCount似乎仍为0,因此该解决方案无法正常工作。
阅读本页后,我进行了另一次搜索,发现此页面存在类似问题: Problem with RadioGroup.ControlCount in Delphi 2010
看起来避免抛出异常的解决方法是检查RadioGroup.ControlCount是否大于您要访问的按钮的索引。 如果RadioGroup.ControlCount为0,您可能不想访问该无线电组。
它并没有真正解决何时初始化它的问题,但它解决了何时不更新它的问题。
迪伦