CListCtrl::SortItems的用法

 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://0
            
//自己按0列规则排序代码
                
//想要pInfo1(所代表的item)排在pInfo2(所代表的item)之前,则nRet小于0;反之大于0;顺序不变等于0
        break;
    
case 1://1列

        
//自己按1列规则排序代码
                
//...
        break;
    }


    
return nRet;
}

你可能感兴趣的:(Windows编程)