上一節雞啄米講了列表框控件ListBox的使用,本節主要講解組合框控件Combo Box。組合框同樣相當常見(jiàn),例如,在Windows系統的控制面板上設置語(yǔ)言或位置時(shí),有很多選項,用來(lái)進(jìn)行選擇的控件就是組合框控件。它為我們的日常操作提供了很多方便。
組合框控件簡(jiǎn)介
組合框其實(shí)就是把一個(gè)編輯框和一個(gè)列表框組合到了一起,分為三種:簡(jiǎn)易(Simple)組合框、下拉式(Dropdown)組合框和下拉列表式(Drop List)組合框。下面講講它們的區別。
簡(jiǎn)易組合框中的列表框是一直顯示的,效果如下圖:

下拉式組合框默認不顯示列表框,只有在點(diǎn)擊了編輯框右側的下拉箭頭才會(huì )彈出列表框,列表框彈出后如下圖:

下拉列表式組合框的編輯框是不能編輯的,只能由用戶(hù)在下拉列表框中選擇了某項后,在編輯框中顯示其文本。下拉列表式組合框如下圖:

經(jīng)過(guò)上面的介紹,大家應該知道,最常用的當屬下拉式組合框和下拉列表式組合框了,它們在很多時(shí)候能使程序看起來(lái)更專(zhuān)業(yè),更簡(jiǎn)潔,讓用戶(hù)在進(jìn)行選擇操作時(shí)更方便。
組合框被操作時(shí)會(huì )向父窗口發(fā)送通知消息,這些通知消息及其含義如下:
CBN_CLOSEUP:組合框的列表框組件被關(guān)閉,簡(jiǎn)易組合框不會(huì )發(fā)送該通知消息
CBN_DBLCLK:用戶(hù)在某列表項上雙擊鼠標,只有簡(jiǎn)易組合框才會(huì )發(fā)送該通知消息
CBN_DROPDOWN:組合框的列表框組件下拉,簡(jiǎn)易式組合框不會(huì )發(fā)送該通知消息
CBN_EDITUPDATE:在編輯框準備顯示改變了的正文時(shí)發(fā)送該消息,下拉列表式組合框不會(huì )發(fā)送該消息
CBN_EDITCHANGE:編輯框的內容被用戶(hù)改變了,與CBN_EDITUPDATE不同,該消息是在編輯框顯示的正文被刷新后才發(fā)出的,下拉列表式組合框不會(huì )發(fā)送該消息
CBN_ERRSPACE:組合框無(wú)法申請足夠的內存來(lái)容納列表項
CBN_SELENDCANCEL:表明用戶(hù)的選擇應該取消,當用戶(hù)在列表框中選擇了一項,然后又在組合框控件外單擊鼠標時(shí)就會(huì )導致該消息的發(fā)送
CBN_SELENDOK:用戶(hù)選擇了一項,然后按了回車(chē)鍵或單擊了下滾箭頭,該消息表明用戶(hù)確認了自己所作的選擇
CBN_KILLFOCUS:組合框失去了輸入焦點(diǎn)
CBN_SELCHANGE:用戶(hù)通過(guò)單擊或移動(dòng)箭頭鍵改變了列表的選擇
CBN_SETFOCUS:組合框獲得了輸入焦點(diǎn)
組合框控件的創(chuàng )建
MFC將組合框控件的所有操作都封裝到了CComboBox類(lèi)中。
我們在對話(huà)框中加入組合框時(shí),可以往對話(huà)框模板中拖入Combo Box控件,而后添加CComboBox類(lèi)型的控件變量使用,但如果我們想在程序中動(dòng)態(tài)創(chuàng )建的話(huà),就要使用CComboBox類(lèi)的成員函數Create了。Create函數的原型如下:
virtual BOOL Create(
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID
);
大家可以看出,CComboBox類(lèi)的Create成員函數同前面幾個(gè)控件類(lèi)的Create成員函數非常類(lèi)似,dwStyle指定組合框控件的風(fēng)格,rect為列表框彈出后組合框的位置和尺寸,pParentWnd是指向父窗口的指針,不能為NULL,nID指定組合框控件的ID。最后還是重點(diǎn)講講dwStyle參數。組合框控件的風(fēng)格包括以下幾種,并給出了相應說(shuō)明:
CBS_AUTOHSCROLL:使編輯框組件具有水平滾動(dòng)的風(fēng)格
CBS_DISABLENOSCROLL:使列表框在不需要滾動(dòng)時(shí)顯示一個(gè)禁止的垂直滾動(dòng)條
CBS_DROPDOWN:指定一個(gè)下拉式組合框
CBS_DROPDOWNLIST:指定一個(gè)下拉列表式組合框
CBS_HASSTRINGS:指定一個(gè)含有字符串的自繪式組合框
CBS_LOWERCASE:將編輯框和列表框中的所有文本都自動(dòng)轉換為小寫(xiě)字符
CBS_NOINTEGRALHEIGHT:組合框的尺寸由應用程序而不是Windows 指定,通常,由Windows指定尺寸會(huì )使列表項的某些部分隱藏起來(lái)
CBS_OEMCONVERT:使編輯框組件中的正文可以在A(yíng)NSI 字符集和OEM字符集之間相互轉換。這在編輯框中包含文件名時(shí)是很有用的
CBS_OWNERDRAWFIXED:指定自繪式組合框,即由父窗口負責繪制列表框的內容,并且列表項有相同的高度
CBS_OWNERDRAWVARIABLE:指定自繪式組合框,并且列表項有不同的高度
CBS_SIIMPLE:指定一個(gè)簡(jiǎn)易組合框
CBS_SORT:自動(dòng)對列表框組件中的項進(jìn)行排序
CBS_UPPERCASE:將編輯框和列表框中的所有文本都自動(dòng)轉換為大寫(xiě)字符
dwStyle參數可以是以上風(fēng)格的組合。跟其他控件一樣,創(chuàng )建時(shí)一般也還要指定WS_CHILD、WS_VISIBLE、WS_TABSTOP和WS_VSCROLL等風(fēng)格。
在對話(huà)框模板中直接添加組合框控件時(shí),其屬性頁(yè)中的屬性包含了以上風(fēng)格,例如屬性Uppercase設為T(mén)rue就相當于指定了CBS_UPPERCASE風(fēng)格。
CComboBox類(lèi)的主要成員函數
因為組合框是由編輯框和列表框組合而成的,所以組合框的操作和編輯框與列表框的操作有很多相似之處,同樣的,CComboBox類(lèi)的成員函數也和CEdit類(lèi)與CListBox類(lèi)的成員函數有很多相似之處,不但功能相似,甚至函數名和參數也很相似。雞啄米下面大概講解下CComboBox類(lèi)的主要成員函數,更詳細的內容可以參見(jiàn)MSDN。
int GetCount( ) const;
獲取組合框控件的列表框中列表項的數量。
int GetCurSel( ) const;
獲取組合框控件的列表框中選中項的索引,如果沒(méi)有選中任何項,該函數返回CB_ERR。
int SetCurSel(int nSelect);
在組合框控件的列表框中選擇某項。nSelect參數指定了要選擇的列表項的索引,如果為-1則列表框中當前選擇項被取消選中,編輯框也被清空。
DWORD GetEditSel( ) const;
獲取組合框控件的編輯框中當前選擇范圍的起始和終止字符的位置。該函數返回一個(gè)32位數,低16位存放起始位置,高16位存放選擇范圍后第一個(gè)非選擇字符的位置。如果該函數用于下拉列表式組合框時(shí),會(huì )返回CB_ERR。
BOOL SetEditSel(int nStartChar,int nEndChar);
用于在組合框控件的編輯框中選擇字符。nStartChar參數指定起始位置,nEndChar參數指定終止位置。
DWORD_PTR GetItemData(int nIndex) const;
獲取組合框中指定項所關(guān)聯(lián)的32位數據。nIndex參數指定組合框控件的列表框某項的索引(從0開(kāi)始)。
int SetItemData(int nIndex,DWORD_PTR dwItemData);
為某個(gè)指定的組合框列表項設置一個(gè)關(guān)聯(lián)的32位數。nIndex參數指定要進(jìn)行設置的列表項索引。dwItemData參數指定要關(guān)聯(lián)的新值。
void GetLBText(int nIndex,CString& rString) const;
從組合框控件的列表框中獲取某項的字符串。nIndex參數指定要獲取字符串的列表項的索引,CString參數用于接收取到的字符串。
int GetLBTextLen(int nIndex) const;
獲取組合框控件的列表框中某項的字符串長(cháng)度。nIndex參數指定要獲取字符串長(cháng)度的列表項的索引。
int GetTopIndex( ) const;
獲取組合框控件的列表框中第一個(gè)可見(jiàn)項的索引。
int SetTopIndex(int nIndex);
將組合框控件的列表框中某個(gè)指定項設置為可見(jiàn)的。nIndex參數指定了該列表項的索引。該函數成功則返回0,有錯誤發(fā)生則返回CB_ERR。
BOOL LimitText(int nMaxChars);
用于限制用戶(hù)在組合框控件的編輯框中能夠輸入的最大字節長(cháng)度。nMaxChars參數指定了用戶(hù)能夠輸入文字的最大字節長(cháng)度,如果為0則長(cháng)度被限制為65535個(gè)字節。
int AddString(LPCTSTR lpszString);
為組合框控件中的列表框添加新的列表項。lpszString參數是指向要添加的字符串的指針。該函數的返回值如果大于等于0,那么它就是新列表項的索引,而如果有錯誤發(fā)生則會(huì )返回CB_ERR,如果沒(méi)有足夠的內存存放新字符串則返回CB_ERRSPACE。
int DeleteString(UINT nIndex);
刪除組合框中某指定位置的列表項。nIndex參數指定了要刪除的列表項的索引。該函數的返回值如果大于等于0,那么它就是組合框中剩余列表項的數量。如果nIndex指定的索引超出了列表項的數量則返回CB_ERR。
int FindString(int nStartAfter,LPCTSTR lpszString) const;
在組合框控件的列表框中查找但不選中第一個(gè)包含指定前綴的列表項。nStartAfter參數指定了第一個(gè)要查找的列表項之前的那個(gè)列表項的索引。lpszString指向包含要查找的前綴的字符串。該函數的返回值如果大于等于0,那么它是匹配列表項的索引,如果查找失敗則返回CB_ERR。
int InsertString(int nIndex,LPCTSTR lpszString);
向組合框控件的列表框中插入一個(gè)列表項。nIndex參數指定了要插入列表項的位置,lpszString參數則指定了要插入的字符串。該函數返回字符串被插入的位置,如果有錯誤發(fā)生則會(huì )返回CB_ERR,如果沒(méi)有足夠的內存存放新字符串則返回CB_ERRSPACE。
int SelectString(int nStartAfter,LPCTSTR lpszString);
在組合框控件的列表框中查找一個(gè)字符串,如果查找到則選中它,并將其顯示到編輯框中。參數同FindString。如果字符串被查找到則返回此列表項的索引,如果查找失敗則返回CB_ERR,并且當前選擇項不改變。
此外,CComboBox類(lèi)還繼承了CWnd類(lèi)的成員函數GetWindowText、SetWindowText等。
CComboBox類(lèi)應用實(shí)例
最后雞啄米給大家寫(xiě)一個(gè)簡(jiǎn)單的實(shí)例,說(shuō)明CComboBox的幾個(gè)成員函數及通知消息等的使用方法。此實(shí)例實(shí)現的功能:在組合框中包含一個(gè)網(wǎng)站列表,切換組合框控件的列表框中選擇的列表項時(shí),將新選中的列表項的文本顯示到編輯框中。下面是具體實(shí)現步驟:
1. 創(chuàng )建一個(gè)基于對話(huà)框的MFC工程,名稱(chēng)設置為“Example25”。
2. 在自動(dòng)生成的對話(huà)框模板IDD_EXAMPLE25_DIALOG中,刪除“TODO: Place dialog controls here.”靜態(tài)文本控件、“OK”按鈕和“Cancel”按鈕。添加一個(gè)Combo Box控件,ID設置為IDC_WEB_COMBO,Type屬性設為Drop List,為下拉列表式組合框,編輯框不允許用戶(hù)輸入,Sort屬性設為False,以取消排序顯示。再添加一個(gè)靜態(tài)文本控件和一個(gè)編輯框,靜態(tài)文本控件的Caption屬性設為“您選擇的網(wǎng)站:”,編輯框的ID設為IDC_SEL_WEB_EDIT,Read Only屬性設為T(mén)rue。此時(shí)的對話(huà)框模板如下圖:

3. 為組合框IDC_WEB_COMBO添加CComboBox類(lèi)型的控件變量m_comboWeb。
4. 在對話(huà)框初始化時(shí),我們將站點(diǎn)名加入到組合框中,并默認選擇第一項,那么需要修改CExample25Dlg::OnInitDialog()函數為:
5. 我們希望在組合框中選中的列表項改變時(shí),將最新的選擇項實(shí)時(shí)顯示到編輯框中,那么這就要用到CBN_SELCHANGE通知消息。為列表框IDC_WEB_COMBO的通知消息CBN_SELCHANGE添加消息處理函數CExample25Dlg::OnCbnSelchangeWebCombo(),并修改如下:
6. 運行程序,彈出結果對話(huà)框,在對話(huà)框的組合框中改變選擇項時(shí),編輯框中的顯示會(huì )相應改變。效果圖如下:

組合框的內容就是這些了。相對于CComboBox類(lèi)數量不少的成員函數來(lái)說(shuō),本節的實(shí)例只是用到了很少的幾個(gè),大家可以根據上面所講試試其他的成員函數。有問(wèn)題歡迎繼續到雞啄米來(lái)交流討論。
聯(lián)系客服