CListCtrl::SortItems的用法:
(一)SortItems使用在哪?
CListCtrl::SortItems的原型是:
BOOL SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData );
其中
1)第一個參數pfnCompare為回呼函數,形式為:
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2,
LPARAM lParamSort);
lParam1,lParam2是什嗎?這是SortItems難理解的原因。在(二)中介紹。
lParamSort實際上是列數,等於2)中的dwData。
2)第二個參數dwData為使用者自訂值。
dwData實際傳入的是列數,等於1)中的lParamSort。
下面是SortItems使用的地方:
//LVN_COLUMNCLICK訊息響應函數
void CUpListCtrl::OnColumnclick(NMHDR* pNMHDR, LRESULT* pResult)
...{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
//排序
//CompareFunc是回呼函數
//pNMListView->iSubItem就是列數
SortItems( (PFNLVCOMPARE)CompareFunc, pNMListView->iSubItem );
*pResult = 0;
}
(二)SortItems的的回呼函數的中的lParam1,lParam2是什嗎?
簡單的說:是LV_ITEM::lParam。
LV_ITEM是個結構,見msdn。
可見,我們在向CListCtrl插入item時,必須使用
int InsertItem( const LVITEM* pItem );
InsertItem有好幾種形式,只有這種形式才能夠使用LV_ITEM::lParam。
下面是插入item的代碼的一個樣本:
tagInfo *pFileInfo = new tagInfo;//tagInfo是個結構,儲存了你排序的所需要的資訊。
pFileInfo->strFileName = strFileName;
pFileInfo->strFileSize = FormatFileSize(filefind.GetLength());
pFileInfo->strFileType = GetTypeName(lpszFileName);
//pFileInfo->strFilePath = strPath;
int nItem = GetItemCount();
int nIcon = GetIconIndex(lpszFileName, filefind.IsDirectory(), FALSE);
LV_ITEM lvi;
lvi.mask = LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE;
lvi.iItem = nItem;
lvi.iSubItem = 0;
lvi.pszText = (LPTSTR)(LPCTSTR)pFileInfo->strFileName;
lvi.lParam = (LPARAM)pFileInfo;
lvi.iImage = nIcon;
if( (nItem = InsertItem(&lvi)) != -1 )//插入檔案名稱(即第0列),並顯示相應表徵圖
...{
//MessageInt(nItem);
lvi.mask = LVIF_TEXT;
lvi.iItem = nItem;
//設定第1列(即設定檔案大小)
lvi.iSubItem = 1;
if(!filefind.IsDirectory())//如果不是目錄
...{
lvi.pszText = (LPTSTR)(LPCTSTR)pFileInfo->strFileSize;
SetItem( &lvi );
}
else//如果是目錄
...{
lvi.pszText = (LPTSTR)YCT_UNKNOW_SIZE;
SetItem( &lvi );
}
//設定第2列(即設定檔案類型)
lvi.iSubItem = 2;
lvi.pszText = (LPTSTR)(LPCTSTR)pFileInfo->strFileType;
SetItem( &lvi );
//設定第3列(即設定檔案所在目錄)
lvi.iSubItem = 3;
lvi.pszText = (LPTSTR)(LPCTSTR)strPath;
SetItem( &lvi );
//更新介面
//Update( lvi.iItem );
}
現在lParam指向的是new出來的空間,當然要用delete刪除。以下是刪除代碼:
//LVN_DELETEITEM訊息響應函數
//每刪除一個item,系統都要自動調用這個函數的
void CUpListCtrl::OnDeleteitem(NMHDR* pNMHDR, LRESULT* pResult)
...{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
//刪除LV_ITEM::lParam所指向的空間
LV_ITEM lvi;
lvi.mask = LVIF_PARAM;
lvi.iItem = pNMListView->iItem;
lvi.iSubItem = 0;
if ( GetItem( &lvi ) )
...{
CUpListCtrl::tagInfo* pInfo = (CUpListCtrl::tagInfo*)(lvi.lParam);
delete pInfo;
}
*pResult = 0;
}
(三)編寫回呼函數
這個就比較簡單了,按你的規則排序就可以了。
這裡回呼函數是個靜態成員函數。
//回呼函數
int CALLBACK CUpListCtrl::CompareFunc(CUpListCtrl::tagInfo* pInfo1, CUpListCtrl::tagInfo* pInfo2, LPARAM lCol)
...{
//CListCtrl::SortItems使用的回呼函數
//[IN]pInfo1,pInfo2:傳入的是LV_ITEM::lParam,在調用InsertItem(const LVITEM* pItem)時指定
//[IN]lCol:指定列數(從零開始),即按哪一列排序
int nRet = 0;
ASSERT(lCol>=0 && lCol<NumCol-1);
ASSERT(pInfo1 != NULL);
ASSERT(pInfo2 != NULL);
switch(lCol)
...{
case 0://O列
//自己按0列規則排序代碼
//想要pInfo1(所代表的item)排在pInfo2(所代表的item)之前,則nRet小於0;反之大於0;順序不變等於0
break;
case 1://1列
//自己按1列規則排序代碼
//...
break;
}
return nRet;
}