首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 列表框 CListBox 與檢查列表框 CCheckListBox 完整開發指南

     編輯:關於C語言

列表框是單列文本展示的基礎控件,支持單選、多選、排序。MFC CListBox 封裝完整操作,CCheckListBox (MFC 4.2+) 在此基礎上添加每行複選框功能。本文系統講解創建風格、項管理、選擇處理、查找匹配、複選框狀態控制及消息映射。

一、 CListBox 創建與風格

BOOL Create(LPCTSTR lpszText, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID = 0xffff);

選擇模式風格(互斥或組合)

風格選擇行為獲取選中方式
(無特殊風格)單選GetCurSel()/SetCurSel()
LBS_MULTIPLESEL點擊即切換選中狀態GetSelCount() + GetSelItems()
LBS_EXTENDEDSELShift/Ctrl + 點擊 範圍/離散選擇GetSelCount() + GetSelItems()

輔助風格

  • LBS_SORT:自動按字母排序
  • LBS_HASSTRINGS:項包含字符串(默認)
  • LBS_OWNERDRAWFIXED/VARIABLE:自繪模式
  • LBS_NOINTEGRALHEIGHT:不調整高度適應整行
  • WS_VSCROLL/WS_HSCROLL:滾動條

二、 項管理核心函數

操作函數返回值
添加項(末尾)AddString(LPCTSTR)索引 (0-based)
插入項(指定位置)InsertString(int, LPCTSTR)索引
刪除項DeleteString(UINT)剩餘項數
清空所有ResetContent()無
獲取項數GetCount()項總數
獲取項文本GetLBText(int, LPTSTR) / GetText(int, CString&)字符長度
查找字符串FindString(int nStartAfter, LPCTSTR)索引 (CB_ERR=未找到)
選中匹配項SelectString(int nStartAfter, LPCTSTR)索引

三、 選擇狀態處理

單選模式

int idx = list.GetCurSel();        // 獲取
list.SetCurSel(idx);               // 設置

多選模式 (LBS_MULTIPLESEL / LBS_EXTENDEDSEL)

// 1. 獲取選中項數
int count = list.GetSelCount();

// 2. 分配數組接收索引
int* indices = new int[count];
list.GetSelItems(count, indices);

// 3. 遍歷處理
for (int i = 0; i < count; ++i) {
    CString text;
    list.GetText(indices[i], text);
    // 處理選中項...
}
delete[] indices;

設置多選狀態

list.SetSel(index, TRUE);   // 選中
list.SetSel(index, FALSE);  // 取消選中
list.SelItemRange(TRUE, 0, 9); // 批量選中 0-9

四、 CCheckListBox 檢查列表框

繼承自 CListBox,擁有所有基類功能,額外提供每行複選框

創建關鍵要求

// 必須指定自繪風格之一
dwStyle |= LBS_OWNERDRAWFIXED;  // 或 LBS_OWNERDRAWVARIABLE
m_checkList.Create(dwStyle, rect, pParent, nID);

複選框樣式控制

// 設置/獲取複選框樣式 (參考 Button 控件 BS_* 風格)
void SetCheckStyle(UINT nStyle);
UINT GetCheckStyle();

複選狀態核心操作

操作函數狀態值
設置檢查狀態SetCheck(int nIndex, int nCheck)0=未選, 1=選中, 2=不確定(三態)
獲取檢查狀態GetCheck(int nIndex)同上
批量設置循環調用 SetCheck-

三態複選框邏輯

  • BS_AUTO3STATE / BS_3STATE:支持 0/1/2 三態
  • 狀態 2(不確定/灰色)通常表示「部分選中」或「禁用」
  • 父子節點關聯時:父節點狀態 = 子節點全選(1)/全不選(0)/混合(2)

五、 常用消息映射

ON_LBN_XXX(IDC_LIST, OnXxxList)
// 處理函數:afx_msg void OnXxxList();
宏觸發條件
ON_LBN_SELCHANGE選擇項改變(單選/多選)
ON_LBN_DBLCLK雙擊項
ON_LBN_SELCANCEL取消選擇(再次點擊已選項,僅多選模式)
ON_LBN_SETFOCUS/KILLFOCUS獲得/失去焦點
ON_LBN_ERRSPACE內存分配失敗

六、 實戰代碼模板

1. 初始化檢查列表框

void CMyDialog::InitCheckList() {
    // 風格必須包含 LBS_OWNERDRAWFIXED
    DWORD style = WS_CHILD | WS_VISIBLE | WS_VSCROLL | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS;
    m_checkList.Create(style, rect, this, IDC_CHECKLIST);
    
    // 添加項
    m_checkList.AddString(_T("選項一"));
    m_checkList.AddString(_T("選項二"));
    m_checkList.AddString(_T("選項三"));
    
    // 設置默認勾選
    m_checkList.SetCheck(0, 1); // 選中第一項
    m_checkList.SetCheck(2, 2); // 第三項不確定狀態
    
    // 設置複選框樣式 (可選)
    m_checkList.SetCheckStyle(BS_AUTOCHECKBOX | BS_LEFTTEXT); // 文字在左
}

2. 獲取所有勾選項

void CMyDialog::OnGetChecked() {
    CString result;
    for (int i = 0; i < m_checkList.GetCount(); ++i) {
        if (m_checkList.GetCheck(i)) { // 1或2視為勾選
            CString text;
            m_checkList.GetText(i, text);
            result += text + _T("; ");
        }
    }
    AfxMessageBox(_T("已勾選: ") + result);
}

3. 父子聯動邏輯(樹形結構扁平化)

void CMyDialog::OnSelchangeChecklist() {
    // 簡單示例:項0為父,項1-3為子
    int parentCheck = m_checkList.GetCheck(0);
    if (parentCheck == 1) { // 父選中 → 全選子
        for (int i = 1; i < 4; ++i) m_checkList.SetCheck(i, 1);
    } else if (parentCheck == 0) { // 父未選 → 全不選子
        for (int i = 1; i < 4; ++i) m_checkList.SetCheck(i, 0);
    }
    // 父為不確定態(2)時保持子項現狀
}

七、 避坑指南

  1. 忘記 LBS_OWNERDRAWFIXED:CCheckListBox 不顯示複選框、SetCheck 無效
  2. 多選模式下 GetCurSel 失效:必須用 GetSelCount + GetSelItems
  3. FindString 前綴匹配不區分大小寫:需精確匹配請自行遍歷比較
  4. 大量項操作閃爍:用 SetRedraw(FALSE) 批量操作後 SetRedraw(TRUE) + Invalidate()
  5. 三態邏輯混淆:明確業務含義:0=無、1=有、2=部分/不確定,UI與數據模型同步

本文整理自 MFC 經典技術文檔,適用於 VC6~VS2022 所有版本。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved