Difference between revisions of "VirtualTreeview Example for Lazarus/es"
Line 443: | Line 443: | ||
end;</delphi> | end;</delphi> | ||
− | + | Cuando ejecute el programa, haga clic en una columna, despues mantenga presionado abajo, el boton derecho del raton, y gire la rueda arriba, para incrementar el ancho. Gire la rueda abajo decrementar los valores mencionados. | |
+ | 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 + "+". | ||
=Checkbox= | =Checkbox= |
Revision as of 01:33, 1 November 2011
│
English (en) │
español (es) │
français (fr) │
polski (pl) │
русский (ru) │
Aqui hay algunos ejemplos acerca de como how usar el control VirtualTreeview para Lazarus (probado en win32). La mayoria 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 detallas. Para mas explicaciones y otros metodos o funciones, obtenga los documentos oficiales y el tutorial.
Ejemplo Tree Listview basico con 3 columnas
1. Instalar el componente. Ejecutar Lazarus.
2. Arrastre un componente TVirtualStringTree (bajo la pagina Controles Visuales).
3. Vaya al editor de codigo (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 : <delphi>uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, VirtualStringTree, VirtualTrees;</delphi>
4. Vaya al Diseñador de Formas (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 boton, al lado de "0 elementos". Haga clic 3 veces en agregar boton para agregar 3 columnas. No cierre esta ventana.
5. En la ventana para Edicion de Columna, aparecera la 3ra. columna como seleccionada. Vaya al Inspector de Objetos. Haga clic en Opciones (expandalo) -> y asigne coAllowClick como False.
6. Haga clic en Texto. Escriba Column2.
7. Haga clic en ancho, escriba 100 y oprima la tecla Enter (Return).
8. Vaya a la ventana para Edicion 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).
9. Cierre la ventana para Edicion de Columna. Seleccione el component Virtual Tree en la forma. En el Inspector de Objetos vaya a Encabezado -> Opciones (expandalo). Asigne coAllowClick como True.
10. Desplazece hacia abajo hasta Style, y asignelo como hsFlatButtons.
11. Desplazece hacia abajo hasta TreeOptions (expandalo) -> MiscOption (expandalo), y asigne toEditable como True. Asigne toGridExtensions como True.
12. Desplazece hacia abajo hasta SelectionOptions (expandalo) -> y asigne toExtendedFocus como True. Asigne toMultiSelect como True. En el Diseñador de Formas cambie el tamaño del VST (componente Virtual) para para poder visualizar todas las columnas, en caso de que sea necesario.
13. Ahora, para agregar 3 botones en la forma. Arrastrelos desde la paleta de componentes - Pagina Estandar (Etiquetados como "OK").
14. Haga clic en Button1, en el Inspector de Objetos cambie Titulo a "AddRoot". Haga clic en el Button2, cambie el titulo a "AddChild". Cambie el titulo de Button3 a "Delete".
15. Mantenga esto aqui y vaya al editor de codigo (oprima la tecla F12). En el Editor de Codigo reemplace la linea:
{$mode objfpc}{$H+} with {$MODE DELPHI}
16. Bajo la sentencia "implementation" pegue las siguientes lineas de codigo:
<delphi>type
PTreeData = ^TTreeData; TTreeData = record Column0: String; Column1: String; Column2: String; end;</delphi>
17. Vaya al Diseñador de Formas (oprima la tecla F12). Seleccione el control VST. Vaya al Inspector de Objetos, seleccione la pagina Eventos, desplazece hasta el evento onChange. Haga doble clic en el control combobox.
18. Desplazece hasta el evento onFocusChanged. Haga doble clic y pegue el codigo siguiente: <delphi>procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex);
begin
VST.Refresh;
end;</delphi>
19. Desplazece hasta el evento onFreeNode. Haga doble clic y pegue el codigo siguiente: <delphi>procedure TForm1.VSTFreeNode(Sender: TBaseVirtualTree; Node: PVirtualNode); var
Data: PTreeData;
begin
Data:=VST.GetNodeData(Node); if Assigned(Data) then begin Data^.Column0 := ; Data^.Column1 := ; Data^.Column2 := ; end;
end;</delphi>
20. Desplazece hasta el evento onGetNodeDataSize. Haga doble clic y pegue el codigo siguiente: <delphi>procedure TForm1.VSTGetNodeDataSize(Sender: TBaseVirtualTree; var NodeDataSize: Integer); begin
NodeDataSize := SizeOf(TTreeData);
end;</delphi>
21. Desplazece hasta el evento onGetText. Haga doble clic y pegue el codigo siguiente: <delphi>procedure TForm1.VSTGetText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; TextType: TVSTTextType; var CellText: WideString);
var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node); case Column of 0: CellText := Data^.Column0; 1: CellText := Data^.Column1; 2: CellText := Data^.Column2; end;
end;</delphi>
22. Oprima la tecla F12 para ir al Diseñador de Formas. Haga doble clic en el boton "AddRoot". Haga doble clic y pegue el codigo siguiente:
<delphi>procedure TForm1.Button1Click(Sender: TObject); Var
Data: PTreeData; XNode: PVirtualNode; Rand: Integer;
Begin
Randomize; Rand := Random(99); XNode:=VST.AddChild(nil); if VST.AbsoluteIndex(XNode) > -1 then Begin Data := VST.GetNodeData(Xnode); Data^.Column0:= 'One ' + IntToStr(Rand); Data^.Column1:= 'Two ' + IntToStr(Rand + 10); Data^.Column2:= 'Three ' + IntToStr(Rand - 10); End;
End;</delphi>
23. Oprima la tecla F9 para Ejecutar el proyecto y revisarlo. Haga clic en el boton "AddRoot" para agregar un nodo. SI no hay problema alguno, el nodo sera agregado al control VST.
24. Detenga la ejecucion del programa. En el Diseñador de Formas haga doble clic en el boton titulado "AddChild". Haga doble clic y pegue el codigo siguiente:
<delphi>procedure TForm1.Button2Click(Sender: TObject); var
XNode: PVirtualNode; Data: PTreeData;
begin
if not Assigned(VST.FocusedNode) then Exit; XNode := VST.AddChild(VST.FocusedNode); Data := VST.GetNodeData(Xnode); Data^.Column0:= 'Ch 1'; Data^.Column1:= 'Ch 2'; Data^.Column2:= 'Ch 3';
VST.Expanded[VST.FocusedNode]:=True;
end;</delphi>
25. En el Diseñador de Formas haga doble clic en el boton titulado "Delete". Haga doble clic y pegue el codigo siguiente:
<delphi>procedure TForm1.Button3Click(Sender: TObject); begin
VST.DeleteSelectedNodes;
end;</delphi>
26. Ejecute el proyecto, oprimiendo la tecla F9 para revisarlo. Haga varias pruebas, agregando algunos nodos principales, nodos hijos y eliminelos.
27. Intente editar un node. 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 seccion siguiente titulada "Cuando la edicion de celda no puede verse".
28. Para obtener que el V.S.T. muestre el nuevo valor capturado despues de la edicion, vaya al Diseñador de Formas, y seleccione V.S.T. Haga doble clic, en la cajacombo de el Inspector de Objetos -> Events -> OnNewText. Haga doble clic y pegue el codigo siguiente:
<delphi>procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; NewText: WideString);
Var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node); Case Column of 0: Data^.Column0:= NewText; 1: Data^.Column1:= NewText; 2: Data^.Column2:= NewText; End;
end;</delphi>
Hasta ahora, el ejemplo para uso basico, termina aqui. Usted podria arrastrar algunos botones adicionales en la forma para probar algunos de los comandos mencionados, mas adelante. El paso siguiente, podria ser, desplegar una casill para marcar o "checkbox", imagen, color para tipo de fuente de texto, o agregar una cajacombo al nodo.
- Otra forma para agregar el nodo raiz:
<delphi>procedure TForm1.Button8Click(Sender: TObject); begin
with VST do RootNodeCount:=RootNodeCount+1;
end;</delphi>
- Otra forma para agregar un nodo hijo:
<delphi>procedure TForm1.Button9Click(Sender: TObject); begin
if Assigned(VST.FocusedNode) Then VST.ChildCount[VST.FocusedNode]:=VST.ChildCount[VST.FocusedNode]+1;
end;</delphi>
- Determinar y eliminar los nodos hijos de un nodo:
<delphi>procedure TForm1.Button4Click(Sender: TObject); Var
c: Integer;
begin
if not Assigned(VST.FocusedNode) then Exit; If VST.HasChildren[VST.FocusedNode] then Begin c := VST.ChildCount[VST.FocusedNode]; VST.DeleteChildren(VST.FocusedNode); ShowMessage('Number of deleted child:' + #13#10 + IntToStr(c)); End;
end;</delphi>
- Eliminar un nodo:
<delphi>procedure TForm1.Button5Click(Sender: TObject); begin {VST.Clear; //Delete All Nodes}
if not Assigned(VST.FocusedNode) then Exit; VST.DeleteNode(VST.FocusedNode);
end;</delphi>
- Buscar y seleccionar un nodo:
<delphi>procedure TForm1.Button6Click(Sender: TObject); bar
XNode: PVirtualNode; Data: PTreeData;
begin
XNode:= VST.GetFirst;
while XNode <> nil do begin Data:=VST.GetNodeData(XNode); if Data^.Column0 = '1' then begin VST.ClearSelection; VST.Selected[XNode]:=True; VST.SetFocus; break; end else XNode:= VST.GetNextSibling(XNode); end;
end;</delphi>
- Determinar el nodo padre de un nodo:
<delphi>procedure TForm1.Button13Click(Sender: TObject); var
XNode: PVirtualNode;
begin
if not Assigned(VST.FocusedNode) then Exit; XNode:=VST.FocusedNode; while VST.GetNodeLevel(XNode) > 0 do Begin XNode := XNode.Parent; VST.Selected[XNode]:= True; End; VST.Refresh; VST.SetFocus;
end;</delphi>
- Buscar todos los nodos:
<delphi>procedure TForm1.Button7Click(Sender: TObject); Var
XNode: PVirtualNode; Data: PTreeData;
begin
If VST.GetFirst = nil then Exit; XNode:=nil; Repeat if XNode = nil then XNode:=VST.GetFirst Else XNode:=VST.GetNext(XNode); Data:=VST.GetNodeData(XNode); If (Data^.Column0 = '1') OR (Data^.Column1 = '1') OR (Data^.Column2 = '1') then Begin ShowMessage('Found at Node Level : ' + IntToStr(VST.GetNodeLevel(XNode)) ); break; End; Until XNode = VST.GetLast();
end;</delphi>
- Buscar el nodo siguiente:
<delphi>procedure TForm1.Button8Click(Sender: TObject); var
XNode: PVirtualNode; Data: PTreeData;
begin
if not Assigned(VST.GetFirst) then Exit else XNode := VST.GetFirst; repeat XNode := VST.GetNext(XNode); Data := VST.GetNodeData(XNode); if Pos(LowerCase(SearchEdit.Text), LowerCase(Data^.Column0)) > 0 then begin VST.FocusedNode := XNode; VST.Selected[XNode] := True; if MessageDlg('Item found?', mtConfirmation, mbYesNo, 0) = mrYes then begin VST.Expanded[XNode] := True; VST.Refresh; VST.SetFocus; Break; end; end; until XNode = VST.GetLast;
end;</delphi>
- Insertar Nodo:
<delphi>procedure TForm1.Button12Click(Sender: TObject); var
XNode: PVirtualNode;
begin
If Assigned(VST.FocusedNode) then begin XNode := VST.InsertNode(VST.FocusedNode,amInsertBefore); // To Insert After Selected Node. {XNode := VST.InsertNode(VST.FocusedNode,amInsertAfter);} VST.Refresh; end;
end;</delphi>
- Asignar la altura de un nodo:
<delphi>procedure TForm1.Button14Click(Sender: TObject); begin
If Assigned(VST.FocusedNode) then VST.NodeHeight[VST.FocusedNode] := 32;
end;</delphi>
- Guardar y Cargar:
EL arbol simple (sin columnas), puede ser guardado y recargado con:
<delphi> VST.SaveToFile('filename.dat'); VST.LoadFromFile('filename.dat'); </delphi>
Para guardar y cargar el ejemplo mencionado arriba, coloque 2 botones en la forma, cambie el titulo de un boton a "Guardar", y el titulo del otro boton 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:
<delphi>procedure TForm1.VSTLoadNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
Var
Data: PTreeData; Len: Integer;
begin
Data := VST.GetNodeData(Node); Stream.read(Len, SizeOf(Len)); SetLength(Data^.Column0, Len); Stream.read(PChar(Data^.Column0)^, Len);
Stream.read(Len, SizeOf(Len)); SetLength(Data^.Column1, Len); Stream.read(PChar(Data^.Column1)^, Len);
Stream.read(Len, SizeOf(Len)); SetLength(Data^.Column2, Len); Stream.read(PChar(Data^.Column2)^, Len);
end;</delphi>
Otra vez, en la pagina Events del Inspector de Objetos, desplazece hasta OnSaveNode, haga doble cilc y pegue el codigo siguiente:
<delphi> procedure TForm1.VSTSaveNode(Sender: TBaseVirtualTree; Node: PVirtualNode;
Stream: TStream);
Var
Data: PTreeData; Len: Integer;
begin
Data := VST.GetNodeData(Node); Len := Length(Data^.Column0); Stream.write(Len, SizeOf(Len)); Stream.write(PChar(Data^.Column0)^, Len);
Len := Length(Data^.Column1); Stream.write(Len, SizeOf(Len)); Stream.write(PChar(Data^.Column1)^, Len);
Len := Length(Data^.Column2); Stream.write(Len, SizeOf(Len)); Stream.write(PChar(Data^.Column2)^, Len);
end;</delphi>
En el Diseñador de Formas, haga doble clic en el boton titulado "Save" o "Guargar", y pegue el codigo siguiente:
<delphi>procedure TForm1.Button10Click(Sender: TObject); begin
VST.SaveToFile('C:\vst.dat');
end;</delphi>
En el Diseñador de Formas, haga doble clic en el boton titulado "Load" o "Cargar", y pegue el codigo siguiente:
<delphi> procedure TForm1.Button11Click(Sender: TObject); begin
VST.LoadFromFile('C:\vst.dat');
end; </delphi>
Ahora, haga pruebas, para guardar y volver a cargar el arbol.
- Problema de desplazamiento
The header of the treeview disappears fully or partially when scrolling. I could not find a good solution for this. One way to overcome this is to set the header height to 0, then using general label for columns. This is good while there are few columns, and all are visible without horizontal scrolling. Or, the header height can be set to a higher value like 25 or 30. VST.Refresh can be added to the OnScroll event.
- Cambiar el tamaño de las columnas
It was not possible to resize column by dragging mouse on VST header. May be it is for the header bug or I have missed something. If it is for the header, probably will be fixed on next version of Lazarus. See this link: http://bugs.freepascal.org/view.php?id=11209
Anyway, it is possible to resize column from code. When you press down right mouse button and move mouse-wheel up, the width of the selected column increases and press down the right mouse button and move mouse-wheel down, to decrease the width of the selected column. To do this:
1. Add a variable in the source editor named as CurCol: Integer; So it looks like: <delphi>var
Form1: TForm1; CurCol: Integer; // <- Add this line only.
implementation
{ TForm1 } </delphi>
2. On the Form Designer double click the form to generate an event OnCreate. Inside the OnCreate procedure type Form1.OnMouseWheelUp:= and press Ctrl+Shift+C, this will complete the code and make skeleton of the MouseWheelUp event. Now get back to procedure TForm1.FormCreate(Sender: TObject); And add another event for MouseWheelDown. Type Form1.OnMouseWheelDown:= and press Ctrl+Shift+C, to generate the MouseWheelDown event. FormCreate procedure now looks like: <delphi>procedure TForm1.FormCreate(Sender: TObject); begin
Form1.OnMouseWheelUp:=@Form1MouseWheelUp; Form1.OnMouseWheelDown:=@Form1MouseWheelDown;
end;</delphi>
3. Fill the TForm1.Form1MouseWheelUp procedure as: <delphi>procedure TForm1.Form1MouseWheelUp(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
If VST.Focused then if ssRight in Shift then VST.Header.Columns[CurCol].Width:= VST.Header.Columns[CurCol].Width + 10;
end;</delphi>
4. Fill the TForm1.Form1MouseWheelDown procedure as: <delphi>procedure TForm1.Form1MouseWheelDown(Sender: TObject; Shift: TShiftState;
MousePos: TPoint; var Handled: Boolean);
begin
If VST.Focused then if ssRight in Shift then VST.Header.Columns[CurCol].Width:= VST.Header.Columns[CurCol].Width - 10;
end;</delphi>
5. Go to the Form Designer (press F12), select VST, on Object Inspector's Events tab scroll to OnFocusChanged, double click & paste: <delphi>procedure TForm1.VSTFocusChanged(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex);
begin
CurCol:=Column;
end;</delphi>
Cuando ejecute el programa, haga clic en una columna, despues mantenga presionado abajo, el boton derecho del raton, y gire la rueda arriba, para incrementar el ancho. Gire la rueda abajo decrementar los valores mencionados. 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 + "+".
Checkbox
On Form Designer select VST. Go to:
- Object Inspector -> Properties -> CheckImageKind and select ckDarkCheck.
- Object Inspector -> Properties -> TreeOptions -> MiscOptions -> toCheckSupport and set it to True.
Now switch to Events tab.
- Scroll to OnInitNode. Double click and paste the followings:
<delphi>procedure TForm1.VSTInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode; var InitialStates: TVirtualNodeInitStates);
Var
Level: Integer;
begin
Level := VST.GetNodeLevel(Node); if Level = 0 then Node.CheckType:=ctCheckBox;
if Level = 2 then Node.CheckType:=ctRadioButton;
if Level = 1 then begin Node.CheckType:=ctTriStateCheckBox; Node.CheckState := csCheckedNormal; end;
if Level = 3 then Node.CheckType:=ctButton;
end;</delphi> Run the program, add rootnode and child then child of the child, and check if you can check and uncheck properly. If not, close the program. Go to the Object Inspector's Events tab.
- Scroll to OnChecked, double click and paste:
<delphi>procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode); begin
vst.Refresh;
end;</delphi>
- Scroll to OnChecking, double click and paste:
<delphi>procedure TForm1.VSTChecking(Sender: TBaseVirtualTree; Node: PVirtualNode;
var NewState: TCheckState; var Allowed: Boolean);
begin
VST.Refresh;
end;</delphi>
Hope now it is ok. To determine checkbox state use like:
If XNode.CheckState = csCheckedNormal then
ShowMessage('Checked.');
Other states are:
<delphi>csUncheckedNormal = unchecked and not pressed
csUncheckedPressed = unchecked and pressed
csCheckedNormal = checked and not pressed
csCheckedPressed = checked and pressed
csMixedNormal = 3-state check box and not pressed
csMixedPressed = 3-state check box and pressed</delphi>
Other types are:
<delphi>ctNone
ctTriStateCheckBox
ctCheckBox
ctRadioButton
ctButton</delphi>
- To Catch Checkbox's Button (ctButton) Click
Go to Object Inspector's Events tab. Scroll to OnChecked, double click and paste: <delphi>procedure TForm1.VSTChecked(Sender: TBaseVirtualTree; Node: PVirtualNode); begin
if Node.CheckType = ctButton then ShowMessage('Ok.'); VST.Refresh;
end;</delphi>
End of checkbox.
Images
To show image on VST nodes, a list of image should be created.
- 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/
- Now on the Form Designer select VST, and on Object Inspector's Properties tab, scroll to Images and select ImageList1
- On Object Inspector's Events tab scroll to OnGetImageIndex, double click and paste:
<delphi>procedure TForm1.VSTGetImageIndex(Sender: TBaseVirtualTree; Node: PVirtualNode;
Kind: TVTImageKind; Column: TColumnIndex; var Ghosted: Boolean; var ImageIndex: Integer);
begin
if Kind in [ikNormal , ikSelected] then // Either Selected or not begin if Column = 0 then // if 1st Column ImageIndex:=0; // 1st Image of the ImageList1
if Column = 1 then // if 2nd Column ImageIndex:=1; // 2nd Image of the ImageList1
if Sender.FocusedNode = Node then // Only show if Focused if Column =2 then // if 3rd Column ImageIndex:=2; // 3rd Image of the ImageList1 end; {Sender.NodeHeight[node]:=40; //If Image is big}
end;</delphi>
Font Colour
On the Form Designer select VST, and on Object Inspector's Events tab, scroll to OnPaintText, double click and paste: <delphi>procedure TForm1.VSTPaintText(Sender: TBaseVirtualTree;
const TargetCanvas: TCanvas; Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType);
Var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node); if Data^.Column0 = 'sky' then TargetCanvas.Font.Color:=clBlue; if Column = 1 then begin TargetCanvas.Font.Color:=clRed; TargetCanvas.Font.Style:= Font.Style + [fsItalic]; end; if Column = 2 then begin
// ImageList1.Draw(Form1.Canvas,-1,-1,2); {draw top left of form, 3rd image of ImageList1??}
TargetCanvas.Font.Size:= 9; TargetCanvas.Font.Color:=clHighlightText; end;
end;</delphi>
Adding A Combobox
- 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.
- 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:
<delphi>uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, VirtualStringTree, VirtualTrees, combo;</delphi>
- The combo.pas unit
<delphi>unit combo;
{$mode delphi}
interface
uses
Classes, SysUtils, LResources, Forms, Controls, Graphics, Dialogs, VirtualStringTree, VirtualTrees, messages, windows, StdCtrls;
type
TStringEditLink = class(TInterfacedObject, IVTEditLink) private FEdit: TWinControl; FTree: TVirtualStringTree; FNode: PVirtualNode; FColumn: Integer; protected procedure EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); public destructor Destroy; override; function BeginEdit: Boolean; stdcall; function CancelEdit: Boolean; stdcall; function EndEdit: Boolean; stdcall; function GetBounds: TRect; stdcall; function PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; stdcall; procedure ProcessMessage(var Message: TMessage); stdcall; procedure SetBounds(R: TRect); stdcall; end;
implementation
destructor TStringEditLink.Destroy; begin
FEdit.Free; inherited;
end;
procedure TStringEditLink.EditKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin
case Key of VK_ESCAPE: begin FTree.CancelEditNode; Key := 0; FTree.setfocus; end; VK_RETURN: begin PostMessage(FTree.Handle, WM_KEYDOWN, VK_DOWN, 0); Key := 0; FTree.EndEditNode; FTree.setfocus; end; End; //case
end;
function TStringEditLink.BeginEdit: Boolean; begin
Result := True; //FEdit.Height:=(FTree.DefaultNodeHeight - 1); //Needed for editbox. Not combo FEdit.Show; TComboBox(FEdit).DroppedDown:=True; FEdit.SetFocus;
end;
function TStringEditLink.CancelEdit: Boolean; begin
Result := True; FEdit.Hide;
end;
function TStringEditLink.EndEdit: Boolean; var
S: WideString;
begin
Result := True; S:= TComboBox(FEdit).Text; FTree.Text[FNode, FColumn] := S;
FTree.InvalidateNode(FNode); FEdit.Hide; FTree.SetFocus;
end;
function TStringEditLink.GetBounds: TRect; begin
Result := FEdit.BoundsRect;
end;
function TStringEditLink.PrepareEdit(Tree: TBaseVirtualTree; Node: PVirtualNode; Column: TColumnIndex): Boolean; begin
Result := True; FTree := Tree as TVirtualStringTree; FNode := Node; FColumn := Column;
FEdit.Free; FEdit := nil;
FEdit := TComboBox.Create(nil); with FEdit as TComboBox do begin Visible := False; Parent := Tree; Items.Add('Google'); Items.Add('Yahoo'); Items.Add('Altavista'); OnKeyDown := EditKeyDown; end;
end;
procedure TStringEditLink.ProcessMessage(var Message: TMessage); begin
FEdit.WindowProc(Message);
end;
procedure TStringEditLink.SetBounds(R: TRect); var
Dummy: Integer;
begin
FTree.Header.Columns.GetColumnBounds(FColumn, Dummy, R.Right); FEdit.BoundsRect := R;
end;
End.</delphi>
- 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.
- Switch to Object Inspector's Events tab. Scroll to OnCreateEditor, double click and paste:
<delphi>procedure TForm1.VSTCreateEditor(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; out EditLink: IVTEditLink);
begin
EditLink:=TStringEditLink.Create;
end;</delphi>
- On Object Inspector's Events tab. Scroll to OnNewText, double click and paste:
<delphi>procedure TForm1.VSTNewText(Sender: TBaseVirtualTree; Node: PVirtualNode;
Column: TColumnIndex; NewText: WideString);
Var
Data: PTreeData;
begin
Data := VST.GetNodeData(Node); Case Column of 0: Data^.Column0:= NewText; 1: Data^.Column1:= NewText; 2: Data^.Column2:= NewText; End;
end;</delphi> Run program, select a node and press F2 to get combobox. On pressing Enter new value should appear on the node.
If Cell Editing Can't Be Seen
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: <delphi>function TStringEditLink.BeginEdit: Boolean; stdcall;
// Notifies the edit link that editing can start now. Descentants may cancel node edit // by returning False.
begin
Result := not FStopping; if Result then begin FEdit.Show; FEdit.SelectAll; FEdit.SetFocus; end;
end;</delphi>
Now add "FEdit.Height:=18;". It should look like:
<delphi>function TStringEditLink.BeginEdit: Boolean; stdcall;
// Notifies the edit link that editing can start now. Descentants may cancel node edit // by returning False.
begin
Result := not FStopping; if Result then begin FEdit.Show; FEdit.SelectAll; FEdit.SetFocus; FEdit.Height:=18; // <--- Added this line. end;
end;</delphi>
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.
External links
- Programando en Pascal - Spanish tutorial focused on FPC/Lazarus, hosted in Wikibooks.
(In progress)
[En desarrollo]