====== Virtual Tree View ======
===== Fonctionnement =====
Les TVirtualTrees contiennent un ensemble de **Node** (de type PVirtualNode).
Chaque **Node** contient un membre **Data** TVirtualNode.Data (''Data: record end;'')
Ce **Data** contient la donnée a gérer pour ce nœud.\\
En general la donnée est un record qui peut contenir n'importe quoi , par exemple...
TTreeData = record
Text: String;
URL: string[255];
ImageIndex: integer;
end;
PTreeData = ^TTreeData;
On déclare aussi un type pointer vers TTreeData (''PTreeData'') qui nous sera utile plus tard...
==== Initialisation ====
Il faut initialiser le TVirtualTree en lui disant la taille des noeuds grace a **NodeDataSize**
procedure TForm1.FormCreate(Sender: TObject);
begin
VSTMain.NodeDataSize := SizeOf(TTreeData);
end;
Notez bien que c'est SizeOf(**T**TreeData) et **NON** SizeOf(**P**TreeData) \\
Sinon ça bug dans tous les sens...
==== Ajout d'un Noeud ====
Pour ajouter un noeud :
procedure TForm1.FormCreate(Sender: TObject);
var
pNode: PVirtualNode;
pData: PTreeData;
begin
VSTMain.BeginUpdate;
pNode := VSTMain.AddChild(nil);
pData := VSTMain.GetNodeData(pNode);
pData^.Text := 'root';
VSTMain.EndUpdate;
end;
==== Affichage d'un Noeud ====
=== Affichage du texte du noeud ===
Lors du dessin du composant, le TVirtualTree se sert de l'evenement ''OnGetText'' pour recuperer le texte a afficher.
procedure TForm1.VSTMainGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: String);
var
pData: PTreeData;
begin
pData := VST.GetNodeData(Node);
case Column of
0: CellText:= IntToStr(pData^.id);
1: CellText:= IntToStr(pData^.Flags);
2: CellText:= IntToStr(pData^.Current);
3: CellText:= IntToStr(pData^.Worst);
end;
end;
=== Affichage des images/icones ===
On peut mettre deux images avant le texte du noeud.
- L'image "Normale", dont le ''TImageList'' sera stocké dans la property ''images'' et la largeur définie dans la propety ''imagesWidth''.
- L'image "State", dont le ''TImageList'' sera stocké dans la property ''StateImages'' et la largeur définie dans la propety ''StateImagesWidth''.
Lorsque le VST veux récupérer l'index de l'image à afficher, le paramètre ''Kind'' contient l'information du type d'image qu'il souhaite:
* ''ikNormal'' : L'image "Normale"
* ''ikSelected'' : L'image "Normale" quand la ligne est séléctionnée
* ''ikState'' : L'image "State"
* ''ikOverlay'' : .....
Le paramètre ''Column'' contient l'index de la colonne pour laquelle il veut l'ImageIndex.
procedure TFrameVSTDisks.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode; Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: boolean; var ImageIndex: integer);
var
pData: PTreeData;
begin
pData := VST.GetNodeData(Node);
ImageIndex := -1;
case Column of
C_COL_DEVICE: case Kind of
ikState: ImageIndex := -1;
ikNormal,ikSelected: ImageIndex := pData^.Img;
end;
C_COL_SMART: case Kind of
ikState: ImageIndex := -1;
ikNormal,ikSelected: ImageIndex := pData^.SmartImg;
end;
end;
end;
==== Expanded ====
=== Un noeud ===
{ Expand un Node }
VSTMain.Expanded[FRootNode]:=true;
{ Savoir si un Node est expanded }
ExpBool:=VSTMain.Expanded[FRootNode];
=== Tout ===
VST.FullExpand;
VST.FullCollapse;
==== Tri ====
Le tri d'une colonne peut etre déclenché par :
* Click sur l’entête de la colonne. Dans ce cas l'option ''Header/Options/hoHeaderClickAutoSort'' doit etre à ''True''.
* Appel a la procédure Sort : ''VST.Sort(Node,Column,Sens);''
Pour comparer les nœuds le VST utilise l'event ''OnCompareNodes''
{ Exemple simpliste sans prise en compte de l'index de la column }
procedure TFrameVSTDisks.VSTCompareNodes(Sender: TBaseVirtualTree; Node1,
Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
pD1,pD2: PTreeData;
begin
pD1:= VST.GetNodeData(Node1);
pD2:= VST.GetNodeData(Node2);
Result:=0; // Les noeud sont égaux
if pD1^.Index>pD2^.Index then Result:=1; // node1>node2 -> Result= 1
if pD1^.Index Result= -1
end;
Ressources pour le tri :
* [[https://documentation.help/VirtualTreeview/TBaseVirtualTree_Sort@PVirtualNode@TColumnIndex@TSortDirection@Boolean.html|Procédure SORT @Doc Officielle]]
* [[https://documentation.help/VirtualTreeview/TBaseVirtualTree_OnCompareNodes.html|OnCompareNode @DocOfficielle]]
==== Modifications ====
=== BeginUpdate / EndUpdate ===
Lorsque l'on met a jour un VST, il est bon pour l'affichage et la rapidité d'entourer ces mises a jour par un ''BeginUpdate'' et un ''EndUpdate''.
VST.BeginUpdate;
try
...
finally
VST.EndUpdate;
end;
==== Déstruction du VST ====
=== OnFreeNode ===
J'ai eu un pb de MemoryLeak avec un VST que j'ai résolu de la façon suivante
procedure TForm1.VSTMainFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
Data: PTreeData;
begin
Data := VSTMain.GetNodeData(Node);
Finalize(Data^);
end;
On en parle ici :[[https://www.remkoweijnen.nl/blog/2010/06/09/memory-leaks-when-using-virtual-treeview-component/]]
Plus d'infos sur ''Finalize()'' : [[https://www.freepascal.org/docs-html/rtl/system/finalize.html]]
On voit aussi...
procedure TForm1.VSTMainFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
var
Data: PTreeData;
begin
Data := VSTMain.GetNodeData(Node);
Data^.Text:='';
Data^.URL:='';
end;
===== Sources et Ressources =====
* [[https://jlelong.developpez.com/articles/virtualtreeview/]]
* [[https://documentation.help/VirtualTreeview/$Main.html]]
* [[https://wiki.freepascal.org/VirtualTreeview_Example_for_Lazarus/fr]]