TreeView

目录

入门和简单示例

TreeView 通过缩进父项目下的子项目来显示出层级关系. 最常见的例子是资源管理器的驱动器和文件夹树.

TreeView 通常看起来像这样:

TreeView

创建 TreeView 的语法为:

GuiCtrl := MyGui.Add("TreeView", Options)
GuiCtrl := MyGui.AddTreeView(Options)

这是一个创建和显示简单项目层次结构的可运行脚本:

MyGui := Gui()
TV := MyGui.Add("TreeView")
P1 := TV.Add("First parent")
P1C1 := TV.Add("Parent 1's first child", P1)  ; 指定 P1 为此项目的父项目.
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)

MyGui.Show()  ; 显示窗口和 TreeView.

Parameters

Options

Type: String

In addition to the general options and styles, the following are supported or noteworthy:

BackgroundColor: Background color. Specify for Color 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 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.

CColor: Text color. Specify for Color 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 the GetNext or Get methods.

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

ImageListID: This is the means by which icons are added to a TreeView. Specify for ID the ImageList ID returned from a previous call to IL_Create. This option has an effect only when creating a TreeView. Alternatively, the SetImageList method can be used without the limitation previously mentioned. For details, see ImageLists.

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 F2 (see the WantF2 option below). 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, as in example #1.

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

Wn: Sets the width of the control. For example, specifying w400 would make the control 400 pixels wide. If omitted, the default is 30 times the current font size.

Rn or Hn: Sets the height of the control. For example, specifying r7 would make room for 7 rows inside the control, while h400 would set the total height of the control to 400 pixels. If both R and H are omitted, the default is 5 rows.

