来源网站:http://blog.csdn.net/hgy413/article/details/6719908
列表控件(CListCtrl)的排序功能不像其它直接调用API就可以完成的功能一样.它比较复杂.今天将我的一点体会简单地谈一下. 列表控件的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。回调函数就好像是一个中断处理函数,操作系统在符合你设定的条件时自动调用。
·CListCtrl提供了用于排序的函数
函数原型为:
BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData);
其中第一个参数为全局排序函数(它就是回调函数)的地址,
第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。
该函数返回-1,代表第一项排应在第二项前面;
返回1代表第一项排应在第二项后面;
返回0代表两项相等。·排序函数原形为:
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。
第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/
BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。
·我们什么时候需要排序(消息映射)呢?
实现这点可以在父窗口中对LVN_COLUMNCLICK消息进行处理来实现。
例子:
//排序回调函数实现 static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { <span style="white-space:pre"> </span>// lParamSort contains a pointer to the list view control. <span style="white-space:pre"> </span>// The lParam of an item is just its index. <span style="white-space:pre"> </span>//以第一列为根据排序 <span style="white-space:pre"> </span>CListCtrl* pListCtrl = (CListCtrl*) lParamSort; <span style="white-space:pre"> </span>CString strItem1 = pListCtrl->GetItemText(lParam1, 0); <span style="white-space:pre"> </span>CString strItem2 = pListCtrl->GetItemText(lParam2, 0); //比较两个数 <span style="white-space:pre"> </span>LPCTSTR s1=(LPCTSTR)strItem1; <span style="white-space:pre"> </span>LPCTSTR s2=(LPCTSTR)strItem2; <span style="white-space:pre"> </span>int n1=atoi(s1); <span style="white-space:pre"> </span>int n2=atoi(s2);if (n1>n2) <span style="white-space:pre"> </span>return -1; <span style="white-space:pre"> </span>else <span style="white-space:pre"> </span>return 1; } <span style="white-space:pre"> </span>void C***::OnColumnclickList(NMHDR* pNMHDR, LRESULT* pResult) { <span style="white-space:pre"> </span>NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; <span style="white-space:pre"> </span>// TODO: Add your control notification handler code here //调用排序函数 <span style="white-space:pre"> </span>m_ShowData.SortItems( MyCompareProc, (DWORD)&m_ShowData ); <span style="white-space:pre"> </span>*pResult = 0;}
/////////////////////////////////////////// //按第六列排序 int CALLBACK listCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort) { CListCtrl* pListCtrl = (CListCtrl*)lParamSort; CString strItem1 = pListCtrl->GetItemText(lParam1,5); CString strItem2 = pListCtrl->GetItemText(lParam2,5); LVCOLUMN Vol; CString csStr(""); TCHAR szCol[MAX_PATH]; Vol.pszText = szCol; Vol.mask=LVCF_TEXT; Vol.cchTextMax=sizeof(szCol); pListCtrl->GetColumn(0,&Vol); csStr = CString(Vol.pszText); if (csStr.Right(1) == CString("▼")) { return _tcscmp(strItem2.GetBuffer(MAX_PATH),strItem1.GetBuffer(MAX_PATH)); } else if (csStr.Right(1) == CString("▲")) { return _tcscmp(strItem1.GetBuffer(MAX_PATH),strItem2.GetBuffer(MAX_PATH)); } else { return _tcscmp(strItem1.GetBuffer(MAX_PATH),strItem2.GetBuffer(MAX_PATH)); } } /////////////////// void CManageView::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult) { NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR; // TODO: Add your control notification handler code here CListCtrl &m_ListCtrl = GetListCtrl();for(int i = 0; i < m_ListCtrl.GetItemCount(); ++i) m_ListCtrl.SetItemData(i,i); m_ListCtrl.SortItems(listCompare,(LPARAM)&m_ListCtrl);*pResult = 0; }