TTreeView
Hierarchical tree control with expand/collapse, checkboxes, drag-drop, and label editing
Source: source/classes/ttreevie.prg, source/classes/treeitem.prg | Parent: TControl
Overview
TTreeView wraps the Windows SysTreeView32 common control. It displays data in a hierarchical tree structure where each node can have child nodes. Nodes can be expanded/collapsed, support icons via image lists, optional checkboxes, in-place label editing, and drag-and-drop reordering.
Architecture
graph TD
TV["TTreeView
(SysTreeView32)"] TV --> ITEMS["aItems[]
Top-level TVItem nodes"] TV --> IMGLIST["oImageList
Node icons"] ITEMS --> I1["TVItem: Project"] ITEMS --> I2["TVItem: Libraries"] I1 --> I1A["TVItem: Source"] I1 --> I1B["TVItem: Resources"] I1A --> I1A1["TVItem: main.prg"] I1A --> I1A2["TVItem: utils.prg"] I2 --> I2A["TVItem: fiveh.lib"] I2 --> I2B["TVItem: fivehc.lib"] style TV fill:#1c2129,stroke:#58a6ff,stroke-width:2px,color:#e6edf3 style I1 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3 style I2 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3
(SysTreeView32)"] TV --> ITEMS["aItems[]
Top-level TVItem nodes"] TV --> IMGLIST["oImageList
Node icons"] ITEMS --> I1["TVItem: Project"] ITEMS --> I2["TVItem: Libraries"] I1 --> I1A["TVItem: Source"] I1 --> I1B["TVItem: Resources"] I1A --> I1A1["TVItem: main.prg"] I1A --> I1A2["TVItem: utils.prg"] I2 --> I2A["TVItem: fiveh.lib"] I2 --> I2B["TVItem: fivehc.lib"] style TV fill:#1c2129,stroke:#58a6ff,stroke-width:2px,color:#e6edf3 style I1 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3 style I2 fill:#1c2129,stroke:#3fb950,stroke-width:1px,color:#e6edf3
TVItem -- Tree Node
Source: source/classes/treeitem.prg
Each node in the tree is a TVItem object (internally called TTreeItem in the Win32 version). Items form a linked list with oPrev/oNext pointers and can contain a sub-tree of children.
| Property | Type | Description |
|---|---|---|
cPrompt | String | Text label displayed for this node |
hItem | Handle | Win32 handle for this tree item |
nLevel | Numeric | Depth level in the tree (root = 0 or 1) |
lOpened | Logical | Whether the node is expanded |
oTree | Object | Sub-tree object (children container) |
oPrev / oNext | Object | Previous and next sibling items |
bAction | Block | Action when this item is activated |
Cargo | Any | User data attached to the item |
Value | Any | Item value (via ACCESS/ASSIGN, uses bSetGet) |
hBmpOpen / hBmpClose | Handle | Bitmap handles for expanded/collapsed states |
TVItem Methods
| Method | Description |
|---|---|
Open() / Close() | Expand or collapse this node |
Toggle() | Toggle expand/collapse state |
SetText( cPrompt ) | Change the item label |
GetNext() / GetPrev() | Navigate to next/previous visible item |
Add( cPrompt ) | Add a sibling item after this one |
AddChild( ocItem, lFirst ) | Add a child item to this node |
Delete( oRoot ) | Remove this item from the tree |
Skip( n ) | Navigate n items forward or backward |
MakeVisible() | Scroll the tree so this item is visible |
MoveUp( oRoot ) / MoveDown( oRoot ) | Reorder this item among its siblings |
Promote() / Demote() | Change item level (outdent/indent) |
Sort( oRoot, lAsc, lRecurs ) | Sort children alphabetically |
Parent( nParent ) | Get the parent item at a specific level |
IsVisible() | Whether the item is currently visible in the tree |
TTreeView Properties
| Property | Type | Description |
|---|---|---|
aItems | Array | Array of top-level TVItem objects |
oImageList | Object | Image list for node icons |
bChanged | Block | Code block executed when the selected node changes |
bExpanded | Block | Code block executed when a node is expanded |
hEdit | Handle | Handle of the in-place edit control during label editing |
TTreeView Methods
| Method | Description |
|---|---|
New( nTop, nLeft, oWnd, nClrFore, nClrBack, lPixel, lDesign, nWidth, nHeight, cMsg, lCheckBoxes, bChange, lEditable ) | Constructor |
ReDefine( nId, oWnd, nClrFore, nClrBack, lDesign, cMsg, bChange ) | Redefine from resource |
Add( cPrompt, nImage, nValue ) | Add a top-level item with optional image and value |
InsertAfter( oItem, cPrompt, nImage, nValue ) | Insert an item after a specific node |
GetSelected() | Returns the currently selected TVItem |
GetSelText() | Returns the text of the selected item |
Select( oItem ) | Programmatically select an item |
SetSelText( cText ) | Change the text of the selected item |
DeleteAll() | Remove all items from the tree |
GoTop() / GoBottom() | Select the first or last item |
GoNext() / GoPrev() | Select the next or previous visible item |
Expand() | Expand all top-level items |
ExpandAll( oItem ) | Recursively expand all items |
CollapseAll( oItem ) | Recursively collapse all items |
ExpandBranch( oItem ) | Expand a specific branch and its children |
CollapseBranch( oItem ) | Collapse a specific branch |
Toggle() | Toggle expand/collapse of all top-level items |
ToggleAll( oItem ) | Toggle all items recursively |
EditLabel( oItem ) | Start in-place label editing on an item |
SetImageList( oImageList ) | Assign an image list for node icons |
SetColor( nClrText, nClrPane ) | Set tree text and background colors |
SetItemImage( oItem, nImage ) | Change the image of a specific item |
SetItemHeight( nHeight ) | Set the height of tree items |
GetCheck( oItem ) | Get the checkbox state of an item (requires CHECKBOXES) |
SetCheck( oItem, lOnOff ) | Set the checkbox state of an item |
HitTest( nRow, nCol ) | Determine which item is at screen coordinates |
SetItems( aItems ) | Populate the tree from an array |
Scan( bAction ) | Execute a code block for every item in the tree |
Count() | Total number of items (including children) |
Len() | Number of top-level items |
SwapUp() / SwapDown() | Swap the selected item with its sibling |
Rebuild() | Rebuild the Win32 tree from the internal item array |
GenMenu( lPopup ) | Generate a menu from the tree structure |
LoadFromMenu( oMenu ) | Populate the tree from a menu object |
Command Syntax
@ nRow, nCol TREEVIEW [ oTV ] ;
[ OF oWnd ] ;
[ SIZE nWidth, nHeight ] ;
[ COLOR nClrFore, nClrBack ] ;
[ PIXEL ] ;
[ ON CHANGE bChange ] ;
[ CHECKBOXES ] ;
[ EDITABLE ]
REDEFINE TREEVIEW [ oTV ] ;
ID nId ;
[ OF oWnd ] ;
[ COLOR nClrFore, nClrBack ] ;
[ ON CHANGE bChange ]
Tree Navigation Flow
stateDiagram-v2
[*] --> Root : Tree created
Root --> Expanded : User clicks [+]
Expanded --> ChildSelected : User clicks child
ChildSelected --> Expanded : User clicks [+] on child
Expanded --> Collapsed : User clicks [-]
Collapsed --> Root : All collapsed
ChildSelected --> Editing : EditLabel()
Editing --> ChildSelected : Enter / Escape
note right of Editing
hEdit control active
TVN_BEGINLABELEDIT
TVN_ENDLABELEDIT
end note
Code Examples
Example 1: File Browser Tree
#include "FiveWin.ch"
FUNCTION FileTreeDemo()
LOCAL oDlg, oTV, oImgList
LOCAL oRoot, oSrc, oRes
DEFINE DIALOG oDlg TITLE "Project Explorer" SIZE 400, 500
// Image list: folder and file icons
DEFINE IMAGELIST oImgList SIZE 16, 16
IMAGELIST ADD BITMAP oImgList NAME "FOLDER", "FILE"
@ 0.5, 0.5 TREEVIEW oTV OF oDlg ;
SIZE 190, 220 PIXEL ;
ON CHANGE { || ShowItemInfo( oTV ) }
oTV:SetImageList( oImgList )
// Build the tree
oRoot := oTV:Add( "MyProject", 0 ) // folder icon = 0
oSrc := oRoot:AddItem( "Source", 0 )
oSrc:AddItem( "main.prg", 1 ) // file icon = 1
oSrc:AddItem( "utils.prg", 1 )
oSrc:AddItem( "database.prg", 1 )
oRes := oRoot:AddItem( "Resources", 0 )
oRes:AddItem( "main.rc", 1 )
oRes:AddItem( "icons.rc", 1 )
oTV:Add( "Libraries", 0 )
// Start expanded
oTV:ExpandAll()
@ 11, 1 BUTTON "Expand All" OF oDlg SIZE 60, 14 ;
ACTION oTV:ExpandAll()
@ 11, 7 BUTTON "Collapse All" OF oDlg SIZE 60, 14 ;
ACTION oTV:CollapseAll()
ACTIVATE DIALOG oDlg CENTERED
RETURN NIL
STATIC FUNCTION ShowItemInfo( oTV )
LOCAL oItem := oTV:GetSelected()
IF oItem != NIL
// oItem:cPrompt has the label
// oItem:Cargo can hold custom data
SayStatus( "Selected: " + oItem:cPrompt )
ENDIF
RETURN NIL
Example 2: Tree with Checkboxes
@ 0.5, 0.5 TREEVIEW oTV OF oDlg ;
SIZE 190, 220 PIXEL ;
CHECKBOXES
oTV:Add( "Option A" )
oTV:Add( "Option B" )
oTV:Add( "Option C" )
// Later, check which items are selected:
FOR n := 1 TO Len( oTV:aItems )
IF oTV:GetCheck( oTV:aItems[ n ] )
? "Checked:", oTV:aItems[ n ]:cPrompt
ENDIF
NEXT
Example 3: Editable Tree with Reordering
@ 0.5, 0.5 TREEVIEW oTV OF oDlg ;
SIZE 190, 220 PIXEL ;
EDITABLE ;
ON CHANGE { || UpdatePreview( oTV ) }
// Populate tree
oTV:Add( "Chapter 1" )
oTV:Add( "Chapter 2" )
oTV:Add( "Chapter 3" )
// Edit label of selected item
@ 11, 1 BUTTON "Rename" OF oDlg SIZE 50, 14 ;
ACTION oTV:EditLabel()
// Reorder items
@ 11, 5.5 BUTTON "Move Up" OF oDlg SIZE 50, 14 ;
ACTION oTV:SwapUp()
@ 11, 10 BUTTON "Move Down" OF oDlg SIZE 55, 14 ;
ACTION oTV:SwapDown()
Tips
- Use
Cargoon eachTVItemto store associated data (record IDs, file paths, etc.). - The
CHECKBOXESclause enables checkboxes on all items. UseGetCheck()/SetCheck()to manage state. - For large trees, populate children lazily in the
bExpandedcallback instead of loading everything at startup. - Call
Rebuild()after programmatic item manipulation (move, promote, demote) to sync the Win32 tree. Scan( bAction )traverses every item recursively -- useful for searching or collecting checked items.- Use
SetItemHeight()for larger touch-friendly tree items.
See Also
- TControl -- parent class
- TListView -- flat list with icons
- TMenu -- can be generated from/loaded into tree
- Resources (GDI) -- TImageList for node icons