Sign in Join
Wiki copytemporary

VirtualTreeview Example for Lazarus/es: what changed

Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.

Title: VirtualTreeview Example for Lazarus/es

OldNewLine
1+Aqui hay algunos ejemplos acerca de como usar el control VirtualTreeview para Lazarus (probado en win32). La mayoría de estos ejemplos han sido recolectados de la web, escritos para delphi, y de los documentos o tutoriales por Philipp Frenzel y Mike Lischke. Los documentos o tutoriales pueden ser descargados desde <http://www.soft-gems.net> . Abajo, usted puede encontrar alguna forma rapida de como utilizar VirtualTreeview en Lazarus, no explicaciones detalladas. Para más explicaciones y otros métodos o funciones, obtenga los documentos oficiales y el tutorial.
2+
3+# Ejemplo Tree Listview basico con 3 columnas
4+
5+1\. Instalar el componente. Ejecutar Lazarus.
6+
7+2\. Arrastre un componente TVirtualStringTree (bajo la pagina Controles Visuales).
8+
9+3\. Vaya al editor de código (oprima la tecla F12). Bajo la sentencia *Uses* agregue una unidad - escriba VirtualTrees (si no existe previamente, no confunda con la unidad VirtualStringTree). Se vera de forma igual o similar a :
10+
11+``` pascal
12+ uses
13+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, VirtualStringTree, VirtualTrees;
14+```
15+
16+4\. Vaya al Diseñador de Formularios (oprima la tecla F12). Seleccione el componente Virtual Tree. En el Inspector de Objetos haga clic en Nombre, escriba VST y oprima la tecla Enter (Return). Haga clic en Encabezado (expandalo) -\> Columnas, haga clic en el pequeño botón, al lado de "0 elementos". Haga clic 3 veces en el botón agregar para agregar 3 columnas. No cierre esta ventana.
17+
18+5\. En la ventana para Edición de Columna, aparecerá la 3ra. columna como seleccionada. Vaya al Inspector de Objetos. Haga clic en Opciones (expandalo) -\> y asigne coAllowClick como False.
19+
20+6\. Haga clic en Texto. Escriba Column2.
21+
22+7\. Haga clic en ancho, escriba 100 y oprima la tecla Enter (Return).
23+
24+8\. Vaya a la ventana para Edición de Columna, seleccione las columnas 1ra. y 2da., y asigne su propiedad como la de arriba (para el campo Texto, use nombres diferentes, ejemplo: Columna0, Columna1).
25+
26+9\. Cierre la ventana para Edición de Columna. Seleccione el componente *Virtual Tree* en el formulario. En el Inspector de Objetos vaya a Encabezado -\> Opciones (expandalo). Asigne coAllowClick como True.
27+
28+10\. Desplacese hacia abajo hasta Style, y asignelo como hsFlatButtons.
29+
30+11\. Desplacese hacia abajo hasta TreeOptions (expandalo) -\> MiscOption (expandalo), y asigne toEditable como True. Asigne toGridExtensions como True.
31+
32+12\. Desplacese hacia abajo hasta SelectionOptions (expandalo) -\> y asigne toExtendedFocus como True. Asigne toMultiSelect como True. En el Diseñador de Formularios cambie el tamaño del VST (componente Virtual) para para poder visualizar todas las columnas, en caso de que sea necesario.
33+
34+13\. Ahora, para agregar 3 botones en el formulario. Arrastrelos desde la paleta de componentes - Pagina Estándar (Etiquetados como "OK").
35+
36+14\. Haga clic en Button1, en el Inspector de Objetos cambie Titulo a "Añadir Nodo". Haga clic en el Button2, cambie el titulo a "Añadir Hijo". Cambie el titulo de Button3 a "Borrar".
37+
38+15\. Mantenga esto aquí y vaya al editor de código (oprima la tecla F12). En el Editor de Código reemplace la linea:
39+
40+``` pascal
41+{$mode objfpc}{$H+}
42+```
43+
44+Con la linea:
45+
46+``` pascal
47+{$MODE DELPHI}
48+```
49+
50+16\. Bajo la sentencia "implementation" pegue las siguientes lineas de código:
51+
52+``` pascal
53+ type
54+ PTreeData = ^TTreeData;
55+ TTreeData = record
56+ Column0: String;
57+ Column1: String;
58+ Column2: String;
59+ end;
60+```
61+
62+17\. Vaya al Diseñador de Formularios (oprima la tecla F12). Seleccione el control VST. Vaya al Inspector de Objetos, seleccione la pagina Eventos, desplacese hasta el evento onChange. Haga doble clic en el control combobox.
63+
64+18\. Desplacese hasta el evento onFocusChanged. Haga doble clic y pegue el código siguiente:
65+
66+``` pascal
67+ procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
68+ Column: TColumnIndex);
69+ begin
70+ VST.Refresh;
71+ end;
72+```
73+
74+19\. Desplacese hasta el evento onFreeNode. Haga doble clic y pegue el código siguiente:
75+
76+``` pascal
77+ procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode);
78+ var
79+ Data: PTreeData;
80+ begin
81+ Data:=VST.GetNodeData(Node);
82+ if Assigned(Data) then begin
83+ Data^.Column0 := '';
84+ Data^.Column1 := '';
85+ Data^.Column2 := '';
86+ end;
87+ end;
88+```
89+
90+20\. Desplacese hasta el evento onGetNodeDataSize. Haga doble clic y pegue el código siguiente:
91+
92+``` pascal
93+ procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer);
94+ begin
95+ NodeDataSize := SizeOf(TTreeData);
96+ end;
97+```
98+
99+21\. Desplacese hasta el evento onGetText. Haga doble clic y pegue el código siguiente:
100+
101+``` pascal
102+ procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
103+ Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
104+var
105+ Data: PTreeData;
106+begin
107+ Data := VST.GetNodeData(Node);
108+ case Column of
109+ 0: CellText := Data^.Column0;
110+ 1: CellText := Data^.Column1;
111+ 2: CellText := Data^.Column2;
112+ end;
113+end;
114+```
115+
116+22\. Oprima la tecla F12 para ir al Diseñador de Formularios. Haga doble clic en el botón "Añadir Nodo". Haga doble clic y pegue el código siguiente:
117+
118+``` pascal
119+ procedure TForm1.Button1Click(Sender: TObject);
120+ Var
121+ Data: PTreeData;
122+ XNode: PVirtualNode;
123+ Rand: Integer;
124+ Begin
125+ Randomize;
126+ Rand := Random(99);
127+ XNode:=VST.AddChild(nil);
128+
129+ if VST.AbsoluteIndex(XNode) > -1 then
130+ Begin
131+ Data := VST.GetNodeData(Xnode);
132+ Data^.Column0:= 'Uno ' + IntToStr(Rand);
133+ Data^.Column1:= 'Dos ' + IntToStr(Rand + 10);
134+ Data^.Column2:= 'Tres ' + IntToStr(Rand - 10);
135+ End;
136+ End;
137+```
138+
139+23\. Oprima la tecla F9 para Ejecutar el proyecto y revisarlo. Haga clic en el botón "Añadir Nodo" para agregar un nodo. Si no hay problema alguno, el nodo sera agregado al control V.S.T.
140+
141+24\. Detenga la ejecución del programa. En el Diseñador de Formularios haga doble clic en el botón titulado "Añadir Hijo". Haga doble clic y pegue el código siguiente:
142+
143+``` pascal
144+ procedure TForm1.Button2Click(Sender: TObject);
145+ var
146+ XNode: PVirtualNode;
147+ Data: PTreeData;
148+ begin
149+ if not Assigned(VST.FocusedNode) then
150+ Exit;
151+
152+ XNode := VST.AddChild(VST.FocusedNode);
153+ Data := VST.GetNodeData(Xnode);
154+
155+ Data^.Column0:= 'Ch 1';
156+ Data^.Column1:= 'Ch 2';
157+ Data^.Column2:= 'Ch 3';
158+
159+ VST.Expanded[VST.FocusedNode]:=True;
160+ end;
161+```
162+
163+25\. En el Diseñador de Formularios haga doble clic en el botón titulado "Borrar". Haga doble clic y pegue el código siguiente:
164+
165+``` pascal
166+ procedure TForm1.Button3Click(Sender: TObject);
167+ begin
168+ VST.DeleteSelectedNodes;
169+ end;
170+```
171+
172+26\. Ejecute el proyecto, oprimiendo la tecla F9 para revisarlo. Haga varias pruebas, agregando algunos nodos principales, nodos hijos y eliminelos.
173+
174+27\. Intente editar un nodo. Seleccione un nodo y oprima la tecla F2, y escriba un nuevo valor. Si puede ver lo que esta escribiendo, entonces, el paso esta bien. De lo contrario, lea la sección siguiente titulada "Cuando la edición de celda no puede verse".
175+
176+28\. Para obtener que el V.S.T. muestre el nuevo valor capturado después de la edición, vaya al Diseñador de Formularios, y seleccione V.S.T. Haga doble clic, en el *combo* del Inspector de Objetos -\> Events -\> OnNewText.
177+
178+   Haga doble clic y pegue el código siguiente:
179+
180+``` pascal
181+ procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
182+ Column: TColumnIndex; NewText: WideString);
183+ Var
184+ Data: PTreeData;
185+ begin
186+ Data := VST.GetNodeData(Node);
187+ Case Column of
188+ 0: Data^.Column0:= NewText;
189+ 1: Data^.Column1:= NewText;
190+ 2: Data^.Column2:= NewText;
191+ End;
192+ end;
193+```
194+
195+   Hasta ahora, el ejemplo para uso básico, termina aquí. Usted podría arrastrar algunos botones adicionales en el formulario para probar algunos de los comandos mencionados, mas adelante. El paso siguiente, podría ser, desplegar una casilla para marcar o *checkbox*, imagen, color para tipo de fuente de texto, o agregar un *combo* al nodo.
196+
197+- Otra forma para agregar el nodo raíz:
198+
199+``` pascal
200+ procedure TForm1.Button8Click(Sender: TObject);
201+ begin
202+ with VST do
203+ RootNodeCount:=RootNodeCount+1;
204+ end;
205+```
206+
207+- Otra forma para agregar un nodo hijo:
208+
209+``` pascal
210+ procedure TForm1.Button9Click(Sender: TObject);
211+ begin
212+ if Assigned(VST.FocusedNode) Then
213+ VST.ChildCount[VST.FocusedNode]:=VST.ChildCount[VST.FocusedNode]+1;
214+ end;
215+```
216+
217+- Determinar y eliminar los nodos hijos de un nodo:
218+
219+``` pascal
220+ procedure TForm1.Button4Click(Sender: TObject);
221+ Var
222+ c: Integer;
223+ begin
224+ if not Assigned(VST.FocusedNode) then
225+ Exit;
226+ If VST.HasChildren[VST.FocusedNode] then
227+ Begin
228+ c := VST.ChildCount[VST.FocusedNode];
229+ VST.DeleteChildren(VST.FocusedNode);
230+ ShowMessage('Number of deleted child:' + #13#10 + IntToStr(c));
231+ End;
232+ end;
233+```
234+
235+- Eliminar un nodo:
236+
237+``` pascal
238+ procedure TForm1.Button5Click(Sender: TObject);
239+ begin
240+ {VST.Clear; //Delete All Nodes}
241+ if not Assigned(VST.FocusedNode) then
242+ Exit;
243+ VST.DeleteNode(VST.FocusedNode);
244+ end;
245+```
246+
247+- Buscar y seleccionar un nodo:
248+
249+``` pascal
250+ procedure TForm1.Button6Click(Sender: TObject);
251+ var
252+ XNode: PVirtualNode;
253+ Data: PTreeData;
254+ begin
255+ XNode:= VST.GetFirst;
256+
257+ while XNode <> nil do
258+ begin
259+ Data:=VST.GetNodeData(XNode);
260+ if Data^.Column0 = '1' then
261+ begin
262+ VST.ClearSelection;
263+ VST.Selected[XNode]:=True;
264+ VST.SetFocus;
265+ break;
266+ end else
267+ XNode:= VST.GetNextSibling(XNode);
268+ end;
269+ end;
270+```
271+
272+- Determinar el nodo padre de un nodo:
273+
274+``` pascal
275+ procedure TForm1.Button13Click(Sender: TObject);
276+ var
277+ XNode: PVirtualNode;
278+ begin
279+ if not Assigned(VST.FocusedNode) then
280+ Exit;
281+ XNode:=VST.FocusedNode;
282+ while VST.GetNodeLevel(XNode) > 0 do
283+ Begin
284+ XNode := XNode.Parent;
285+ VST.Selected[XNode]:= True;
286+ End;
287+ VST.Refresh;
288+ VST.SetFocus;
289+ end;
290+```
291+
292+- Buscar todos los nodos:
293+
294+``` pascal
295+ procedure TForm1.Button7Click(Sender: TObject);
296+ Var
297+ XNode: PVirtualNode;
298+ Data: PTreeData;
299+ begin
300+ If VST.GetFirst = nil then Exit;
301+ XNode:=nil;
302+ Repeat
303+ if XNode = nil then XNode:=VST.GetFirst Else XNode:=VST.GetNext(XNode);
304+ Data:=VST.GetNodeData(XNode);
305+ If (Data^.Column0 = '1') OR (Data^.Column1 = '1') OR (Data^.Column2 = '1') then
306+ Begin
307+ ShowMessage('Found at Node Level : ' + IntToStr(VST.GetNodeLevel(XNode)) );
308+ break;
309+ End;
310+ Until XNode = VST.GetLast();
311+ end;
312+```
313+
314+- Buscar el nodo siguiente:
315+
316+``` pascal
317+ procedure TForm1.Button8Click(Sender: TObject);
318+ var
319+ XNode: PVirtualNode;
320+ Data: PTreeData;
321+ begin
322+ if not Assigned(VST.GetFirst) then
323+ Exit
324+ else
325+ XNode := VST.GetFirst;
326+ repeat
327+ XNode := VST.GetNext(XNode);
328+ Data := VST.GetNodeData(XNode);
329+ if Pos(LowerCase(SearchEdit.Text), LowerCase(Data^.Column0)) > 0 then
330+ begin
331+ VST.FocusedNode := XNode;
332+ VST.Selected[XNode] := True;
333+ if MessageDlg('Item found?', mtConfirmation, mbYesNo, 0) = mrYes then
334+ begin
335+ VST.Expanded[XNode] := True;
336+ VST.Refresh;
337+ VST.SetFocus;
338+ Break;
339+ end;
340+ end;
341+ until XNode = VST.GetLast;
342+ end;
343+```
344+
345+- Insertar Nodo:
346+
347+``` pascal
348+ procedure TForm1.Button12Click(Sender: TObject);
349+ var
350+ XNode: PVirtualNode;
351+ begin
352+ If Assigned(VST.FocusedNode) then
353+ begin
354+ XNode := VST.InsertNode(VST.FocusedNode,amInsertBefore);
355+ // To Insert After Selected Node.
356+ {XNode := VST.InsertNode(VST.FocusedNode,amInsertAfter);}
357+ VST.Refresh;
358+ end;
359+ end;
360+```
361+
362+- Asignar la altura de un nodo:
363+
364+``` pascal
365+ procedure TForm1.Button14Click(Sender: TObject);
366+ begin
367+ If Assigned(VST.FocusedNode) then
368+ VST.NodeHeight[VST.FocusedNode] := 32;
369+ end;
370+```
371+
372+- Guardar y Cargar:
373+
374+   El arbol simple (sin columnas), puede ser guardado y recargado con:
375+
376+``` pascal
377+ VST.SaveToFile('filename.dat');
378+ VST.LoadFromFile('filename.dat');
379+```
380+
381+   Para guardar y cargar el ejemplo mencionado arriba, coloque 2 botones en el formulario, cambie el título de un botón a "Guardar", y el titulo del otro botón a "Cargar". Seleccione el V.S.T., En el Inspector de Objetos -\> TreeOptions -\> StringOptions. Asegurese, que el valor de la propiedad toSaveCaptions este asignada como True. Vaya a la pagina del Inspector de Eventos Events. Desplazece hasta OnLoadNode, haga doble cilc y pegue el codigo siguiente:
382+
383+``` pascal
384+ procedure TForm1.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
385+ Stream: TStream);
386+ Var
387+ Data: PTreeData;
388+ Len: Integer;
389+ begin
390+ Data := VST.GetNodeData(Node);
391+ Stream.read(Len, SizeOf(Len));
392+ SetLength(Data^.Column0, Len);
393+ Stream.read(PChar(Data^.Column0)^, Len);
394+
395+ Stream.read(Len, SizeOf(Len));
396+ SetLength(Data^.Column1, Len);
397+ Stream.read(PChar(Data^.Column1)^, Len);
398+
399+ Stream.read(Len, SizeOf(Len));
400+ SetLength(Data^.Column2, Len);
401+ Stream.read(PChar(Data^.Column2)^, Len);
402+ end;
403+```
404+
405+ Otra vez, en la pagina Events del Inspector de Objetos, desplazece hasta OnSaveNode, haga doble cilc y pegue el codigo siguiente:
406+
407+``` pascal
408+ procedure TForm1.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
409+ Stream: TStream);
410+ Var
411+ Data: PTreeData;
412+ Len: Integer;
413+ begin
414+ Data := VST.GetNodeData(Node);
415+ Len := Length(Data^.Column0);
416+ Stream.write(Len, SizeOf(Len));
417+ Stream.write(PChar(Data^.Column0)^, Len);
418+
419+ Len := Length(Data^.Column1);
420+ Stream.write(Len, SizeOf(Len));
421+ Stream.write(PChar(Data^.Column1)^, Len);
422+
423+ Len := Length(Data^.Column2);
424+ Stream.write(Len, SizeOf(Len));
425+ Stream.write(PChar(Data^.Column2)^, Len);
426+ end;
427+```
428+
429+   En el Diseñador de Formularios, haga doble clic en el botón titulado "Save" o "Guargar", y pegue el codigo siguiente:
430+
431+``` pascal
432+ procedure TForm1.Button10Click(Sender: TObject);
433+ begin
434+ VST.SaveToFile('C:\vst.dat');
435+ end;
436+```
437+
438+  En el Diseñador de Formularios, haga doble clic en el botón titulado "Load" o "Cargar", y pegue el codigo siguiente:
439+
440+``` pascal
441+procedure TForm1.Button11Click(Sender: TObject);
442+begin
443+ VST.LoadFromFile('C:\vst.dat');
444+end;
445+```
446+
447+   Ahora, haga pruebas, para guardar y volver a cargar el arbol.
448+
449+- Problema de desplazamiento
450+
451+   El encabezado de control vistaarbol desaparece parcialmente o completamente al desplazarse. No pude encontrar una buena solucion a esto. Una forma de sobrepasar esto, es asignar la altura del encabezado a 0, y utilizar una etiqueta generica para las columnas, y todas las columnas estan visibles sin desplazamiento horizontal. O, la altura del encabezado puede ser asignada un valor mas alto, entre 25 o 30. El metodo VST.Refresh puede ser asignado al evento OnScroll.
452+
453+- Cambiar el tamaño de las columnas
454+
455+   No fue posible cambiar el tamaño de las columnas, arrastrando el ratón en el encabezado del V.S.T. Tal vez, sea debido al "bug" del encabezado, o tal vez, omiti algo. En caso de que la causa haya sido el encabezado, tal vez sea corregido en la siguiente version de Lazarus. Puede ver este enlace: <http://bugs.freepascal.org/view.php?id=11209>\
456+   De cualquier forma, es posible cambiar el tamaño de las columnas por medio de codigo. Cuando presione mantenga presionado el botón derecho del ratón, y gire la rueda arriba, el ancho de la columna seleccionada se incrementa, y manteniendo presionado abajo, el botón derecho del ratón y girando hacia abjo la rueda del ratón, podra decrementar el ancho de la columna seleccionada. Para hacer esto:\
457+1\. Agregue una variable en el editor de codigo llamada como CurCol: Integer; Se vera como esto:
458+
459+``` pascal
460+ var
461+ Form1: TForm1;
462+ CurCol: Integer; // <- Agregue solo esta linea.
463+
464+ implementation
465+
466+ { TForm1 }
467+```
468+
469+2\. En el Diseñador de Formularios, haga doble clic en el formulario para generar un procedimiento para el evento OnCreate. En el procedimiento OnCreate, escriba Form1.OnMouseWheelUp:= y presione Ctrl+Shift+C, esto completara el codigoy hara el esqueleto del procedimiento para el evento MouseWheelUp. ahora, regrese al procedimiento TForm1.FormCreate(Sender: TObject); Y agregue otro procedimiento, esta vez para el evento MouseWheelDown. Escriba Form1.OnMouseWheelDown:= y oprima la combinacion de teclas Ctrl+Shift+C, para generar el procedimiento para el evento MouseWheelDown. El procedimiento FormCreate quedará asi:
470+
471+``` pascal
472+ procedure TForm1.FormCreate(Sender: TObject);
473+ begin
474+ Form1.OnMouseWheelUp:=@Form1MouseWheelUp;
475+ Form1.OnMouseWheelDown:=@Form1MouseWheelDown;
476+ end;
477+```
478+
479+3\. Capture el procedimiento para el evento TForm1.Form1MouseWheelUp procedure como:
480+
481+``` pascal
482+ procedure TForm1.Form1MouseWheelUp(Sender: TObject; Shift: TShiftState;
483+ MousePos: TPoint; var Handled: Boolean);
484+ begin
485+ If VST.Focused then
486+ if ssRight in Shift then
487+ VST.Header.Columns[CurCol].Width:= VST.Header.Columns[CurCol].Width + 10;
488+ end;
489+```
490+
491+4\. Capture el procedimiento para el evento TForm1.Form1MouseWheelDown procedure como:
492+
493+``` pascal
494+ procedure TForm1.Form1MouseWheelDown(Sender: TObject; Shift: TShiftState;
495+ MousePos: TPoint; var Handled: Boolean);
496+ begin
497+ If VST.Focused then
498+ if ssRight in Shift then
499+ VST.Header.Columns[CurCol].Width:= VST.Header.Columns[CurCol].Width - 10;
500+ end;
501+```
502+
503+5\. Vaya al Diseñador de Formularios (puede oprimir F12), seleccione el V.S.T., En la pagina Events, del Inspector de Objetos, desplazece hasta OnFocusChanged, haga doble clic y pegue el codigo siguiente:
504+
505+``` pascal
506+ procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree;
507+ Node: PVirtualNode; Column: TColumnIndex);
508+ begin
509+ CurCol:=Column;
510+ end;
511+```
512+
513+   Cuando ejecute el programa, haga clic en una columna, después mantenga presionado abajo, el botón derecho del ratón, y gire la rueda arriba, para incrementar el ancho. Gire la rueda abajo decrementar los valores mencionados.
514+
515+  Podria modificar los procedimientos anteriores, para ajustar un poco el resultado, si es necesario. O, agregar algun evento para el teclado, con algo como *if (key=187) and (ssShift in Shift) then* para utilizar la combinacion de teclas "Shift" y "+".
516+
517+# Casillas de verificación ( "Checkboxes" )
518+
519+   En el Diseñador de Formularios selecciona el control V.S.T. y desplazate hasta:
520+
521+1. Inspector de Objetos -\> Propiedades -\> CheckImageKind y seleccione ckDarkCheck.
522+2. Inspector de Objetos -\> Propiedade -\> TreeOptions -\> MiscOptions -\> toCheckSupport y asignelo como True.
523+
524+   Ahora, cambia a la página de **Eventos**.
525+
526+- Desplazate hasta el evento ***OnInitNode***. Haz doble clic y pega el código siguiente:
527+
528+``` pascal
529+ procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
530+ Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
531+ Var
532+ Level: Integer;
533+ begin
534+ Level := VST.GetNodeLevel(Node);
535+ if Level = 0 then
536+ Node.CheckType:=ctCheckBox;
537+
538+ if Level = 2 then
539+ Node.CheckType:=ctRadioButton;
540+
541+ if Level = 1 then
542+ begin
543+ Node.CheckType:=ctTriStateCheckBox;
544+ Node.CheckState := csCheckedNormal;
545+ end;
546+
547+ if Level = 3 then
548+ Node.CheckType:=ctButton;
549+ end;
550+```
551+
552+   Ejecuta el programa, y agrega el nodo raiz y nodos hijos, y posteriormente, nodos hijos a los nodos hijos, y revisa marcar y desmarcar las casillas correctamente. Cuando no sea el caso, cierra el programa. Ve a la pestaña **Eventos** del Inspector de Eventos.
553+
554+- Deslizate al evento ***OnChecked***, haz doble clic y pega el texto siguiente:
555+
556+``` pascal
557+ procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
558+ begin
559+ vst.Refresh;
560+ end;
561+```
562+
563+- Va hasta el evento ***OnChecking***, haz doble clic y pege el texto siguiente:
564+
565+``` pascal
566+ procedure TForm1.VSTChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
567+ var NewState: TCheckState; var Allowed: Boolean);
568+ begin
569+ VST.Refresh;
570+ end;
571+```
572+
573+   Esperemos que ahora funcione. Para determinar el estado actual de la casilla escribe algo como:\
574+
575+``` pascal
576+ If XNode.CheckState = csCheckedNormal then ShowMessage('Marcado.');
577+```
578+
579+- Otros estados son:
580+ - ***csUncheckedNormal*** : Sin marcar y sin presionar
581+ - ***csUncheckedPressed*** : Sin marcar y presionado
582+ - ***csCheckedNormal*** : Marcado y sin presionar
583+ - ***csCheckedPressed*** : Marcado y presionado
584+ - ***csMixedNormal*** : Casilla de 3 estados y sin presionar
585+ - ***csMixedPressed*** : Casilla de 3 estados y presionados
586+
587+- Otros tipos son:
588+ - ***ctNone*** : Sin asignar
589+ - ***ctTriStateCheckBox*** : casilla de 3 estados
590+ - ***ctCheckBox*** : casilla estándar de 2 estados
591+ - ***ctRadioButton*** : Botón tipo Radio, en vez de casilla
592+ - ***ctButton*** : botón estándar
593+
594+- Para capturar el evento ***Clic*** del boton o casilla (ctButton)
595+
596+  Ve a la pestaña Eventos del Inspector de Objetos. Desplazace al evento ***OnChecked***, haz doble clic y pega el texto siguiente:
597+
598+``` pascal
599+procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode);
600+ begin
601+ if Node.CheckType = ctButton then
602+ ShowMessage('Correcto');
603+ VST.Refresh;
604+ end;
605+```
606+
607+Fin de Casillas.
608+
609+# Imagenes
610+
611+To show image on VST nodes, a list of image should be created.
612+
613+- Go to the Component Palette -\> Common Controls. Select and drop a TImageList component on the form. Right click on the component icon and select ImageList Editor. Click on Add button and and select some images (at least 3 for now), then click on tick button to accept and close the ImageList Editor. By the way, there are some nice images you can download from <http://www.famfamfam.com/lab/icons/silk/>
614+- Now on the Form Designer select VST, and on Object Inspector's Properties tab, scroll to Images and select ImageList1
615+- On Object Inspector's Events tab scroll to OnGetImageIndex, double click and paste:
616+
617+``` pascal
618+procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
619+ Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean;
620+ var ImageIndex: Integer);
621+begin
622+ if Kind in [ikNormal , ikSelected] then // Either Selected or not
623+ begin
624+ if Column = 0 then // if 1st Column
625+ ImageIndex:=0; // 1st Image of the ImageList1
626+
627+ if Column = 1 then // if 2nd Column
628+ ImageIndex:=1; // 2nd Image of the ImageList1
629+
630+ if Sender.FocusedNode = Node then // Only show if Focused
631+ if Column =2 then // if 3rd Column
632+ ImageIndex:=2; // 3rd Image of the ImageList1
633+ end;
634+ {Sender.NodeHeight[node]:=40; //If Image is big}
635+end;
636+```
637+
638+# Font Colour
639+
640+On the Form Designer select VST, and on Object Inspector's Events tab, scroll to OnPaintText, double click and paste:
641+
642+``` pascal
643+procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
644+ const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex;
645+ TextType: TVSTTextType);
646+Var
647+ Data: PTreeData;
648+begin
649+ Data := VST.GetNodeData(Node);
650+
651+ if Data^.Column0 = 'sky' then
652+ TargetCanvas.Font.Color:=clBlue;
653+
654+ if Column = 1 then
655+ begin
656+ TargetCanvas.Font.Color:=clRed;
657+ TargetCanvas.Font.Style:= Font.Style + [fsItalic];
658+ end;
659+
660+ if Column = 2 then
661+ begin
662+// ImageList1.Draw(Form1.Canvas,-1,-1,2); {draw top left of form, 3rd image of ImageList1??}
663+ TargetCanvas.Font.Size:= 9;
664+ TargetCanvas.Font.Color:=clHighlightText;
665+ end;
666+end;
667+```
668+
669+# Adding A Combobox
670+
671+- I guess you have an open project on Lazarus IDE having VST on it and can edit the nodes. If not see the "Basic Tree Listview With 3 Columns" above, and atleast complete steps 1 to 21.
672+
673+- Bellow there is an unit file named combo. Copy that unit and save as combo.pas inside the project directory. Under your program's uses clause add combo. So it may look like:
674+
675+``` pascal
676+ uses
677+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
678+ VirtualStringTree, VirtualTrees, combo;
679+```
680+
681+- The combo.pas unit
682+
683+``` pascal
684+ unit combo;
685+
686+ {$mode delphi}
687+
688+ interface
689+
690+ uses
691+ Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs,
692+ VirtualStringTree, VirtualTrees, messages, windows, StdCtrls;
693+
694+ type
695+ TStringEditLink = class(TInterfacedObject, IVTEditLink)
696+ private
697+ FEdit: TWinControl;
698+ FTree: TVirtualStringTree;
699+ FNode: PVirtualNode;
700+ FColumn: Integer;
701+ protected
702+ procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
703+ public
704+ destructor Destroy; override;
705+ function BeginEdit: Boolean; stdcall;
706+ function CancelEdit: Boolean; stdcall;
707+ function EndEdit: Boolean; stdcall;
708+ function GetBounds: TRect; stdcall;
709+ function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall;
710+ procedure ProcessMessage(var Message: TMessage); stdcall;
711+ procedure SetBounds(R: TRect); stdcall;
712+ end;
713+
714+ implementation
715+
716+ destructor TStringEditLink.Destroy;
717+ begin
718+ FEdit.Free;
719+ inherited;
720+ end;
721+
722+ procedure TStringEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
723+ begin
724+ case Key of
725+ VK_ESCAPE:
726+ begin
727+ FTree.CancelEditNode;
728+ Key := 0;
729+ FTree.setfocus;
730+ end;
731+ VK_RETURN:
732+ begin
733+ PostMessage(FTree.Handle, WM_KEYDOWN, VK_DOWN, 0);
734+ Key := 0;
735+ FTree.EndEditNode;
736+ FTree.setfocus;
737+ end;
738+ End; //case
739+ end;
740+
741+ function TStringEditLink.BeginEdit: Boolean;
742+ begin
743+ Result := True;
744+ //FEdit.Height:=(FTree.DefaultNodeHeight - 1); //Needed for editbox. Not combo
745+ FEdit.Show;
746+ TComboBox(FEdit).DroppedDown:=True;
747+ FEdit.SetFocus;
748+ end;
749+
750+ function TStringEditLink.CancelEdit: Boolean;
751+ begin
752+ Result := True;
753+ FEdit.Hide;
754+ end;
755+
756+ function TStringEditLink.EndEdit: Boolean;
757+ var
758+ S: WideString;
759+ begin
760+ Result := True;
761+ S:= TComboBox(FEdit).Text;
762+ FTree.Text[FNode, FColumn] := S;
763+
764+ FTree.InvalidateNode(FNode);
765+ FEdit.Hide;
766+ FTree.SetFocus;
767+ end;
768+
769+ function TStringEditLink.GetBounds: TRect;
770+ begin
771+ Result := FEdit.BoundsRect;
772+ end;
773+
774+ function TStringEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean;
775+ begin
776+ Result := True;
777+ FTree := Tree as TVirtualStringTree;
778+ FNode := Node;
779+ FColumn := Column;
780+
781+ FEdit.Free;
782+ FEdit := nil;
783+
784+ FEdit := TComboBox.Create(nil);
785+ with FEdit as TComboBox do
786+ begin
787+ Visible := False;
788+ Parent := Tree;
789+ Items.Add('Google');
790+ Items.Add('Yahoo');
791+ Items.Add('Altavista');
792+ OnKeyDown := EditKeyDown;
793+ end;
794+ end;
795+
796+ procedure TStringEditLink.ProcessMessage(var Message: TMessage);
797+ begin
798+ FEdit.WindowProc(Message);
799+ end;
800+
801+ procedure TStringEditLink.SetBounds(R: TRect);
802+ var
803+ Dummy: Integer;
804+ begin
805+ FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right);
806+ FEdit.BoundsRect := R;
807+ end;
808+
809+ End.
810+```
811+
812+- After saving the file, on the Form Designer select VST and on Object Inspector's Properties, scroll to TreeOptions -\> MiscOptions, set toEditable to True. Then get to TreeOptions -\> SelectionOptions, set toExtendedFocus to True.
813+
814+- Switch to Object Inspector's Events tab. Scroll to OnCreateEditor, double click and paste:
815+
816+``` pascal
817+ procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree;
818+ Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
819+ begin
820+ EditLink:=TStringEditLink.Create;
821+ end;
822+```
823+
824+- On Object Inspector's Events tab. Scroll to OnNewText, double click and paste:
825+
826+``` pascal
827+ procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
828+ Column: TColumnIndex; NewText: WideString);
829+ Var
830+ Data: PTreeData;
831+ begin
832+ Data := VST.GetNodeData(Node);
833+ Case Column of
834+ 0: Data^.Column0:= NewText;
835+ 1: Data^.Column1:= NewText;
836+ 2: Data^.Column2:= NewText;
837+ End;
838+ end;
839+```
840+
841+Run program, select a node and press F2 to get combobox. On pressing Enter new value should appear on the node.
842+
843+# If Cell Editing Can't Be Seen
844+
845+Open VirtualStringTree.pas unit file (if you are still on the above example project, right click on VirtualStringTree under Uses clause and select Find Declaration. This opens the file on next tab. Go to that file's tab.). Get to the "function TStringEditLink.BeginEdit: Boolean; stdcall;". It looks like:
846+
847+``` pascal
848+ function TStringEditLink.BeginEdit: Boolean; stdcall;
849+
850+ // Notifies the edit link that editing can start now. Descentants may cancel node edit
851+ // by returning False.
852+
853+ begin
854+ Result := not FStopping;
855+ if Result then
856+ begin
857+ FEdit.Show;
858+ FEdit.SelectAll;
859+ FEdit.SetFocus;
860+ end;
861+ end;
862+```
863+
864+Now add "FEdit.Height:=18;". It should look like:
865+
866+``` pascal
867+ function TStringEditLink.BeginEdit: Boolean; stdcall;
868+
869+ // Notifies the edit link that editing can start now. Descentants may cancel node edit
870+ // by returning False.
871+
872+ begin
873+ Result := not FStopping;
874+ if Result then
875+ begin
876+ FEdit.Show;
877+ FEdit.SelectAll;
878+ FEdit.SetFocus;
879+ FEdit.Height:=18; // <--- Added this line.
880+ end;
881+ end;
882+```
883+
884+Save the file (press Ctrl + S). If you are on the example project, close this (Project -\> Close Project). Click on Tools -\> Configure "Build Lazarus" ... Select Clean Up + Build All and then click on the Build button. After compile Lazarus should be restarted. Now open the example project and try to edit node on VST. This time it should be ok.
885+
886+# External links
887+
888+- [Programando en Pascal](http://es.wikibooks.org/wiki/Programaci%C3%B3n_en_Pascal) - Spanish tutorial focused on FPC/Lazarus, hosted in Wikibooks.
889+
890+(In progress)
891+
892+\[En desarrollo\]
893+
894+---
895+*From the Free Pascal wiki, page "VirtualTreeview Example for Lazarus/es", as it stood on 2020-03-03 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
896+Category: Castellano
897+Category: Español

Back to history