关于列表框

列表框控件包含一个简单的列表,用户通常可从中选择一个或多个项。 与列表视图控件相比,列表框提供的灵活性有限。

列表框项可以由文本字符串、位图或两者表示。 如果列表框不够大,无法同时显示所有列表框项,则列表框提供滚动条。 用户滚动浏览列表框项,并根据需要应用或删除选择状态。 选择列表框项会更改其视觉外观,通常通过将文本和背景颜色更改为由相关操作系统指标指定的颜色。 当用户选择或取消选择某个项目时,系统会向列表框的父窗口发送一条通知消息。

对于 ANSI 应用程序,系统使用 CP_ACP 代码页将列表框中的文本转换为 Unicode。 这可能会导致问题。 例如,在 Windows 中,非 Unicode 列表框中的重音罗马字符,日语版本会出现乱码。 若要解决此问题,可将应用程序编译为 Unicode 或使用所有者绘制的列表框。

本部分讨论了以下主题:

创建列表框

在对话框中创建列表框的最简单方法是将其从 Microsoft Visual Studio 中的工具箱拖到对话框资源上。 若要动态创建列表框或在对话框以外的窗口中创建列表框,请使用 CreateWindowEx 函数,指定 WC_LISTBOX 窗口类和相应的列表框样式

列表框类型和样式

有两种类型的列表框:单选(默认值)和多选。 在单个选择列表框中,用户一次只能选择一个项目。 在多选列表框中,用户一次可以选择多个项。 若要创建多选列表框,请指定 LBS_MULTIPLESELLBS_EXTENDEDSEL 样式。

列表框的外观和操作由列表框样式和窗口样式控制。 这些样式指示列表是否排序、排列在多个列中、由应用程序绘制等。 列表框的尺寸和样式通常在包含在应用程序的资源的对话框模板中定义。

注意

若要对这些控件使用视觉样式,应用程序必须包含清单,并且必须在程序开头调用 InitCommonControls。 有关视觉样式的信息,请参阅视觉样式。 有关清单信息,请参阅启用视觉样式

列表框函数

DlgDirList 函数将列表框的内容替换为与指定条件集匹配的驱动器、目录和文件的名称。 DlgDirSelectEx 函数检索由 DlgDirList 初始化的列表框中的当前选定内容。 通过这些函数,用户可以从列表框中选择驱动器、目录或文件,而无需键入文件的位置和名称。

此外,GetListBoxInfo 函数返回指定列表框中每个列的项数。

列表框中的通知消息

在列表框中发生事件时,列表框会以 WM_COMMAND 消息的形式向所有者窗口的对话框过程发送通知代码。 当用户选择、双击或取消列表框项时,将发送列表框通知代码;当列表框接收或失去键盘焦点时;当系统无法为列表框请求分配足够的内存时。 WM_COMMAND 消息包含 wParam 参数的低序单词中的列表框标识符,以及高序单词中的通知代码。 lParam 参数包含控件窗口句柄。

处理这些消息不需要对话框过程;默认窗口过程处理它们。

应用程序监视和处理以下列表框通知代码。

通知代码 说明
LBN_DBLCLK 用户双击列表框中的项目。
LBN_ERRSPACE 列表框无法分配足够的内存来满足请求。
LBN_KILLFOCUS 列表框会失去键盘焦点。
LBN_SELCANCEL 用户取消列表框中项的选择。
LBN_SELCHANGE 列表框中的选择即将更改。
LBN_SETFOCUS 列表框接受键盘焦点。

给列表框的消息

对话框过程可以将消息发送到列表框,以添加、删除、检查和更改列表框项。 例如,对话框过程可以将 LB_ADDSTRING 消息发送到列表框以添加项,发送 LB_GETSEL 消息,以确定该项是否处于选中状态。 其他消息设置和检索有关列表框的大小、外观和行为的信息。 例如,LB_SETHORIZONTALEXTENT 消息设置列表框的可滚动宽度。 对话框过程可以使用 SendMessageSendDlgItemMessage 函数将任何消息发送到列表框。

