TreeView

Table of Contents

Introduction and Simple Example

A Tree-View displays a hierarchy of items by indenting child items beneath their parents. The most common example is Explorer's tree of drives and folders.

The syntax for creating a TreeView is:

TV := Gui.Add("TreeView", Options)

Here is a working script that creates and displays a simple hierarchy of items:

Gui := GuiCreate()
TV := Gui.Add("TreeView")
P1 := TV.Add("First parent")
P1C1 := TV.Add("Parent 1's first child", P1)  ; Specify P1 to be this item's parent.
P2 := TV.Add("Second parent")
P2C1 := TV.Add("Parent 2's first child", P2)
P2C2 := TV.Add("Parent 2's second child", P2)
P2C2C1 := TV.Add("Child 2's first child", P2C2)

Gui.Show()  ; Show the window and its TreeView.

Options and Styles for the Options parameter

Background: Specify the word Background followed immediately by a color name (see color chart) or RGB value (the 0x prefix is optional). Examples: BackgroundSilver, BackgroundFFDD99. If this option is not present, the TreeView initially defaults to the system's default background color. Specifying BackgroundDefault or -Background applies the system's default background color (usually white). For example, a TreeView can be restored to the default color via TV.Opt("+BackgroundDefault").

Buttons: Specify -Buttons (minus Buttons) to avoid displaying a plus or minus button to the left of each item that has children.

C: Text color. Specify the letter C followed immediately by a color name (see color chart) or RGB value (the 0x prefix is optional). Examples: cRed, cFF2211, c0xFF2211, cDefault.

Checked: Provides a checkbox at the left side of each item. When adding an item, specify the word Check in its options to have the box to start off checked instead of unchecked. The user may either click the checkbox or press the spacebar to check or uncheck an item. To discover which items in a TreeView are currently checked, call TV.GetNext or TV.Get.

HScroll: Specify -HScroll (minus HScroll) to disable horizontal scrolling in the control (in addition, the control will not display any horizontal scroll bar).

ImageList: This is the means by which icons are added to a TreeView. Specify the word ImageList followed immediately by the ImageListID returned from a previous call to IL_Create. This option has an effect only when creating a TreeView (however, TV.SetImageList does not have this limitation). Here is a working example:

Gui := GuiCreate()
ImageListID := IL_Create(10)  ; Create an ImageList with initial capacity for 10 icons.
Loop 10  ; Load the ImageList with some standard system icons.
    IL_Add(ImageListID, "shell32.dll", A_Index)
TV := Gui.Add("TreeView", "ImageList%ImageListID%")
TV.Add("Name of Item", 0, "Icon4")  ; Add an item to the TreeView and give it a folder icon.
Gui.Show()

Lines: Specify -Lines (minus Lines) to avoid displaying a network of lines connecting parent items to their children. However, removing these lines also prevents the plus/minus buttons from being shown for top-level items.

ReadOnly: Specify -ReadOnly (minus ReadOnly) to allow editing of the text/name of each item. To edit an item, select it then press the F2 key. Alternatively, you can click an item once to select it, wait at least half a second, then click the same item again to edit it. After being edited, an item can be alphabetically repositioned among its siblings via the following example:

TV := Gui.Add("TreeView", "-ReadOnly")
TV.OnEvent("ItemEdit", "MyTree_Edit")  ; Call MyTree_Edit whenever a user has finished editing an item.
; ...
MyTree_Edit(TV, Item)
{
    TV.Modify(TV.GetParent(Item), "Sort")  ; This works even if the item has no parent.
}

R: Rows of height (upon creation). Specify the letter R followed immediately by the number of rows for which to make room inside the control. For example, R10 would make the control 10 items tall.

WantF2: Specify -WantF2 (minus WantF2) to prevent an F2 keystroke from editing the currently selected item. This setting is ignored unless -ReadOnly is also in effect.

(Unnamed numeric styles): Since styles other than the above are rarely used, they do not have names. See the TreeView styles table for a list.

Built-in Methods for TreeViews

Additionally to the default methods/properties of a GUI control, the following methods can be specified for a TreeView. If the associated GuiControl object does not exist or does not belongs to a TreeView, the TreeView methods throw an exception.

Add, Modify, and Delete Items

Add

Adds a new item to the TreeView, and returns its unique Item ID number.

