列表控件(CListCtrl)的頂部有壹行按鈕,用戶可以通過選擇不同的列對記錄進行排序。但是,CListCtrl不具備自動排序功能。我們需要添加壹個用於排序的回調函數來比較兩個數據的大小,我們還需要響應排序按鈕被單擊的消息。下面說說具體做法。
CListCtrl提供了壹個排序函數。該函數的原型是Bool clist ctrl::Sort Items(pfnlvcompare pfn compare,dword dwdata)。第壹個參數是全局排序函數的地址,第二個參數是用戶數據。您可以根據需要傳遞數據或指針。該函數返回-1表示第壹項應該在第二項前面,返回1表示第壹項應該在第二項後面,返回0表示兩項相等。
用於排序的函數原型是:int回調列表比較(lparam lparam 1,lparam lparam 2,lparam lparam sort),其中第三個參數是調用者傳遞的數據(即調用SortItems時的第二個參數dwData)。第壹個和第二個參數是用於比較的兩個項目的ItemData。您可以通過dword clist ctrl::getitemdata(int nitem)/Bool clist ctrl::setitemdata(int nitem,dword dwdata)訪問每個項目的ItemData。還可以通過在添加項時選擇特定的CListCtrl::InsertItem來設置該值。因為在排序時只能通過該值來確定項目的位置,所以應該清楚地確定該值的含義。
最後,我們需要知道何時需要排序,這可以通過處理父窗口中的LVN _列單擊消息來實現。
讓我們看壹個例子。此示例是壹個派生類,支持順序排序和反向排序。為了簡單地對全局數據進行排序,在實際應用中會有多組數據需要排序,因此需要通過傳遞參數來告訴排序函數需要對哪些數據進行排序。
//全局數據
結構演示數據
{
char SZ name【20】;
int iAge
} strall data【5】= { {“王“,30},{“張“,40},{“吳“,32},{““,20},{“李“,36 } };
//CListCtrl派生類定義
類CSortList : public CListCtrl
{
//構造
公共:
CSortList();
BOOL m _ fAsc//是否按順序排序?
int m _ nSortedCol//當前排序的列
受保護:
//{ { AFX _ MSG(CSortList)
//}}AFX_MSG
...
};
//父窗口包含CListCtrl派生類對象。
class CSort _ in _ list _ ctrl DLG:public CDialog
{
//構造
公共:
CSort _ in _ list _ ctrl DLG(CWnd * p parent = NULL);//標準構造函數
//對話數據
//{ { AFX _ DATA(CSort _ in _ list _ ctrl DLG)
enum { IDD = IDD _ SORT _ IN _ LIST _ CTRL _ DIALOG };
CSortList m _ listTest
//}}AFX_DATA
}
//在父窗口中定義LVN _列單擊消息映射。
BEGIN _ MESSAGE _ MAP(CSort _ in _ list _ ctrl DLG,CDialog)
//{ { AFX _ MSG _ MAP(CSort _ in _ list _ ctrl DLG)
ON _ NOTIFY(LVN專欄點擊,IDC列表1,專欄點擊列表1)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
//初始化數據
BOOL CSort _ in _ list _ ctrl DLG::OnInitDialog()
{
CDialog::OnInitDialog();
//初始化ListCtrl中的數據列表
M_listTest。insert column(0,“name“);
m _ list test . insert column(1,“age“);
m_listTest。setcolumnwwidth(0,80);
m_listTest。setcolumnwwidth(1,80);
for(int I = 0;我& lt5;i++)
{
m_listTest。insert item(I,strall data【I】。SZ name);
char szAge【10】;
sprintf(szAge,“%d“,strall data【I】。iAge);
m_listTest。SetItemText(I,1,szAge);
//將每壹項的ItemData設置為數組中數據的索引。
//數據由排序函數中的ItemData確定。
m_listTest。SetItemData(I,I);
}
返回TRUE//除非將焦點設置到控件上,否則返回TRUE
}
//處理消息
void CSort _ in _ list _ ctrl DLG::oncolumnclicklist 1(nmh dr * pNMHDR,LRESULT* pResult)
{
NM _ LISTVIEW * pNMListView =(NM _ LISTVIEW *)pNMHDR;
//設置排序方法
if(pNMListView-& gt;iSubItem = = m _ list test . m _ nSortedCol)
m_listTest.m_fAsc =!m _ listTest.m _ fAsc
其他
{
m _ listTest.m _ fAsc = TRUE
m _ list test . m _ nSortedCol = pNMListView-& gt;iSubItem
}
//呼叫排序功能
m_listTest。sort items(list compare,(DWORD)& amp;m _ list test);
* pResult = 0;
}
//排序函數的實現
int回調list compare(LPARAM LPARAM 1,LPARAM lParam2,LPARAM lParamSort)
{
//通過傳遞的參數獲取CSortList對象指針,從而得到排序方法。
CSortList * pV =(CSortList *)lParamSort;
//通過ItemData確定數據。
DEMO _ DATA * pinfo 1 = strall DATA+lparam 1;
DEMO _ DATA * pinfo 2 = strall DATA+lparam 2;
CString szComp1,szComp2
int iCompRes
開關(pV-& gt;m_nSortedCol)
{
案例(0):
//按第壹列排序
SZ comp 1 = pinfo 1-& gt;szName
SZ comp 2 = pinfo 2-& gt;szName
iCompRes=szComp1。比較(SZ comp 2);
打破;
案例(1):
//按第二列排序
if(pinfo 1-》;iAge = = pinfo 2-& gt;iAge)
I compres = 0;
其他
iCompRes =(pinfo 1-& gt;iAge & ltpinfo 2-& gt;iAge)?-1:1;
打破;
默認值:
斷言(0);
打破;
}
//根據當前排序方式進行調整。
if(pV-& gt;m_fAsc)
返回iCompRes
其他
return iCompRes *-1;
}