列表框项通常由其索引引用,该整数表示项在列表框中的位置。 列表框中第一项的索引为 0,第二项的索引为 1,以此类推。

下表介绍了预定义列表框过程如何响应列表框消息。

Message 响应
LB_ADDFILE 将文件插入到由 DlgDirList 函数填充的目录列表框中,并检索插入项的列表框索引。
LB_ADDSTRING 将字符串添加到列表框并返回其索引。
LB_DELETESTRING 从列表框中删除字符串,并返回列表中保留的字符串数。
LB_DIR 将文件名列表添加到列表框中,并返回最后添加的文件名的索引。
LB_FINDSTRING 返回列表框中以指定字符串开头的第一个字符串的索引。
LB_FINDSTRINGEXACT 返回列表框中等于指定字符串的字符串的索引。
LB_GETANCHORINDEX 返回鼠标上次选择的项目的索引。
LB_GETCARETINDEX 返回具有焦点矩形的项的索引。
LB_GETCOUNT 返回列表框中的项数。
LB_GETCURSEL 返回当前所选项目的索引。
LB_GETHORIZONTALEXTENT 返回列表框的可滚动宽度(以像素为单位)。
LB_GETITEMDATA 返回与指定项关联的值。
LB_GETITEMHEIGHT 返回列表框中项目的高度(以像素为单位)。
LB_GETITEMRECT 检索指定列表框项的客户端坐标。
LB_GETLOCALE 检索列表框的区域设置。 高序位词包含国家/地区代码,低高序位词包含语言标识符。
LB_GETSEL 返回列表框项的选择状态。
LB_GETSELCOUNT 返回多选列表框中选定项的数目。
LB_GETSELITEMS 在多选列表框中创建所有选定项的索引数组,并返回选定项的总数。
LB_GETTEXT 检索与指定项和字符串长度关联的字符串。
LB_GETTEXTLEN 返回与指定项关联的字符串的长度(以字符为单位)。
LB_GETTOPINDEX 返回列表框中第一个可见项的索引。
LB_INITSTORAGE 为指定的项数及其关联的字符串分配内存。
LB_INSERTSTRING 在列表框中的指定索引处插入字符串。
LB_ITEMFROMPOINT 检索列表框中最接近指定点的项的从零开始的索引。
LB_RESETCONTENT 从列表框中移除所有项。
LB_SELECTSTRING 选择它找到的第一个与指定前缀匹配的字符串。
LB_SELITEMRANGE 在列表框中选择指定的项目范围。
LB_SELITEMRANGEEX 如果区域中第一项的索引小于区域中最后一项的索引,则选择指定的项范围。 如果第一项的索引大于最后一项,则取消区域中的选择。
LB_SETANCHORINDEX 将鼠标上次选择的项目设置为指定的项目。
LB_SETCARETINDEX 将焦点矩形设置为指定的列表框项目。
LB_SETCOLUMNWIDTH 设置列表框中所有列的宽度(以像素为单位)。
LB_SETCOUNT 设置列表框中的项目数。
LB_SETCURSEL 选择指定的列表框项。
LB_SETHORIZONTALEXTENT 设置列表框的可滚动宽度(以像素为单位)。
LB_SETITEMDATA 将值与列表框项相关联。
LB_SETITEMHEIGHT 设置列表框中项的高度(以像素为单位)。
LB_SETLOCALE 设置列表框的区域设置并返回以前的区域设置标识符。
LB_SETSEL 在多选列表框中选择一个项目。
LB_SETTABSTOPS 将制表位设置为指定数组中指定的制表位。
LB_SETTOPINDEX 滚动列表框,使指定的项目位于可见范围的顶部。

默认窗口消息处理

