CListCtrl自动排序



在C++界面开发中,WLT::CListCtrl和MFC的CListCtrl都没有自动排序功能,不过他们都提供了一个回调函数,通过SortItems或者SortItemsEx方法来进行。激活SortItems方法,需要接受Column的Click事件,然后设置合适的数据,就可以实现自动排序了。

 

 

CListCtrl的排序

微软的VC++实在是个弱智的IDE,编程10小时,至少有5小时是在和windows作斗争,还是C++Builder好啊。不过微软横行霸道,Borland已经没有turbo c时代的雄风了,现在做WinCE的程序,不用VC++还不行。

CListCtrl是个让人头痛不已的控件,十分难用。CListCtrl的排序,是通过调用SortItems函数实现的。
 BOOL SortItems(
 PFNLVCOMPARE pfnCompare,
 DWORD_PTR dwData 
 ); 
其中, pfnCompare 是排序时被调用的回调函数, dwData是调用SortItems时传给回调函数的参数,是回调函数的第三个参数。
pfnCompare的定义是:
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, 
LPARAM lParamSort);
 

其中,lParam1、lParam2是和两个列表项相关的参数,这个参数在调用InsertItem/SetItem时,被存储于LVITEM::lParam中。这个参数被用于标定列表项,是我们在排序和查找列表项的“特征”,就像人名用于标定一个人一样。设置LVITEM::

lParam是排序的关键,不设置这个变量,就无法找到进行比较的两个项目,调用SortItems()就不起作用。这一点,MSDN里面没有说的很清楚。

知道排序的原理,那么来看看具体的实现方法:


1. 添加回调函数

//********************************
 // Call back funtion for sorting
 //********************************
 static int CALLBACK
 MyCompareProc(LPARAM lParam1,    //lParam1 and lParam2 are set                                  //in LVITEM::lParam
               LPARAM lParam2,    //In this case, we associate
                                  //it with item index;
               LPARAM lParamSort  //The parameter transfered
                                  //from SortItem();
               ) 
 { 
     CSPListCtrl * pListCtrl = (CSPListCtrl*)lParamSort; 
     LVFINDINFO pInfo1, pInfo2;
     pInfo1.flags = LVFI_PARAM;
     pInfo2.flags = LVFI_PARAM;
     pInfo1.lParam = lParam1;
     pInfo2.lParam = lParam2;
     int ind1 = pListCtrl->FindItem(&pInfo1);//根据在
                                            //Insert/SetItem时
                                            //指定的参数找到
                                            //被比较的项目
    int ind2 = pListCtrl->FindItem(&pInfo2);
     //本例根据第一列项目(item)的名字排序,故读取项目的text:
    //GetItemText第一个参数是项目号,实际是List行号,
    //第二个参数是子项目号,实际是项目的列号,本例是0
     //代表只对第一列的名字排序:
    CString strItem1 = pListCtrl->GetItemText(ind1,0);
     CString strItem2 = pListCtrl->GetItemText(ind2,0);
     //进行比较,m_iSortAsc是自定义CListCtrl类中的int类型标志变量.
     //用于指定按照降序还是升序排序:
    return pListCtrl->m_iSortAsc ? lstrcmp( strItem1, strItem2 )
            : lstrcmp( strItem2, strItem1 );
 }  

 2. 在自定义的CListCtrl派生类中定义SortItem函数:
BOOL CSPListCtrl::SortItem(int sortup)
 {
     m_iSortAsc=sortup;
     SortItems(MyCompareProc,(DWORD_PTR)this);
     return 1;
 }

 3. 在插入/设置项目时,设置项目的标识参数lParam

     没有这一步,是调用SortItems函数失败的关键。代码如下:
     ...............
     //Insert items for the item:
     item.mask=LVIF_TEXT|LVIF_IMAGE|LVIF_STATE|LVIF_PARAM;
     item.iItem   =nrow;
     item.iSubItem=ncol;
     item.pszText=text;
     item.iImage=nimg;
     item.state=state;
     //The parameter identifies the item:
     item.lParam=(LPARAM)(nrow*100+ncol);
     //Insert item:
     if(nrow>=GetRowCount()&&ncol==0)
     {
         re=CListCtrl::InsertItem(&item);
     }
     //If the item exists
     else if((nrow0)
     {
         re=CListCtrl::SetItem(&item);
     }
     ...............

 4. 在使用ListCtrl的对话框类中,调用我们的派生类的SortItem函数:
    ...................
     m_pListMain=(CSPListCtrl *) GetDlgItem(IDC_LISTMAIN);
     ...................
     m_pListMain->SortItem();
     ...................

  这里再就CListCtrl的项目说明一下。CListCtrl的项目分为项目和子项目,项目(item)就是列表某一行的第一列的元素,项目号实际就是行号,而该行第一列之后的叫子项目(subitem),子项目号实际就是列号。添加项目需要先添加第一列,再用InserItem()函数添加,而子项目的添加则不同,在添加列以后,只要调用SetItem()函数即可。

你可能感兴趣的:(vc++)