关于MFC的CListCtrl的排序问题

back1999 2016-12-09 03:44:37
找了些资料,不过没有找到要点。
关于ListCtrl的SortItems排序,其中的回调函数,提供的参数貌似不太给力。。。

现在的情况是。
有一个ListCtrl,多行多列,点击一列的时候排序,每一个item都关联了数据。
往简单的说,我只想对每一列的所有item做字符串比对处理,但是现在卡在的怎么找这个item的问题上,
排序的前两个入参是ItemData,想通过这个找item,我现在使用的listCtrl编码不适合。
请问有大神知道有什么比较合适的方法?
...全文
361 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
schlafenhamster 2016-12-12
  • 打赏
  • 举报
回复
int now=InsrtItem( nItem,lpszItem, nImage);
//This function sets the 32-bit application-specific value associated with the item specified by nItem. This value is the lParam member of theLVITEM structure, as described in the Platform SDK.
SetItemData(now, dwData );
back1999 2016-12-12
  • 打赏
  • 举报
回复
引用 13 楼 schlafenhamster 的回复:
可能你 填 list时 ,数据 不对 LVITEM lvi; lvi.mask=LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE; // fill list lvi.iSubItem=0;// name lvi.iItem=current; //lparam will be used when sortitems ! lvi.lParam=current; //get filename lvi.pszText=pfinddata->name;// original name
问题就在这里面,目前程序大部分地方都是用的 CListCtrl::InsertItem(int nItem, LPCTSTR lpszItem, int nImage)这个签名上式。。。 而且您给的这个LVITEM 也只是InsertItem(LVITEM m)的时候,在查找的时候支持FindItem。。。 但实际上,在现有程序结构下,我没有办法去处理
schlafenhamster 2016-12-12
  • 打赏
  • 举报
回复
另一种 //lparam will be used when sortitems ! lvi.lParam=(LPARAM) pNode;
schlafenhamster 2016-12-12
  • 打赏
  • 举报
回复
可能你 填 list时 ,数据 不对 LVITEM lvi; lvi.mask=LVIF_TEXT|LVIF_PARAM|LVIF_IMAGE; // fill list lvi.iSubItem=0;// name lvi.iItem=current; //lparam will be used when sortitems ! lvi.lParam=current; //get filename lvi.pszText=pfinddata->name;// original name
back1999 2016-12-12
  • 打赏
  • 举报
回复
引用 11 楼 schlafenhamster 的回复:

char ListStr[][20]=
{
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四"
};



int CALLBACK ListSortCompare(LPARAM lp1,LPARAM lp2,LPARAM Check)
{ // lp1,lp2 are the 'ID' original oders. the iItem will changes
// 不使用 ListStr
	CListCheckDlg* pDlg=(CListCheckDlg* )AfxGetMainWnd();
	CString str1 = pDlg->m_List.GetItemText((int)lp1,1);
	CString str2 = pDlg->m_List.GetItemText((int)lp2,1);
	afxDump << str1 << "\n";
	afxDump << str2 << "\n\n";
//  使用 ListStr
	if((strcmp(ListStr[(int)lp1],(char *)Check)==0) && ((strcmp(ListStr[(int)lp2],(char *)Check)==0))) return 0;
	else if((strcmp(ListStr[(int)lp1],(char *)Check)==0)) return -1;
	else if((strcmp(ListStr[(int)lp2],(char *)Check)==0)) return 1;
	else return 0;
}

这个方法行不通,项目不能做这样的更改。 现有的想法就是,抽象list中的ItemData,在排序中不涉及ItemData,这样项目的ListCtrl的代码量才能做到最低,变更做到最小。 但是现在来看,不现实。 不过真的搞不明白,微软为什么要把Lp1和Lp2设计成ItemData,既然是比较函数,比较的前后两行,设计成ItemIndex完全没有 问题啊,根据ItemIndex得到ItemData也是So Easy啊。。。
schlafenhamster 2016-12-11
  • 打赏
  • 举报
回复

char ListStr[][20]=
{
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四",
"王二麻子",
"张三",
"李四"
};



