列表框是窗口类名为"ListBox"的预定义子窗口,在窗口矩形内包含有一些可以滚动显示的栏状字符串列表。标准的列表框只能允许选中一个条目,选中的条目将以系统颜色COLOR_HIGHLIGHT高亮显示。Windows还提供了多种不同风格的标准列表框,其中包括多选列表框、多列显示的列表框和可以显示图象的拥有者画(Owner-draw)列表框等。另一种与列表框相关的控件是组合框,该控件预定义类名为"COMBOBOX",实际是一个编辑控件同一个彼此相关的列表框控件的组合。用户既可以在组合框的编辑栏上直接输入、编辑文字也可以从下拉列表中显示的可能选择中进行选取。
MFC的CListBox 类封装了列表框控件,由成员函数Create()完成对列表框的创建,在创建的同时指定了控件的窗口风格。当列表框中的条目被选中或被鼠标双击后将向父窗口发送WM_COMMAND消息。如果列表框采用了LBS_NOTIFY风格,父窗口就可以通过ON_LBN消息映射宏直接将通知消息同消息处理函数建立起映射关系。列表框提供了十余种窗口风格,现将列表框风格及说明列表如下:
缺省的,列表框在每添加或删除一个条目后都会自动重绘,如果在列表框中已经有了几百条甚至上千条条目,将会因为重绘而引起比较严重的闪烁。可以通过使用LBS_NOREDRAW风格来禁止列表框的自动重绘。在需要更新显示时强制重绘列表框窗口即可。如果在创建时未使用LBS_NOREDRAW风格,可以在增删条目前向列表框发送WM_SETREDRAW消息,指定其不重绘,增添完毕后再次发送WM_SETREDRAW消息重新启用自动重绘风格。示例过程如下:
列表框创建之初是不含任何条目的,通过CListBox成员函数AddString()和InsertString()向列表框增添或插入条目。如果列表框具有LBS_SORT风格,那么新添加字串的位置是不固定的,要根据字串的字母进行排序;如果不具有该风格,新字串将添加到列表框的末尾。
如果有必要,可以使用SetItemDataPtr()或SetItemData()将一个32位的指针(或一个DWORD的值)同列表框中的一个条目联系起来,并且在设置后可以通过调用GetItemDataPtr()或GetItemData()而获取。这样做的目的是可以将列表框中的条目同外部数据建立联系。例如:可以用这种方式非常方便地将一个包含有地址、电话号码和E-mail地址等信息的数据结构同列举在列表框中的持有人建立起关联。当从列表框中选中某个人时,可以同时得到有关该人的通讯信息。
当操作列表框时,将会通过WM_COMMAND消息发送通知给父窗口,消息参数lParam的高字节包含了通知码标识符。在MFC应用程序中,列表框的通知消息通过ON_LBN消息映射宏而映射到类成员函数。下表给出了列表框的几个通知消息以及相应的ON_LBN宏。其中,LBN_DBLCLK,LBN_SELCHANGE和LBN_SELCANCEL通知消息只有在列表框使用了LBS_NOTIFY或LBS_STANDARD风格时才会被发出,其他通知消息则无此限制。
其中,最经常使用的两个通知消息是LBN_DBLCLK和LBN_SELCHANGE。对于不可复选的列表框可以通过GetCurSel()来获取当前双击的是列表框条目的索引值;对于允许多选的列表框则需要用GetCaretIndex()来代替GetCurSel()。下面通过一段示例代码对列表控件的使用做一个直观的演示:
虽然组合框实际是列表框和编辑框的组合,但在使用中的表现使得组合框同其他控件一样当作一个独立的控件去使用。MFC的CComboBox类提供了对组合框的功能支持。在使用Create()函数创建组合框时可以同时指定组合框的风格(参见下表)。
对组合框进行操作也会向父窗口发送通知消息,处理过程同前面几种控件大同小异,是通过ON_CBN消息映射宏完成对通知消息的映射的。下面就给出这些ON_CBN宏的详细说明:
最后给出一段有关组合框的示例代码,从代码实现不难看出组合框控件同前面给出的列表控件在编程实现上的相似性。
MFC的CListBox 类封装了列表框控件,由成员函数Create()完成对列表框的创建,在创建的同时指定了控件的窗口风格。当列表框中的条目被选中或被鼠标双击后将向父窗口发送WM_COMMAND消息。如果列表框采用了LBS_NOTIFY风格,父窗口就可以通过ON_LBN消息映射宏直接将通知消息同消息处理函数建立起映射关系。列表框提供了十余种窗口风格,现将列表框风格及说明列表如下:
列表框风格 | 说明 |
LBS_STANDARD | 创建一个具有边界和垂直滚动条、当选择发生变化或条目被双击时能够通知父窗口的标准列表框。所有条目按字母排序。 |
LBS_SORT | 按字母排序。 |
LBS_NOSEL | 条目可视但不可选。 |
LBS_NOTIFY | 当用户选择或双击一个串时,发出消息通知父窗口。 |
LBS_DISABLENOSCROLL | 在条目不多时依然显示并不起作用的滚动条。 |
LBS_MULTIPLESEL | 允许条目多选。 |
LBS_EXTENDEDSEL | 可用SHIFT和鼠标或指定键组合来选择多个条目。 |
LBS_MULTICOLUMN | 允许多列显示。 |
LBS_OWNERDRAWVARIABLE | 创建一个拥有者画列表框,条目高度可以不同。 |
LBS_OWNERDRAWFIXED | 创建一个具有相同条目高度的拥有者画列表框。 |
LBS_USETABSTOPS | 允许使用TAB制表符。 |
LBS_NOREDRAW | 当条目被增删后不自动更新列表显示。 |
LBS_HASSTRINGS | 记忆了添加到列表中的字串。 |
LBS_WANTKEYBOARDINPUT | 当有键按下时向父窗口发送WM_VKEYTOITEM或WM_CHARTOITEM消息。 |
LBS_NOINTEGRALHEIGHT | 按程序设定尺寸创建列表框。 |
缺省的,列表框在每添加或删除一个条目后都会自动重绘,如果在列表框中已经有了几百条甚至上千条条目,将会因为重绘而引起比较严重的闪烁。可以通过使用LBS_NOREDRAW风格来禁止列表框的自动重绘。在需要更新显示时强制重绘列表框窗口即可。如果在创建时未使用LBS_NOREDRAW风格,可以在增删条目前向列表框发送WM_SETREDRAW消息,指定其不重绘,增添完毕后再次发送WM_SETREDRAW消息重新启用自动重绘风格。示例过程如下:
CListBox m_ctrListBox; // 禁止自动重绘 m_ctrListBox.SendMessage(WM_SETREDRAW, FALSE, 0); // 进行条目增删操作 …… // 允许自动重绘 m_ctrListBox.SendMessage(WM_SETREDRAW, TRUE, 0); |
列表框创建之初是不含任何条目的,通过CListBox成员函数AddString()和InsertString()向列表框增添或插入条目。如果列表框具有LBS_SORT风格,那么新添加字串的位置是不固定的,要根据字串的字母进行排序;如果不具有该风格,新字串将添加到列表框的末尾。
如果有必要,可以使用SetItemDataPtr()或SetItemData()将一个32位的指针(或一个DWORD的值)同列表框中的一个条目联系起来,并且在设置后可以通过调用GetItemDataPtr()或GetItemData()而获取。这样做的目的是可以将列表框中的条目同外部数据建立联系。例如:可以用这种方式非常方便地将一个包含有地址、电话号码和E-mail地址等信息的数据结构同列举在列表框中的持有人建立起关联。当从列表框中选中某个人时,可以同时得到有关该人的通讯信息。
当操作列表框时,将会通过WM_COMMAND消息发送通知给父窗口,消息参数lParam的高字节包含了通知码标识符。在MFC应用程序中,列表框的通知消息通过ON_LBN消息映射宏而映射到类成员函数。下表给出了列表框的几个通知消息以及相应的ON_LBN宏。其中,LBN_DBLCLK,LBN_SELCHANGE和LBN_SELCANCEL通知消息只有在列表框使用了LBS_NOTIFY或LBS_STANDARD风格时才会被发出,其他通知消息则无此限制。
通知码标识符 | ON_LBN宏 | 值 | 含义 |
LBN_SETFOCUS | ON_LBN_SETFOCUS | 4 | 列表框接收到输入焦点 |
LBN_KILLFOCUS | ON_LBN_KILLFOCUS | 5 | 列表框接失去输入焦点 |
LBN_ERRSPACE | ON_LBN_ERRSPACE | -2 | 列表框存储溢出 |
LBN_DBLCLK | ON_LBN_DBLCLK | 2 | 双击条目 |
LBN_SELCHANGE | ON_LBN_SELCHANGE | 1 | 改变选择 |
LBN_SELCANCEL | ON_LBN_SELCANCEL | 3 | 取消选择 |
其中,最经常使用的两个通知消息是LBN_DBLCLK和LBN_SELCHANGE。对于不可复选的列表框可以通过GetCurSel()来获取当前双击的是列表框条目的索引值;对于允许多选的列表框则需要用GetCaretIndex()来代替GetCurSel()。下面通过一段示例代码对列表控件的使用做一个直观的演示:
// 创建并初始化列表框 // 创建列表框 m_ctrListBox.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | LBS_STANDARD,CRect(270, 50, 370, 150), this, IDC_LIST1); // 添加条目 CString Item[9] = {"Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9"}; for (int i = 0; i < 9; i++) m_ctrListBox.AddString(Item[i]); // 选中第4个条目 m_ctrListBox.SetCurSel(3); …… // 父窗口对通知消息的处理函数的声明(在头文件中) //{{AFX_MSG(CSample02View) afx_msg void OnLbnDblClk(); //}}AFX_MSG DECLARE_MESSAGE_MAP() …… // 父窗口对通知消息的映射入口 (在实现文件中) BEGIN_MESSAGE_MAP(CSample02View, CView) //{{AFX_MSG_MAP(CSample02View) ON_LBN_DBLCLK(IDC_LIST1, OnLbnDblClk) //}}AFX_MSG_MAP // Standard printing commands END_MESSAGE_MAP() …… // 父窗口对LBN_DBLCLK通知消息的处理 void CSample02View::OnLbnDblClk() { // 得到当前选中条目的索引 int Index = m_ctrListBox.GetCurSel(); // 得到此条目的内容 char Text[20]; m_ctrListBox.GetText(Index, Text); // 以信息框报告得到的内容 AfxMessageBox(CString(Text)); } |
虽然组合框实际是列表框和编辑框的组合,但在使用中的表现使得组合框同其他控件一样当作一个独立的控件去使用。MFC的CComboBox类提供了对组合框的功能支持。在使用Create()函数创建组合框时可以同时指定组合框的风格(参见下表)。
窗口风格 | 说明 |
CBS_AUTOHSCROLL | 当在行尾输入字符时自动将编辑框中的文字向右滚动。 |
CBS_DROPDOWN | 同CBS_SIMPLE风格类似,只是只有在用户点击下拉图标时才会显示出下拉列表。 |
CBS_DROPDOWNLIST | 同CBS_DROPDOWN类似,只是显示当前选项的编辑框为一静态框所代替。 |
CBS_HASSTRINGS | 创建一个包含了由字串组成的项目的拥有者画组合框。 |
CBS_OEMCONVERT | 将组合框中的ANSI字串转化为OEM字符。 |
CBS_OWNERDRAWFIXED | 由下拉列表框的拥有者负责对内容的绘制;列表框中各项目高度相同。 |
CBS_OWNERDRAWVARIABLE | 由下拉列表框的拥有者负责对内容的绘制;列表框中各项目高度可以不同。 |
CBS_SIMPLE | 下拉列表始终显示。 |
CBS_SORT | 自动对下拉列表中的项目进行排序。 |
CBS_DISABLENOSCROLL | 当下拉列表显示内容过少时显示垂直滚动条。 |
CBS_NOINTEGRALHEIGHT | 在创建控件时以指定的大小来精确设定组合框尺寸。 |
对组合框进行操作也会向父窗口发送通知消息,处理过程同前面几种控件大同小异,是通过ON_CBN消息映射宏完成对通知消息的映射的。下面就给出这些ON_CBN宏的详细说明:
ON_CBN宏 | 对应事件 |
ON_CBN_CLOSEUP | 关闭下拉列表。 |
ON_CBN_DBLCLK | 双击下拉列表中的项目。 |
ON_CBN_DROPDOWN | 下拉显示列表框。 |
ON_CBN_EDITCHANGE | 编辑框中文本内容被改动。 |
ON_CBN_EDITUPDATE | 编辑框内容更新显示。 |
ON_CBN_ERRSPACE | 组合框不能为某个特殊请求分配足够的内存。 |
ON_CBN_SELENDCANCEL | 用户的选择被取消。 |
ON_CBN_SELENDOK | 用户选择了一个项目并且通过回车键或按下鼠标而隐藏组合框的下拉列表。 |
ON_CBN_KILLFOCUS | 组合框失去焦点。 |
ON_CBN_SELCHANGE | 选择发生变化。 |
ON_CBN_SETFOCUS | 组合框获得输入焦点。 |
最后给出一段有关组合框的示例代码,从代码实现不难看出组合框控件同前面给出的列表控件在编程实现上的相似性。
// 组合框的创建 // 创建列表控件 m_ctrComboBox.Create(WS_VISIBLE | WS_CHILD | WS_BORDER | CBS_DROPDOWN, CRect(400, 50, 470, 150), this, IDC_COMBOX1); // 添加条目 CString Item[9] = {"Item1", "Item2", "Item3", "Item4", "Item5", "Item6", "Item7", "Item8", "Item9"}; for (int i = 0; i < 9; i++) m_ctrComboBox.AddString(Item[i]); // 选中第4个条目 m_ctrComboBox.SetCurSel(3); …… // 通知消息响应函数的声明(在头文件中) //{{AFX_MSG(CSample02View) afx_msg void OnCbnSelChange(); //}}AFX_MSG DECLARE_MESSAGE_MAP() …… // 对通知消息的响应处理(在实现文件中) BEGIN_MESSAGE_MAP(CSample02View, CView) //{{AFX_MSG_MAP(CSample02View) ON_CBN_SELCHANGE(IDC_COMBOX1, OnCbnSelChange) //}}AFX_MSG_MAP END_MESSAGE_MAP() …… void CSample02View::OnCbnSelChange() { // 得到当前选中条目的索引 int Index = m_ctrComboBox.GetCurSel(); // 得到此条目的内容 char Text[20]; m_ctrComboBox.GetLBText(Index, Text); // 以信息框报告得到的内容 AfxMessageBox(CString(Text)); } |