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

CListCtrl 欄位點擊排序完整實作:回調函數與訊息處理範例

     編輯:VC 教學

核心 API

BOOL CListCtrl::SortItems(PFNLVCOMPARE pfnCompare, DWORD dwData);
  • pfnCompare:全域回調函數指標,簽章 int CALLBACK Compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)。
  • dwData:使用者自定義資料,傳遞給比較函數第三參數 lParamSort。
  • 回傳值:-1 (項目1 < 項目2)、0 (相等)、1 (項目1 > 項目2)。

比較函數設計要點

  • 每個 List 項目的 ItemData (透過 SetItemData/GetItemData) 應能唯一映射到資料源索引或指標。
  • 比較函數中透過 lParamSort 取得排序上下文 (如目前排序欄位、升冪/降冪旗標)。

觸發排序:處理 LVN_COLUMNCLICK

// 對話框/視圖類訊息對應
ON_NOTIFY(LVN_COLUMNCLICK, IDC_MY_LIST, OnColumnClick)

// 處理函數
void CMyDialog::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult) {
    NM_LISTVIEW* pNM = (NM_LISTVIEW*)pNMHDR;
    int col = pNM->iSubItem;

    // 切換升冪/降冪
    if (col == m_listCtrl.m_nSortedCol)
        m_listCtrl.m_bAscending = !m_listCtrl.m_bAscending;
    else {
        m_listCtrl.m_nSortedCol = col;
        m_listCtrl.m_bAscending = TRUE;
    }

    // 呼叫排序,傳遞 this 指標作為上下文
    m_listCtrl.SortItems(CompareFunc, (DWORD)&m_listCtrl);
    *pResult = 0;
}

完整可執行範例 (對話框專案)

資料結構與全域測試資料

struct DEMO_DATA { char szName[20]; int iAge; };
DEMO_DATA g_data[5] = {
    {"王某", 30}, {"張某", 40}, {"武某", 32}, {"陳某", 20}, {"李某", 36}
};

衍生列表控制類別

class CSortList : public CListCtrl {
public:
    CSortList() : m_bAscending(TRUE), m_nSortedCol(-1) {}
    BOOL m_bAscending;   // 升冪旗標
    int  m_nSortedCol;   // 目前排序欄位
};

對話框初始化與資料填充

BOOL CMyDialog::OnInitDialog() {
    CDialog::OnInitDialog();
    m_listCtrl.InsertColumn(0, _T("姓名"), LVCFMT_LEFT, 80);
    m_listCtrl.InsertColumn(1, _T("年齡"), LVCFMT_RIGHT, 80);

    for (int i = 0; i < 5; i++) {
        m_listCtrl.InsertItem(i, g_data[i].szName);
        CString strAge; strAge.Format(_T("%d"), g_data[i].iAge);
        m_listCtrl.SetItemText(i, 1, strAge);
        m_listCtrl.SetItemData(i, i); // ItemData = 陣列索引
    }
    return TRUE;
}

全域比較回調函數

int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) {
    CSortList* pList = (CSortList*)lParamSort;
    DEMO_DATA* p1 = &g_data[lParam1];
    DEMO_DATA* p2 = &g_data[lParam2];
    int result = 0;

    switch (pList->m_nSortedCol) {
    case 0: // 姓名 (字串比較)
        result = strcmp(p1->szName, p2->szName);
        break;
    case 1: // 年齡 (數值比較)
        if (p1->iAge == p2->iAge) result = 0;
        else result = (p1->iAge < p2->iAge) ? -1 : 1;
        break;
    default: ASSERT(0); break;
    }

    return pList->m_bAscending ? result : -result;
}

進階擴展建議

  • 多資料源支援:lParamSort 傳遞結構體指標,包含資料源指標、型別資訊,實現通用比較器。
  • 排序指示器:SetColumnImage 或 Owner Draw 繪製欄標標題箭頭 (▲/▼)。
  • 效能優化:大量資料 (萬筆以上) 建議使用虛擬清單 (LVS_OWNERDATA) 配合記憶體內排序,避免頻繁回調開銷。
  • 多欄位複合排序:lParamSort 擴展為排序規則陣列,比較函數依序應用。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved