1. 组合框控件简介
组合框其实就是把一个编辑框和一个列表框组合到了一起,分为三种:简易(Simple)组
合框、下拉式(Dropdown)组合框和下拉列表式(Drop List)组合框。下面讲讲它们的区
别。
简易组合框中的列表框是一直显示。下拉式组合框默认不显示列表框,只有在点击了编辑框右侧的下拉箭头才会弹出列表框,可以编辑。下拉列表式组合框的编辑框是不能编辑的,只能由用户在下拉列表框中选择了某项后,在编辑框中显示其文本。具体形式在IDE上设置相应属性后,然后按下“CTRL+T”得到控件的预览,就可以看到combo box的真面目了。
2. CComboBox类的主要成员函数
因为组合框是由编辑框和列表框组合而成的,所以组合框的操作和编辑框与列表框的操作有很多相似之处,同样的,CComboBox类的成员函数也和CEdit类与CListBox类的成员函数有很多相似之处,不但功能相似,甚至函数名和参数也很相似。
下面摘下CComboBox类的主要成员函数,更详细的内容可以参见MSDN。
int GetCount( ) const;
获取组合框控件的列表框中列表项的数量。
int GetCurSel( ) const;
获取组合框控件的列表框中选中项的索引,如果没有选中任何项,该函数返回CB_ERR。若焦点在编辑框中,返回-1
int SetCurSel(int nSelect);
在组合框控件的列表框中选择某项并显示。nSelect参数指定了要选择的列表项的索引,
如果为-1则列表框中当前 选择项被取消选中,编辑框也被清空。
DWORD GetEditSel( ) const;
获取组合框控件的编辑框中当前选择范围的起始和终止字符的位置。该函数返回一个32位数。
如果该函数用于下拉列表式组合框时,会返回CB_ERR。
BOOL SetEditSel(int nStartChar,int nEndChar);
用于在组合框控件的编辑框中选择字符。nStartChar参数指定起始位置,nEndChar参数指定终止位置。
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等。
3. MFC CComboBox Class来操作列表
1、定义控件对应变量
假定已经创建了一个Dialog,并且从控件工具箱将 Combo Box 控件拖放到上面。打开 Class Wizard,添加控件对应变量,如
CComboBox m_commoweb;
2、向控件添加 Items
1) 在Combo Box控件属性的Data标签里面添加,各行用;分开。
2) 利用函数 AddString() 向 Combo Box 控件添加 Items,如:
m_cbExample.AddString(“StringData1”);
m_cbExample.AddString(“StringData2”);
m_cbExample.AddString(“StringData3”);
3) 也可以调用函数 InsertString() 将 Item 插入指定位置 nIndex,如:
m_cbExample.InsertString( nIndex, “StringData” );
4)从编辑框中输入 这个比较人性化
((CComboBox*)GetDlgItem(IDC_COMBO2))->GetWindowText(comboxstr);//当前选中的行。
m_commoweb.AddString(comboxstr);
3、从控件得到选定的Item
假设在控件列表中已经选定某项,现在要得到被选定项的内容,首先要得到该项的位置,然后得到对应位置的内容。这里会用
到两个函数,如:
void Ctree_controlDlg::OnCbnSelchangeCombo2()
{
// TODO: 在此添加控件通知处理程序代码
CString strweb;
int n;
n= m_commoweb.GetCurSel();
if(n>=0){
m_commoweb.GetLBText(n, strweb);
SetDlgItemText(IDC_EDIT1, strweb);
}
}
这样,得到的内容就保存在 strCBText 中。
4、选择列表某行的函数
1)选中:
int iPos=((CComboBox*)GetDlgItem(IDC_COMBO_CF))->GetCurSel();//当前选中的行。
2)设置
((CComboBox*)GetDlgItem(IDC_COMBO_CF))->SetCurSel(n)//设置第n行内容为显示的内容。
5、取得Combo Box框内容
1)取当前内容
((CComboBox*)GetDlgItem(IDC_COMBO_CF))->GetWindowText(strTemp);
2)取其他行内容
((CComboBox*)GetDlgItem(IDC_COMBO_CF))->GetLBText(n,strTemp);
6、获得焦点
通常要判断控件是否获得了焦点,可以用GetFocus()函数
例如:if(GetFocus()==GetDlgItem(IDC_EDIT_VALUE2))//判断焦点是否在编辑框IDC_EDIT_VALUE2内。
但是combobox 的焦点不同,因为它是由edit和listbox两部分组成的
所以获得焦点要用GetParent():if ((GetFocus()->GetParent())==GetDlgItem(IDC_COMBO_CF))
4. combo box编辑框对回车键的响应
当我们在combo box编辑框中输完内容后习惯性回车,但是在combox控件编辑框中回车,就会发生对话框被销毁。普通编辑框有want return 属性可以选择。对于combox控件编辑框,该如何呢?
首先学习响应机制:
Windows操作系统下各个窗口、控件归根结底都是通过系统的各种各样的消息来相互协调、相互联系的,而我们所遇到的这个问题换到消息的角度说就是”如何使程序能响应在编辑框上输入的回车键所发出的消息”,只要能响应到这个消息,剩下的工作都可以在消息处理函数中完成。所以有必要对Windows系统的消息机制做些了解。
在系统下最常用的消息循环是调用GetMessage()函数从消息队列中取出消息,然后调用DespatchMessage() 函数让系统把消息发送给窗口函数,一般情况下其结果是把窗口的所有消息都传送给窗口函数。但特殊情况下可以在GetMessage()函数获得消息而又没发送出去之前,通过TranslateMessage()函数可以中途对消息进行解析,可以对指定的消息进行拦截,拦截后即可以照样发送出去,也可以不继续发送,完成对该消息的拦截,下面代码是该过程的示例:
MSG msg;
while(GetMessage(&msg,NULL,NULL,NULL,NULL){
TranslateMessage(&msg);
…… //对拦截的消息进行处理
DispathchMessage(&msg);
}
由于按下回车键时把产生的消息加入到消息队列中了,也传给了编辑框,但仅仅是由于编辑框没有能力处理该消息而造成了无法对回车键的响应,所以可以在消息循环里在把消息发送到编辑框之前就对消息进行拦截,并对其进行处理。其效果同编辑框响应回车键是一样的,仅在时序上有所提前而已。上述代码是在SDK(Software Develope Kits)下使用的,在MFC(Microsoft Foundation Class)下早已对其进行了封装,可以通过重载虚函数PreTranslateMessage()对所关心的消息进行解析:
BOOL CTestView::PreTranslateMessage(MSG* pMsg)
{
if (WM_KEYFIRST <= pMsg->message &&pMsg->message <= WM_KEYLAST)
{
if(pMsg->wParam==VK_RETURN )
{
UpdateData(TRUE);
AfxMessageBox(m_Text);
}
}
return CFormView::PreTranslateMessage(pMsg);
}
在上面的代码中,首先将pMsg->message所表示的消息同WM_KEYFIRST 和WM_KEYLAST比较,确定是键盘消息,然后通过消息参数pMsg->wParam的值来判断是否是回车键(VK_RETURN,虚拟键码可以从SDK相关资料查到)。如是,则可以将已输入到编辑框中的字符读取到m_Text中,并将其显示出来。
若有多个编辑框,可以利用资源的ID号区分。见Resource.h
if(pMsg->wParam==VK_RETURN )
{
HWND hWnd=::GetFocus();
int iID=::GetDlgCtrlID(hWnd);
if(iID==1000)//第一个编辑框的标识为1000
{
UpdateData(TRUE);
AfxMessageBox(m_Text1);//显示第一个编辑框的内容
}
if(iID==1001) //第二个编辑框的标识为1001
{
UpdateData(TRUE);
AfxMessageBox(m_Text2);//显示第二个编辑框的内容
}
}
在此通过API函数::GetFocus()(注意前面的”::”,标识是全局API函数,而非某个类中的成员函数)取得当前光标所处的(即有焦点的)编辑框的句柄,然后通过API函数::GetDlgCtrlID()根据这个句柄返回此窗口资源的ID 号,该ID号是动态获取的,使之同预先查看好的编辑框的ID作下比较即可区分出是需要哪个编辑框对回车键作出响应。
了解相关原因后,我们这样处理combo box编辑框对回车键的响应
BOOL Ctree_controlDlg::PreTranslateMessage(MSG* pMsg)
{
if(pMsg->message==WM_KEYDOWN&&pMsg->wParam==VK_RETURN)
{
//当一个非系统键被按下时该消息发送给具有键盘焦点的窗口。非系统键即不与ALT联用的情况
((CComboBox*)GetDlgItem(IDC_COMBO2))->GetWindowText(comboxstr);//当前选中的行。
if ((GetFocus()->GetParent())==GetDlgItem(IDC_COMBO2))
{
m_commoweb.AddString(comboxstr);
}
m_commoweb.SetWindowText(0);
return TRUE;
}
return CDialogEx::PreTranslateMessage(pMsg);
}
当然如果不在意回车键的话,可以在OnCbnDropdownCombo2()响应函数里面添加代码AddString(comboxstr)
。
参考:
- 鸡啄米:vs2010 mfc编程入门教程
- 用VC实现特定编辑框上对回车键响应
- MFC——ComBox用法大全
- WM_CHAR、WM_KEYDOWN和WM_SYSKEYDOWN消息