Sign in Join
Wiki copytemporary

TTreeView: what changed

Revision 2 to 3. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
1-A **TTreeView** ![](/wiki-images/a/a3/Ttreeview.png) is a graphical control element that presents a hierarchical view of information. Each item can have a number of subitems.
1+A **TTreeView** [![ttreeview.png](/wiki-images/c/cd/ttreeview.png)](</File:ttreeview.png>) is a graphical control element that presents a hierarchical view of information. Each item can have a number of subitems.
22
3-An item can be expanded to reveal subitems, if any exist, and collapsed to hide subitems.
3+An item can be expanded to reveal subitems, if any exist, and collapsed to hide subitems.
44
55## A Short example of using TTreeview
66
7-Here is a simple example:
7+Here is a simple example:
88
9-- Create a new application.
10-- Add an empty treeview to the form, a button1 with caption "Add Child" and a button2 with caption "Delete"
11-- Assign the following code to the buttons' OnClick events. Compile and run.
9+ * Create a new application.
10+ * Add an empty treeview to the form, a button1 with caption "Add Child" and a button2 with caption "Delete"
11+ * Assign the following code to the buttons' OnClick events. Compile and run.
1212
13-``` pascal
13+```
1414procedure TForm1.Button1Click(Sender: TObject);
15-var
16- n: integer;
17- s: string;
18-begin
19- // If there are no nodes, create a root node with a parent of nil
20- if TreeView1.Items.Count = 0 then
21- begin
22- Treeview1.Items.Add(nil,'Root Node');
23- exit;
24- end;
25-
26- // Set up a simple text for each new node - "Node1", "Node2" etc
27- n := Treeview1.Items.Count;
28- s := 'Node ' + IntToStr(n);
29-
30- // Add a new node to the currently selected node
31- if TreeView1.Selected <> nil then
32- Treeview1.Items.AddChild(Treeview1.Selected, s);
33-end;
34-
35-procedure TForm1.Button2Click(Sender: TObject);
36-
37- // A procedure to recursively delete nodes
38- procedure DeleteNode(ANode: TTreeNode);
39- begin
40- while ANode.HasChildren do
41- DeleteNode(ANode.GetLastChild);
42- TreeView1.Items.Delete(ANode);
43- end;
44-
45-begin
46- if TreeView1.Selected = nil then
47- exit;
48-
49- // If the selected node has child nodes, first ask for confirmation
50- if Treeview1.Selected.HasChildren then
51- if MessageDlg('Delete node and all children?', mtConfirmation, [mbYes,mbNo], 0 ) <> mrYes then
52- exit;
53- DeleteNode(TreeView1.Selected);
54-end;
15+ var
16+ n: integer;
17+ s: string;
18+ begin
19+ // If there are no nodes, create a root node with a parent of nil
20+ if TreeView1.Items.Count = 0 then
21+ begin
22+ Treeview1.Items.Add(nil,'Root Node');
23+ exit;
24+ end;
25+
26+ // Set up a simple text for each new node - "Node1", "Node2" etc
27+ n := Treeview1.Items.Count;
28+ s := 'Node ' + IntToStr(n);
29+
30+ // Add a new node to the currently selected node
31+ if TreeView1.Selected <> nil then
32+ Treeview1.Items.AddChild(Treeview1.Selected, s);
33+ end;
34+
35+ procedure TForm1.Button2Click(Sender: TObject);
36+
37+ // A procedure to recursively delete nodes
38+ procedure DeleteNode(ANode: TTreeNode);
39+ begin
40+ while ANode.HasChildren do
41+ DeleteNode(ANode.GetLastChild);
42+ TreeView1.Items.Delete(ANode);
43+ end;
44+
45+ begin
46+ if TreeView1.Selected = nil then
47+ exit;
48+
49+ // If the selected node has child nodes, first ask for confirmation
50+ if Treeview1.Selected.HasChildren then
51+ if MessageDlg('Delete node and all children?', mtConfirmation, [mbYes,mbNo], 0 ) <> mrYes then
52+ exit;
53+ DeleteNode(TreeView1.Selected);
54+ end;
5555```
5656
57-When running, the treeview is empty. If you click "Add Child", a root node is created. After that a child will be added to any selected node by clicking "Add Child" again.
57+When running, the treeview is empty. If you click "Add Child", a root node is created. After that a child will be added to any selected node by clicking "Add Child" again.
5858
59-The "Delete" button will delete the currently selected node. If it doesn't have children, it will delete it immediately, but if it has children, it will first ask.
59+The "Delete" button will delete the currently selected node. If it doesn't have children, it will delete it immediately, but if it has children, it will first ask.
6060
6161## Adding a new item in code
6262
63-To add a sibling node to pre-existing node, use TTreeView.ITems.Add.
64-
65-``` pascal
66-TreeView1.Items.Add(ATreeNode, 'Added node');
63+To add a sibling node to pre-existing node, use TTreeView.ITems.Add.
6764```
68-
69-To add the first node, it becomes:
70-
71-``` pascal
72-TreeView1.Items.Add(nil, 'First node');
65+TreeView1.Items.Add(ATreeNode, 'Added node');
7366```
7467
75-Use TTreeView.Items.AddChild or AddChildObject to add child node.
68+To add the first node, it becomes:
69+```
70+TreeView1.Items.Add(nil, 'First node');
71+```
7672
77-``` pascal
73+Use TTreeView.Items.AddChild or AddChildObject to add child node.
74+```
7875TreeView1.Items.AddChild(ATreeNode, 'Child node');
7976```
8077
8178## Creating a TreeView which loads items only when expanding
8279
83-To add the expansion symbol to a node without subitems use:
84-
85-``` pascal
80+To add the expansion symbol to a node without subitems use:
81+```
8682MyNode.HasChildren := True;
8783```
8884
89-And then set an event handler for the OnExpanding event. In this even you should return if the expansion can actually be made or not and when yes, you should add subitems to the node. If the expansion cannot be done, the expansion symbol will be automatically removed even if you have previously set HasChildren to true.
85+And then set an event handler for the OnExpanding event. In this even you should return if the expansion can actually be made or not and when yes, you should add subitems to the node. If the expansion cannot be done, the expansion symbol will be automatically removed even if you have previously set HasChildren to true.
9086
9187## How to move a node in TTreeview
9288
93-Assuming you have UP and Down buttons to move the selected node in the TTreeview, these procedures will achieve moving the selected node.
94-
95-``` pascal
89+Assuming you have UP and Down buttons to move the selected node in the TTreeview, these procedures will achieve moving the selected node.
90+```
9691procedure TForm1.UpBtnClick(Sender: TObject);
97-begin
98- // Ensure a node is selected
99- if(Treeview1.Selected <> nil) then
100- // Ensure there is a previous sibling node
101- if Treeview1.Selected.GetPrevSibling <> nil then
102- // If we have made it this far, move it UP
103- Treeview1.Selected.MoveTo(Treeview1.Selected.GetPrevSibling, naInsert);
104-end;
105-
106-procedure TForm1.DownBtnClick(Sender: TObject);
107-begin
108- // Ensure a node is selected
109- if(Treeview1.Selected <> nil) then
110- // Ensure there is a next sibling node
111- if Treeview1.Selected.GetNextSibling <> nil then
112- // If we have made it this far, move it DOWN
113- Treeview1.Selected.MoveTo(Treeview1.Selected.GetNextSibling, naInsertBehind);
114-end;
92+ begin
93+ // Ensure a node is selected
94+ if(Treeview1.Selected <> nil) then
95+ // Ensure there is a previous sibling node
96+ if Treeview1.Selected.GetPrevSibling <> nil then
97+ // If we have made it this far, move it UP
98+ Treeview1.Selected.MoveTo(Treeview1.Selected.GetPrevSibling, naInsert);
99+ end;
100+
101+ procedure TForm1.DownBtnClick(Sender: TObject);
102+ begin
103+ // Ensure a node is selected
104+ if(Treeview1.Selected <> nil) then
105+ // Ensure there is a next sibling node
106+ if Treeview1.Selected.GetNextSibling <> nil then
107+ // If we have made it this far, move it DOWN
108+ Treeview1.Selected.MoveTo(Treeview1.Selected.GetNextSibling, naInsertBehind);
109+ end;
115110```
116111
117-Note: These procedures will only move nodes which are at the same level in the TTreeview.
118-
119-<thead>
120-
121-</thead>
122-<tbody>
123-
124-</tbody>
112+Note: These procedures will only move nodes which are at the same level in the TTreeview.
125113
114+Table of attachment mode of Nodes
115+---
116+Mode | Effect
117+naAdd | add as last sibling of target node
118+naAddFirst | add as first sibling of target node
119+naAddChild | add as last child of target node
120+naAddChildFirst | add as first child of target node
121+naInsert | insert in front of target node
122+naInsertBehind | insert behind target node
123+
126124## Using multiple node selection
127125
128-To allow multiple selection, you need to set the `tvoAllowMultiSelect` flag of the `Options` property. This will allow you to select additional nodes by `Ctrl`+`Mouse click`.
129-
130-To get a list of selected nodes from code, you can use the `TreeView1.Selections` property:
126+To allow multiple selection, you need to set the `tvoAllowMultiSelect` flag of the `Options` property. This will allow you to select additional nodes by `Ctrl`+`Mouse click`.
131127
132-``` pascal
128+To get a list of selected nodes from code, you can use the `TreeView1.Selections` property:
129+```
133130procedure TForm1.Button1Click(Sender: TObject);
134-var
135- i: integer;
136-begin
137- Memo1.Lines.Clear;
138- for i := 0 to TreeView1.SelectionCount - 1 do
139- Memo1.Lines.Add(TreeView1.Selections[i].GetTextPath);
140-end;
131+ var
132+ i: integer;
133+ begin
134+ Memo1.Lines.Clear;
135+ for i := 0 to TreeView1.SelectionCount - 1 do
136+ Memo1.Lines.Add(TreeView1.Selections[i].GetTextPath);
137+ end;
141138```
142139
143140## Freeing TreeNode Data
144141
145-Use the TreeView's OnDeletion event to free your object.
146-
147-``` pascal
142+Use the TreeView's OnDeletion event to free your object.
143+```
148144procedure TForm1.TreeView1Deletion(Sender: TObject; Node: TTreeNode);
149-begin
150- TMyObject(Node.Data).Free;
151- Node.Data := nil;
152-end;
145+ begin
146+ TMyObject(Node.Data).Free;
147+ Node.Data := nil;
148+ end;
153149```
154150
155151## Using Drag and Drop in a TreeView
156152
157-If you want to allow a drag and drop function in your treeview, you need to :
158-
159-1. Set to DmAutomatic, the property "Drag Mode" of your treeview
160-2. Create events for `onDragDrop` and `OnDragOver`:
161-
162-``` pascal
163-...
153+If you want to allow a drag and drop function in your treeview, you need to :
164154
165-Var
166- Node: TTreeNode;
155+ 1. Set to DmAutomatic, the property "Drag Mode" of your treeview
156+ 2. Create events for `onDragDrop` and `OnDragOver`:
167157
158+```
168159...
169-
170-procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
171-begin
172- Treeview1 := TTreeView(Sender); { Sender is TreeView where the data is being dropped }
173- Node := Treeview1.GetNodeAt(x,y); { x,y are drop coordinates (relative to the Sender) }
174- { since Sender is TreeView we can evaluate }
175- { a tree at the X,Y coordinates }
176- if Source = Sender then { drop is happening within a TreeView }
160+
161+ Var
162+ Node: TTreeNode;
163+
164+ ...
165+
166+ procedure TForm1.TreeView1DragDrop(Sender, Source: TObject; X, Y: Integer);
177167 begin
178- if Assigned(Treeview1.Selected) and { check if any node has been selected }
179- (Node <> Treeview1.Selected) then { and we're dropping to another node }
180- begin
181- if Node <> nil then
182- Treeview1.Selected.MoveTo(Node, naAddChild) { complete drop, by moving selected node }
183- else
184- Treeview1.Selected.MoveTo(Node, naAdd); { complete drop, by moving selected node in root }
185- end;
168+ Treeview1 := TTreeView(Sender); { Sender is TreeView where the data is being dropped }
169+ Node := Treeview1.GetNodeAt(x,y); { x,y are drop coordinates (relative to the Sender) }
170+ { since Sender is TreeView we can evaluate }
171+ { a tree at the X,Y coordinates }
172+ if Source = Sender then { drop is happening within a TreeView }
173+ begin
174+ if Assigned(Treeview1.Selected) and { check if any node has been selected }
175+ (Node <> Treeview1.Selected) then { and we're dropping to another node }
176+ begin
177+ if Node <> nil then
178+ Treeview1.Selected.MoveTo(Node, naAddChild) { complete drop, by moving selected node }
179+ else
180+ Treeview1.Selected.MoveTo(Node, naAdd); { complete drop, by moving selected node in root }
181+ end;
182+ end;
186183 end;
187-end;
188-
189-procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
190-begin
191- Accept := true;
192-end;
184+
185+ procedure TForm1.TreeView1DragOver(Sender, Source: TObject; X, Y: Integer; State: TDragState; var Accept: Boolean);
186+ begin
187+ Accept := true;
188+ end;
193189```
194190
195191## Comments on Events
196192
197-Event handlers are convenient places for developing LCL applications. There are some peculiar events for TTreeview.
193+Event handlers are convenient places for developing LCL applications. There are some peculiar events for TTreeview.
198194
199195**When selected node is changed**
200-
201-``` pascal
196+```
202197procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
203198```
204199
205-The `OnChange` event is fired when another node is selected. It can be used in a program to update some data.
206-
207-``` pascal
200+The `OnChange` event is fired when another node is selected. It can be used in a program to update some data.
201+```
208202procedure TForm1.TreeView1Changing(Sender: TObject; Node: TTreeNode; var AllowChange: Boolean);
209203```
210204
211-The `OnChanging` event is called before `OnChange`, which allows you to prevent node selection under certain conditions. To do this, just set `AllowChange` to `false`. It is not necessary to set to `true` as this is the default value.
205+The `OnChanging` event is called before `OnChange`, which allows you to prevent node selection under certain conditions. To do this, just set `AllowChange` to `false`. It is not necessary to set to `true` as this is the default value.
212206
213-Please note that in Delphi the `Node` variable points to the node that leaves the selection. In Lazarus, the `Node` variable points to the node receiving the selection, but you can use the `Selected` property to find out the "previous" node.
207+Please note that in Delphi the `Node` variable points to the node that leaves the selection. In Lazarus, the `Node` variable points to the node receiving the selection, but you can use the `Selected` property to find out the "previous" node.
214208
215-In both events, the `Node` and `Selected` can be equal to `nil` (if there was no selection or it is being removed).
209+In both events, the `Node` and `Selected` can be equal to `nil` (if there was no selection or it is being removed).
216210
217211**When a node is inserted**
218212
219-When a new node is inserted, related events occur in the following order.
220-
221-```text
222- 1) OnNodeChanged
223- 2) (OnChanging): This is called if there was a previously selected node.
224- 3) OnSelectionChanged
225- 4) OnChange
213+When a new node is inserted, related events occur in the following order.
226214```
215+1) OnNodeChanged
216+ 2) (OnChanging): This is called if there was a previously selected node.
217+ 3) OnSelectionChanged
218+ 4) OnChange
219+```
227220
228221**When deleting a node**
229222
230-When the selected node is deleted, the following events occur.
231-
232-```text
233- 1) OnDelete
234- 2) OnChanging
235- 3) SelectionChanged
236- 4) OnChange : This is called because when you delete a node, another node is selected.
223+When the selected node is deleted, the following events occur.
237224```
225+1) OnDelete
226+ 2) OnChanging
227+ 3) SelectionChanged
228+ 4) OnChange : This is called because when you delete a node, another node is selected.
229+```
238230
239-If an unselected node is deleted, e.g. programmatically, then only the OnDelete event handler is called.
231+If an unselected node is deleted, e.g. programmatically, then only the OnDelete event handler is called.
240232
241233**When Form is Closed**
242234
243-OnChanging event occurs, as the selected node is "de"selected. But OnChanging eventhander is executed AFTER the form is closed. This means that you cannot access the form's other data (other controls, other variables, etc.) within the OnChanging event handler procedure.
235+OnChanging event occurs, as the selected node is "de"selected. But OnChanging eventhander is executed AFTER the form is closed. This means that you cannot access the form's other data (other controls, other variables, etc.) within the OnChanging event handler procedure.
244236
245-**When Drag&Drop is done**
237+**When Drag &Drop is done**
246238
247-When you drag a node to another node and drop, the following events occur.
239+When you drag a node to another node and drop, the following events occur.
240+```
241+1) OnSelectionChanged
242+ 2) OnNodeChanged
243+ 3) OnChange
244+```
248245
249-```text
250- 1) OnSelectionChanged
251- 2) OnNodeChanged
252- 3) OnChange
246+## Painting of the TreeView
247+
248+The treeview can draw itself in three ways:
249+
250+ * **Themed painting** (default) is done by dedicated, theme-specific drawing routines of the operating system/widgetset. You have litte control over the appearance of the tree (mostly the colors), but it looks consistently across applications, in particular concerning selection and hot-tracking.
251+ * **Non-themed painting** is activated by removing the element `tvoThemedDraw` from the treeview's `Options` property. It gives you more control over the drawing process. For example, you can set the color of the selection background (`SelectionColor`) and text (`SelectionFontColor`), or the color of the hot-tracked node text (`HotTrackColor`).
252+ * **Custom painting** gives you full control over the drawing process by providing handlers for specific events. Depending on the return value of the event parameter `DefaultDraw`, you can determine whether you want to draw everything yourself (`DefaultDraw = false`) or whether you still want to use the built-in routines, but use different parameters that you specify in the event handler (`DefaultDraw = true`).
253+
254+Basically the drawing process of the treeview consists of two phases:
255+
256+ * Drawing of the **background** : You can custom-draw the background by providing a handler for the `OnCustomDraw` and/or `OnAdvancedCustomDraw` events.
257+ * Drawing of the **individual tree nodes** over this background: You can custom-draw the nodes by providing a handler for the `OnCustomDrawItem` and/or `OnAdvancedCustomDrawItem` events.
258+
259+The "advanced" events are fired several times during the painting process. There is a `Stage` parameter which signals what is happening at the moment. It is an enumeration of the following elements:
260+
261+ * `cdPrePaint` and `cdPostPaint` are set by the `OnAdvancedCustomDraw` and `OnAdvancedCustomDrawItem` events before any drawing action begins (`cdPrePaint`) / after drawing has been completed (`cdPostPaint`), respectively. Be careful when setting `DefaultDraw` to `false` here because the drawing procedure will be left after the event handler - it is assumed that you had done all the following steps yourself.
262+ * `cdPreErase` and `cdPostErase` have not been used for a long time (also in Delphi). But they were implemented in Lazarus v4.99 to get more control over the custom drawing process of the nodes in the `OnAdvancedCustomDrawItem` event:
263+ * `cdPreErase` is set in `OnAdvancedCustomDrawItem` before the normal background of a tree node is painted.
264+ * `cdPostErase` is set in`OnAdvancedCustomDrawItem` before the background and the text of a selected or hot-tracked node is painted.
265+
266+They still are not used by the `OnAdvancedCustomDraw` event.
267+
268+In contrast to `cdPrePaint`, setting `DefaultDraw` to `false` here only inhibits painting of the background of the current node.
269+
270+The `OnCustomDraw*` events are equivalent to the "advanced" events in the `cdPrePaint` stage.
271+
272+### Example: Custom-painting a treeview with a background gradient
273+
274+The gradient must be painted at the very beginning of the drawing cyle, i.e. we must provide a handler for the `OnAdvancedCustomDraw` event at the `cdPrePaint` stage:
253275```
276+procedure TForm1.BackgroundGradient_AdvancedCustomDraw(Sender: TCustomTreeView;
277+ const ARect: TRect; Stage: TCustomDrawStage; var DefaultDraw: Boolean);
278+ begin
279+ if Stage = cdPrePaint then
280+ begin
281+ // Draw the gradient (sky-blue at the top, to white at the bottom)
282+ Sender.Canvas.GradientFill(ARect, clSkyBlue, clWhite, gdVertical);
283+ // Avoid painting the normal background below the last node
284+ Sender.Canvas.Brush.Color := clNone;
285+ end;
286+ // We must not set DefaultDraw to false here because the CustomDraw
287+ // PrePaint stage would force us to paint everything by ourselves.
288+ end;
289+```
254290
291+However, that's not all because when the default painting routine of the node background is executed the gradient is overwritten by the node rectangle over the entire tree width. Therefore we must inhibit drawing of the normal background in `OnAdvancedCustomDrawItem` in the `cdPreErase` stage:
292+```
293+procedure TMainForm.BackgroundGradient_AdvancedCustomDrawItem(Sender: TCustomTreeView;
294+ Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
295+ var PaintImages, DefaultDraw: Boolean);
296+ begin
297+ if Stage = cdPreErase then
298+ // Avoid overwriting the gradient with the node background color
299+ DefaultDraw := false;
300+ end;
301+```
302+
303+When `tvoThemedDraw` is contained in the treeview's `Options`, this draws a themed treeview, but with gradient background. If you want to custom-draw also the selected and hot-tracked nodes you must remove `tovThemedDraw` from the `Options` and also set the corresponding canvas properties in the `cdPostErase` stage:
304+```
305+procedure TMainForm.BackgroundGradient_AdvancedCustomDrawItem(Sender: TCustomTreeView;
306+ Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage;
307+ var PaintImages, DefaultDraw: Boolean);
308+ begin
309+ case Stage of
310+ cdPreErase:
311+ // Avoid overwriting the gradient with the node background color
312+ DefaultDraw := false;
313+ cdPostErase:
314+ // Set selected and hot-track properties as usual
315+ if ([cdsFocused, cdsSelected] * State <> []) then // selected node
316+ begin
317+ Sender.Canvas.Brush.Color := clNavy;
318+ Sender.Canvas.Font.Color := clYellow;
319+ Sender.Canvas.Font.Style := [fsBold];
320+ end else
321+ if (cdsHot in State) then // hot-tracked node
322+ begin
323+ Sender.Canvas.Brush.Color := clGray;
324+ Sender.Canvas.Font.Color := clHighlightText;
325+ Sender.Canvas.Font.Style := [];
326+ end else // normal node
327+ // Setting Brush.Color to clNone inhibits drawing the rectangle for the normal nodes.
328+ // Don't use Sender.Canvas.BrushStyle = bsClear because it will be reset by changing the brush color.
329+ Sender.Canvas.Brush.Color := clNone;
330+ end;
331+ end;
332+```
333+
334+All this looks rather complicated... Yes, it is. Therefore, you can find more worked-out examples in the demo project in the _examples/treeview/customdrawing_ folder of the Lazarus installation.
335+
336+## Saving and loading a TTreeView
337+
338+Using TTreeView's method SaveTFile (or SaveToStream) you can save the Items of a TTreeView.
339+Notice that this will save only the Text of each Item in a plain text format.
340+A file (or stream) created as such, can be loaded using the LoadFromFile (or LoadFromStream) method.
341+
342+As of Lazarus 4.99 you can use the procedures in the TreeStorage unit to save and restore the items of a TTreeView along with most of the item's properties.
343+By default it will save the properties `Expanded`, `Selected`, `Focused`, `Visible`, `Enabled`, `ImageIndex`, `SelectedIndex`, `StateIndex` and `tsoOverlayIndex`.
344+You can supply a callback event to these procedures to load (and save) arbitrary data.
345+The example below saves the contents of a TTreeView into a stream and shows the stream in a TSynEdit with additional information using a callback event.
346+
347+```
348+uses
349+ ..., TreeStorage, Laz2_Dom, ...
350+
351+ function DbgS(AGraphicsDrawEffect: TGraphicsDrawEffect): String; overload;
352+ begin
353+ WriteStr(Result, AGraphicsDrawEffect);
354+ end;
355+
356+ procedure TForm1.WriteCallBack(ATreeNode: TTreeNode; ADomNode: TDomNode);
357+ begin
358+ TDomElement(ADomNode).Attribute['NodeEffect'] := Dbgs(ATreeNode.NodeEffect)
359+ end;
360+
361+ procedure TForm1.Button2Click(Sender: TObject);
362+ var
363+ F: TextFile;
364+ S: String;
365+ Str: TMemoryStream;
366+ begin
367+ Str := TMemoryStream.Create;
368+ try
369+ TreeStorage.TreeSaveToXML(TreeView1, Str, TreeItemStorageDefaultOptions, @WriteCallBack);
370+ Str.Position := 0;
371+ SynEdit1.Lines.LoadFromStream(Str);
372+ finally
373+ Str.Free;
374+ end;
375+ end;
376+```
377+
255378## See also
256379
257-- [[Drag and Drop sample]]
258-- [[doc:/lcl/comctrls/ttreeview.html|TTreeView doc]]
259-- [[TListView]]
260-- [[VirtualTreeview]]
380+ * [[Drag and Drop sample]]
381+ * [ TTreeView doc](<http://lazarus-ccr.sourceforge.net/docs//lcl/comctrls/ttreeview.html> "doc:/lcl/comctrls/ttreeview.html")
382+ * [[TListView]]
383+ * [[VirtualTreeview]]
261384
385+
386+
387+[[LCL Components]] Component Tab | Components
388+---|---
389+[[Standard tab|Standard]] | [[TMainMenu]] • [[TPopupMenu]] • [[TButton]] • [[TLabel]] • [[TEdit]] • [[TMemo]] • [[TToggleBox]] • [[TCheckBox]] • [[TRadioButton]] • [[TListBox]] • [[TComboBox]] • [[TScrollBar]] • [[TGroupBox]] • [[TRadioGroup]] • [[TCheckGroup]] • [[TPanel]] • [[TFrame]] • [[TActionList]]
390+[[Additional tab|Additional]] | [[TBitBtn]] • [[TSpeedButton]] • [[TStaticText]] • [[TImage]] • [[TShape]] • [[TBevel]] • [[TPaintBox]] • [[TNotebook]] • [[TLabeledEdit]] • [[TSplitter]] • [[TTrayIcon]] • [[TControlBar]] • [[TFlowPanel]] • [[TMaskEdit]] • [[TCheckListBox]] • [[TScrollBox]] • [[TApplicationProperties]] • [[TStringGrid]] • [[TDrawGrid]] • [[TPairSplitter]] • [[TColorBox]] • [[TColorListBox]] • [[TValueListEditor]]
391+[[Common Controls tab|Common Controls]] | [[TTrackBar]] • [[TProgressBar]] • TTreeView • [[TListView]] • [[TStatusBar]] • [[TToolBar]] • [[TCoolBar]] • [[TUpDown]] • [[TPageControl]] • [[TTabControl]] • [[THeaderControl]] • [[TImageList]] • [[TPopupNotifier]] • [[TDateTimePicker]]
392+[[Dialogs tab|Dialogs]] | [[TOpenDialog]] • [[TSaveDialog]] • [[TSelectDirectoryDialog]] • [[TColorDialog]] • [[TFontDialog]] • [[TFindDialog]] • [[TReplaceDialog]] • [[TTaskDialog]] • [[TOpenPictureDialog]] • [[TSavePictureDialog]] • [[TCalendarDialog]] • [[TCalculatorDialog]] • [[TPrinterSetupDialog]] • [[TPrintDialog]] • [[TPageSetupDialog]]
393+[[Data Controls tab|Data Controls]] | [[TDBNavigator]] • [[TDBText]] • [[TDBEdit]] • [[TDBMemo]] • [[TDBImage]] • [[TDBListBox]] • [[TDBLookupListBox]] • [[TDBComboBox]] • [[TDBLookupComboBox]] • [[TDBCheckBox]] • [[TDBRadioGroup]] • [[TDBCalendar]] • [[TDBGroupBox]] • [[TDBGrid]] • [[TDBDateTimePicker]]
394+[[Data Access tab|Data Access]] | [[TDataSource]] • [[TCSVDataSet]] • [[TSdfDataSet]] • [[TBufDataset]] • [[TFixedFormatDataSet]] • [[TDbf]] • [[TMemDataset]]
395+[[System tab|System]] | [[TTimer]] • [[TIdleTimer]] • [[TLazComponentQueue]] • [[THTMLHelpDatabase]] • [[THTMLBrowserHelpViewer]] • [[TAsyncProcess]] • [[TProcessUTF8]] • [[TProcess]] • [[TSimpleIPCClient]] • [[TSimpleIPCServer]] • [[TXMLConfig]] • [[TEventLog]] • [[TServiceManager]] • [[TCHMHelpDatabase]] • [[TLHelpConnector]]
396+[[Misc tab|Misc]] | [[TColorButton]] • [[TSpinEdit]] • [[TFloatSpinEdit]] • [[TArrow]] • [[TCalendar]] • [[TEditButton]] • [[TFileNameEdit]] • [[TDirectoryEdit]] • [[TDateEdit]] • [[TTimeEdit]] • [[TCalcEdit]] • [[TFileListBox]] • [[TFilterComboBox]] • [[TComboBoxEx]] • [[TCheckComboBox]] • [[TButtonPanel]] • [[TShellTreeView]] • [[TShellListView]] • [[TXMLPropStorage]] • [[TINIPropStorage]] • [[TJSONPropStorage]] • [[TIDEDialogLayoutStorage]] • [[TMRUManager]] • [[TStrHolder]]
397+[[LazControls tab|LazControls]] | [[TCheckBoxThemed]] • [[TDividerBevel]] • [[TExtendedNotebook]] • [[TListFilterEdit]] • [[TListViewFilterEdit]] • [[TLvlGraphControl]] • [[TShortPathEdit]] • [[TSpinEditEx]] • [[TFloatSpinEditEx]] • [[TTreeFilterEdit]] • [[TExtendedTabControl]] •
398+[[RTTI tab|RTTI]] | [[TTIEdit]] • [[TTIComboBox]] • [[TTIButton]] • [[TTICheckBox]] • [[TTILabel]] • [[TTIGroupBox]] • [[TTIRadioGroup]] • [[TTICheckGroup]] • [[TTICheckListBox]] • [[TTIListBox]] • [[TTIMemo]] • [[TTICalendar]] • [[TTIImage]] • [[TTIFloatSpinEdit]] • [[TTISpinEdit]] • [[TTITrackBar]] • [[TTIProgressBar]] • [[TTIMaskEdit]] • [[TTIColorButton]] • [[TMultiPropertyLink]] • [[TTIPropertyGrid]] • [[TTIGrid]]
399+[[SQLdb tab|SQLdb]] | [[TSQLQuery]] • [[TSQLTransaction]] • [[TSQLScript]] • [[TSQLConnector]] • [[TMSSQLConnection]] • [[TSybaseConnection]] • [[TPQConnection]] • [[TPQTEventMonitor]] • [[TOracleConnection]] • [[TODBCConnection]] • [[TMySQL40Connection]] • [[TMySQL41Connection]] • [[TMySQL50Connection]] • [[TMySQL51Connection]] • [[TMySQL55Connection]] • [[TMySQL56Connection]] • [[TMySQL57Connection]] • [[TSQLite3Connection]] • [[TIBConnection]] • [[TFBAdmin]] • [[TFBEventMonitor]] • [[TSQLDBLibraryLoader]]
400+[[Pascal Script tab|Pascal Script]] | [[TPSScript]] • [[TPSScriptDebugger]] • [[TPSDllPlugin]] • [[TPSImport Classes]] • [[TPSImport DateUtils]] • [[TPSImport ComObj]] • [[TPSImport DB]] • [[TPSImport Forms]] • [[TPSImport Controls]] • [[TPSImport StdCtrls]] • [[TPSCustomPlugin]]
401+[[SynEdit tab|SynEdit]] | [[TSynEdit]] • [[TSynCompletion]] • [[TSynAutoComplete]] • [[TSynMacroRecorder]] • [[TSynExporterHTML]] • [[TSynPluginSyncroEdit]] • [[TSynPasSyn]] • [[TSynFreePascalSyn]] • [[TSynCppSyn]] • [[TSynJavaSyn]] • [[TSynPerlSyn]] • [[TSynHTMLSyn]] • [[TSynXMLSyn]] • [[TSynLFMSyn]] • [[TSynDiffSyn]] • [[TSynUNIXShellScriptSyn]] • [[TSynCssSyn]] • [[TSynPHPSyn]] • [[TSynTeXSyn]] • [[TSynSQLSyn]] • [[TSynPythonSyn]] • [[TSynVBSyn]] • [[TSynAnySyn]] • [[TSynMultiSyn]] • [[TSynBatSyn]] • [[TSynIniSyn]] • [[TSynPoSyn]]
402+[[Chart tab|Chart]] | [[TChart]] • [[TListChartSource]] • [[TRandomChartSource]] • [[TUserDefinedChartSource]] • [[TCalculatedChartSource]] • [[TDbChartSource]] • [[TChartToolset]] • [[TChartAxisTransformations]] • [[TChartStyles]] • [[TChartLegendPanel]] • [[TChartNavScrollBar]] • [[TChartNavPanel]] • [[TIntervalChartSource]] • [[TDateTimeIntervalChartSource]] • [[TChartListBox]] • [[TChartExtentLink]] • [[TChartImageList]]
403+[[IPro tab|IPro]] | [[TIpFileDataProvider]] • [[TIpHtmlDataProvider]] • [[TIpHttpDataProvider]] • [[TIpHtmlPanel]]
404+[[Virtual Controls tab|Virtual Controls]] | [[TVirtualDrawTree]] • [[TVirtualStringTree]] • [[TVTHeaderPopupMenu]]
405+
262406---
263-*From the Free Pascal wiki, page "TTreeView", as it stood on 2024-02-24 after a change by N7800, 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).*
407+*From the Free Pascal wiki, page "TTreeView", as the Internet Archive kept it on 2025-06-16, last changed on 2025-05-17. 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).*

Back to history