Solving: Image index out of bounds.

oob

The problem.

One of my customers is getting an “Image index out of bounds.” error message in his application.
The cause of this could be difficult to track down. Depending on the complexity of the form which is causing the error message, any control on the form could have an invalid value for it’s ImageIndex property.

The Solution?

The invalid ImageIndex might be simply an invalid property setting, or it could be that the property is incorrectly set somewhere in code.┬áIf the problem is as simple as an invalid property setting, this solution may help us find the problem….

In order to make finding the cause of the problem easier, I’ve written this button ‘OnClick’ handler which searches for all components on the form with an ImageIndex property, and for which the image index is not the default ‘-1’…

(*note: This might be useful for tracking other invalid property settings with modification, which is why I felt it was worth sharing here.*)

procedure TForm1.Button1Click(Sender: TObject);

  function TestImageIndex( Component: TComponent; var Found: boolean ): int32;
  var
    LContext: TRttiContext;
    LClass: TRttiInstanceType;
    Properties: TArray<TRttiProperty>;
    l: uint32;
    idx: uint32;
  const
    utImageIndex = 'IMAGEINDEX';
  begin
    Found := False;
    LContext := TRttiContext.Create;
    LClass := LContext.GetType(Component.ClassType) as TRttiInstanceType;
    Properties := LClass.GetDeclaredProperties;
    l := length(Properties);
    if l>0 then begin
      for idx := 0 to pred(l) do begin
        if Uppercase(Trim(Properties[idx].Name))=utImageIndex then begin
          Found := True;
          Result := Properties[idx].GetValue(Component).AsInteger;
          Exit;
        end;
      end;
    end;
  end;

  function RecursiveSearch( Component: TComponent; Current: string ): string;
  var
    Test: boolean;
    Value: int32;
    idx: int32;
  begin
    // Test the current component
    Value := TestImageIndex(Component,Test);
    if ((Test) and (Value<>-1)) then begin
      Result := Current + ' ' + Component.Name;
    end;
    // Test child components
    if Component.ComponentCount>0 then begin
      for idx := 0 to pred(Component.ComponentCount) do begin
        Result := Result + RecursiveSearch( Component.Components[idx], Result );
      end;
    end;
  end;

var
  TestStr: string;

begin
  TestStr := '';
  TestStr := Trim(RecursiveSearch(Self,''));
  if (TestStr<>'') then begin
    ShowMessage('Found incorrect image index: '+TestStr);
  end else begin
    ShowMessage('No incorrect image index found.');
  end;
end;

The following video demonstrates me using this code to track down a faulty ImageIndex property…
(* best viewed full screen *)

As you can see in the video, if the problem is so simple as an invalid property setting, we can resolve the problem using RTTI to locate the violating property. In the case of TButton, no exception is raised for the invalid property, however, other controls / third party controls may behave differently and raise the message that my customer is seeing.

Let’s hope this helps!

Facebooktwittergoogle_plusredditpinterestlinkedintumblrmail

Leave a Reply