UniqueID := TV.Add(Name, ParentItemID, Options)
Name
The displayed text of the item, which can be text or numeric (including numeric expression results).
ParentItemID
The ID number of the new item's parent (omit it or specify 0 to add the item at the top level).
Options

Contains zero or more words from the list below (not case sensitive). Separate each word from the next with a space or tab. To remove an option, precede it with a minus sign. To add an option, a plus sign is permitted but not required.

Bold: Displays the item's name in a bold font. To later un-bold the item, use TV.Modify(ItemID, "-Bold").

Check: Shows a checkmark to the left of the item (if the TreeView has checkboxes). To later uncheck it, use TV.Modify(ItemID, "-Check"). The word Check may optionally be followed immediately by a 0 or 1 to indicate the starting state. In other words, both "Check" and "Check" . VarContainingOne are the same (the period used here is the concatenation operator).

Expand: Expands the item to reveal its children (if any). To later collapse the item, use TV.Modify(ItemID, "-Expand"). If there are no children, TV.Modify returns 0 instead of the item's ID. By contrast, TV.Add marks the item as expanded in case children are added to it later. Unlike "Select" (below), expanding an item does not automatically expand its parent. Finally, the word Expand may optionally be followed immediately by a 0 or 1 to indicate the starting state. In other words, both "Expand" and "Expand" . VarContainingOne are the same.

First | Sort | N: These options apply only to TV.Add. They specify the new item's position relative to its siblings (a sibling is any other item on the same level). If none of these options is present, the new item is added as the last/bottom sibling. Otherwise, specify First to add the item as the first/top sibling, or specify Sort to insert it among its siblings in alphabetical order. If a plain integer (N) is specified, it is assumed to be ID number of the sibling after which to insert the new item (if integer N is the only option present, it does not have to be enclosed in quotes).

Icon: Specify the word Icon followed immediately by the number of this item's icon, which is displayed to the left of the item's name. If this option is absent, the first icon in the ImageList is used. To display a blank icon, specify a number that is larger than the number of icons in the ImageList. If the control lacks an ImageList, no icon is displayed nor is any space reserved for one.

Select: Selects the item. Since only one item at a time can be selected, any previously selected item is automatically de-selected. In addition, this option reveals the newly selected item by expanding its parent(s), if necessary. To find out the current selection, call TV.GetSelection.

Sort: For TV.Modify, this option alphabetically sorts the children of the specified item. To instead sort all top-level items, use TV.Modify(0, "Sort"). If there are no children, 0 is returned instead of the ID of the modified item.

Vis: Ensures that the item is completely visible by scrolling the TreeView and/or expanding its parent, if necessary.

VisFirst: Same as above except that the TreeView is also scrolled so that the item appears at the top, if possible. This option is typically more effective when used with TV.Modify than with TV.Add.

 Note: When adding a large number of items, performance can be improved by using TV.Opt("-Redraw") before adding the items, and TV.Opt("+Redraw") afterward.

Modify

Modifies the attributes and/or name of an item, and returns the item's own ID.

CurrentItemID := TV.Modify(ItemID , Options, NewName)
ItemID
The item to modify. When only this parameter is present, the specified item is selected.
Options
See the list above.
NewName
The new name of the item. If omitted, the current name is left unchanged.

Delete

Deletes the specified item, and returns 1 upon success and 0 upon failure.

TV.Delete(ItemID)
ItemID
The item to delete. If omitted, all items in the TreeView are deleted.

Getting Data Out of a TreeView

GetSelection

Returns the selected item's ID number.

SelectedItemID := TV.GetSelection()

GetCount

Returns the total number of items in the control.

CountNumber := TV.GetCount()

 Note: The return value will be retrieved instantly, because the control keeps track of the count.

GetParent

Returns the specified item's parent as an item ID.

ParentItemID := TV.GetParent(ItemID)
ItemID
 The item to check. Items at the top level have no parent and thus return 0.

GetChild

Returns the ID number of the specified item's first/top child (or 0 if none).

TopChildID := TV.GetChild(ParentItemID)
ParentItemID
The parent item to check.

GetPrev

Returns the ID number of the sibling above the specified item (or 0 if none).

PrevItemID := TV.GetPrev(ItemID)
ItemID
The item to check.

GetNext

Returns the ID number of the next item below the specified item (or 0 if none).