预定义列表框窗口类的窗口过程对列表框未处理的所有消息执行默认处理。 当列表框过程为消息返回 FALSE 时,预定义的窗口过程会检查消息并执行默认操作,如下表所示。

Message 默认操作
WM_CHAR 将所选内容移动到以用户键入的字符开头的第一个项目。 如果列表框具有 LBS_OWNERDRAW 样式,则不会发生任何操作。 在短间隔内键入的多个字符被视为组,选择以该系列字符开头的第一项。
WM_CREATE 创建一个空的列表框。
WM_DESTROY 销毁列表框并释放它使用的任何资源。
将消息传递给对话框过程或父窗口进程。
WM_ENABLE 如果控件可见,则使矩形无效,以便字符串可以被绘制为灰色。
WM_ERASEBKGND 擦除列表框的背景。 如果列表框具有 LBS_OWNERDRAW 样式,则不会擦除背景。
WM_GETDLGCODE 返回 DLGC_WANTARROWS | DLGC_WANTCHARS,指示默认列表框过程处理箭头键和 WM_CHAR 消息。
WM_GETFONT 返回列表框的当前字体的句柄。
WM_HSCROLL 水平滚动列表框。
WM_KEYDOWN 处理用于滚动的虚拟键。 虚拟键是要将插入点移动到的项的索引。 所选内容不会更改。
WM_KILLFOCUS 关闭插入点并销毁它。 将 LBN_KILLFOCUS 通知代码发送到列表框的所有者。
WM_LBUTTONDBLCLK 跟踪列表框工作区中的鼠标。 这样,如果用户的鼠标按钮在列表框工作区外释放,则用户可以取消选择。
WM_LBUTTONDOWN 跟踪列表框工作区中的鼠标。 这样,如果用户的鼠标按钮在列表框工作区外释放,则用户可以取消选择。
WM_LBUTTONUP 跟踪列表框工作区中的鼠标。 这样,如果用户的鼠标按钮在列表框工作区外释放,则用户可以取消选择。
WM_MOUSEMOVE 跟踪列表框工作区中的鼠标。 这样,如果用户的鼠标按钮在列表框工作区外释放,则用户可以取消选择。
WM_PAINT 使用列表框句柄执行设备上下文 (DC) 的子类绘制操作。
WM_SETFOCUS 打开插入符号并将 LBN_SETFOCUS 通知代码发送到列表框的所有者。
WM_SETFONT 设置列表框的新字体。
WM_SETREDRAW 根据 wParam 的值设置或清除重绘标志。
WM_SIZE 将列表框的大小调整为项目的整数个数。
WM_VSCROLL 垂直滚动列表框。

预定义的列表框将所有其他消息传递到 DefWindowProc,以便进行默认处理。

所有者绘制的列表框

应用程序可以创建一个所有者绘制的组合框来负责绘制列表项。 需要绘制列表框的一部分时,所有者绘制列表框(其所有者)的父窗口或对话框会收到 WM_DRAWITEM 消息。 所有者绘制的列表框可以列出除文本字符串以外的信息,也可以列出文本字符串之外的信息。

所有者绘制的列表框的所有者必须处理 WM_DRAWITEM 消息。 每当必须重绘列表框的一部分时,就会发送此消息。 所有者可能需要处理其他消息,具体取决于为列表框指定的样式。

应用程序可以通过指定 LBS_OWNERDRAWFIXEDLBS_OWNERDRAWVARIABLE 样式来创建所有者绘制的列表框。 如果列表框中的所有列表项高度相同(如字符串或图标),则应用程序可以使用 LBS_OWNERDRAWFIXED 样式。 如果列表项的高度不同(如不同大小的位图),则应用程序可以使用 LBS_OWNERDRAWVARIABLE 样式。

