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;
}