CListCtrl自动排序及添加排序箭头

来源:互联网 发布:snap软件 编辑:程序博客网 时间:2024/06/02 04:16

应客户要求,在点击CListCtrl列表每列标题时进行排序,类似于WINDOWS资源管理器的效果。

首先在资源中添加LVN_COLUMNCLICK消息,生成OnLvnColumnclickListInfo函数,在函数里进行处理即可。

1.最最笨的方法是点击标题时,依次获取每行的内容,自己比较排序,这里不多说,略过。


2.用控制自带的排序功能。

1)为了能显示箭头,在列表初始化时增加图标,如下

CHeaderCtrl *pHeaderCtrl=m_ListCtrl.GetHeaderCtrl();m_ImageList.Create(16,16,ILC_COLOR16 | ILC_MASK,0,4);m_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON1));//IDI_ICON1和IDI_ICON2是自己资源中的箭头ID,类型为ICONm_ImageList.Add(AfxGetApp()->LoadIcon(IDI_ICON2));pHeaderCtrl->SetImageList(&m_ImageList);//m_ImageList是头文件中申明的CImageList m_ImageList

2.进行排序并显示箭头

int sort_column=-1; // 记录点击的列bool method = false; // 记录比较方法// 比较函数static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort){// 从参数中提取所需比较lc的两行数据int row1 = (int)lParam1;//这里的参数实际是SetItemData函数设置的值,比较的第一列int row2 =(int)lParam2;//这里的参数实际是SetItemData函数设置的值,比较的第二列CListCtrl* lc= (CListCtrl*)lParamSort;CString lp1 = lc->GetItemText(row1,sort_column);CString lp2 = lc->GetItemText(row2,sort_column); LPCTSTR s1=(LPCTSTR)lp1; LPCTSTR s2=(LPCTSTR)lp2; // 比较,对不同的列,不同比较,注意记录前一次排序方向,下一次要相反排序 if (method){return  strcmp(s2,s1);}else{return  strcmp(s1,s2);}
}
void CDlgWorklistInfo::OnLvnColumnclickListInfo(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);//在排序前一定用这个函数设置每行值,类似于自定义索引}// 自定义图标排序箭头样式  CHeaderCtrl* pHdrCtrl = m_ListCtrl.GetHeaderCtrl();  if(pHdrCtrl && pHdrCtrl->GetSafeHwnd())    {  int n = pHdrCtrl->GetItemCount();  HDITEM hdi={0};  TCHAR szBuf[129] = {0};       hdi.mask = HDI_TEXT; //取字符掩码     hdi.pszText = szBuf; //字符缓冲区     hdi.cchTextMax = 128; //缓冲区大小    for( int i = 0; i < n; i++ )  {  hdi.mask = HDI_IMAGE | HDI_FORMAT;  // 读取排序箭头图标状态,必需指定  pHdrCtrl->GetItem(i, &hdi);  if( i == sort_column )  {  if( hdi.fmt & HDF_IMAGE )   //前后2次点击同一列时, 已经排序,改变升降序,并切换箭头图标。  {  hdi.iImage = 1 - hdi.iImage;  method = !method;}  else  //前后点击不同列时图标显示在新点击列头{  hdi.iImage = 0;  hdi.fmt |= HDF_IMAGE | HDF_BITMAP_ON_RIGHT;  if (method)//为了保证新点击的列与上次显示一致{hdi.iImage = 1 - hdi.iImage;}}  }  else  {  hdi.mask = HDI_FORMAT;  hdi.fmt &= ~HDF_IMAGE & ~HDF_BITMAP_ON_RIGHT;  }  pHdrCtrl->SetItem( i, &hdi );  }  }m_ListCtrl.SortItems(MyCompareProc,(DWORD)&m_ListCtrl);//排序第二个参数是比较函数的第三个参数*pResult =0;}


总结:另外网上有说用CMFCListCtrl类(VS2008以上)比较好用,有兴趣可以自己试试。还有调试过程中用的是第三方类继承CListCtrl导致
LPARAM lParam1, LPARAM lParam2
始终传过来是很大的随机值,后面直接换回微软自带的CListCtrl解决。