在做的一个项目要求对CListCtrl控件能够实现点击列标题时,实现按列排序。因本来就对MFC不熟悉,故不知从何下手。在网上搜了一些文章,好多都是通过回调函数来实现,找了一篇文章http://wenku.baidu.com/view/813213170b4e767f5acfce85.html 因我的程序里本来已经建好了对话框,并且在其上添加了ListCtrl控件,并有数据显示,故对于列表框的初始化不再赘述,只将排序的实现过程。我的对话框类叫做CInstallbaseDlg,
在CInstallbaseDlg.h中在类定义之前添加如下代码:(定义一个结构体和一个全局变量)
struct DATA
{
CListCtrl *plist;//用于存储列表控件的指针
int col;//用于存储要排序主列的序号
};//回调函数第三个参数对应的数据结构,可以自定义,至少要包含这两项
BOOL fav=FALSE;//排序方法(递增或递减)
在CInstallbaseDlg.cpp中定义回调函数MylistCompare:
int CALLBACK MylistCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
DATA * MyData=(DATA*)lParamSort;
int col=MyData->col;//点击的列项传递给col,用来判断点击了第几列
//取项的字符串
CString strItem1, strItem2;
strItem1=MyData->plist->GetItemText(lParam1,col);
strItem2=MyData->plist->GetItemText(lParam2,col);//获得要比较的字符串 //因我的列表框有16列,且第16列为日期列,故做了如下的操作,如果只是字符串的话,只执行if下面的语句应该就好了,其实我觉得日期比较也可用if下面的语句达 //到效果,只是已经写上去了,就懒得再做修改 if(col!=15)//说明比较的不是日期列
return strItem1.CompareNoCase(strItem2);//不区分大小写进行比较
else
{
int year1=atoi(strItem1.Left(4));
int year2=atoi(strItem2.Left(4));
if(year1==year2)
{
int mon1=atoi(strItem1.Left(7).Right(2));
int mon2=atoi(strItem2.Left(7).Right(2));
if(mon1==mon2)
{
int day1=atoi(strItem1.Right(2));
int day2=atoi(strItem2.Right(2));
return day1-day2;
}
else
return mon1-mon2;
}
else
return year1-year2;
}
}
对对话框中的listctrl控件添加消息LVN_COLOUMCLICK_响应函数:
void CInstallbaseDlg::OnColumnclickList(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
// TODO: Add your control notification handler code here
DATA data;
data.col=pNMListView->iSubItem;//取列
data.plist=&m_list;//取列表指针
fav=!fav;//排序每点一次列就变一次,若想固定排序,那就去掉这局
//设置列表相关项,以便排序
int len=m_list.GetItemCount();
for(int i=0;i<len;i++)
{
m_list.SetItemData(i,i);
}
m_list.SortItems(MylistCompare,(LPARAM)&data);
*pResult = 0;
}
我对回调函数不了解,对 SortItems也不了解,只是个人觉得CListCtrl成员函数 SortItems的两个参数第一个是回调函数的名称,第二个参数和回调函数中第三个参数是同一个值。至于是冒泡还是其他的排序方法就不知道了,回调函数MylistCompare只是将比较结果进行了返回,lparam1<lparam2返回-1,相等返回0,大于返回1,然后SortItems根据返回值自动排序。