什么是组合框? 在这里我做了一个例程,选择不同的边缘会又不一样的值,并且能修改和保存。 下面是效果图。
组合框其实就是把一个编辑框和一个列表框组合到了一起,分为三种:简易(Simple)组合框、下拉式(Dropdown)组合框和下拉列表式(Drop List)组合框。下面讲讲它们的区别。
简易组合框中的列表框是一直显示的。
下拉式组合框默认不显示列表框,只有在点击了编辑框右侧的下拉箭头才会弹出列表框。
下拉列表式组合框的编辑框是不能编辑的,只能由用户在下拉列表框中选择了某项后,在编辑框中显示其文本。
经过上面的介绍,大家应该知道,最常用的当属下拉式组合框和下拉列表式组合框了,它们在很多时候能使程序看起来更专业,更简洁,让用户在进行选择操作时更方便。
组合框被操作时会向父窗口发送通知消息,这些通知消息及其含义如下:
CBN_CLOSEUP:组合框的列表框组件被关闭,简易组合框不会发送该通知消息
CBN_DBLCLK:用户在某列表项上双击鼠标,只有简易组合框才会发送该通知消息
CBN_DROPDOWN:组合框的列表框组件下拉,简易式组合框不会发送该通知消息
CBN_EDITUPDATE:在编辑框准备显示改变了的正文时发送该消息,下拉列表式组合框不会发送该消息
CBN_EDITCHANGE:编辑框的内容被用户改变了,与CBN_EDITUPDATE不同,该消息是在编辑框显示的正文被刷新后才发出的,下拉列表式组合框不会发送该消息
CBN_ERRSPACE:组合框无法申请足够的内存来容纳列表项
CBN_SELENDCANCEL:表明用户的选择应该取消,当用户在列表框中选择了一项,然后又在组合框控件外单击鼠标时就会导致该消息的发送
CBN_SELENDOK:用户选择了一项,然后按了回车键或单击了下滚箭头,该消息表明用户确认了自己所作的选择
CBN_KILLFOCUS:组合框失去了输入焦点
CBN_SELCHANGE:用户通过单击或移动箭头键改变了列表的选择
CBN_SETFOCUS:组合框获得了输入焦点
组合框控件的创建
MFC将组合框控件的所有操作都封装到了CComboBox类中。
我们在对话框中加入组合框时,可以往对话框模板中拖入Combo Box控件,而后添加CComboBox类型的控件变量使用,但如果我们想在程序中动态创建的话,就要使用CComboBox类的成员函数Create了。Create函数的原型如下:
virtual BOOL Create(
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID
);
大家可以看出,CComboBox类的Create成员函数同前面几个控件类的Create成员函数非常类似,dwStyle指定组合框控件的风格,rect为列表框弹出后组合框的位置和尺寸,pParentWnd是指向父窗口的指针,不能为NULL,nID指定组合框控件的ID。最后还是重点讲讲dwStyle参数。组合框控件的风格包括以下几种,并给出了相应说明:
CBS_AUTOHSCROLL:使编辑框组件具有水平滚动的风格
CBS_DISABLENOSCROLL:使列表框在不需要滚动时显示一个禁止的垂直滚动条
CBS_DROPDOWN:指定一个下拉式组合框
CBS_DROPDOWNLIST:指定一个下拉列表式组合框
CBS_HASSTRINGS:指定一个含有字符串的自绘式组合框
CBS_LOWERCASE:将编辑框和列表框中的所有文本都自动转换为小写字符
CBS_NOINTEGRALHEIGHT:组合框的尺寸由应用程序而不是Windows 指定,通常,由Windows指定尺寸会使列表项的某些部分隐藏起来
CBS_OEMCONVERT:使编辑框组件中的正文可以在ANSI 字符集和OEM字符集之间相互转换。这在编辑框中包含文件名时是很有用的
CBS_OWNERDRAWFIXED:指定自绘式组合框,即由父窗口负责绘制列表框的内容,并且列表项有相同的高度
CBS_OWNERDRAWVARIABLE:指定自绘式组合框,并且列表项有不同的高度
CBS_SIIMPLE:指定一个简易组合框
CBS_SORT:自动对列表框组件中的项进行排序
CBS_UPPERCASE:将编辑框和列表框中的所有文本都自动转换为大写字符
dwStyle参数可以是以上风格的组合。跟其他控件一样,创建时一般也还要指定WS_CHILD、WS_VISIBLE、WS_TABSTOP和WS_VSCROLL等风格。
在对话框模板中直接添加组合框控件时,其属性页中的属性包含了以上风格,例如属性Uppercase设为True就相当于指定了CBS_UPPERCASE风格。
CComboBox类的主要成员函数
因为组合框是由编辑框和列表框组合而成的,所以组合框的操作和编辑框与列表框的操作有很多相似之处,同样的,CComboBox类的成员函数也和CEdit类与CListBox类的成员函数有很多相似之处,不但功能相似,甚至函数名和参数也很相似。下面大概讲解下CComboBox类的主要成员函数,更详细的内容可以参见MSDN。
int GetCount( ) const;
获取组合框控件的列表框中列表项的数量。
int GetCurSel( ) const;
获取组合框控件的列表框中选中项的索引,如果没有选中任何项,该函数返回CB_ERR。
int SetCurSel(int nSelect);
在组合框控件的列表框中选择某项。nSelect参数指定了要选择的列表项的索引,如果为-1则列表框中当前选择项被取消选中,编辑框也被清空。
DWORD GetEditSel( ) const;
获取组合框控件的编辑框中当前选择范围的起始和终止字符的位置。该函数返回一个32位数,低16位存放起始位置,高16位存放选择范围后第一个非选择字符的位置。如果该函数用于下拉列表式组合框时,会返回CB_ERR。
BOOL SetEditSel(int nStartChar,int nEndChar);
用于在组合框控件的编辑框中选择字符。nStartChar参数指定起始位置,nEndChar参数指定终止位置。
DWORD_PTR GetItemData(int nIndex) const;
获取组合框中指定项所关联的32位数据。nIndex参数指定组合框控件的列表框某项的索引(从0开始)。
int SetItemData(int nIndex,DWORD_PTR dwItemData);
为某个指定的组合框列表项设置一个关联的32位数。nIndex参数指定要进行设置的列表项索引。dwItemData参数指定要关联的新值。
void GetLBText(int nIndex,CString& rString) const;
从组合框控件的列表框中获取某项的字符串。nIndex参数指定要获取字符串的列表项的索引,CString参数用于接收取到的字符串。
int GetLBTextLen(int nIndex) const;
获取组合框控件的列表框中某项的字符串长度。nIndex参数指定要获取字符串长度的列表项的索引。
int GetTopIndex( ) const;
获取组合框控件的列表框中第一个可见项的索引。
int SetTopIndex(int nIndex);
将组合框控件的列表框中某个指定项设置为可见的。nIndex参数指定了该列表项的索引。该函数成功则返回0,有错误发生则返回CB_ERR。
BOOL LimitText(int nMaxChars);
用于限制用户在组合框控件的编辑框中能够输入的最大字节长度。nMaxChars参数指定了用户能够输入文字的最大字节长度,如果为0则长度被限制为65535个字节。
int AddString(LPCTSTR lpszString);
为组合框控件中的列表框添加新的列表项。lpszString参数是指向要添加的字符串的指针。该函数的返回值如果大于等于0,那么它就是新列表项的索引,而如果有错误发生则会返回CB_ERR,如果没有足够的内存存放新字符串则返回CB_ERRSPACE。
int DeleteString(UINT nIndex);
删除组合框中某指定位置的列表项。nIndex参数指定了要删除的列表项的索引。该函数的返回值如果大于等于0,那么它就是组合框中剩余列表项的数量。如果nIndex指定的索引超出了列表项的数量则返回CB_ERR。
int FindString(int nStartAfter,LPCTSTR lpszString) const;
在组合框控件的列表框中查找但不选中第一个包含指定前缀的列表项。nStartAfter参数指定了第一个要查找的列表项之前的那个列表项的索引。lpszString指向包含要查找的前缀的字符串。该函数的返回值如果大于等于0,那么它是匹配列表项的索引,如果查找失败则返回CB_ERR。
int InsertString(int nIndex,LPCTSTR lpszString);
向组合框控件的列表框中插入一个列表项。nIndex参数指定了要插入列表项的位置,lpszString参数则指定了要插入的字符串。该函数返回字符串被插入的位置,如果有错误发生则会返回CB_ERR,如果没有足够的内存存放新字符串则返回CB_ERRSPACE。
int SelectString(int nStartAfter,LPCTSTR lpszString);
在组合框控件的列表框中查找一个字符串,如果查找到则选中它,并将其显示到编辑框中。参数同FindString。如果字符串被查找到则返回此列表项的索引,如果查找失败则返回CB_ERR,并且当前选择项不改变。
此外,CComboBox类还继承了CWnd类的成员函数GetWindowText、SetWindowText等。
最后给大家写一个简单的实例,说明CComboBox的几个成员函数及通知消息等的使用方法。此实例实现的功能:在组合框中包含一个网站列表,切换组合框控件的列表框中选择的列表项时,将新选中的列表项的文本显示到编辑框中。下面是具体实现步骤:
创建一个基于对话框的MFC工程,名称设置为“ComBoxtest”。
在自动生成的对话框模板IDD_ComBoxtest_DIALOG中,删除“TODO: Place dialog controls here.”静态文本控件、“OK”按钮和“Cancel”按钮。添加一个Combo Box控件,ID设置为IDC_COMBO,Type属性设为Drop List,为下拉列表式组合框,编辑框不允许用户输入,Sort属性设为False,以取消排序显示。再添加四一个静态文本控件和两个编辑框,静态文本控件的Caption属性分为设置为设为“边缘选择”,“找边宽度”,“阈值“,”mm“,编辑框的ID设为IDC_EDIT1和IDC_EDIT2,Read Only属性设为True。此时的对话框模板如下图:
为组合框IDC_WEB_COMBO添加CComboBox类型的控件变量m_ComBox1。
为两个编辑框添加变量,分别为m_EdgeThreshold,m_EdgeWidth。
并定位6个double类型的变量用于存贮 每条边的找边宽度和阈值。
//定义每条边的参数;
double Up_EdgeWidth = 0; //上边缘找边宽度
double Up_Threshold = 0; //上边缘阈值
double Under_EdgeWidth = 0;
double Under = 0;
double L_EdgeWidth = 0;
double L_Thresh// CComBoxTestDlg 消息处理程序
BOOL CComBoxTestDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// 将“关于...”菜单项添加到系统菜单中。
// IDM_ABOUTBOX 必须在系统命令范围内。
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
BOOL bNameValid;
CString strAboutMenu;
bNameValid = strAboutMenu.LoadString(IDS_ABOUTBOX);
ASSERT(bNameValid);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标
// TODO: 在此添加额外的初始化代码
m_ComBox1.AddString(__T("上边缘"));
m_ComBox1.AddString(__T("左侧边缘"));
m_ComBox1.AddString(__T("下边缘"));
m_ComBox1.AddString(__T("右侧边缘"));
return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}
5.我们希望在组合框中选中的列表项改变时,将最新的选择项实时显示到编辑框中,那么这就要用到CBN_SELCHANGE通知消息。为列表框IDC_COMBO的通知消息CBN_SELCHANGE添加消息处理函数CComBoxTestDlg::OnCbnSelchangeCombo(),并修改如下:
/****************************************
*函 数 名: CComBoxTestDlg::OnCbnSelchangeCombo()
*描 述: 当选中组合框中的字符串的时候会调用此函数
*输入参数:无
*输出参数:无
*作 者:shirunfa
******************************************/
void CComBoxTestDlg::OnCbnSelchangeCombo()
{
// TODO: 在此添加控件通知处理程序代码
CString strtemp;
int nsel;
// 获取组合框控件的列表框中选中项的索引
nsel = m_ComBox1.GetCurSel();
//根据索引获取该字符串
m_ComBox1.GetLBText(nsel,strtemp);
if(strtemp==__T("上边缘"))
{
m_EdgeThreshold = Up_Threshold;
m_EdgeWidth = Up_EdgeWidth;
}
if(strtemp==__T("下边缘"))
{
m_EdgeThreshold = Under_EdgeWidth;
m_EdgeWidth = Under_EdgeWidth;
}
if(strtemp==__T("左侧边缘"))
{
m_EdgeThreshold = L_Threshold;
m_EdgeWidth = L_EdgeWidth;
}
if(strtemp==__T("右侧边缘"))
{
m_EdgeThreshold = R_Threshold;
m_EdgeWidth = R_EdgeWidth;
}
UpdateData(FALSE);
}
6.然后给两个编辑框添加消息处理函数,代码如下:
/****************************************
*函 数 名: CComBoxTestDlg::OnEnChangeEdit1()
*描 述: 当选中找边宽度编辑框的时候会调用此函数
*输入参数:无
*输出参数:无
*作 者:shirunfa
******************************************/
void CComBoxTestDlg::OnEnChangeEdit1()
{
UpdateData(TRUE);
//先判断选择哪一条边
int E_num;
CString strtemp;
E_num = m_ComBox1.GetCurSel();
m_ComBox1.GetLBText(E_num,strtemp);
if(strtemp == __T("上边缘"))
{
Up_EdgeWidth = m_EdgeWidth;
}
if(strtemp == __T("下边缘"))
{
Under_EdgeWidth = m_EdgeWidth;
}
if(strtemp == __T("左侧边缘"))
{
L_EdgeWidth = m_EdgeWidth;
}
if(strtemp == __T("右侧边缘"))
{
R_EdgeWidth = m_EdgeWidth;
}
}
/****************************************
*函 数 名: CComBoxTestDlg::OnEnChangeEdit2()
*描 述: 当选中阈值编辑框的时候会调用此函数
*输入参数:无
*输出参数:无
*作 者:shirunfa
******************************************/
void CComBoxTestDlg::OnEnChangeEdit2()
{
UpdateData(TRUE);
//先判断选择哪一条边
int E_num;
CString strtemp;
E_num = m_ComBox1.GetCurSel();
m_ComBox1.GetLBText(E_num,strtemp);
if(strtemp == __T("上边缘"))
{
Up_Threshold = m_EdgeThreshold;
}
if(strtemp == __T("下边缘"))
{
Under_EdgeWidth = m_EdgeThreshold;
}
if(strtemp == __T("左侧边缘"))
{
L_Threshold = m_EdgeThreshold;
}
if(strtemp == __T("右侧边缘"))
{
R_Threshold = m_EdgeThreshold;
}
}