int CALLBACK ListSortCompare(LPARAM lp1,LPARAM lp2,LPARAM Check)
{ // lp1,lp2 are the 'ID' original oders. the iItem will changes
// 不使用 ListStr
	CListCheckDlg* pDlg=(CListCheckDlg* )AfxGetMainWnd();
	CString str1 = pDlg->m_List.GetItemText((int)lp1,1);
	CString str2 = pDlg->m_List.GetItemText((int)lp2,1);
	afxDump << str1 << "\n";
	afxDump << str2 << "\n\n";
//  使用 ListStr
	if((strcmp(ListStr[(int)lp1],(char *)Check)==0) && ((strcmp(ListStr[(int)lp2],(char *)Check)==0))) return 0;
	else if((strcmp(ListStr[(int)lp1],(char *)Check)==0)) return -1;
	else if((strcmp(ListStr[(int)lp2],(char *)Check)==0)) return 1;
	else return 0;
}

schlafenhamster 2016-12-10
  • 打赏
  • 举报
回复

//
int CALLBACK ListSortCompare(LPARAM lp1,LPARAM lp2,LPARAM subItem)
{ // lp1,lp2 are the original oders. the iItem will changes
	CMainFrame*  pMain=(CMainFrame*)AfxGetMainWnd();// m_pMainWnd;
	if(pMain->m_bRevSort)
		return (pMain->m_szListData[subItem][lp2].CompareNoCase(
				pMain->m_szListData[subItem][lp1]));
	else
		return (pMain->m_szListData[subItem][lp1].CompareNoCase(
				pMain->m_szListData[subItem][lp2]));
}
m_szListData 是 :LisCtrl 的 副本 填充 ListCtrl 时 同时 保存。
back1999 2016-12-10
  • 打赏
  • 举报
回复
引用 9 楼 schlafenhamster 的回复:
可以根据 lp1 lp2 (这2个 是 控件 排序时 给你 的 ItemID)直接取控件的 text
lp1和lp2是itemID? 按照文档不是ItemData吗? 而且代码里面像这样 strItemA = pListView->GetListCtrl().GetItemText((int)lParam1, m_iSubItem); 取不出text。。。。
schlafenhamster 2016-12-10
  • 打赏
  • 举报
回复
可以根据 lp1 lp2 (这2个 是 控件 排序时 给你 的 ItemID)直接取控件的 text
back1999 2016-12-10
  • 打赏
  • 举报
回复
引用 7 楼 schlafenhamster 的回复:

//
int CALLBACK ListSortCompare(LPARAM lp1,LPARAM lp2,LPARAM subItem)
{ // lp1,lp2 are the original oders. the iItem will changes
	CMainFrame*  pMain=(CMainFrame*)AfxGetMainWnd();// m_pMainWnd;
	if(pMain->m_bRevSort)
		return (pMain->m_szListData[subItem][lp2].CompareNoCase(
				pMain->m_szListData[subItem][lp1]));
	else
		return (pMain->m_szListData[subItem][lp1].CompareNoCase(
				pMain->m_szListData[subItem][lp2]));
}
m_szListData 是 :LisCtrl 的 副本 填充 ListCtrl 时 同时 保存。
您的意思是,使用一个辅助的ListCtrl,保持和主体的ListCtrl同步,在这里先为辅助list设置排序关键字,然后比较的时候用辅助的Listl来? 这样的话,不现实啊,程序挺大挺杂,这样做起来,不一定可行。
back1999 2016-12-09
  • 打赏
  • 举报
回复
引用 5 楼 schlafenhamster 的回复:
Remarks Sorts list view items using an application-defined comparison function. The index of each item changes to reflect the new sequence. The comparison function has the following form: int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); The comparison function must return a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent. The lParam1 and lParam2 parameters specify the item data for the two items being compared. The lParamSort parameter is the same as the dwData value. “The lParam1 and lParam2 parameters specify the item data for the two items being compared. ” 由控件自己提供
都说了这两个参数是关联的数据。。。 那到底怎么找到当前比对的行索引呢
schlafenhamster 2016-12-09
  • 打赏
  • 举报
