List-View 是由操作系统提供的最精心设计的控件之一. 在其最容易识别的形式中, 它显示一个多行多列组成的表格视图, 最常见的例子是资源管理器的文件和文件夹列表(详细信息视图).
ListView 通常是这样的:
尽管它可能是精细的, 但 ListView 的基本功能也易于使用. 创建 ListView 的语法为:
GuiCtrl := MyGui.Add("ListView", Options, ColumnTitles) GuiCtrl := MyGui.AddListView(Options, ColumnTitles)
这是一个可运行脚本, 它创建并显示一个 ListView 其中包含用户的 "我的文档" 目录中的文件列表:
; 创建窗口:
MyGui := Gui()
; 创建含名称和大小两列的 ListView:
LV := MyGui.Add("ListView", "r20 w700", ["Name", "Size (KB)"])
; 每当用户双击某行时, 通知脚本:
LV.OnEvent("DoubleClick", LV_DoubleClick)
; 从文件夹中获取文件名列表并把它们放入 ListView:
Loop Files, A_MyDocuments "\*.*"
LV.Add(, A_LoopFileName, A_LoopFileSizeKB)
LV.ModifyCol() ; 根据内容自动调整每列的大小.
LV.ModifyCol(2, "Integer") ; 为了进行排序, 指出列 2 是整数.
; 显示窗口:
MyGui.Show()
LV_DoubleClick(LV, RowNumber)
{
RowText := LV.GetText(RowNumber) ; 从行的第一个字段中获取文本.
ToolTip("You double-clicked row number " RowNumber ". Text: '" RowText "'")
}
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 ListView initially defaults to the system's default background color. Specifying BackgroundDefault applies the system's default background color (usually white). For example, a ListView can be restored to the default color via LV.Opt("+BackgroundDefault").
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 row. When adding a row, 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 a row.
CountN: Specify for N the total number of rows that the ListView will ultimately contain. This is not a limit: rows beyond the count can still be added. Instead, this option serves as a hint to the control that allows it to allocate memory only once rather than each time a row is added, which greatly improves row-adding performance (it may also improve sorting performance). To improve performance even more, use LV.Opt("-Redraw") prior to adding a large number of rows and LV.Opt("+Redraw") afterward. See Redraw for more details.
Grid: Provides horizontal and vertical lines to visually indicate the boundaries between rows and columns.
Hdr: Specify -Hdr (minus Hdr) to omit the header (the special top row that contains column titles). To make it visible later, use LV.Opt("+Hdr").
Icon, Tile, IconSmall, List, or Report: See View Modes for details.
LVn: Specify for n the number of an extended ListView style. These styles are entirely separate from generic extended styles. For example, specifying -E0x200 would remove the generic extended style WS_EX_CLIENTEDGE to eliminate the control's default border. By contrast, specifying -LV0x20 would remove LVS_EX_FULLROWSELECT.
LV0x10: Specify -LV0x10 to prevent the user from dragging column headers to the left or right to reorder them. However, it is usually not necessary to do this because the physical reordering of columns does not affect the column order seen by the script. For example, the first column will always be column 1 from the script's point of view, even if the user has physically moved it to the right of other columns.
LV0x20: Specify -LV0x20 to require that a row be clicked at its first field to select it (normally, a click on any field will select it). The advantage of this is that it makes it easier for the user to drag a rectangle around a group of rows to select them.
Multi: Specify -Multi (minus Multi) to prevent the user from selecting more than one row at a time.
NoSortHdr: Prevents the header from being clickable. It will take on a flat appearance rather than its normal button-like appearance. Unlike most other ListView styles, this one cannot be changed after the ListView is created.
NoSort: Turns off the automatic sorting that occurs when the user clicks a column header. However, the header will still behave visually like a button (unless the NoSortHdr option has been specified). In addition, the ColClick event is still raised, so the script can respond with a custom sort or other action.
ReadOnly: Specify -ReadOnly (minus ReadOnly) to allow editing of the text in the first column of each row. To edit a row, select it then press F2 (see the WantF2 option below). Alternatively, you can click a row once to select it, wait at least half a second, then click the same row again to edit it.
Sort: The control is kept alphabetically sorted according to the contents of the first column.
SortDesc: Same as above except in descending order.
WantF2: Specify -WantF2 (minus WantF2) to prevent F2 from editing the currently focused row. 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. If the ListView is created with a view mode other than report view, the control is sized to fit rows of icons instead of rows of text. Note that adding icons to a ListView's rows will increase the height of each row, which will make this option inaccurate.
(Unnamed numeric styles): Since styles other than the above are rarely used, they do not have names. See the ListView styles table for a list.
Type: Array
An array of column titles such as ["Red", "Green", "Blue"], which form the header of the ListView.
ListView 有五种视图模式, 其中最常见的是报告视图(这是默认的). 要使用其他某种视图, 请在 Options 中指定它的名称. 还可以在控件创建后改变视图模式; 例如: LV.Opt("+IconSmall").
Icon: 显示大图标视图. 在该视图和除 Report 之外的所有其他视图中, 除第一列之外的其他列中的文本是不可见的. 要在这种模式下显示图标, 必须有一个大图标 ImageList 分配给它.
Tile: 显示大图标视图, 但具有人体工学差异, 例如每项的文本显示在图标的右边而不是下面. Checkbox 在此视图中不起作用.
IconSmall: 显示小图标视图.
List: 以列表格式显示小图标视图, 其中图标显示在列中. 列数取决于控件的宽度和其中最宽的文本项的宽度.
Report: 切换回报告视图, 这是最初的默认模式. 例如: LV.Opt("+Report").
In addition to the default methods/properties of a GUI control, this control type has the following methods.
When the phrase "row number" is used on this page, it refers to a row's current position within the ListView. The top row is 1, the second row is 2, and so on. After a row is added, its row number tends to change due to sorting, deleting, and inserting of other rows. Therefore, to locate specific row(s) based on their contents, it is usually best to use the GetText method in a loop.
行的方法:
列的方法:
检索方法:
其他方法:
添加新行到列表底部.
RowNumber := LV.Add(Options, Col1, Col2, ...)
类型: 字符串
如果为空或省略, 则默认为无选项. 否则, 请指定下表中的一或多个选项(不区分大小写). 选项间使用空格或 tab 分隔. 要移除某个选项, 请在该选项前加上负号. 要添加选项, 允许添加加号, 但不是必须的.
Check: 在行中显示选中标记(需要 ListView 含有 Checkbox). 以后要取消选中它, 请使用 LV.Modify(RowNumber, "-Check").
Col: 指定单词 Col 后紧跟着列号, 从此列开始往后应用参数 Col1 及以后. 此选项通常和 Modify 方法一起使用来修改行中的个别字段, 而不会影响其左侧的字段.
Focus: 设置键盘焦点到此行(通常和下面的 Select 选项一起使用). 以后要取消它的焦点, 请使用 LV.Modify(RowNumber, "-Focus").
Icon: 指定单词 Icon 后紧跟着这行图标的编号, 这行图标显示在首列的左侧. 如果此选项不存在, 则使用 ImageList 中的首个图标. 要显示空白图标, 请指定 -1 或一个大于图像列表中图标数目的数字. 如果控件没有小图标的图像列表, 则报告视图中既不显示图标也不为其保留空间.
该选项接受基于 1 开始的的图标编号, 但在内部转换为基于 0 开始的索引; 因此, Icon0 对应于常数 I_IMAGECALLBACK, 它通常被定义为 -1, 而 Icon-1 对应于 I_IMAGENONE. 其他超出范围的值也可能导致图标所在位置出现空白.
Select: 选择行. 以后要取消选择, 请使用 LV.Modify(RowNumber, "-Select"). 当选择行时, 通常最好确保至少有一行总含有聚焦属性, 为这样允许 Apps 键在焦点行附近显示其上下文菜单(如果有). 单词 Select 后可以紧跟着 0 或 1 来表示初始状态. 换句话说, both "Select" 和 "Select" . VarContainingOne 是一样的(此处的句点是连接运算符). 这种技术也适用于上面的 Focus 和 Check 选项.
Vis: 必要时通过滚动 ListView 来确保指定行完全可见. 此参数仅对 LV.Modify 有效; 例如: LV.Modify(RowNumber, "Vis").
类型: 字符串
新行中的列, 可以是文本或数字(包括数字表达式的结果). 要使任何字段成为空, 请指定 "" 或等价物. 如果字段太少无法填满所有的列, 那么末尾的列将被留空. 如果字段太多, 末尾的字段将被完全忽略.
类型: 整数
在指定行号插入一个新行.
RowNumber := LV.Insert(RowNumber , Options, Col1, Col2, ...)
类型: 整数
新插入行的行号. 任何位于 RowNumber 或其下方的行都会被向下移动, 以便为新行腾出空间. 如果 RowNumber 大于列表中的行数(甚至大于 2147483647), 新的行将被添加到列表的最后.
类型: 字符串
如果为空或省略, 则默认为无选项. 否则, 请指定上表中一个或多个选项.
类型: 字符串
新行中的列, 可以是文本或数字(包括数字表达式的结果). 要使任何字段成为空, 请指定 "" 或等价物. 如果字段太少无法填满所有的列, 那么末尾的列将被留空. 如果字段太多, 末尾的字段将被完全忽略.
类型: 整数
该方法返回指定的行号.
修改行的属性和/或文本.
LV.Modify(RowNumber , Options, NewCol1, NewCol2, ...)
类型: 整数
要修改的行. 如果为 0, 那么控件中的 所有 的行都会被修改.
类型: 字符串
如果为空或省略, 则默认为无选项. 否则, 请指定上表中的一个或多个选项. ColN 选项可用于更新特定的列而不影响其他列.
类型: 字符串
指定行的新列, 可以是文本或数字(包括数字表达式的结果). 要使任何字段成为空, 请指定 "" 或等价物. 如果字段太少无法填满所有的列, 那么末尾的列将被留空. 如果字段太多, 末尾的字段将被完全忽略.
如果只存在前两个参数, 则仅修改行的属性而不改变其文本.
删除指定行或所有行.
LV.Delete(RowNumber)
类型: 整数
如果省略, 则删除 ListView 中的 所有 行. 否则, 请指定要删除的行号.
修改指定列和标题的属性和/或文本.
LV.ModifyCol(ColumnNumber, Options, ColumnTitle)
类型: 整数
如果省略所有参数, 则调整所有列的宽度以适应行的内容. 只有在报告(详细信息) 视图中才有效果.
否则, 请指定要修改的列的列号. 首列的列号为 1(不是 0).
类型: 整数
如果省略, 则默认为 Auto(则调整列的宽度以适应其的内容). 否则, 请指定下表中的一个或多个选项(不区分大小写). 选项间使用空格或 tab 分隔. 要移除选项, 请在选项前加上负号. 要添加选项, 允许使用加号, 但不是必需的.
常规选项
N: 指定 N 为列的新宽度, 单位为像素. 如果是唯一的选择, 这个数字可以不加引号. 例如, 后面两种形式都是有效的: LV.ModifyCol(1, 50) 和 LV.ModifyCol(1, "50 Integer").
Auto: 调整列宽来适应其内容. 只有在报告(详细信息) 视图中这才有效果.
AutoHdr: 调整列宽来适应其内容和列标题的文本, 以其中较宽的为准. 当应用于最后一列时, 它将被设置为至少和 ListView 中剩余空间的宽度一样. 通常最好仅在行已经添加后才应用此设置, 因为这样允许当调整最后一列的大小时考虑到可能新增加的垂直滚动栏. 只有在报告(详细信息) 视图中这才有效果.
Icon: 指定单词 Icon 后紧跟着图像列表中要显示在列标题文本后的图标的编号. 指定 -Icon(负 icon) 来移除任何现有的图标.
IconRight: 把图标放在列的右边而不是左.
数据类型选项
Float: 为了进行排序, 指明此列包含浮点数(不支持十六进制格式). 浮点数和文本列的排序性能最多可能比整数列的慢 25 倍.
Integer: 为了进行排序, 指明此列包含整数. 要正确排序, 每个整数必须是 32 位的; 即在范围 -2147483648 到 2147483647 内. 任何非整数的值在排序时将被视为零(不过如果这些值以一个数字开头, 则使用这个数字). 数字格式可以为十进制或十六进制(例如 0xF9E0).
Text: 更改列返回到文本模式进行排序, 这是每列初始默认的排序方式. 在排序时只有文本开始的 8190 个字符是有意义的(如果如果使用了 Logical 选项, 此时限制为 4094).
对齐选项
Center: 让文本居于列中央. 要让 Integer 或 Float 列居中, 请把单词 Center 加到 Integer 或 Float 后.
Left: 左对齐列文本, 这是每列初始默认的对齐方式. 在较旧的操作系统中, 首列可能会强制进行左对齐.
Right: 右对齐列文本. 对于 Integer 和 Float 列不需要指定此属性, 因为它们默认是右对齐的. 通过指定例如 "Integer Left" 或 "Float Center" 的字符串可以覆盖此默认的对齐方式.
排序选项
Case: 让列排序区分大小写(仅影响文本列). 如果 Case, CaseLocale 和 Logical 选项都省略, 则在排序中大写字母 A-Z 被视为等同于它们相应的小写形式.
CaseLocale: 让列排序基于当前用户的区域设置且不区分大小写(仅影响文本列). 例如, 大多数英语和西欧地区把字母 A-Z 和 ANSI 字母例如 Ä 和 Ü 等同于它们的小写形式. 这种方法也使用 "单词排序", 它把单词中的连字符和撇号例如 "coop" 和 "co-op" 保持在一起.
Desc: 降序排列. 用户首次对此列排序时使用下降的顺序.
Logical: 与 CaseLocale 相同, 除了把文本中的任何数字位序列看成真正的数字而不仅仅字符. 例如, 字符串 "T33" 将被视为大于 "T4". Logical 和 Case 是互斥的: 只有最近指定的那个才有效.
NoSort: 避免用户点击此列对自动排序产生的影响. 然而, ColClick 事件仍然会被触发, 所以脚本可以用自定义的排序或其他操作来响应. 要禁用所有列的排序而不仅是其中的子集, 请在 ListView 的选项中包含 NoSort.
Sort: 立即对列按升序排列(即使它含有 Desc 选项).
SortDesc: 立即对列按降序排列.
Uni: 单向排序. 此选项防止在相同列进行第二次点击来反转排序方向.
类型: 字符串
如果省略, 当前标题保持不变. 否则, 请指定列的新标题.
在指定列号插入一个新列.
ColumnNumber := LV.InsertCol(ColumnNumber, Options, ColumnTitle)
类型: 整数
如果省略或大于控件中的当前列数, 则新列将添加到右侧最后一列的旁边.
否则, 指定新插入的列的列号. 在 ColumnNumber 处和其右侧的任何列都会向右移动, 以便为新列腾出空间. 第一列的编号为 1(不是 0).
类型: 字符串
类型: 字符串
如果为空或省略, 则默认为空的标题. 否则, 请指定列的标题.
类型: 整数
函数返回新列的位置编号.
新插入列的初始内容为空, 然而如果它是首列则会继承原来首列的内容, 同时原来首列的内容变为空白.
ListView 中的最大列数是 200.
删除指定的列及其中所有内容.
LV.DeleteCol(ColumnNumber)
类型: 整数
要删除的列. 当一列被删除后, 位于其右侧的列号将减少 1. 因此, 调用 LV.DeleteCol(2) 两次, 将删除第二列和第三列.
返回控件中行数或列数.
Count := LV.GetCount(Mode)
类型: 字符串
如果为空或省略, 该方法返回控件中的总行数. 否则, 请指定以下字符串之一:
S 或 Selected: 计数仅包括选择的/高亮的行.
Col 或 Column: 方法返回控件中的列数.
类型: 整数
此方法返回控件的行数或列数. 该值总是即时返回的, 因为控件会跟踪这些计数.
这个方法通常用于 Loop 的顶行, 在这种情况下, 这个方法只会被调用一次(在首次循环前). 例如:
Loop LV.GetCount()
{
RetrievedText := LV.GetText(A_Index)
if InStr(RetrievedText, "some filter text")
LV.Modify(A_Index, "Select") ; 选择首个字段包含过滤文本的所有行.
}
要获取 ListView 的列宽 -- 用于例如保存它们到 INI 文件以便在会话期间保持一致 -- 请参照此例:
Loop LV.GetCount("Column")
{
ColWidth := SendMessage(0x101D, A_Index - 1, 0, LV) ; 0x101D 是 LVM_GETCOLUMNWIDTH.
MsgBox("Column " A_Index "'s width is " ColWidth ".")
}
返回下一个选择, 选中或具有焦点的行的行号.
RowNumber := LV.GetNext(StartingRowNumber, RowType)
类型: 整数
如果省略或小于 1, 则从列表的顶部开始搜索. 否则, 请指定开始搜索的行号.
类型: 字符串
如果省略, 则方法搜索下一个选择的/高亮的行(请参阅下面的例子). 否则, 请指定以下字符串之一:
C 或 Checked: 寻找下一个选中的行.
F 或 Focused: 寻找焦点行. 在整个列表中不可能有多个焦点行, 且有时甚至没有.
类型: 整数
此方法返回下一个选择, 选中或聚焦的行的行号. 如果没有找到, 返回 0.
下面的示例, 报告 ListView 中所有选择的行:
RowNumber := 0 ; 这样使得首次循环从列表的顶部开始搜索.
Loop
{
RowNumber := LV.GetNext(RowNumber) ; 在前一次找到的位置后继续搜索.
if not RowNumber ; 上面返回零, 所以选择的行已经都找到了.
break
Text := LV.GetText(RowNumber)
MsgBox('The next selected row is #' RowNumber ', whose first field is "' Text '".')
}
判断一个特定的行是否被选中的另一种方法如下:
ItemState := SendMessage(0x102C, RowNumber - 1, 0xF000, LV) ; 0x102C 是 LVM_GETITEMSTATE. 0xF000 是 LVIS_STATEIMAGEMASK. IsChecked := (ItemState >> 12) - 1 ; 如果 RowNumber 为选中的则设置 IsChecked 为真, 否则为假.
检索指定行号和列号的文本.
Text := LV.GetText(RowNumber , ColumnNumber)
类型: 整数
要检索文本的行的编号. 如果为 0, 则获取列标题的文本.
类型: 整数
如果省略, 默认为 1(首列的文本). 否则, 请指定 RowNumber 所在的行中的列号.
类型: 整数
此方法返回检索到的文本. 最多只能检索 8191 个字符.
脚本中看到的列编号不会因为用户所做的拖放而改变. 例如, 最初首列的编号仍是 1, 即使用户把它拖到其他列的右边.
设置或替换用于显示图标的 ImageList(图像列表).
PrevImageListID := LV.SetImageList(ImageListID , IconType)
类型: 整数
从之前调用 IL_Create 返回的 ID 数字.
类型: 整数
如果省略, 则自动检测 ImageList 中的图标类型为大图标或小图标. 否则, 指定 0 为大图标, 1 为小图标, 或者 2 为状态图标(这还不直接支持, 但可以通过 SendMessage 使用).
类型: 整数
成功时, 函数返回先前与 ListView 关联的 ImageList ID. 失败时, 返回 0. 任何这样分离的 ImageList 通常应该通过 IL_Destroy 来销毁.
这个方法通常在向 ListView 添加任何行之前被调用. 它设置 ImageList, 其中的图标会显示在 ListView 的行中(可选的, 以及列).
一个 ListView 最多可以有两个图像列表: 小图标和/或大图标. 当脚本允许用户在大图标视图之间进行切换时, 这很有用. 要再关联一个图像列表到 ListView, 请再次调用 SetImageList 方法, 指定第二个列表的 ImageListID. 一个同时拥有大图标和小图标 ImageList 的 ListView 应该确保两个列表中的图标顺序相同. 这是因为相同的 ID 号被用来引用特定图标的大版本和小版本.
尽管除了图标模式和平铺模式外, 传统的所有的视图模式都显示小图标, 但可以通过传递一个大图标列表到 SetImageList 方法, 并且在第二个参数中指定 1(小图标) 覆盖此行为. 这也增加了 ListView 中每行的高度以适合大图标.
以下事件可以通过调用 GuiControl.OnEvent 来注册一个回调函数或方法来检测:
| 事件 | 当...触发 |
|---|---|
| Click | 控件被点击. |
| DoubleClick | 控件被双击. |
| ColClick | 列标题被点击. |
| ContextMenu | 当控件拥有键盘焦点时, 用户右键单击控件或按下 Menu 或 Shift+F10. |
| Focus | 控件获得键盘焦点. |
| LoseFocus | 控件失去键盘焦点. |
| ItemCheck | 一个项目被选中或取消选中. |
| ItemEdit | 一个项目的标签被用户编辑. |
| ItemFocus | 焦点项目改变. |
| ItemSelect | 一个项目被选中或取消选中. |
额外的(很少使用的) 通知可以通过使用 GuiControl.OnNotify 来检测. 这些通知在 Microsoft Docs 上都有文档. Microsoft Docs 没有显示每个通知代码的数值; 这些可以在 Windows SDK 中找到, 或者在互联网上搜索.
图像列表是存储在内存中的一组相同大小的图标. 在创建时, 每个图像列表是空的. 脚本重复调用 IL_Add 来添加图标到列表中, 且给每个图标分配一个序号, 序号从 1 开始. 脚本引用此编号在一行中或列标题中显示一个特定的图标. 这是个可运行示例, 其中演示了如何在 ListView 的行中显示图标:
MyGui := Gui() ; 创建 Gui 窗口.
LV := MyGui.Add("ListView", "h200 w180", ["Icon & Number", "Description"]) ; 创建 ListView.
ImageListID := IL_Create(10) ; 创建加载 10 个小图标的图像列表.
LV.SetImageList(ImageListID) ; 把上面的图像列表指定给当前的 ListView.
Loop 10 ; 把 DLL 中的一系列图标装入图像列表.
IL_Add(ImageListID, "shell32.dll", A_Index)
Loop 10 ; 在 ListView 中添加行(出于演示的目的, 每个图标一行).
LV.Add("Icon" . A_Index, A_Index, "n/a")
MyGui.Show()
ImageList functions:
创建一个新的初始为空的图像列表.
ImageListID := IL_Create(InitialCount, GrowCount, LargeIcons)
类型: 整数
如果省略, 默认为 2. 否则, 请指定希望立即放入列表的图标数量.
类型: 整数
如果省略, 默认为 5. 否则, 请指定每次超过当前列表容量时, 列表将增加的图标数量.
类型: 布尔值
如果省略, 则默认为 false.
如果为 false, ImageList 将包含小图标.
如果为 true, ImageList 将包含大图标.
添加到列表中的图标自动进行缩放, 以符合系统中大小图标的尺寸.
类型: 整数
成功时, 函数返回新创建的图像列表的唯一 ID. 失败时, 返回 0.
添加图标或图片到指定的图像列表.
IconIndex := IL_Add(ImageListID, IconFileName , IconNumber) IconIndex := IL_Add(ImageListID, PicFileName, MaskColor, Resize)
类型: 整数
之前调用 IL_Create 返回的 ID 号.
类型: 字符串
图标(.ICO), 光标(.CUR) 或动画光标(.ANI) 文件的名称(动态光标在 ListView 中显示时实际将不会动), 或图标句柄 , 如 "HBITMAP:" handle. 图标的其他来源包含下列类型的文件: EXE, DLL, CPL, SCR, 以及包含图标资源的其他类型.
类型: 整数
如果省略, 默认为 1(第一个图标组). 否则, 请指定请指定文件中要使用的图标组的编号. 如果为负数, 则假定其绝对值表示可执行文件中图标的资源 ID. 在下面的例子中, 将使用第二个图标组中的默认图标: IL_Add(ImageListID, "C:\My Application.exe", 2).
类型: 字符串
非图标图像的名称, 例如 BMP, GIF, JPG, PNG, TIF, Exif, WMF 和 EMF, 或位图句柄, 如 "HBITMAP:" handle.
类型: 整数
屏蔽的/透明的颜色编码. 对于大多数图片, 0xFFFFFF(白色) 可能是最佳的.
类型: 布尔值
如果为 true, 则图片缩放为单个图标.
如果为 false, 则图片将被分割为多个可以匹配实际宽度的图标.
类型: 整数
成功时, 函数返回新图标的索引(首个图标索引为 1, 第二个为 2, 依此类推). 失败时, 返回 0.
删除指定的图像列表.
IsDestroyed := IL_Destroy(ImageListID)
类型: 整数(布尔值)
成功时, 函数返回 1(true). 失败时, 返回 0(false).
通常没必要销毁图像列表, 因为一旦关联到 ListView, 当 ListView 或其父窗口销毁时它们会被自动销毁. 但是, 如果一个 ListView 和其他 ListView 共享图像列表(通过在 Options 中包含 0x40), 在所有使用此图像列表的 ListView 销毁后脚本应该显式地销毁它. 同样地, 如果脚本使用一个新的图像列表代替 ListView 中原来的, 则应该显式销毁原来的图像列表.
Gui.Submit 对 ListView 控件没有效果.
在对某个列进行排序后 -- 通过用户点击其标题或脚本调用 LV.ModifyCol(1, "Sort") -- 任何随后添加的行将出现在列表的底部而不会遵循排序顺序. 例外情况是 Sort 和 SortDesc 样式, 它们会把新添加的行移动正确的位置.
当 ListView 拥有焦点时如果要检测到用户是否按下 Enter 键, 请使用默认按钮(如果需要则可以隐藏它). 例如:
MyGui.Add("Button", "Hidden Default", "OK").OnEvent("Click", LV_Enter)
...
LV_Enter(*) {
global
if MyGui.FocusedCtrl != LV
return
MsgBox("Enter was pressed. The focused row number is " LV.GetNext(0, "Focused"))
}
使用键盘除了在行与行之间导航外, 用户还可以通过输入首列中一个项目名称的前几个字符来进行增量搜索. 这使得选择对象跳转到最近匹配的行.
尽管 ListView 中的每个字段可以存储任意长度的文本, 但仅显示开始的 260 个字符.
尽管 ListView 中可以使用的最大行数仅受系统可用内存的限制, 但参照 Count 选项中描述的方法可以极大地提高添加行的性能.
可以使用图片作为 ListView 周围的背景(即作为 ListView 的框架). 要实现这个效果, 请在 ListView 后创建图片控件并且在图片控件的 Options 中包含 0x4000000(这是 WS_CLIPSIBLINGS).
脚本可以在每个窗口中创建多个 ListView.
最好不要使用 SendMessage 直接插入或删除列. 这是因为程序为每个列维护一个排序参数集, 而这会让它们无法同步. 作为替代, 请使用内置的列的方法.
要对 ListView 执行一些操作(例如调整大小, 隐藏或改变字体), 请参阅 GuiControl 对象.
要从外部 ListView(那些不属于脚本自身的) 中提取文本, 请使用 ListViewGetContent.
TreeView, 其他控件类型, Gui, ContextMenu 事件, Gui 对象, GuiControl 对象, ListView 样式列表
LV.Modify(0, "Select") ; 选择所有行. LV.Modify(0, "-Select") ; 取消选择所有行. LV.Modify(0, "-Check") ;取消选中所有复选框.
LV.ModifyCol() ; 此模式不需要参数.
下面是一个比页面顶部的脚本更复杂的可工作的脚本. 它显示用户选择的文件夹中的文件, 且每个文件分配一个与其类型关联的图标. 用户在一个文件上双击或在一个或多个文件上右击后, 会显示上下文菜单.
; 创建 GUI 窗口:
MyGui := Gui("+Resize") ; 允许用户最大化窗口或拖动来改变窗口的大小.
; 创建一些按钮:
B1 := MyGui.Add("Button", "Default", "Load a folder")
B2 := MyGui.Add("Button", "x+20", "Clear List")
B3 := MyGui.Add("Button", "x+20", "Switch View")
; 创建 ListView 及其列:
LV := MyGui.Add("ListView", "xm r20 w700", ["Name", "In Folder", "Size (KB)", "Type"])
LV.ModifyCol(3, "Integer") ; 为了排序, 表示 Size 列中的内容是整数.
; 创建图像列表, 这样 ListView 才可以显示图标:
ImageListID1 := IL_Create(10)
ImageListID2 := IL_Create(10, 10, true) ; 搭配小图标列表的大图标列表.
; 将图像列表附加到 ListView 上, 这样它就可以在以后显示图标:
LV.SetImageList(ImageListID1)
LV.SetImageList(ImageListID2)
; 应用控件事件:
LV.OnEvent("DoubleClick", RunFile)
LV.OnEvent("ContextMenu", ShowContextMenu)
B1.OnEvent("Click", LoadFolder)
B2.OnEvent("Click", (*) => LV.Delete())
B3.OnEvent("Click", SwitchView)
; 应用窗口事件:
MyGui.OnEvent("Size", Gui_Size)
; 创建弹出式菜单, 作为上下文菜单使用:
ContextMenu := Menu()
ContextMenu.Add("Open", ContextOpenOrProperties)
ContextMenu.Add("Properties", ContextOpenOrProperties)
ContextMenu.Add("Clear from ListView", ContextClearRows)
ContextMenu.Default := "Open" ; 将 "Open(打开)" 改为粗体字, 以表明这是双击的默认动作.
; 显示窗口:
MyGui.Show()
LoadFolder(*)
{
static IconMap := Map()
MyGui.Opt("+OwnDialogs") ; 强制用户在使用主窗口之前关闭下面的对话框.
Folder := DirSelect(, 3, "Select a folder to read:")
if not Folder ; 用户取消对话框.
return
; 检查文件夹名称的最后一个字符是否为反斜杠, 对于根目录则会如此,
; 例如 C:\. 如果是, 则移除这个反斜杠以避免之后出现两个反斜杠.
if SubStr(Folder, -1, 1) = "\"
Folder := SubStr(Folder, 1, -1) ; 移除尾部的反斜杠.
; 计算 SHFILEINFO 结构需要的缓冲大小.
sfi_size := A_PtrSize + 688
sfi := Buffer(sfi_size)
; 获取所选择文件夹中的文件名列表并添加到 ListView:
LV.Opt("-Redraw") ; 在加载时禁用重绘来提升性能.
Loop Files, Folder "\*.*"
{
FileName := A_LoopFilePath ; 必须保存到可写的变量中供后面使用.
; 建立唯一的扩展 ID 以避免变量名中的非法字符,
; 例如破折号. 这种使用唯一 ID 的方法也会执行地更好,
; 因为在数组中查找项目不需要进行搜索循环.
SplitPath(FileName,,, &FileExt) ; 获取文件扩展名.
if FileExt ~= "i)\A(EXE|ICO|ANI|CUR)\z"
{
ExtID := FileExt ; 特殊 ID 作为占位符.
IconNumber := 0 ; 将其标记为未找到, 以便这些类型可以有一个唯一的图标.
}
else ; 其他的扩展名/文件类型, 计算它们的唯一 ID.
{
ExtID := 0 ; 进行初始化来处理比其他更短的扩展名.
Loop 7 ; 限制扩展名为 7 个字符, 这样之后计算的结果才能存放到 64 位值.
{
ExtChar := SubStr(FileExt, A_Index, 1)
if not ExtChar ; 没有更多字符了.
break
; 把每个字符与不同的位置进行运算来得到唯一 ID:
ExtID := ExtID | (Ord(ExtChar) << (8 * (A_Index - 1)))
}
; 检查此文件扩展名的图标是否已经在图像列表中. 如果是,
; 可以避免多次调用并极大提高性能,
; 尤其对于包含数以百计文件的文件夹而言:
IconNumber := IconMap.Has(ExtID) ? IconMap[ExtID] : 0
}
if not IconNumber ; 此扩展名还没有相应的图标, 所以进行加载.
{
; 取与此文件扩展名关联的高质量小图标:
if not DllCall("Shell32\SHGetFileInfoW", "Str", FileName
, "Uint", 0, "Ptr", sfi, "UInt", sfi_size, "UInt", 0x101) ; 0x101 是 SHGFI_ICON+SHGFI_SMALLICON
IconNumber := 9999999 ; 把它设置到范围外来显示空图标.
else ; 成功加载图标.
{
; 从结构中提取 hIcon 成员:
hIcon := NumGet(sfi, 0, "Ptr")
; 直接添加 HICON 到小图标和大图标列表.
; 下面加上 1 来把返回的索引从基于零转换到基于一:
IconNumber := DllCall("ImageList_ReplaceIcon", "Ptr", ImageListID1, "Int", -1, "Ptr", hIcon) + 1
DllCall("ImageList_ReplaceIcon", "Ptr", ImageListID2, "Int", -1, "Ptr", hIcon)
; 现在已经把它复制到图像列表, 所以应销毁原来的:
DllCall("DestroyIcon", "Ptr", hIcon)
; 缓存图标来节省内存并提升加载性能:
IconMap[ExtID] := IconNumber
}
}
; 在 ListView 中创建新行并把它和上面的图标编号进行关联:
LV.Add("Icon" . IconNumber, A_LoopFileName, A_LoopFileDir, A_LoopFileSizeKB, FileExt)
}
LV.Opt("+Redraw") ; 重新启用重绘(上面把它禁用了).
LV.ModifyCol() ; 根据内容自动调整每列的大小.
LV.ModifyCol(3, 60) ; 把 Size 列加宽一些以便显示出它的标题.
}
SwitchView(*)
{
static IconView := false
if not IconView
LV.Opt("+Icon") ; 切换到图标视图.
else
LV.Opt("+Report") ; 切换回详细信息视图.
IconView := not IconView ; 进行反转以为下次做准备.
}
RunFile(LV, RowNumber)
{
FileName := LV.GetText(RowNumber, 1) ; 获取首个字段的文本.
FileDir := LV.GetText(RowNumber, 2) ; 获取第二个字段的文本.
try
Run(FileDir "\" FileName)
catch
MsgBox("Could not open " FileDir "\" FileName ".")
}
ShowContextMenu(LV, Item, IsRightClick, X, Y) ; 响应右键或 Apps 键.
{
; 在所提供的 X 和 Y 坐标处显示菜单.
; 这些应该被使用, 因为即使用户按了 Apps 键, 它们也能提供正确的坐标:
ContextMenu.Show(X, Y)
}
ContextOpenOrProperties(ItemName, *) ; 用户在上下文菜单中选择了 "Open" 或 "Properties".
{
; 简单地说, 只对焦点行进行操作, 而不是对所有选中的行进行操作:
FocusedRowNumber := LV.GetNext(0, "F") ; 查找焦点行.
if not FocusedRowNumber ; 没有聚焦行.
return
FileName := LV.GetText(FocusedRowNumber, 1) ; 获取首个字段的文本.
FileDir := LV.GetText(FocusedRowNumber, 2) ; 获取第二个字段的文本.
try
{
if (ItemName = "Open") ; 用户在上下文菜单中选择了 "Open".
Run(FileDir "\" FileName)
else
Run("properties " FileDir "\" FileName)
}
catch
MsgBox("Could not perform requested action on " FileDir "\" FileName ".")
}
ContextClearRows(*) ; 用户在上下文菜单中选择了 "Clear".
{
RowNumber := 0 ; 这会使得首次循环从顶部开始搜索.
Loop
{
; 由于删除了一行使得此行下面的所有行的行号都减小了,
; 所以把行号减 1, 这样搜索里包含的行号才会与之前找到的行号相一致
; (以防选择了相邻行):
RowNumber := LV.GetNext(RowNumber - 1)
if not RowNumber ; 上面返回零, 所以没有更多选择的行了.
break
LV.Delete(RowNumber) ; 从 ListView 中删除行.
}
}
Gui_Size(thisGui, MinMax, Width, Height) ; 扩大或缩小 ListView 来响应用户对窗口大小的改变.
{
if MinMax = -1 ; 窗口被最小化了. 无需进行操作.
return
; 否则, 窗口的大小被调整过或被最大化了. 调整 ListView 的大小来适应.
LV.Move(,, Width - 20, Height - 40)
}