所有者绘制的列表框的所有者可以处理 WM_MEASUREITEM 消息以指定列表项的尺寸。 如果应用程序使用 LBS_OWNERDRAWFIXED 样式创建列表框,则系统仅发送 WM_MEASUREITEM 消息一次。 所有者指定的维度用于所有列表项。 如果使用 LBS_OWNERDRAWVARIABLE 样式,系统将为每个添加到列表框的列表项发送 WM_MEASUREITEM 消息。 所有者可以通过分别使用 LB_GETITEMHEIGHTLB_SETITEMHEIGHT 消息来确定或设置列表项的高度。

如果所有者绘制列表框中显示的信息包括文本,则应用程序可以通过指定 LBS_HASSTRINGS 样式来跟踪每个列表项的文本。 具有 LBS_SORT 样式的列表框将基于此文本进行排序。 如果列表框已排序,但是不是 LBS_HASSTRINGS 样式,则所有者必须处理 WM_COMPAREITEM 消息。

在所有者绘制的列表框中,所有者必须跟踪包含除文本以外的信息的列表项。 执行此操作的一种简便方法是使用 LB_SETITEMDATA 消息将句柄另存为项数据。 若要释放与列表框中的项目关联的数据对象,所有者可以处理 WM_DELETEITEM 消息。

有关所有者绘制的列表框的示例,请参阅如何创建所有者绘制的列表框

拖动列表框

拖动列表框是一种特殊的列表框类型,使用户能够将项目从一个位置拖动到另一个位置。 应用程序可以使用拖动列表框来显示特定序列中的字符串,并使用户能够通过将项拖动到位置来更改序列。

创建拖动列表框

拖动列表框具有相同的窗口样式,并处理与标准列表框相同的消息。 若要创建拖动列表框,请先创建标准列表框,然后调用 MakeDragList 函数。 若要将对话框中的列表框转换为拖动列表框,可以在处理 WM_INITDIALOG 消息时调用 MakeDragList

拖动列表框消息

拖动列表框通过向其发送拖动列表消息来通知拖动事件的父窗口。 父窗口必须处理拖动列表消息。

调用 MakeDragList 函数时,拖动列表框将注册此消息。 若要检索拖动列表消息的消息标识符(数值),请调用 RegisterWindowMessage 函数并指定 DRAGLISTMSGSTRING 值。

拖动列表消息的 wParam 参数是拖动列表框的控制标识符。 lParam 参数是 DRAGLISTINFO 结构的地址,其中包含拖动事件和其他信息的通知代码。 消息的返回值取决于通知。

拖动列表框通知代码

拖动列表通知代码(由拖动列表消息随附的 DRAGLISTINFO 结构的 uNotification 成员标识)可以是 DL_BEGINDRAGDL_DRAGGINGDL_CANCELDRAGDL_DROPPED

当光标位于列表项上并且用户单击鼠标左键时,将发送 DL_BEGINDRAG 通知代码。 父窗口返回 TRUE,开始拖动操作;或返回 FALSE,禁止拖动。 通过这种方式,父窗口可以为某些列表项启用拖动,而为其他列表项禁用拖动。 可以使用 LBItemFromPt 函数确定位于指定位置的列表项。

如果拖动有效,则无论何时移动鼠标,都会发送 DL_DRAGGING 通知代码;如果未移动鼠标,则会定期发送通知代码。 父窗口应首先使用 LBItemFromPt 确定光标下的列表项,然后使用 DrawInsert 函数绘制插入图标。 通过为 LBItemFromPtbAutoScroll 参数指定 TRUE,如果光标位于其工作区上方或下方,则列表框可能会滚动一行。 为此通知返回的值指定拖动列表框应设置的鼠标光标类型。

如果用户通过单击鼠标右键或按 ESC 键取消拖动操作,则会发送 DL_CANCELDRAG 通知代码。 如果用户通过释放鼠标左键完成拖动操作,则会发送 DL_DROPPED 通知代码,即使光标不在列表项上也是如此。 拖动列表框会在发送任一通知之前释放鼠标捕获。 这两个通知的返回值将被忽略。 拖动列表