Error in FMX.Treeview function TTreeViewContent.GetLastVisibleObjectIndex

  

I am migrating a VCL application to Firemonkey. It features a couple of TTreeview controls which display folder trees. In the main form’s OnCreate event handler the paths of the folders are read from a .Ini file and the treeviews are set up. At some point before the main form appears on screen, an exception occurs in the FMX.TreeView TTreeViewContent.GetLastVisibleObjectIndex function, which is:

function TTreeViewContent.GetLastVisibleObjectIndex: Integer;
var
Item: TTreeViewItem;
begin
if (FTreeView.FGlobalList.Count > 0) and (FTreeView.FLastVisibleItem < FTreeView.FGlobalList.Count) then
begin
Item := FTreeView.FGlobalList[FTreeView.FLastVisibleItem];
{etc.}
end
else
Result := ControlsCount;
end;

I have inspected the values of the variables and found that FTreeView.FGlobalList.Count =1 and FTreeView.FLastVisibleItem = -1. The error occurs in the statement

Item := FTreeView.FGlobalList[FTreeView.FLastVisibleItem];

since the array index is invalid.

This code seems to be related to determining which treeview items are visible within the scrolling window of the treeview control. Since the error occurs before the form has been displayed, I tried making the treeview invisible during the update of the treview, as in the following code:

procedure TFormMain.UpdateTreeview(var Folder: TFolder; Treeview: TTreeview);
begin
if Folder= FInputFolder then
begin
if not FTreeviewInputFolderValid then
begin
Treeview.Visible:= False;
Treeview.BeginUpdate;
FolderToTreeView(Folder, Treeview);
//Treeview.InvalidateRect(Treeview.ContentRect);
Treeview.ExpandAll;
Treeview.EndUpdate;
Treeview.Visible:= True;
FTreeviewInputFolderValid:= True;
end;
end;
{Ditto for FOutputFolder}
end;

If the program is run without setting up the treeview controls before the form is shown, i.e. by not reading the folder paths from a .ini file and not updating the treeview controls, then the error does not occur.

Any suggestions about how to avoid what seems to be a coding error in function TTreeViewContent.GetLastVisibleObjectIndex?

In answer to Tom, the code of FolderToTreeview is:

procedure TFormMain.FolderToTreeview(Folder: TFolder; Treeview: TTreeview);
var
TreeviewOwner: TComponent;
RootNode: TTreeViewItemFolderCpt;

procedure AddFolderChildCpts(ParentTreeNode: TTreeViewItemFolderCpt; Folder: TFolder);
var
i: integer;
FolderCpt: TFolderCpt;
FileCpt: TFileCpt;
SubFolder: TFolder;
ChildTreeNode: TTreeViewItemFolderCpt;
Found: Boolean;
begin
{Add all cpts of folder to child nodes of ParentTreeNode}
for i:= 0 to Folder.CptCount-1 do
begin
FolderCpt:= Folder.Cpts[i];
ChildTreeNode:= TTreeViewItemFolderCpt.Create(ParentTreeNode);
ParentTreeNode.AddObject(ChildTreeNode);
ChildTreeNode.Parent:= ParentTreeNode;
ChildTreeNode.FolderCpt:= FolderCpt;
ChildTreeNode.OnPaint:= TreeViewItemPaint;
if FolderCpt is TFileCpt then
begin
FileCpt:= FolderCpt as TFileCpt;
ChildTreeNode.ImageIndex:= 1;
end
else if FolderCpt is TFolder then
begin
SubFolder:= FolderCpt as TFolder;
ChildTreeNode.ImageIndex:= 0;
{Recursively add subfolder:}
AddFolderChildCpts(ChildTreeNode, SubFolder);
end;
end;
end;

begin
if not Folder.IsSorted then
Folder.Sort(True);
{Delete all existing nodes in tree:}
Treeview.Clear;
{Create a new root node and add to tree:}
RootNode:= TTreeviewItemFolderCpt.Create(Treeview);
Treeview.AddObject(RootNode);
RootNode.Parent:= Treeview;
{Link folder object to root tree node:}
RootNode.FolderCpt:= Folder;
RootNode.ImageIndex:= 0;
RootNode.OnPaint:= TreeViewItemPaint;
{Now install child folder cpts:}
AddFolderChildCpts(RootNode, Folder);
end;

TFolder, TFolderCpt, TFileCpt are elements of a separate class hierarchy to store in a memory tree structure the names and metadata of all files and folders under the root folder. The root object of class TFolder has a method Read(Path: string) which generates all its nodes by visiting the files and directories under the root directory using FindFirst and FindNext procedures. Folder.Read is called before FolderToTreeview is called. Because of this extra complication I don’t think that you be able to run the FolderToTreeview method.

Comments are closed.