Virtual Treeview jsem již uváděl v přehledu zajímavých komponent pro Delphi. Abych se přiznal, tak tuto komponentu považuji za jednu z nejlepších co pro Delphi existují a navíc se jedná o Open Source kód. Dá se použít jako pekelně rychlý strom nebo něco jako ListView nebo kombinace obojího a nebo prostě cokoli.
Výsledkem dnešního cvičení bude v podstatě minimální základ pro reálné použití VT. Jednoúrovňový strom s pozadím a více sloupci (konkrétně dvěma) - viz obrázek.

Výsledný program za běhu
Ještě než začneme tak jen upozorním, že přidání cca 1 mil. uzlů na průměrném současném počítači trvá kolem 1s.
Program byl s ohledem na majitele starších verzí Delphi napsán na Delphi 5, ale není problém aby fungoval na Delphi 2010. Ještě ke kompatibilitě komponenty: aktuální verze je VT 5 a něco a ta je kompatibilní s Delphi 7+, ale kolem verze 4.8 byla podpora i pro Delphi 5 a zároveň i s unicode Delphi, což je optimální pokud portujete starší projekt (nejdříve upgradujete všechny komponenty v původní verzi Delphi a pak teprve provedete switch).
Založíme nový projekt a na formulář vložíme TVirtualStringTree s názvem vt, jeden edit box (edtNodeCountEdit), tlačítko a TLabel (lblSelected). Rozdíl proti TVirtualDrawTree je v lepší podpoře pro práci s řetězci, ale pokud chcete úplnou kontrolu nad kreslením položek tak neváhejte a zvolte TVirtualDrawTree.
Nyní nastavíme pár property u stromu (sice by to šlo za běhu, ale nebudeme to komplikovat):
- DblClickem se zobrazí editor sloupců, kde přidáme dva sloupce se šířkami 150 pixelů (a nezapomeneme nastavit Text, což je text v záhlaví).
- v TreeOptions je podsekce SelectionOptions a tam nastavíme Multiselect popř. jiné
- v Header.Options nastavíme hoVisible na True (ukáže se záhlaví sloupců)
- SelectionCurveRadius nastavíme na 5 (zaoblení výběru)
- v sekci Colors se můžeme vyřádit dle libosti
- v Background načteme pozadí (viz níže) a v TreeOptions.PaintOptions nastavíme toShowBackground na true

Pozadí pro program
To je tak všechno pro tuto chvilku, ale zdaleka ne co se dá s VT nastavovat. Klidně si zkuste nastavovat různé Options, je jich tam mraky.
Nyní přejdeme na kód. Nejdříve deklarujeme strukturu, v které budeme uchovávat naše data pro zobrazení ve stromu.
type
TMyNodeData = record
iCommission: Integer; // cislo zakazky pro prvni sloupec
crPrice: Currency; // cena zakázky pro druhý sloupec
end;
PMyNodeData = ^TMyNodeData;
Nyní musíme říct VT velikost naší struktury, aby mohl pro jednotlivé uzly alokovat paměť a to obsloužením GetNodeDataSize. Nebo to jde udělat i za běhu nastavením NodeDataSize třeba ve FormCreate.
procedure TfrmVTtest.vtGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
NodeDataSize := SizeOf(TMyNodeData)
end;
Další na řadě je inicializace jednotlivých uzlů a to buďto obsloužením OnInitNode nebo za běhu.
procedure TfrmVTtest.vtInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
var
MyNodeData:PMyNodeData;
begin
MyNodeData := Sender.GetNodeData(Node); // získáme data pro uzel
MyNodeData^.iCommission := Node.Index; // a pro ukázku nastavíme číslo zakázky
MyNodeData^.crPrice := Random(1000); // nějaká náhodná cena
end;
Nyní obsluha tlačítka.
procedure TfrmVTtest.AddButtonClick(Sender: TObject);
var
iCount: Integer;
begin
Screen.Cursor := crHourGlass;
with vt do
try
iCount := StrToInt(edtNodeCountEdit.Text); //kolik uzlů přidat
// o tolik zvětšit počet uzlů z kořene, podobně i pro pod uzly,
// postupně se bude volat OnInitNode
RootNodeCount := Integer(RootNodeCount) + iCount;
finally
Screen.Cursor := crDefault;
end;
end;
Tak teď už jen co se bude zobrazovat. Pro teď nebudeme řešit ikony nebo speciální kreslení - jen získání textu v OnGetText.
procedure TfrmVTtest.vtGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType;
var CellText: WideString);
var
MyNodeData:PMyNodeData;
begin
MyNodeData := Sender.GetNodeData(Node); // získej data pro uzel
with MyNodeData^ do
begin
case Column of
0: CellText := 'Zakázka: '+IntToStr(iCommission); // první sloupec
1: CellText := FloatToStr(crPrice); // druhý sloupec
end;
end;
end;
A informaci o vybraných uzlech při změně atd. lze získat v OnChange
procedure TfrmVTtest.vtChange(Sender: TBaseVirtualTree; Node: PVirtualNode);
begin
lblSelected.Caption := Format('Vybráno: %d', [vt.SelectedCount]);
end;
A to je vše, jedná se opravdu minimální demo. Zdrojové kódu ke stažení zde (13 KB). Jinak k VT je dostupné na stránkách autora velké demo (včetně zdrojových kódů), které opravdu stojí za pozornost.