关于组合框

组合框将编辑框或静态文本与列表组合在一起。

本主题包含以下各节:

组合框类型和样式

组合框由一个列表和一个选择字段组成。 该列表显示用户可以选择的选项,选择字段显示当前选择。 如果选择字段是一个编辑控件,则用户可以输入列表外的信息;否则,用户只能选择列表中的项目。

通用控件库包括三种主要样式的组合框,如下表所示。

组合框类型 样式常量 说明
简单 CBS_SIMPLE 始终显示列表,并在编辑控件中显示所选项目。
下拉列表 CBS_DROPDOWN 单击图标时显示列表,并在编辑控件中显示所选项目。
下拉列表(下拉列表) CBS_DROPDOWNLIST 单击图标时显示列表,并在静态控件中显示所选项目。

 

下面的屏幕截图分别显示了在 WindowsVista 中可能出现的三种组合框。 在第一个屏幕截图中,用户在简单组合框中选择了一个项目。 用户还可以在该控件的编辑框中键入新值。 该列表已在 Microsoft Visual Studio 资源编辑器中进行了调整,其大小仅足以容纳两个项目。

screen shot showing an item selected in a simple combo box

在第二个屏幕截图中,用户在下拉组合框的编辑控件中键入了新文本。 用户也可以选择一个现有的项目。 列表框将展开以容纳尽可能多的项目。

screen shot showing text typed into a drop-down combo box

在第三个屏幕截图中,用户打开了下拉列表组合框。 列表框将展开以容纳尽可能多的项目。 用户无法输入新文本。

screen shot showing an item selected in a drop-down list combo box

还有许多组合框样式可以定义特定的属性。 组合框样式定义组合框的特定属性。 可以组合样式;但是,有些样式仅适用于某些组合框类型。 有关组合框样式的表,请参阅组合框样式

注意

若要将视觉样式与组合框一起使用,应用程序必须包含清单,并且必须在程序开头调用 InitCommonControls。 有关视觉样式的信息,请参阅视觉样式。 有关清单信息,请参阅启用视觉样式

 

组合框列表

列表是显示用户可以选择的项目的组合框的一部分。 通常,应用程序在创建组合框时会初始化列表的内容。 用户选择的任何列表项都是当前选择。 无法选择多个项。 在简单的下拉组合框中,用户可以在选择字段中键入,而不是选择列表项。 在这些情况下,没有当前选择,并且应用程序负责将项添加到列表中并将其设为当前选择(如果合适的话)。

本部分讨论了以下主题:

当前选择

当前选择是用户已经选择的列表项;所选文本显示在组合框的选择字段中。 但是,对于简单的组合框或下拉组合框,当前选择只是组合框中可能的用户输入的一种形式。 用户也可以在选择字段中键入文本。

当前选择由所选列表项的从零开始的索引标识。 应用程序可以随时设置和检索它。 当用户更改组合框的当前选择时,父窗口或对话框过程会收到通知。 应用程序更改所选内容时,不会通知父窗口或对话框。

创建组合框时,没有当前选择。 如果用户编辑了所选字段的内容,则对于简单组合框或下拉组合框也是如此。 要设置当前选择,应用程序会向组合框发送 CB_SETCURSEL 消息。 应用程序还可以使用 CB_SELECTSTRING 消息将当前选定内容设置为以指定字符串开头的列表项。 要确定当前选择,应用程序会向组合框发送 CB_GETCURSEL 消息。 如果没有当前选择,此消息将返回 CB_ERR。

当用户更改组合框中的当前选择时,父窗口或对话框过程会收到一条 WM_COMMAND 消息,其中 wParam 参数的高位字中包含 CBN_SELCHANGE 通知代码。 使用 CB_SETCURSEL 消息设置当前所选内容时,不会发送此通知代码。

下拉列表关闭时,下拉列表框或下拉列表框会将 CBN_CLOSEUP 通知代码发送到父窗口或对话框过程。 如果用户更改了当前选择,则组合框还会在下拉列表关闭时发送通知代码 CBN_SELCHANGE。 若要在用户每次选择列表项时执行特定进程,你可以处理 CBN_SELCHANGE 或 CBN_CLOSEUP 通知代码。 通常情况下,要先等待 CBN_CLOSEUP 通知代码,然后再处理当前所选内容的更改。 如果需要处理大量内容,这一点尤其重要。

应用程序还可以处理 CBN_SELENDOKCBN_SELENDCANCEL 通知代码。 当用户选择一个列表项目,或者选择一个项目然后关闭列表时,系统会发送 CBN_SELENDOK。 这表示用户已经完成,并且应该处理选择。 当用户选择一个项目,但随后选择另一个控件、在下拉列表打开时按 ESC 或关闭对话框时,将发送 CBN_SELENDCANCEL。 这表示应忽略用户的选择。 CBN_SELENDOK 在每条 CBN_SELCHANGE 消息之前发送。

在一个简单组合框中,当用户双击列表项时,系统会发送 CBN_DBLCLK 通知代码。 在下拉列表组合框或下拉列表中,单击即可隐藏列表,因此无法双击项。

某些通知和消息仅适用于包含下拉列表的组合框。 当下拉列表打开或关闭时,组合框的父窗口会收到一条 WM_COMMAND 消息形式的通知。 如果列表处于打开状态,则 wParam 的高序位词为 CBN_DROPDOWN。 如果列表正在关闭,则为 CBN_CLOSEUP

应用程序可以使用 CB_SHOWDROPDOWN 消息打开下拉列表框或下拉列表框的列表。 它可以使用 CB_GETDROPPEDSTATE 消息确定列表是否打开,并且可以使用 CB_GETDROPPEDCONTROLRECT 消息确定下拉列表的坐标。 应用程序还可以使用 CB_SETDROPPEDWIDTH 消息来增加下拉列表的宽度。

