我刚刚遇到Delphi中的一个行为,这对我来说似乎是个错误.
在Delphi中,只需在表单上删除一个THeaderControl,并为其分配至少一个部分.如果在当前表单上调用FlipChildren(true),则会出现“列表索引超出范围”错误.看起来TCustomHeaderControl的FlipChildren过程中存在问题.
由于在各种版本的Delphi(我已经尝试过Delphi 6和Delphi 2010)中可以重现相同的行为,我有点不愿意将这个版本归类为bug.其他人之前遇到过这个问题?
最佳答案 这绝对是一个错误.我希望代码在Delphi 1中起作用,但是THeaderSections的实现以破坏它的方式发生了变化.从那时起,您似乎是第一个执行代码的人!
这是代码:
procedure TCustomHeaderControl.FlipChildren(AllLevels: Boolean);
var
Loop, FirstWidth, LastWidth: Integer;
ASectionsList: THeaderSections;
begin
if HandleAllocated and
(Sections.Count > 0) then
begin
{ Get the true width of the last section }
LastWidth := ClientWidth;
FirstWidth := Sections[0].Width;
for Loop := 0 to Sections.Count - 2 do Dec(LastWidth, Sections[Loop].Width);
{ Flip 'em }
ASectionsList := THeaderSections.Create(Self);
try
for Loop := 0 to Sections.Count - 1 do with ASectionsList.Add do
Assign(Self.Sections[Loop]);
for Loop := 0 to Sections.Count - 1 do
Sections[Loop].Assign(ASectionsList[Sections.Count - Loop - 1]);
finally
ASectionsList.Free;
end;
{ Set the width of the last Section }
if Sections.Count > 1 then
begin
Sections[Sections.Count-1].Width := FirstWidth;
Sections[0].Width := LastWidth;
end;
UpdateSections;
end;
end;
我们的想法是构建一个临时的标题部分列表,从真实的部分中分配属性.然后以相反的顺序遍历临时列表,分配回标题部分的真实列表.但它不起作用.
整个代码都是假的,因为实际上只涉及一个集合.与控件关联的集合. THeaderSections的设计假定标题控件和THeaderSections对象之间存在一对一的关系.可以很容易地观察到,ASectionsList.Add实际上将项添加到SectionsList!
所以,当这段代码完成运行时
for Loop := 0 to Sections.Count - 1 do with ASectionsList.Add do
Assign(Self.Sections[Loop]);
您将观察到Sections.Count已加倍,并且ASectionsList.Count仍为零.那么当我们继续运行时
for Loop := 0 to Sections.Count - 1 do
Sections[Loop].Assign(ASectionsList[Sections.Count - Loop - 1]);
ASectionsList [Sections.Count – Loop – 1]的访问超出范围.
代码非常糟糕.我对此感到震惊.所需要的只是一个包含宽度的简单整数数组.这是它应该如何看,用插入器实现:
type
THeaderControl = class(Vcl.ComCtrls.THeaderControl)
public
procedure FlipChildren(AllLevels: Boolean); override;
end;
procedure THeaderControl.FlipChildren(AllLevels: Boolean);
var
Index, Count: Integer;
Widths: TArray<Integer>;
begin
Count := Sections.Count;
if Count>1 then
begin
SetLength(Widths, Count);
for Index := 0 to Count-2 do
Widths[Index] := Sections[Index].Width;
Widths[Count-1] := ClientWidth;
for Index := 0 to Count-2 do
dec(Widths[Count-1], Widths[Index]);
Sections.BeginUpdate;
try
for Index := 0 to Sections.Count-1 do
Sections[Index].Width := Widths[Count-Index-1];
finally
Sections.EndUpdate;
end;
end;
end;
我建议您提交质量控制报告.