Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

List index out of bounds in TPageControl

I am stuck with a TPageControl that exhibits some strange behaviour..

The control has 3 pages but when I do

for I:=0 to PageControl.PageCount-1 do begin
  PageControl.Pages[I].TabVisible := False;
  PageControl.Pages[I].Visible    := Ord(iColorScale.GenerationMode) = I;
end;

I get a 'List index out of bounds (3)' error when executing the first line of the first iteration of the loop equivalent to

PageControl.Pages[0].TabVisible := False;

Now, when I view the PageControl properties in the debugger, everything seems to be in order. The PageCount is expectedly 3, and I can see all the pages and their properties, including TabVisible of page 0, in the evaluator

I'm using Delphi XE on a windows 7 machine.. Does anyone have an idea what is going on? I'm at a loss.

like image 224
Bjarke Moholt Avatar asked Jul 20 '15 12:07

Bjarke Moholt


1 Answers

tldr: set PageControl.HandleNeeded before setting TabVisible.

There is a good explanation here (by Greg Chapman): TabVisible on TabSheet and index error
For future SO reference (copy/paste):

If the PageControl's handle was destroyed (which can happen if setting some property in the PageControl or any of its parent windows causes a call to RecreateWnd), the PageControl saves the visible tabs in a TStringList (FSaveTabs). Setting TabVisible results in a call to this routine:

procedure TTabSheet.SetTabShowing(Value: Boolean);
var
  Index: Integer;
begin
  if FTabShowing <> Value then
    if Value then
    begin
      FTabShowing := True;
      FPageControl.InsertTab(Self);
    end else
    begin
      Index := TabIndex;
      FTabShowing := False;
      FPageControl.DeleteTab(Self, Index);
    end;
end; 

During the call to FPageControl.DeleteTab, the PageControl will recreate its handle if necessary. In doing so, it tries to reset the visible tabs using FSaveTabs. However, it can get confused because one of the tabs that it added to FSaveTabs is now invisible (TabSheet.FTabShowing = false). This causes the IndexError. So the fix is to make sure the handle is recreated before setting TabVisible.

like image 106
kobik Avatar answered Sep 19 '22 13:09

kobik