VC/MFC项目开发——使用回调函数为CListCtrl排序(k_eckel转自微软高校博客K_eckel's mindview

CListCtrl经常在开发中被用来显示数据,但是系统提供的CListCtrl(无论是ListCtrl控件还是CListView中CListCtrl)都没有提供对列进行排序的功能(这正是很多系统要求的),虽然已经有对CListCtrl控件扩展的ListCtrl,但是我们可以通过自己编写回调函数来实现对列的排序。其有点至少有2:1)你可以自己任意的定制排序算法和要求;2)在这个过程中,你的个人能力可以得到提高。
     以下给出的一个CSortClass类为:

//CSortClass.h
#ifndef  _CSORTCLASS_H_
#define _CSORTCLASS_H_

class CSortClass 
{
public:
 
        CSortClass();

        virtual ~CSortClass();

       CSortClass(CListCtrl* _pWnd,const int _iCol,const
                        bool _bIsNumeric);
public:
         int iCol;
         CListCtrl* pWnd;
         bool bIsNumeric;

public:
         void Sort(const bool bAsc);

         static int CALLBACK CompareAsc(LPARAM
         lParam1,LPARAM lParam2,LPARAM lParamSort);

         static int CALLBACK CompareDes(LPARAM
         lParam1,LPARAM lParam2,LPARAM lParamSort);

         static int CALLBACK CompareAscI(LPARAM 
         lParam1,LPARAM lParam2,LPARAM lParamSort);

         static int CALLBACK CompareDesI(LPARAM 
         lParam1,LPARAM lParam2,LPARAM lParamSort);

public:
         class CSortItem
         {
          public:
          virtual ~CSortItem();

          CSortItem(const DWORD _dw,const CString& _txt);
          CString txt;
          DWORD dw;
         };

         class CSortItemInt
         {
         public:
         CSortItemInt(const DWORD _dw,CString _txt);

          int iInt;

          DWORD dw;
         };

};

#endif //~_CSORTCLASS_H_

#include "SortClass.h"

CSortClass::CSortClass(CListCtrl* _pWnd,const int _iCol,const bool _bIsNumeric)
{
 iCol = _iCol;

 pWnd = _pWnd;

 bIsNumeric = _bIsNumeric;

 ASSERT(pWnd);

 int max = pWnd->GetItemCount();

 DWORD dw;

 CString txt;

 if (bIsNumeric)
 {
  for (int t = 0; t < max; t++)
  {
   dw = pWnd->GetItemData(t);

   txt = pWnd->GetItemText(t,iCol);

         pWnd->SetItemData(t,(DWORD) new CSortItemInt(dw,txt));
  }
 }
 else
 {
  for (int t = 0; t < max; t++)
  {
   dw = pWnd->GetItemData(t);

   txt = pWnd->GetItemText(t,iCol);

         pWnd->SetItemData(t,(DWORD) new CSortItem(dw,txt));
  }
 }
}

CSortClass::~CSortClass()
{
 ASSERT(pWnd);

 int max = pWnd->GetItemCount();
 
 if (bIsNumeric)
 {
  CSortItemInt* pItem;

  for (int t = 0; t < max; t++)
  {
   pItem = (CSortItemInt*)pWnd->GetItemData(t);
   ASSERT(pItem);
   
   pWnd->SetItemData(t,pItem->dw);

   delete pItem;
  }
 }
 else
 {
  CSortItem* pItem;

  for (int t = 0; t < max; t++)
  {
   pItem = (CSortItem*)pWnd->GetItemData(t);
   ASSERT(pItem);
   
   pWnd->SetItemData(t,pItem->dw);

   delete pItem;
  }
 }
}

void CSortClass::Sort(const bool bAsc)
{
 if (bIsNumeric)
 {
  if (bAsc)
  {
   pWnd->SortItems(CompareAscI,0L);
  }
  else
  {
   pWnd->SortItems(CompareDesI,0L);
  }
 }
 else
 {
  if (bAsc)
  {
   pWnd->SortItems(CompareAsc,0L);
  }
  else
  {
   pWnd->SortItems(CompareDes,0L);
  }
 }
}

int CALLBACK CSortClass::CompareAsc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
 CSortItem* i1 = (CSortItem*)lParam1;

 CSortItem* i2 = (CSortItem*)lParam2;
 ASSERT(i1 && i2);

 return i1->txt.CompareNoCase(i2->txt);
}

int CALLBACK CSortClass::CompareDes(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
 CSortItem* i1 = (CSortItem*)lParam1;

 CSortItem* i2 = (CSortItem*)lParam2;
 ASSERT(i1 && i2);

 return i2->txt.CompareNoCase(i1->txt);
}

int CALLBACK CSortClass::CompareAscI(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
 CSortItemInt* i1 = (CSortItemInt*)lParam1;

 CSortItemInt* i2 = (CSortItemInt*)lParam2;
 ASSERT(i1 && i2);

 if (i1->iInt == i2->iInt)
  return 0;
 return i1->iInt > i2->iInt ? 1 : -1;
}

int CALLBACK CSortClass::CompareDesI(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
 CSortItemInt* i1 = (CSortItemInt*)lParam1;

 CSortItemInt* i2 = (CSortItemInt*)lParam2;
 ASSERT(i1 && i2);

 if (i1->iInt == i2->iInt)
  return 0;
 return i1->iInt < i2->iInt ? 1 : -1;
}

CSortClass::CSortItem::CSortItem(const DWORD _dw,const CString& _txt)
{
 dw = _dw;
 txt = _txt;
}

CSortClass::CSortItem::~CSortItem()
{

}

CSortClass::CSortItemInt::CSortItemInt(const DWORD _dw,CString _txt)
{
 iInt = atoi((LPSTR)(LPCTSTR)_txt);
//EVC中使用的是Unicode编码,要用_wtoi()
//"在VC中则使用_atoi(_txt)"
//iInt = _wtoi(_txt);

 dw = _dw;
}


     在使用时候要注意3点:
     1)在使用CSortClass时候,响应要排序的CListCtrl的NM_COLUMNCLICK消息,然后Include CSortClass头文件,添加以下类似代码:
     CSortClass csc(&m_ListCtrl,iColSelected,bIsNumeric);//m_ListCtrl为待排序的CListCtrl指针,iColSelected为排序的列,bIsNumeric标志是否为数字(否则都按照字符串处理)
    csc.Sort(bAscending);  //bAscending标志升降序
    2)CSortClass不能对汉字进行正确排序,因为汉字编码是Unicode编码,其编码规则不和ASCII相同。
    3)由于在EVC中所有编码都是Unicode编码,因此在CsortClass的实现中(代码中红色字体部分)和VC中有些许差别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值