VS2013/MFC程式設計入門之二十三(常用控制元件:列表框控制元件ListBox)
前面兩節講了比較常用的按鈕控制元件,並通過按鈕控制元件例項說明了具體用法。本文要講的是列表框控制元件(ListBox)及其使用例項。
列表框控制元件簡介
列表框給出了一個選項清單,允許使用者從中進行單項或多項選擇,被選中的項會高亮顯示。列表框可分為單選列表框和多選列表框,顧名思義,單選列表框中一次只能選擇一個列表項,而多選列表框可以同時選擇多個列表項。
列表框也會向父視窗傳送通知訊息。這些通知訊息及含義如下:
LBN_DBLCLK :使用者用滑鼠雙擊了一列表項,只有具有LBS_NOTIFY 的列表框才能傳送該訊息
LBN_ERRSPACE :列表框不能申請足夠的動態記憶體來滿足需要
LBN_KILLFOCUS :列表框失去輸入焦點
LBN_SELCANCEL: 當前的選擇被取消,只有具有LBS_NOTIFY 的列表框才能傳送該訊息
LBN_SELCHANGE:單擊滑鼠選擇了一列表項,只有具有LBS_NOTIFY 的列表框才能傳送該訊息
LBN_SETFOCUS:列表框獲得輸入焦點
WM_CHARTOITEM:當列表框收到WM_CHAR 訊息後, 向父視窗傳送該訊息, 只有具有LBS_WANTKEYBOARDINPUT 風格的列表框才會傳送該訊息
WM_VKEYTOITEM:當列表框收到WM_KEYDOWN 訊息後,向父視窗傳送該訊息,只有具有LBS_WANTKEYBOARDINPUT 風格的列表框才會傳送該訊息
列表框控制元件的建立
MFC將列表框控制元件的所有操作都封裝到了CListBox類中。
建立列表框控制元件時,可以在對話方塊模板中直接拖入列表框控制元件Listbox,然後新增控制元件變數使用。但如果需要動態建立列表框,就要用到CListBox類的Create成員函數了。Create成員函式的原型如下:
virtual BOOL Create(
DWORD dwStyle,
const RECT& rect,
CWnd* pParentWnd,
UINT nID
);
引數rect指定了列表框的位置和尺寸,pParentWnd為父視窗的指標,nID用於指定列表框控制元件的ID。最後重點講講引數dwStyle,它指定了列表框控制元件的風格,以下是各種風格說明:
LBS_EXTENDEDSEL:支援多重選擇,在點選列表項時按住Shift 鍵或Ctrl 鍵即可選擇多個項
LBS_HASSTRINGS:指定一個含有字串的自繪式列表框
LBS_MULTICOLUMN:指定一個水平滾動的多列列表框, 通過呼叫CListBox::SetColumnWidth 來設定每列的寬度
LBS_MULTIPLESEL:支援多重選擇。列表項的選擇狀態隨著使用者對該項單擊或雙擊滑鼠而翻轉
LBS_NOINTEGRALHEIGHT:列表框的尺寸由應用程式而不是Windows 指定。通常,Windows指定尺寸會使列表項的某些部分隱藏起來
LBS_NOREDRAW:當選擇發生變化時防止列表框被更新,可傳送訊息改變該風格
LBS_NOTIFY:當用戶單擊或雙擊滑鼠時通知父視窗
LBS_OWNERDRAWFIXED:指定自繪式列表框,即由父視窗負責繪製列表框的內容,並且列表項有相同的高度
LBS_OWNERDRAWVARIABLE:指定自繪式列表框,並且列表項有不同的高度
LBS_SORT:使插入列表框中的項按升序排列
LBS_STANDARD:相當於指定了WS_BORDER|WS_VSCROLL|LBS_SORT
LBS_USETABSTOPS:使列表框在顯示列表項時識別並擴充套件製表符(‘\t’),預設的製表寬度是32 個對話方塊單位
LBS_WANTKEYBOARDINPUT:允許列表框的父視窗接收WM_VKEYTOITEM 和WM_CHARTOITEM 訊息,以響應鍵盤輸入
LBS_DISABLENOSCROLL:使列表框在不需要滾動時顯示一個禁止的垂直滾動條
dwStyle可以是以上所列風格的組合。與其他控制元件一樣,除了這些風格一般還要為列表框控制元件設定WS_CHILD、WS_VISIBLE、WS_TABSTOP、WS_BORDER、WS_VSCROLL等風格。一般建立單選列表框時,風格要設定為:WS_CHILD|WS_VISIBLE|WS_TABSTOP|LBS_STANDARD,如果不希望列表框項排序顯示則應去掉LBS_STANDARD。建立多選列表框時,只需要在單選列表框風格後新增LBS_MULTIPLESEL或LBS_EXTENDEDSEL風格。
對於對話方塊模板中直接新增的列表框控制元件,其屬性頁中的屬性包含了以上風格,例如屬性Multicolumn對應的就是LBS_MULTICOLUMN風格。
CListBox類的主要成員函式
int GetCount( ) const;
返回值:返回列表框中列表項的數目,如果發生錯誤則返回LB_ERR。
int GetSel(int nIndex) const;
引數:nIndex指定某個列表項的索引。
返回值:返回nIndex指定列表項的狀態。如果此列表項被選擇了則返回一個正值,否則返回0,若發生錯誤則返回LB_ERR。
int SetSel(int nIndex,BOOL bSelect = TRUE);
此函式只用於多選列表框,使用它可以選擇或取消選擇指定的列表項。
引數:nIndex指定某個列表項的索引,若為-1則相當於指定了所有列表項。bSelect為TRUE時選擇指定列表項,否則取消選擇指定列表項。
返回值:如果發生錯誤則返回LB_ERR。
int AddString(LPCTSTR lpszItem);
此函式用來向列表框中新增字串。如果列表框指定了LBS_SORT風格,字串就被以排序順序插入到列表框中,如果沒有指定LBS_SORT風格,字串就被新增到列表框的結尾。
引數:lpszItem指定了要新增的字串。
返回值:返回字串在列表框中新增的位置。如果發生錯誤則返回LB_ERR,記憶體不夠則返回LB_ERRSPACE。
int InsertString(int nIndex, LPCTSTR lpszItem);
該函式用來在列表框中的指定位置插入字串。與AddString函式不同的是,InsertString函式不會導致LBS_SORT風格的列表框重新排序。不要在具有LBS_SORT風格的列表框中使用InsertString函式,以免破壞列表項的次序。
引數:。引數nIndex 給出了插入位置(索引),如果值為-1,則字串將被新增到列表的末尾。引數lpszItem 指定了要插入的字串。
返回值:返回實際的插入位置,若發生錯誤,會返回LB_ERR 或LB_ERRSPACE。
int DeleteString(UINT nIndex);
該函式用於刪除指定的列表項。
引數:nIndex 指定了要刪除項的索引。
返回值:函式的返回值為剩下的列表項數目,如果nIndex 超過了實際的表項總數,則返回LB_ERR。
void ResetContent();
該函式用於清除所有列表項。
int GetText(int nIndex,LPTSTR lpszBuffer) const;
void GetText(int nIndex,CString& rString) const;
這兩個成員函式用於獲取指定列表項的字串。引數nIndex 指定了列表項的索引。引數lpszBuffer 指向一個接收字串的緩衝區。引用引數rString 則指定了接收字串的CString物件。第一個版本的函式會返回獲得的字串的長度,若出錯,則返回LB_ERR;第二個版本的函式則不會。
int GetTextLen(int nIndex) const;
該函式返回指定列表項的字串的位元組長度。
引數:nIndex 指定了列表項的索引。
返回值:若出錯則返回LB_ERR。
int GetCurSel() const;
該函式僅適用於單選列表框,用來返回當前被選擇項的索引,如果沒有列表項被選擇或有錯誤發生,則函式返回LB_ERR。
int SetCurSel(int nSelect);
該函式僅適用於單選列表框,用來選擇指定的列表項。該函式會滾動列表框以使選擇項可見。引數nIndex 指定了列表項的索引,若為-1,那麼將清除列表框中的選擇。若出錯函式返回LB_ERR。
int GetSelCount() const;
該函式僅用於多重選擇列表框,它返回選擇項的數目,若出錯函式返回LB_ERR。
int FindString(int nStartAfter,LPCTSTR lpszItem) const;
該函式用於對列表項進行與大小寫無關的搜尋。引數nStartAfter 指定了開始搜尋的位置,合理指定nStartAfter 可以加快搜索速度,若nStartAfter 為-1,則從頭開始搜尋整個列表。引數lpszItem 指定了要搜尋的字串。函式返回與lpszItem 指定的字串相匹配的列表項的索引,若沒有找到匹配項或發生了錯誤,則會返回LB_ERR。FindString 函式先從nStartAfter指定的位置開始搜尋,若沒有找到匹配項,則會從頭開始搜尋列表。只有找到匹配項,或對整個列表搜尋完一遍後,搜尋過程才會停止,所以不必擔心會漏掉要搜尋的列表項。
int SelectString(int nStartAfter,LPCTSTR lpszItem);
該函式僅適用於單選列表框,用來選擇與指定字串相匹配的列表項。該函式會滾動列表框以使選擇項可見。引數的意義及搜尋的方法與函式FindString 類似。如果找到了匹配的項,函式返回該項的索引,如果沒有匹配的項,函式返回LB_ERR 並且當前的選擇不被改變。
CListBox類應用例項
最後給大家寫一個簡單的例項,說明CListBox的幾個成員函式及通知訊息等的使用方法。此例項實現的功能:在單選列表框中顯示一個網站列表,然後在用滑鼠左鍵選擇某列表項時,將選中列表項的文字顯示到編輯框中。下面是具體實現步驟:
1. 建立一個基於對話方塊的MFC工程,名稱設定為“Example23”。
2. 在自動生成的對話方塊模板IDD_EXAMPLE23_DIALOG中,刪除“TODO: 在此處放置對話方塊控制元件.”靜態文字控制元件、“確定”按鈕和“取消”按鈕。新增一個List box控制元件,ID設定為IDC_WEB_LIST,Sort屬性設為False,以取消排序顯示。再新增一個靜態文字控制元件和一個編輯框,靜態文字控制元件的Caption屬性設為“您選擇的站點:”,編輯框的ID設為IDC_SEL_WEB_EDIT,Read Only屬性設為True。此時的對話方塊模板如下圖:
3. 為列表框IDC_WEB_LIST新增CListBox型別的控制元件變數m_listbox。
4. 在對話方塊初始化時,我們將站點名加入到列表框中,那麼需要修改CExample23Dlg::OnInitDialog()函式為:
BOOL CExample23Dlg::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_listbox.AddString(_T("清華大學"));
m_listbox.AddString(_T("北京大學"));
m_listbox.AddString(_T("上海交通大學"));
m_listbox.AddString(_T("西安交通大學"));
m_listbox.AddString(_T("西南交通大學"));
m_listbox.AddString(_T("北京交通大學"));
return TRUE; // 除非將焦點設定到控制元件,否則返回 TRUE
}
5. 我們希望在選中列表項改變時,將最新的選擇項實時顯示到編輯框中,那麼這就要用到LBN_SELCHANGE通知訊息。為列表框IDC_WEB_LIST的通知訊息LBN_SELCHANGE新增訊息處理函式CExample23Dlg::OnLbnSelchangeWebList(),雙擊列表控制元件即可,並修改如下:
void CExample23Dlg::OnLbnSelchangeWebList()
{
// TODO: 在此新增控制元件通知處理程式程式碼
CString strText;
int nCurSel;
nCurSel = m_listbox.GetCurSel();
m_listbox.GetText(nCurSel, strText);
SetDlgItemText(IDC_SEL_WEB_EDIT, strText);
}
6. 執行程式,彈出結果對話方塊,在對話方塊的列表框中用滑鼠改變選中項時,編輯框中的顯示會相應改變。效果圖如下:
關於列表框ListBox的講解就到此為止了。大家如果想試驗更多的列表框成員函式,可以在上面的小例子中加入更多的功能來體會。感謝大家對本部落格的關注,歡迎大家留言進行交流。