列出内容

当应用程序创建组合框时,通常会通过向列表中添加一个或多个项目来初始化组合框。 稍后,应用程序可以添加或删除列表项、重新初始化列表或从中检索项信息。

应用程序通过向其发送 CB_ADDSTRING 消息,将列表项添加到组合框。 指定的项将添加到列表的末尾,或者,在排序的组合框中,根据项的字符串将其添加到正确的排序位置。 在未排序的组合框中,应用程序可以使用 CB_INSERTSTRING 消息在特定位置插入项。 添加后,列表项将按其位置进行标识。

通过使用 CB_FINDSTRINGCB_FINDSTRINGEXACT 消息,应用程序可以确定列表项的位置。 CB_FINDSTRING 查找字符串以指定字符串开头的项。 CB_FINDSTRINGEXACT 查找其字符串与字符串完全匹配的项。 这两条消息都不区分大小写。

应用程序可以使用 CB_DELETESTRING 消息删除列表项。 如果应用程序需要重新初始化组合框列表,它可以首先使用 CB_RESETCONTENT 消息清除其全部内容。 在显示组合框后向列表中添加多个项目时,应用程序可以清除重绘标志,以防止在添加每个项目后重新绘制组合框。 有关重绘的详细信息,请参阅 WM_SETREDRAW 消息的说明。

若要检索与列表项关联的字符串,应用程序可以使用 CB_GETLBTEXT 消息。 项的字符串被复制到应用程序指定的缓冲区中。 为了确保缓冲区足够大来接收字符串,应用程序可以首先使用 CB_GETLBTEXTLEN 消息来确定字符串的长度。 若要获取组合框中的列表项数,应用程序可以使用 CB_GETCOUNT 消息。

编辑控件选择字段

应用程序可以检索或设置选择字段的内容,并可以确定或设置编辑选择。 应用程序还可以限制用户可以在选择字段中键入的文本量。 当选择字段的内容发生更改时,系统会向父窗口或对话框过程发送通知消息。

若要检索选择字段的内容,应用程序可以向组合框发送 WM_GETTEXT 消息。 若要设置简单组合框或下拉组合框的选择字段的内容,应用程序可以向组合框发送 WM_SETTEXT 消息。

编辑选择是简单组合框或下拉组合框的选择字段中所选文本的范围(如果有)。 应用程序可以使用 CB_GETEDITSEL 消息来确定当前所选内容的起始和结束字符位置。 还可以使用 CB_SETEDITSEL 消息来选择编辑选择中的字符。

最初,用户可以在选择字段中键入的文本量受到选择字段大小的限制。 但是,如果组合框具有 CBS_AUTOHSCROLL 样式,则文本可以继续超出选择字段的大小。 无论控件是否具有 CBS_AUTOHSCROLL 样式,应用程序都可以使用 CB_LIMITTEXT 消息来限制用户可以在选择字段中键入的文本量。

当用户编辑选择字段的内容时,父窗口或对话框过程会收到通知消息。 首先发送 CBN_EDITUPDATE 通知代码,表示选择字段中的文本已被编辑。 显示更改的文本后,系统将发送 CBN_EDITCHANGE。 当选择字段内容因选择列表项而发生更改时,不会发送这些消息。

所有者绘制的组合框

应用程序可以创建一个所有者绘制的组合框来负责绘制列表项。 当需要绘制组合框的一部分时,所有者绘制的组合框(其所有者)的父窗口会收到 WM_DRAWITEM 消息。 所有者绘制的组合框可以列出除文本字符串以外的信息,也可以列出文本字符串之外的信息。 所有者绘制的组合框可以是任何类型。 但是,简单组合框或下拉组合框中的编辑控件只能显示文本,而所有者在下拉列表框中绘制选择字段。

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

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

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

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

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

子类化组合框

子类是一个允许应用程序拦截和处理发送或发布到窗口的消息的过程。 通过使用子类化,应用程序可以用自己的处理来代替某些消息,同时将大多数消息处理留给类定义的窗口过程。

操作系统创建窗口时,会将有关该窗口的信息保存在内部数据结构中,该结构包括指向窗口过程的指针。 若要对窗口进行子类化,应用程序调用 SetClassLong 函数,将指向该过程的指针替换为指向应用程序定义的子类过程的指针。 此后,发送到窗口的所有消息都将发送到子类过程。 然后,此过程使用 CallWindowProc 函数将未处理的消息传递到原始窗口过程。 有关 COMBOBOX 类窗口过程执行的消息处理的说明,请参阅默认组合框行为

当组合框位于对话框之外时,应用程序无法处理 TAB、ENTER 和 ESC 键,除非它使用子类过程。 当简单组合框或下拉组合框收到输入焦点时,它会立即将焦点设置为其子编辑控件。 因此,应用程序必须对编辑控件进行子类化,以截获简单组合框或下拉组合框的键盘输入。 有关此示例,请参阅子类化组合框

如果子类过程处理 WM_PAINT 消息,则必须使用 BeginPaint 函数来准备绘制。 在调用 EndPaint 函数之前,它将设备上下文 (DC) 句柄作为窗口过程的 wParam 参数传递。 如果首先调用 EndPaint,则类窗口过程不会进行绘制,因为 EndPaint 会验证整个窗口。

与子类化相关的一种技术是超类化。 超级类类似于任何其他类,只是它的窗口过程不调用 DefWindowProc 来处理未处理的消息。 相反,它将未处理的消息传递给父窗口类的窗口过程。 请遵循窗口过程中的指导原则,以避免子类化和超类化可能出现的问题。