回复
Remarks Sorts list view items using an application-defined comparison function. The index of each item changes to reflect the new sequence. The comparison function has the following form: int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); The comparison function must return a negative value if the first item should precede the second, a positive value if the first item should follow the second, or zero if the two items are equivalent. The lParam1 and lParam2 parameters specify the item data for the two items being compared. The lParamSort parameter is the same as the dwData value. “The lParam1 and lParam2 parameters specify the item data for the two items being compared. ” 由控件自己提供
back1999 2016-12-09
  • 打赏
  • 举报
回复
引用 1 楼 VisualEleven 的回复:
CListCtrl::GetItemText()获取某行某列的数据,然后比较~
问题是,在回调里面怎么获取到当前比较的前后行数?
back1999 2016-12-09
  • 打赏
  • 举报
回复
引用 2 楼 jacksonfan 的回复:

//表一 次数排序
int CALLBACK CAnalyseDlg::CompareFunc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
	//通过传递的参数来得到CSortList对象指针,从而得到排序方式
	DATA* MyData = (DATA*)lParamSort;
	int col = MyData->col;//点击的列项传递给col,用来判断点击了第几列
	//取项的字符串
	CString strItem1, strItem2;
	strItem1 = MyData->plist->GetItemText((int)lParam1,col); 
	strItem2 = MyData->plist->GetItemText((int)lParam2,col);
	CAnalyseDlg * dlg = (CAnalyseDlg *)MyData->pDlg;

	int nf = 0;
	int nb = 0;
	if(col == 1)
	{
		//对比整型数
		nf = _wtoi(strItem1);
		nb = _wtoi(strItem2);
		if(fav)
			return (nf - nb);
		else
			return (nb - nf);
	}
}
//点击坐标列表 次数 表头 排序
void CAnalyseDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	//NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	DATA data;
	data.col = pNMLV->iSubItem; //取列
	data.plist = &m_FirstList; //取列表指针
	data.pDlg = this;
	if(data.col == 1)
	{
		fav = !fav; //排序每点一次列就变一次,若想固定排序,那就去掉这句
		//设置列表项相关项,以便于排序
		int len = m_FirstList.GetItemCount();
		for(int i = 0;i < len;i ++)
		{ 
			m_FirstList.SetItemData(i,(DWORD_PTR)i); //列表项相关项设为项号
		}
		m_FirstList.SortItems(CompareFunc,(LPARAM)&data); 
	}
	*pResult = 0;
}
列表已经关联数据了,这样关联就失效啦。。。
jacksonfan 2016-12-09
  • 打赏
  • 举报
回复

//表一 次数排序
int CALLBACK CAnalyseDlg::CompareFunc(LPARAM lParam1,LPARAM lParam2,LPARAM lParamSort)
{
	//通过传递的参数来得到CSortList对象指针,从而得到排序方式
	DATA* MyData = (DATA*)lParamSort;
	int col = MyData->col;//点击的列项传递给col,用来判断点击了第几列
	//取项的字符串
	CString strItem1, strItem2;
	strItem1 = MyData->plist->GetItemText((int)lParam1,col); 
	strItem2 = MyData->plist->GetItemText((int)lParam2,col);
	CAnalyseDlg * dlg = (CAnalyseDlg *)MyData->pDlg;

	int nf = 0;
	int nb = 0;
	if(col == 1)
	{
		//对比整型数
		nf = _wtoi(strItem1);
		nb = _wtoi(strItem2);
		if(fav)
			return (nf - nb);
		else
			return (nb - nf);
	}
}
//点击坐标列表 次数 表头 排序
void CAnalyseDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
	//NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
	LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
	DATA data;
	data.col = pNMLV->iSubItem; //取列
	data.plist = &m_FirstList; //取列表指针
	data.pDlg = this;
	if(data.col == 1)
	{
		fav = !fav; //排序每点一次列就变一次,若想固定排序,那就去掉这句
		//设置列表项相关项,以便于排序
		int len = m_FirstList.GetItemCount();
		for(int i = 0;i < len;i ++)
		{ 
			m_FirstList.SetItemData(i,(DWORD_PTR)i); //列表项相关项设为项号
		}
		m_FirstList.SortItems(CompareFunc,(LPARAM)&data); 
	}
	*pResult = 0;
}
Eleven 2016-12-09
  • 打赏
  • 举报
回复
CListCtrl::GetItemText()获取某行某列的数据,然后比较~

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

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