int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort;
CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column);
if(sort_column<2)
{
if(method)

{
method=FALSE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
else
{
method=TRUE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
}
return 0;
}为什么只是排序前2项,觉得if中应该来个循环,我想全部排序,应该怎么做,求解?

解决方案 »

  1.   

    void CClistSortDlg::ListSort(void)
    {
    int listcount = m_list.GetItemCount(); 
    int nColumn =m_list.GetHeaderCtrl()->GetItemCount();
    CString temp0,temp1,temp2; 
    for(int j = 1;j <listcount;j++) 

    for(int i=0;i <listcount-j;i++) 

    temp1 = m_list.GetItemText(i,0); //m_list为控件绑定的变量,根据自己的修改
    temp2 = m_list.GetItemText(i+1,0); 
    //int nRe = StrCmpLogicalW(temp1,temp2); //
    int nRe = StrCmpI(temp1,temp2); //
    if (m_bSort)
    {
    if (nRe < 0)
    {
    for(int n=0;n <nColumn;n++) 

    temp1 = m_list.GetItemText(i,n); 
    temp2 = m_list.GetItemText(i+1,n); 
    m_list.SetItemText(i,n,temp2); 
    m_list.SetItemText(i+1,n,temp1); 
    }
    }
    }
    if (!m_bSort)
    {
    if (nRe > 0)
    {
    for(int n=0;n <nColumn;n++) 

    temp1 = m_list.GetItemText(i,n); 
    temp2 = m_list.GetItemText(i+1,n); 
    m_list.SetItemText(i,n,temp2); 
    m_list.SetItemText(i+1,n,temp1); 

    }
    }
    }
    }
    }
      

  2.   

    MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    这个函数如果是CListCtrl用来排序的回调函数,这样写是对的。
    CListCtrl会针对每行记录调用这个函数来排序。不是用来你自己在对话框中调用的。得加上这个void CListCtrlDlg::OnColumnClickDGrid(NMHDR* pNMHDR, LRESULT* pResult)
    {
    NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR; m_lstctlTable.SortItems((PFNLVCOMPARE)MyCompareProc, &m_lstctlTable);
    *pResult=0;
    }然后点击列表头,就对其中记录按MyCompareProc中的规则,排序了。
      

  3.   

    shen_wei的代码有点缺陷,因为只是交换了itemtext,实际中可能还需要交换图标、itemdata等等。
    用CListCtrl自己的排序,除了实现排序函数,还要满足两个条件:
    1. 各行必须有不同的itemdata。
    2. 不能只有一列。当然,这两点是10年前发现的,当时用2000多些,现在也许没这问题了。
      

  4.   

    刚看了下msdn,现在还是这样要求的。
    int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
     
    The lParam1 parameter is the 32-bit value associated with the first item that is compared, and the lParam2 parameter is the value associated with the second item. These are the values that were specified in the lParam member of the items' LVITEM structure when they were inserted into the list.也就是说,listctrl传给排序函数的参数lParam1和lParam2,其实不是行索引号,是itemData。
    你可以在排序前给每行SetItemData,值就用行索引号,排序后再还原就行了。
      

  5.   


    void CListCtrlDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    sort_column=pNMLV->iSubItem;
    int count=m_ListCtrl.GetItemCount();
    for(int i=0;i<count;i++)
    m_ListCtrl.SetItemData(i,i);
    m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&m_ListCtrl);
    *pResult = 0;
    }int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    int row1=(int)lParam1;
    int row2=(int)lParam2;
    CListCtrl *lc=(CListCtrl*)lParamSort;
    CString lp1=lc->GetItemText(row1,sort_column);
    CString lp2=lc->GetItemText(row2,sort_column);
    LVFINDINFO findInfo;
    findInfo.flags=LVFI_PARAM;
    findInfo.lParam=lParam1;
    findInfo.
    if(sort_column<2)
    {
    if(method)

    {
    method=FALSE;
    return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
    }
    else
    {
    method=TRUE;
    return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
    }
    }
    else
    {
    if(method)
    return lp1.CompareNoCase(lp2);
    else
    return lp2.CompareNoCase(lp1);
    }
    return 1;
    }
    这个是我的代码,关键是为什么只是比较前两项,也就是相邻的两项。setItemData也用了,为什么不行?前两项确实可以排序,但后面就不行了。
      

  6.   


    难道不是响应LVN_COLUMNCLICK 消息?
      

  7.   

    你的代码没放完,可能别的地方有问题,先用这个简化代码看看。理论上来说,直接用itemData当作行索引可能会存在问题,因为排序过程中itemData和行索引的对照关系可能会变,但实际中没发现问题,可能是排序后统一交换行了吧。
    int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)

    int row1=(int)lParam1;
    int row2=(int)lParam2;
    CListCtrl *lc=(CListCtrl*)lParamSort; CString lp1=lc->GetItemText(row1,sort_column);
    CString lp2=lc->GetItemText(row2,sort_column); return lp1.CompareNoCase(lp2);
    }
      

  8.   


    void CListCtrlDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
    {
    LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
    sort_column=pNMLV->iSubItem;
    int count=m_ListCtrl.GetItemCount();
    for(int i=0;i<count;i++)
    m_ListCtrl.SetItemData(i,i);
    m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&m_ListCtrl);
    *pResult = 0;
    }int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    {
    int row1=(int)lParam1;
    int row2=(int)lParam2;
    CListCtrl *lc=(CListCtrl*)lParamSort;
    CString lp1=lc->GetItemText(row1,sort_column);
    CString lp2=lc->GetItemText(row2,sort_column); if(sort_column<2)
    {
    if(method) {
    method=FALSE;
    return _tcscmp(lp1,lp2);
    }
    else
    {
    method=TRUE;
    return  _tcscmp(lp2,lp1);
    } }
    else
    {
    if(method)
    return lp1.CompareNoCase(lp2);
    else
    return lp2.CompareNoCase(lp1);
    }
    return 0;
    }
    这个是我全部代码,method是静态全局函数,表示升序或降序。 我想问下,这个函数一直会遍历完整个行,直到遍历完才返回吗?
      

  9.   

    listctrl采用的是快速排序,该回调函数会被调用多次,类似于qsort函数的回调函数。从你的代码看,如果对第0和第1列排序,在排序过程中,method在不断变化,会导致错误的结果。
    一般升序降序的状态,可以保存到列头CHeaderCtrl中,可以用item的lParam参数保存,排序时通过回调函数的最后一个参数传进去。如:CHeaderCtrl *pHeardCtrl = GetHeaderCtrl();
    HDITEM hdi;
    hdi.mask = HDI_LPARAM;
    pHeardCtrl->GetItem(pNMLV->iSubItem, &hdi);
    BOOL bASC = (hdi.lParam == 0 ? TRUE : FALSE); //当前排序方式和上次相反
    hdi.lParam = bASC; //保存当前的升降序状态
    pHeardCtrl->SetItem(pNMLV->iSubItem, &hdi);
      

  10.   


    我把这个源代码发给你,能否帮我修改一下,一直想实现这个功能。我的QQ [email protected]
      

  11.   

    找到以前写的那个支持排序的列表类了,改了一下放到CSDN资源里了:
    http://download.csdn.net/detail/iamshuke/3929906