NextItemID := TV.GetNext(ItemID := 0, ItemType := "")
ItemID
The item to check. If this parameter is 0 or omitted, the ID number of the first/top item in the TreeView is returned.
ItemType
If omitted, the ID number of the sibling below the specified item will be retrieved. Otherwise specify "Full" or "F" to retrieve the next item regardless of its relationship to the specified item; or specify "Check", "Checked", or "C" to get only the next item with a checkmark.
 The following example traverse the entire tree, item by item:
ItemID := 0  ; Causes the loop's first iteration to start the search at the top of the tree.
Loop
{
    ItemID := TV.GetNext(ItemID, "Full")  ; Replace "Full" with "Checked" to find all checkmarked items.
    if not ItemID  ; No more items in tree.
        break
    ItemText := TV.GetText(ItemID)
    MsgBox('The next Item is %ItemID%, whose text is "%ItemText%".')
}

GetText

Retrieves the text/name of the specified item.

RetrievedText := TV.GetText(ItemID)
ItemID
The ID number of the item, whose text to be retrieved. RetrievedText has a maximum length of 8191.

Get

Returns a non-zero value (item ID) if the specified item has the specified attribute.

CurrentItemID := TV.Get(ItemID, Attribute)
ItemID
The item to check.
Attribute
Specify "E", "Expand", or "Expanded" to determine if the item is currently expanded (that is, its children are being displayed); specify "C", "Check", or "Checked" to determine if the item has a checkmark; or specify "B" or "Bold" to determine if the item is currently bold in font.

Tip: Since an IF-statement sees any non-zero value as "true", if TV.Get(ItemID, "Checked") = ItemID and if TV.Get(ItemID, "Checked") are functionally identical.

Setting Icons

SetImageList

Sets or replaces the ImageList, and returns the ImageListID that was previously associated with this control (or 0 if none).

PrevImageListID := TV.SetImageList(ImageListID , IconType)
ImageListID
The number returned from a previous call to IL_Create.
IconType
If omitted, it defaults to 0. Otherwise, specify 2 for state icons (state icons are not yet directly supported, but they could be used via SendMessage).

Any such detached ImageList should normally be destroyed via IL_Destroy.

Events

The following events can be detected by calling OnEvent to register a callback function or method:

EventRaised when...
ClickThe control is clicked.
DoubleClickThe control is double-clicked.
ContextMenuThe user right-clicks the control or presses the Apps key or Shift-F10 while the control has the keyboard focus.
FocusThe control gains the keyboard focus.
LoseFocusThe control loses the keyboard focus.
ItemCheckAn item is checked or unchecked.
ItemEditAn item's label is edited by the user.
ItemExpandAn item is expanded or collapsed.
ItemSelectAn item is selected.

Additional (rarely-used) notifications can be detected by using OnNotify. These notifications are documented at MSDN. MSDN does not show the numeric value of each notification code; those can be found in the Windows SDK or by searching the Internet.

Remarks

To detect when the user has pressed Enter while a TreeView has focus, use a default button (which can be hidden if desired). For example:

Gui.Add("Button", "Hidden Default", "OK").OnEvent("Click", "ButtonOK")
...
ButtonOK() {
  global
  if Gui.FocusedCtrl != TV
    return
  MsgBox("Enter was pressed. The selected item ID is " TV.GetSelection())
}

In addition to navigating from item to item with the keyboard, the user may also perform incremental search by typing the first few characters of an item's name. This causes the selection to jump to the nearest matching item.

Although any length of text can be stored in each item of a TreeView, only the first 260 characters are displayed.

Although the theoretical maximum number of items in a TreeView is 65536, item-adding performance will noticeably decrease long before then. This can be alleviated somewhat by using the redraw tip described in TV.Add.

Unlike ListViews, a TreeView's ImageList is not automatically destroyed when the TreeView is destroyed. Therefore, a script should call IL_Destroy after destroying a TreeView's window if the ImageList will not be used for anything else. However, this is not necessary if the script will soon be exiting because all ImageLists are automatically destroyed at that time.

A script may create more than one TreeView per window.

To perform actions such as resizing, hiding, or changing the font of a TreeView, see GuiControl object.

Tree View eXtension (TVX) extends TreeViews to support moving, inserting and deleting. It is demonstrated at www.autohotkey.com/forum/topic19021.html

Related

ListView, Other Control Types, GuiCreate, ContextMenu event, Gui object, GuiControl object, TreeView styles table

Example