(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.

TreeViews 的内置方法

除了GUI 控件的默认方法/属性外, 该控件类型拥有以下方法.

项目方法:

检索方法:

其他方法:

Add

添加新的项目到 TreeView.

ItemID := TV.Add(Name, ParentItemID, Options)

参数

Name

类型: 字符串

项目显示的文本, 它可以为文本或数值(包括数值表达式的结果).

ParentItemID

类型: 整数

如果省略, 默认为 0, 这意味着项目将被添加到顶级. 否则, 请指定新项目的父项的 ID.

Options

类型: 字符串

如果为空或省略, 默认为无选项. 否则, 请指定下面的列表中的一个或多个选项(不区分大小写). 选项间使用空格或 tab 分隔. 要移除某个选项, 请在该选项前加上负号. 要添加选项, 选项前允许使用正号, 但不是必须的(可以省略).

Bold: 用粗体显示项目的名称. 以后要取消项目名称的粗体显示, 请使用 TV.Modify(ItemID, "-Bold"). 单词 Bold 后可以可选地紧跟着 0 或 1 以指示起始状态.

Check: 在项目的坐标显示一个复选标记(需要 TreeView 含有复选框). 以后要取消选中, 请使用 TV.Modify(ItemID, "-Check"). 在单词 Check 后可以紧跟着 0 或 1 来表示初始状态. 换句话说, "Check""Check" . VarContainingOne 是等同的(这里中间使用的是连接运算符).

Expand: 展开此项以让其子项目显示出来(如果有). 以后要折叠项目, 请使用 TV.Modify(ItemID, "-Expand"). 如果没有子项目, 那么 Modify 方法返回 0 而不是它的项目 ID. 与之相比, Add 方法标记项目为展开, 以备以后添加子项目时使用. 与下面的 Select 选项不同, 展开一个项目不会自动展开其父项目. 最后, 在单词 Expand 后可以紧跟着 0 或 1 来表示初始状态. 换句话说, "Expand""Expand" . VarContainingOne 是等同的.

First | Sort | N: 这些选项仅适用于 Add 方法. 它们指定新项目相对于 其同级项目的位置(同级项目 是同一级别的其他任何项目). 如果这些选项都不存在, 则新项目被添加到同级项目的最后/底部. 否则, 请指定单词 First 来添加项目到同级项目的第一个/顶部, 或指定单词 Sort 来按字母顺序插入新项目到同级项目中间. 如果指定一个纯整数 N, 则假定它为同级项目的 ID 号, 新项目会被插入到它的后面(如果 N 是唯一使用的选项, 则它不需要括在引号中).

Icon: 指定单词 Icon 后紧跟着此项目图标的编号, 项目图标显示在项目名称的左边. 如果此选项不存在, 则使用图像列表中的首个图标. 要显示空白图标, 请指定一个大于图像列表中图标数目的数字. 如果控件没有图像列表, 则既不显示图标也不为图标保留空间.

Select: 选择项目. 因为一次只能选择一个项目, 此时任何原来选择的项目会自动取消选择. 此外, 如果有必要此选项会展开其父项目以显示新选择的项目. 要找出当前选择的项目, 请调用 GetSelection 方法.

Sort: 对于 Modify 方法, 此选项按字母顺序排列指定项目的子项目. 要对所有顶级项目进行排序, 请使用 TV.Modify(0, "Sort"). 如果不含子项目, 则返回 0 而不是所修改项目的 ID.

Vis: 在需要时, 通过滚动 TreeView 和/或展开其父项目来确保此项目完全可见.

VisFirst: 和上面一样, 不过在可行时它还会滚动 TreeView 使得此项显示在顶部. 此选项与 Modify 方法比与 Add 方法一起使用通常更有效.

返回值

类型: 整数

成功时, 方法返回新添加项目的唯一 ID 号. 失败时, 返回 0.

备注

当添加大量项目时, 可以在添加项目之前使用 TV.Opt("-Redraw"), 之后使用 TV.Opt("+Redraw") 来提高性能. 有关详情, 请参阅 Redraw.

Modify

修改项目的属性和/或名称.

ItemID := TV.Modify(ItemID , Options, NewName)

参数

ItemID

类型: 整数

要修改的项目.

Options

类型: 字符串

如果该参数和 NewName 参数都省略, 则选择项目. 否则, 请指定上表中的一个或多个选项.

NewName

类型: 字符串

如果省略, 则保持当前名称不变. 否则, 请指定项目的新名称.

返回值

类型: 整数

方法返回项目自己的 ID.

Delete

删除指定项目或所有项目.

TV.Delete(ItemID)

参数

ItemID

类型: 整数

如果省略, 则删除 TreeView 中的 所有 项目. 否则, 请指定要删除项目的 ID 号.

GetSelection

返回选择项目的 ID 号.

ItemID := TV.GetSelection()

返回值

类型: 整数

此方法返回选择项目的 ID 号.

GetCount

返回控件中项目的总数.

Count := TV.GetCount()

返回值

类型: 整数

此方法返回控件中项目的总数. 此返回值总是即时检索的, 因为控件会一直跟踪此计数.

GetParent

返回指定项目的父项目的 ID.

ParentItemID := TV.GetParent(ItemID)

参数

ItemID

类型: 整数

要检查的项目.

返回值

类型: 整数

此方法返回指定项目的父项目的 ID 号. 如果项目没有父项目, 返回 0, 这适用于所有顶级项目.

GetChild

返回指定项目的第一个/最上面的子项目的 ID.

ChildItemID := TV.GetChild(ItemID)

参数

ItemID

类型: 整数

要检查项目的 ID. 如果为 0, 返回 TreeView 中首个/顶部项目的 ID 号.

返回值

类型: 整数

此方法返回指定项目的第一个/最上面的子项目的 ID 号. 如果没有子项目, 返回 0.

GetPrev

返回指定项目上面一个的同级项目的 ID 号.

PrevItemID := TV.GetPrev(ItemID)

参数

ItemID

类型: 整数

要检查的项目.

返回值

类型: 整数

此方法返回指定项目上一个同级项目的 ID 号. 如果没有同级项目, 返回 0.

GetNext

返回指定项目下面一个项目的 ID 号.

NextItemID := TV.GetNext(ItemID, ItemType)

参数

ItemID

类型: 整数

要检查的项目. 如果该参数为 0 或省略, 则返回 TreeView 中第一个/顶部项目的 ID 号.

ItemType

类型: 字符串

如果省略, 将检索指定项目下面一个同级项目的 ID 号. 否则, 请指定以下字符串之一:

FullF: 检索下一个项目, 不论它是否为指定项目的同级项目. 这使得脚本可以容易地逐项遍历整个树. 请参阅下面的示例.

Check, CheckedC: 仅获取下一个带复选标记的项目.

返回值

类型: 整数

此方法返回指定项目下一个项目的 ID 号. 如果没有下一个项目, 返回 0.

备注

下面的例子逐项遍历整个树:

ItemID := 0  ; 这样使得首次循环从树的顶部开始搜索.
Loop
{
    ItemID := TV.GetNext(ItemID, "Full")  ; 把 "Full" 替换为 "Checked" 来找出所有含复选标记的项目.
    if not ItemID  ; 没有更多项目了.
        break
    ItemText := TV.GetText(ItemID)
    MsgBox('The next Item is ' ItemID ', whose text is "' ItemText '".')
}

GetText

检索指定项目的文本/名称.

Text := TV.GetText(ItemID)

参数

ItemID

类型: 整数

要检索文本的项目的 ID 号.

返回值

类型: 字符串

此方法返回检索到的文本. 最多只能检索 8191 个字符.

Get

如果指定项目含有指定的属性, 则返回一个项目的 ID.

ItemID := TV.Get(ItemID, Attribute)

参数

ItemID

类型: 整数

要检查的项目的 ID 号.

Attribute

类型: 字符串

指定以下字符串之一:

E, ExpandExpanded: 当前展开的项目(即它的子项目是显示的).

C, CheckChecked: 具有复选标记的项目.

BBold: 当前字体为粗体的项目.

返回值

类型: 整数

如果指定的项目具有指定的属性, 则返回它自己的 ID. 否则, 返回 0.

备注

因为在 IF 语句中把任何非零值视为 "true", if TV.Get(ItemID, "Checked") = ItemIDif TV.Get(ItemID, "Checked") 在功能上是相同的.

SetImageList

设置或替换用于显示图标的 ImageList.

PrevImageListID := TV.SetImageList(ImageListID , IconType)

参数

ImageListID

类型: 整数

上次调用 IL_Create 后返回的 ID 数字.

IconType

类型: 整数

如果省略, 则默认为 0. 否则, 为状态图标指定 2(状态图标还没有被直接支持, 但可以通过 SendMessage 使用).

返回值

类型: 整数

成功时, 此方法返回先前与 TreeView 关联的 ImageList ID. 失败时, 返回 0. 任何这样的分离的 ImageList 通常应该通过 IL_Destroy 来销毁.

事件

通过调用 GuiControl.OnEvent 来注册一个回调函数或方法, 可以检测到以下事件:

事件当...触发
Click控件被点击.
DoubleClick控件被双击.
ContextMenu当控件拥有键盘焦点时, 用户右键单击控件或按下 MenuShift+F10.
Focus控件获得键盘焦点.
LoseFocus控件失去键盘焦点.
ItemCheck一个项目被选中或取消选中.
ItemEdit一个项目的标签被用户编辑.
ItemExpand一个项目被展开或折叠.
ItemSelect一个项目被选中或取消选中.

额外的(很少使用的) 通知可以通过使用 GuiControl.OnNotify 来检测. 这些通知在 Microsoft Docs 上都有文档. Microsoft Docs 没有显示每个通知代码的数值; 这些可以在 Windows SDK 中找到, 或者在互联网上搜索.

ImageLists

An Image-List is a group of identically sized icons stored in memory. Upon creation, each ImageList is empty. The script calls IL_Add repeatedly to add icons to the list, and each icon is assigned a sequential number starting at 1. This is the number to which the script refers to display a particular icon to the left of an item's name. Here is a working example that demonstrates how to put icons into a TreeView:

MyGui := Gui()
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 := MyGui.Add("TreeView", "ImageList" . ImageListID)
TV.Add("Name of Item", 0, "Icon4")  ; Add an item to the TreeView and give it a folder icon.
MyGui.Show()

The SetImageList method can be used as an alternative to the ImageList option.

For detailed information about all ImageList functions, check out the ListView page.

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.

备注

当 TreeView 拥有焦点时如果要检测到用户按下的 Enter 键, 请使用默认按钮(如果需要可以隐藏它). 例如:

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

使用键盘除了在项与项之间导航外, 用户还可以通过输入一个项目名称的前几个字符来进行增量搜索. 这使得选择对象跳转到最近匹配的项目.

尽管 TreeView 中的每个项目可以存储任意长度的文本, 但仅显示开始的 260 个字符.

尽管理论上 TreeView 中的项目数可以多达 65536, 然而接近此数目时添加项的性能将显著降低. 通过使用 Add 方法中描述的重绘提示可以稍微减轻这种情况.

脚本可以在每个窗口中创建多个 TreeView.

要执行一些操作, 例如调整大小, 隐藏或改变 TreeView 的字体, 请参阅 GuiControl 对象.

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

ListView, 其他控件类型, Gui(), ContextMenu 事件, Gui 对象, GuiControl 对象, TreeView 样式表

示例

Creates and displays an editable TreeView containing three items. The TreeView uses GuiControl.OnEvent to process user input. In this case, whenever the user finishes editing an item, it is repositioned alphabetically among its siblings. To test this example, edit an item with F2 or a delayed double-click.

MyGui := Gui()
TV := MyGui.Add("TreeView", "-ReadOnly")
TV.Add("A")
TV.Add("B")
TV.Add("C")
TV.OnEvent("ItemEdit", TV_Edit)  ; Call TV_Edit whenever we finish editing an item.
MyGui.Show()

TV_Edit(TV, Item)
{
    TV.Modify(TV.GetParent(Item), "Sort")  ; This works even if the item has no parent.
}

下面是一个比页面顶部的脚本更复杂的可工作的脚本. 它创建并显示一个 TreeView, 其中包含所有用户开始菜单中的所有文件夹. 当用户选择一个文件夹时, 它的内容会显示在右边的 ListView 中(类似于 Windows 资源管理器). 此外, StatusBar 控件会显示当前选择文件夹的信息.

; 下面的文件夹为 TreeView 的根文件夹. 请注意, 如果指定整个驱动器例如 C:\
; 那么可能需要很长加载时间:
TreeRoot := A_MyDocuments
TreeViewWidth := 280
ListViewWidth := A_ScreenWidth/2 - TreeViewWidth - 30

;  创建 Gui 窗口并在标题栏中显示源目录(TreeRoot):
MyGui := Gui("+Resize", TreeRoot)  ; 让用户可以最大化或拖动调整窗口大小.

; 创建图像列表并在其中放入一些标准的系统图标:
ImageListID := IL_Create(5)
Loop 5 
    IL_Add(ImageListID, "shell32.dll", A_Index)
; 创建 TreeView 和 ListView, 让它们像在 Windows 资源管理器中那样靠在一起:
TV := MyGui.Add("TreeView", "r20 w" TreeViewWidth " ImageList" ImageListID)
LV := MyGui.Add("ListView", "r20 w" ListViewWidth " x+10", ["Name", "Modified"])

; 创建状态栏, 显示文件夹数及其总大小的信息:
SB := MyGui.Add("StatusBar")
SB.SetParts(60, 85)  ; 在状态栏中创建三个部分(第三部分占用所有剩余宽度).

; 添加文件夹及其子文件夹到树中. 如果加载需要很长时间, 则显示提示信息:
M := Gui("ToolWindow -SysMenu Disabled AlwaysOnTop", "Loading the tree..."), M.Show("w200 h0")
DirList := AddSubFoldersToTree(TreeRoot, Map())
M.Hide()

; 每当有新的项目被选中时, 调用 TV_ItemSelect:
TV.OnEvent("ItemSelect", TV_ItemSelect)

; 每当窗口被调整大小时, 调用 Gui_Size:
MyGui.OnEvent("Size", Gui_Size)

; 设置 ListView 的列宽(这是可选的):
Col2Width := 70  ; 缩小到只显示 YYYYMMDD 部分.
LV.ModifyCol(1, ListViewWidth - Col2Width - 30)  ; 允许垂直滚动条.
LV.ModifyCol(2, Col2Width)

; 显示窗口并返回. 每当用户执行符合条件的动作时, 操作系统会通知脚本:
MyGui.Show()

AddSubFoldersToTree(Folder, DirList, ParentItemID := 0)
{
    ; 该函数将指定文件夹中的所有子文件夹添加到 TreeView 中,
    ; 并将它们与 ID 相关联的路径保存到一个对象中, 供以后使用.
    ; 它还可以递归地调用自己来收集任意深度的嵌套文件夹.
    Loop Files, Folder "\*.*", "D"  ; 获取所有文件夹的子文件夹.
    {
        ItemID := TV.Add(A_LoopFileName, ParentItemID, "Icon4")
        DirList[ItemID] := A_LoopFilePath
        DirList := AddSubFoldersToTree(A_LoopFilePath, DirList, ItemID)
    }
    return DirList
}

TV_ItemSelect(thisCtrl, Item)  ; 当选择一个新的项目时, 该函数被调用.
{
    ; 将文件放入 ListView 中:
    LV.Delete()  ; 清除所有行.
    LV.Opt("-Redraw")  ; 通过在加载过程中禁止重绘来提高性能.
    TotalSize := 0  ; 在下面循环之前初始化.
    Loop Files, DirList[Item] "\*.*"  ; 为了简化, 这里省略了文件夹, 所以只在 ListView 中显示文件.
    {
        LV.Add(, A_LoopFileName, A_LoopFileTimeModified)
        TotalSize += A_LoopFileSize
    }
    LV.Opt("+Redraw")

    ; 更新状态栏的三个部分, 让它们显示当前选择的文件夹的信息:
    SB.SetText(LV.GetCount() " files", 1)
    SB.SetText(Round(TotalSize / 1024, 1) " KB", 2)
    SB.SetText(DirList[Item], 3)
}

Gui_Size(thisGui, MinMax, Width, Height)  ; 当用户改变窗口大小时扩展/收缩 ListView 和 TreeView.
{
    if MinMax = -1  ; 窗口被最小化了. 无需进行操作.
        return
    ; 否则, 窗口的大小被调整过或被最大化了. 调整控件大小以适应.
    TV.GetPos(,, &TV_W)
    TV.Move(,,, Height - 30)  ; -30 用于状态栏和边距.
    TV.Move(,, Width - TV_W - 30, Height - 30)
}