Delphi Programming for Beginners - Lesson 5
TListView and TTreeViewSlowly we are learning about more complex components and doing more complex examples (we will talk about the most important component only). These 2 components are very useful and are used pretty often. You can find both implemented in Windows, as shown in the picture below:
TTreeView is that tree on the left side (the appearance can be changed) and TListView is that list on the right.
TTreeView is used for visualising the tree structure (content of a disk, folders and subfolders etc.), whereas TListView is used for visualising a linear list. As shown in the picture, they are used in a combination where in a tree we pick an entity (folder, for example) and in the list we can see the content of this entity.
Both components are often used with TImageList for showing the appropriate icon for every item (so the folder has an icon of a folder, etc.).
Both of components have their own item editors, where particular items can be defined, but pretty often case is to fill items at runtime (for instance with content of the disc) and in design time determine column headers only (such as name, size, extension etc.).
The items editor for a tree is launched by a double-click or by choosing from a pop-menu on a component. In case of a list, an editor of columns or an editor of items can be launched.
Important properties of TListViewImportant one is ViewStyle, which determines a visual mode:
- vsIcon - visualising in an icon mode
- vsList - a simple list
- vsSmallIcon - just like vsIcon, but small icons
- vsReport - the most used mode, a list with columns
Connection with TImageList is provided by properties SmallImages, LargeImages and StateImages, where SmallIgames is the most important one, which are used in all modes but vsIcon.
Another important property is RowSelect which determines whether the selection is the whole line or just an item. But the most important one is Items which holds the list of items.
You can add items when the programme is running like this:
procedure TForm1.FormCreate(Sender: TObject);
var
lvItem: TListItem; // položka TListView
i: Integer;
tvItem: TTreeNode; // položka TTreeView
j: Integer;
begin
lv1.Items.BeginUpdate;
for i := 1 to 10 do //10 polozek do TListView
begin
lvItem := lv1.Items.Add;
lvItem.Caption := 'Položka '+ IntToStr(i);
lvItem.SubItems.Add('Sub'+IntToStr(i)); // druhý sloupec
end;
lv1.Items.EndUpdate;
tv1.Items.BeginUpdate;
for i := 1 to 10 do // 10 položek první úrovně
begin
tvItem := tv1.Items.Add(nil, 'Uzel '+IntToStr(i));
for j := 1 to 5 do // pridame druhou uroven – 5 položek
tv1.Items.AddChild(tvItem, 'sub'+ IntToStr(j));
tvItem.Expanded := true; // rozbal uzel
end;
tv1.Items.EndUpdate;
end;
Calling BeginUpdate/EndUpdate isn’t obligatory but in case of updating more items it speeds up the whole process because it prohibits redrawing and calling different events. Ideally, the calling should be protected by try…finally, that is (because in case of a mistake, a redrawing wouldn’t be allowed):
BeginUpdate
try
…
finally
EndUpdate
end
A practical example
Let’s make our very own File Explorer, that is, we have TTreeView on the left and TListView on the right. I’ll show you how to fill the tree, visualising items based on chosen entity will be your home work. The programme is attached, here’s the code.
After the start, the tree is filled with directories from constant csStart. In a real project the individual levels will load while unpacking, here we load them at once - even though it will take longe.r
procedure TForm1.FormCreate(Sender: TObject);
var
lvItem: TListItem;
i: Integer;
tvItem: TTreeNode;
j: Integer;
const
csStart = 'c:\Windows\System32';
begin
tv1.Items.BeginUpdate;
// mFillTreeLevel(nil, 'c:');
mFillTreeLevel(tv1.Items.Add(nil, csStart), csStart );
tv1.Items.EndUpdate;
end;
The key method for loading one level is discussed here. It’s called a recursive method - it calls itself with different parameters step by step, as it goes through the disk. Combination of FindFirst, FindNext and FindClose will be used for reading the directory.
procedure TForm1.mFillTreeLevel(oParentNode: TTreeNode; const sPath:string);
var
sr: TSearchRec;
oItem: TTreeNode;
begin
if FindFirst(sPath+'\'+'*.*', faAnyFile, sr) = 0 then
begin
repeat
if (sr.Attr and faDirectory) > 0 then
begin
if (sr.name <> '.') and (sr.Name <> '..') then
begin
oItem := tv1.Items.AddChild(oParentNode, sr.Name);
mFillTreeLevel(oItem, sPath + '\'+sr.Name );
end;
end;
until FindNext(sr) <> 0;
end;
FindClose(sr);
end;
A hint for homework:
- You have always call filling ListView in tree’s OnChange
- ListView is cleared by calling Iteams.Clear (after BeginUpdate!)
- You can expend the programme in any way (icons, better files’ details,..)
Sample project regarding homework can be downloaded from here.
About the Author
Ing. Radek ČervinkaEmbarcadero MVP
Web: Delphi.cz
Twitter: @delphi.cz