CListCtrl排序问题

tixisong 2011-12-14 04:06:24
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中应该来个循环,我想全部排序,应该怎么做,求解?
...全文
228 14 打赏 收藏 转发到动态 举报
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
向立天 2012-01-14
  • 打赏
  • 举报
回复
您好
我是本版版主
此帖已多日无人关注
请您及时结帖
如您认为问题没有解决可按无满意结帖处理
另外本版设置了疑难问题汇总帖
并已在版面置顶
相关规定其帖子中有说明
您可以根据规定提交您帖子的链接
如您目前不想结帖只需回帖说明
我们会删除此结帖通知

见此回复三日内无回应
我们将强制结帖
相关规定详见界面界面版关于版主结帖工作的具体办法
tixisong 2011-12-16
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 iamshuke 的回复:]
你的代码没放完,可能别的地方有问题,先用这个简化代码看看。理论上来说,直接用itemData当作行索引可能会存在问题,因为排序过程中itemData和行索引的对照关系可能会变,但实际中没发现问题,可能是排序后统一交换行了吧。


C/C++ code

int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPAR……
[/Quote]

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是静态全局函数,表示升序或降序。 我想问下,这个函数一直会遍历完整个行,直到遍历完才返回吗?
iamshuke 2011-12-16
  • 打赏
  • 举报
回复
你的代码没放完,可能别的地方有问题,先用这个简化代码看看。理论上来说,直接用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);
}
tixisong 2011-12-16
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 ddszhan 的回复:]
MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
这个函数如果是CListCtrl用来排序的回调函数,这样写是对的。
CListCtrl会针对每行记录调用这个函数来排序。不是用来你自己在对话框中调用的。得加上这个

C/C++ code

void CListCtrlDlg::OnColumnClickDG……
[/Quote]

难道不是响应LVN_COLUMNCLICK 消息?
tixisong 2011-12-16
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 ddszhan 的回复:]
MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
这个函数如果是CListCtrl用来排序的回调函数,这样写是对的。
CListCtrl会针对每行记录调用这个函数来排序。不是用来你自己在对话框中调用的。得加上这个

C/C++ code

void CListCtrlDlg::OnColumnClickDG……
[/Quote]



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也用了,为什么不行?前两项确实可以排序,但后面就不行了。
iamshuke 2011-12-16
  • 打赏
  • 举报
回复
找到以前写的那个支持排序的列表类了,改了一下放到CSDN资源里了:
http://download.csdn.net/detail/iamshuke/3929906
tixisong 2011-12-16
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 iamshuke 的回复:]
listctrl采用的是快速排序,该回调函数会被调用多次,类似于qsort函数的回调函数。从你的代码看,如果对第0和第1列排序,在排序过程中,method在不断变化,会导致错误的结果。
一般升序降序的状态,可以保存到列头CHeaderCtrl中,可以用item的lParam参数保存,排序时通过回调函数的最后一个参数传进去。

如:

C/C++ code

CHeaderCtrl *……
[/Quote]

我把这个源代码发给你,能否帮我修改一下,一直想实现这个功能。我的QQ 393707561@qq.com
iamshuke 2011-12-16
  • 打赏
  • 举报
回复
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);

iamshuke 2011-12-15
  • 打赏
  • 举报
回复
刚看了下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,值就用行索引号,排序后再还原就行了。
iamshuke 2011-12-15
  • 打赏
  • 举报
回复
shen_wei的代码有点缺陷,因为只是交换了itemtext,实际中可能还需要交换图标、itemdata等等。
用CListCtrl自己的排序,除了实现排序函数,还要满足两个条件:
1. 各行必须有不同的itemdata。
2. 不能只有一列。

当然,这两点是10年前发现的,当时用2000多些,现在也许没这问题了。
ddszhan 2011-12-15
  • 打赏
  • 举报
回复
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中的规则,排序了。
shen_wei 2011-12-15
  • 打赏
  • 举报
回复
代码复制了就能使用了。。

o(︶︿︶)o 唉。
tixisong 2011-12-15
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 shen_wei 的回复:]
C/C++ code
void CClistSortDlg::ListSort(void)
{
int listcount = m_list.GetItemCount();
int nColumn =m_list.GetHeaderCtrl()->GetItemCount();
CString temp0,temp1,temp2;
for(int j……
[/Quote]

有没有简单一点的?
shen_wei 2011-12-14
  • 打赏
  • 举报
回复
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);
}
}
}
}
}
}

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