; The following is a working script that is more elaborate than the one near the top of this page.
; It creates and displays a TreeView containing all folders of the user's document folder. When the
; user selects a folder, its contents are shown in a ListView to the right (like Windows Explorer).
; In addition, a StatusBar control shows information about the currently selected folder.

; The following folder will be the root folder for the TreeView. Note that loading might take a long
; time if an entire drive such as C:\ is specified:
TreeRoot := A_MyDocuments
TreeViewWidth := 280
ListViewWidth := A_ScreenWidth/2 - TreeViewWidth - 30

; Create the GUI window and display the source directory (TreeRoot) in the title bar:
Gui := GuiCreate("+Resize", TreeRoot)  ; Allow the user to maximize or drag-resize the window.

; Create an ImageList and put some standard system icons into it:
ImageListID := IL_Create(5)
Loop 5 
  IL_Add(ImageListID, "shell32.dll", A_Index)
; Create a TreeView and a ListView side-by-side to behave like Windows Explorer:
TV := Gui.Add("TreeView", "r20 w%TreeViewWidth% ImageList%ImageListID%")
LV := Gui.Add("ListView", "r20 w%ListViewWidth% x+10", "Name|Modified")

; Create a Status Bar to give info about the number of files and their total size:
SB := Gui.Add("StatusBar")
SB.SetParts(60, 85)  ; Create three parts in the bar (the third part fills all the remaining width).

; Add folders and their subfolders to the tree. Display the status in case loading takes a long time:
M := GuiCreate("ToolWindow -SysMenu", "Loading the tree..."), M.Show()
DirList := AddSubFoldersToTree(TV, TreeRoot, {})
M.Hide()

; Call TV_ItemSelect whenever a new item is selected:
TV.OnEvent("ItemSelect", Func("TV_ItemSelect").bind(DirList, SB, LV))

; Call Gui_Size whenever the window is resized:
Gui.OnEvent("Size", Func("Gui_Size").bind(TV, LV))

; Set the ListView's column widths (this is optional):
Col2Width := 70  ; Narrow to reveal only the YYYYMMDD part.
LV.ModifyCol(1, ListViewWidth - Col2Width - 30)  ; Allows room for vertical scrollbar.
LV.ModifyCol(2, Col2Width)

; Display the window. The OS will notify the script whenever the user performs an eligible action:
Gui.Show()

AddSubFoldersToTree(TV, Folder, DirList, ParentItemID := 0)
{
  ; This function adds to the TreeView all subfolders in the specified folder
  ; and saves their paths associated with an ID into an object for later use.
  ; It also calls itself recursively to gather nested folders to any depth.
  LoopFiles("%Folder%\*.*", "D")  ; Retrieve all of Folder's sub-folders.
  {
    ItemID := TV.Add(A_LoopFileName, ParentItemID, "Icon4")
    DirList[ItemID] := A_LoopFilePath
    DirList := AddSubFoldersToTree(TV, A_LoopFilePath, DirList, ItemID)
  }
  return DirList
}

TV_ItemSelect(DirList, SB, LV, TV, Item)  ; This function is called when a new item is selected.
{
  ; Put the files into the ListView:
  LV.Delete()  ; Clear all rows.
  LV.Opt("-Redraw")  ; Improve performance by disabling redrawing during load.
  TotalSize := 0  ; Init prior to loop below.
  LoopFiles(DirList[Item] "\*.*")  ; For simplicity, omit folders so that only files are shown in the ListView.
  {
    LV.Add(, A_LoopFileName, A_LoopFileTimeModified)
    TotalSize += A_LoopFileSize
  }
  LV.Opt("+Redraw")

  ; Update the three parts of the status bar to show info about the currently selected folder:
  SB.SetText(LV.GetCount() " files", 1)
  SB.SetText(Round(TotalSize / 1024, 1) " KB", 2)
  SB.SetText(DirList[Item], 3)
}

Gui_Size(TV, LV, Gui, MinMax, Width, Height)  ; Expand/Shrink ListView and TreeView in response to the user's resizing.
{
  if MinMax = -1  ; The window has been minimized.  No action needed.
    return
  ; Otherwise, the window has been resized or maximized. Resize the controls to match.
  TV.Move("H" Height - 30)  ; -30 for StatusBar and margins.
  LV.Move("H" Height - 30 " W" Width - TV.Pos.W - 30)
}