第一次用ListControl控件,不知道排序功能要怎么实现。虽然网上也找到了一些例子,但是都没有详细的说明文档。我摸索了很久还是没有理清楚其中的逻辑。一个字“菜”,两个字“很菜”。小弟特来求助,不知道哪里有详细的中文资料(e文太差),用于说明ListControl控件排序功能的实现,特别是那个回调函数的实现。请高手帮忙,谢谢!学习,关注……

解决方案 »

  1.   

    参考:http://www.china-askpro.com/msg11/qa52.shtml
    http://www.pconline.com.cn/pcedu/empolder/gj/vc/0404/348784.html
    http://www.vckbase.com/document/viewdoc/?id=243
      

  2.   

    http://www.codeguru.com/listview/sort_on_col.shtml
    Sorting the list based on text in any column - Zafir Anjum (1998/08/06)
    http://www.codeguru.com/listview/sort_on_col_generic.shtml
    Sort list based on text/numeric/date-time in any column - Tal J. Rosen (1998/08/06)
      

  3.   

    用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。
      

  4.   

    //排序函数实现
      int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
      {
       //通过传递的参数来得到CSortList对象指针,从而得到排序方式
       CSortList* pV=(CSortList*)lParamSort;
     
       //通过ItemData来确定数据
       DEMO_DATA* pInfo1=strAllData+lParam1;
       DEMO_DATA* pInfo2=strAllData+lParam2;
       CString szComp1,szComp2;
       int iCompRes;
       switch(pV->m_nSortedCol)
       {
       case(0):
        //以第一列为根据排序
        szComp1=pInfo1->szName;
        szComp2=pInfo2->szName;
        iCompRes=szComp1.Compare(szComp2);
        break;
       case(1):
        //以第二列为根据排序
        if(pInfo1->iAge == pInfo2->iAge)
         iCompRes = 0;
        else
         iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
        break;
       default:
        ASSERT(0);
        break;
       }
       //根据当前的排序方式进行调整
       if(pV->m_fAsc)
        return iCompRes;
       else
        return iCompRes*-1;
      }
      

  5.   

    楼上的大哥,按照你的方法,我插入到LstCtrl中的数据,必须先要保存到一个结构中?而且要Case到n才可以完成全部列的排序功能。请教一点:DEMO_DATA* pInfo1=strAllData+lParam1; 其中strAllData+lParam1是什么意思,不解!        
      

  6.   

    to: kugou123(酷狗)(http://www.xiaozhou.net)
    如果我要把排序的功能封装在一个CLstCtrl的派生类里面,您的方法好象不好用啊请指点,谢谢……学习……
      

  7.   

    我尝试把排序的功能封装到一个CLstCtrl的派生类CSortList里面,但是使用该类的时候出现中断,请看看我的代码://重载OnColumnClick函数,调用SortItems
      this->SortItems(CompareFunction, (LPARAM)this);//CompareFunction函数
    int CALLBACK CSortList::CompareFunction(LPARAM lParam1, LPARAM lParam2, LPARAM lParamData)
    {
       CSortList* pListCtrl = reinterpret_cast<CSortList*>( lParamData );
       ASSERT( pListCtrl->IsKindOf( RUNTIME_CLASS( CListCtrl ) ) );   ItemData* pid1 = reinterpret_cast<ItemData*>( lParam1 );
       ItemData* pid2 = reinterpret_cast<ItemData*>( lParam2 );
       ……
    }我调试的时候发现:lParam1,lParam2 都为0
    不知道是哪里出了问题?
    是不是this->SortItems(CompareFunction, (LPARAM)this)里面的(LPARAM)this没有传给lParamData 
    还是另有原因?请高手指点,谢谢!学习,关注……
      

  8.   

    http://www.zhugang.net/MyMFC/More/SortListCtrl.htm明明白白了解列表控件的排序功能2004年7月16日      大多数系统都需要显示数据,由于这些数据具有一定的规律,所以需要在显示的时候动态控制显示的顺序,其实就是数据显示的排序问题。我们通常使用列表控件来显示数据,那我们就来看看怎么使用列表控件的排序功能      研究列表控件的MSDN文档,我们发现系统本生已经提供了默认的排序功能,即列表控件的默认数据显示顺序:不排序,升序,降序。但是这些设置一旦初始化就不是很容易改变,也就是说开始为升序,那列表控件始终为升序排列,在平常的使用不是很方便,因此我们需要自己根据选择来动态排序。      继续查看MSDN我们看到列表控件提供了一个接口:
    BOOL SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData );
    这就是系统提供给我们自定义排序的接口,第一个参数是我们排序的函数地址,第二个参数是在排序中我们传递给排序函数的相关需要的参数,例如:当前排序安装什么方式:升序,降序等等      有了上面的接口我们就需要定义自己的排序函数了,系统规定的格式是:
    int CALLBACK Compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
    但是我们经常将其定义为改类的静态函数,这样列表控件的每个对象就可以共享了。现在我们了解一下参数的含义,参数1和参数2是系统传递给我们的,提供了需要比较的两个对象的信息(注意:这些信息都是需要我们提供的,下面说明),最后一个参数就是我们在调用SortItems是传递的参数。      有了比较的两个对象(参数1,参数2)已经比较的信息(参数3),我们就可以在Compare中写排序算法了,一般排序有数字排序,字符串排序,这里我就说明这两种,其他的就看自己的需要了CString str1 = ((ListData*)lParam1)->strText;
    CString str2 = ((ListData*)lParam2)->strText;
    int sOrder = (lParSortAsc & 0xFF) ? 1 : -1; 
    if (IsNumber(str1) && IsNumber(str2))
         return (atol(str1) - atol(str2))*sOrder;
    else
         return (str1.Compare(str2))*sOrder;        ListData是我们自己定义的数据结构用来存放比较的信息,代码非常简单我就不说明了,系统根据返回值的大小确定排序的结果,至于排序的次数我们就不需要考虑了,但我们调用SortItems函数后,系统自动调用回调函数,传递需要比较的对象,排序完成后SortItems函数也就返回了。      上面说明排序的方法,现在就说明排序的开始条件,在我们调用SortItems函数以前我们必须将排序的信息准备好,这样系统在回调的时候才能提供数据给我们的排序函数,代码如下for (int i = 0; i < NumItems; i++)
    {
        DWORD dwData = GetItemData(i);
        CString strText = GetItemText(i, m_nSortedCol);
        SetItemData(i, (DWORD)new ListData(dwData, strText)); 
    }      我们将排序的信息以及原来的数据信息打包重新保存到列表控件每个对象的数据地址中,这个地址也就是回调函数传递参数1和2,这样我们比较的信息就能够正确传递到回调函数中了,当SortItems函数返回的时候,排序已经结束,列表控件中对象的顺序已经发生改变,现在我们只需要恢复原来的数据信息就可以了,如下for(i=0; i<NumItems; i++) 
    {
        ListData* pData = (ListData*)GetItemData(i);
        SetItemData(i, pData->dwOldData);
        delete pData;
    }     这样我们的排序功能就完成了,不过为了让排序结果让使用者一下就能看清楚,我们可以在列表控件的头部控件中根据当前列的排序状态显示相关的描述信息(比如:画个三角表示升序),这些方法我就不说明,大家看考代码就明白了,下面是演示程序图片开始状态
    第二列升序排列(字符串)
    第二列降序排列(字符串)
    第四列升序排列(数字)
    第四列降序排列(数字)
        代码下载