ListCtrl点击表头排序的总结
2013-03-07 18:05
387 查看
要使用CListCtrl点击表头进行排序的功能:
对ListCtrl排序的总结;
记得还要添加Sort属性(在资源里)
要实现这个功能,首先要调用c_lstRcdData.SetItemData(i,i);遍历每一个元素,
然后就是点击表头的消息处理了,注意:这里非常关键,因为有两个消息都可以响
应表头被点击的的操作,一个标准的是void UCFVDataSel::OnColumnclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult);
但是在排序里面不要用这个,因为它传的第一个参数老是出问题,所有用另一个:
void UCFVDataSel::OnItemclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult);这个虽然看起来不像
点击表头触发的消息,但是它确实是啊,贴一段我完整的关于这个消息处理的函数:
void UCFVDataSel::OnItemclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER pNMLV = reinterpret_cast<LPNMHEADER>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
static int sSortColumn = 0;
//让它不显示上下三角
HDITEM hdrItem;
c_lstRcdData.GetHeaderCtrl()->GetItem(sSortColumn, &hdrItem);
hdrItem.mask = HDI_FORMAT;
hdrItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
c_lstRcdData.GetHeaderCtrl()->SetItem(sSortColumn, &hdrItem);
//点击相同列,排序方式变反。
//点击不同列,升序排列
static int nAsc = 1;
if(sSortColumn == pNMLV->iItem)
{
nAsc = - nAsc;
}
else
{
sSortColumn = pNMLV->iItem;
nAsc = 1;
}
//显示上三角或下三角
c_lstRcdData.GetHeaderCtrl()->GetItem(sSortColumn, &hdrItem);
hdrItem.mask = HDI_FORMAT;
if(nAsc == 1)
{
hdrItem.fmt |= HDF_SORTUP;
hdrItem.fmt &= ~HDF_SORTDOWN;
}
else
{
hdrItem.fmt |= HDF_SORTDOWN;
hdrItem.fmt &= ~HDF_SORTUP;
}
c_lstRcdData.GetHeaderCtrl()->SetItem(sSortColumn, &hdrItem);
PSORTDATA pSortData = new SORTDATA;
pSortData->nAsc = nAsc;
pSortData->pList = &c_lstRcdData;
pSortData->nSubItem = sSortColumn;
c_lstRcdData.SortItems(SortFunc,(DWORD_PTR)pSortData);
*pResult = 0;
}
其它的注释已经很清楚了,大家运行一下就知道是什么了,需要注意看的是倒数第二句代码
c_lstRcdData.SortItems(SortFunc,(DWORD_PTR)pSortData);这就是API,第一个是回调函数,第二个参数是
回调函数的参数,我把完整的回调函数也贴出来了
///////////////////////////////////////////////////////
/// \brief
/// 自定义排序函数
///
/// \param lParam1
/// 第一行数据
///
/// \param lParam2
/// 第二行数据
///
/// \param lParamSort
/// 自定义数据结构SortData类型变量,SortItems()函数的第二个参数
///
/// \return
/// 第一个数据大于第二个数据返回正数,否则返回负数
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
PSORTDATA pSortData = (PSORTDATA) lParamSort;
CListCtrl *pList = pSortData->pList;
int nSubItem = pSortData->nSubItem;
int nAsc = pSortData->nAsc;
//find item index
LVFINDINFO findInfo;
findInfo.flags = LVFI_PARAM;
findInfo.lParam = lParam1;
//1st index
int nPrevIndex = pList->FindItem(&findInfo, -1);
findInfo.lParam = lParam2;
//2nd index
int nNextIndex = pList->FindItem(&findInfo, -1);
//get item string
CString strPrev = pList->GetItemText(nPrevIndex, nSubItem);
CString strNext = pList->GetItemText(nNextIndex, nSubItem);
int prev = 0, next = 0;
switch ( nSubItem )
{
case 0:
prev = _ttol(strPrev);
next = _ttol(strNext);
if (prev > next)
return nAsc;
else
return -nAsc;
case 1:
strPrev.Replace( _TEXT("/"),_TEXT("") );
strNext.Replace( _TEXT("/"),_TEXT("") );
strPrev.Replace( _TEXT(":"),_TEXT("") );
strNext.Replace( _TEXT(":"),_TEXT("") );
strPrev.Replace( _TEXT(" "),_TEXT("") );
strNext.Replace( _TEXT(" "),_TEXT("") );
prev = _ttol(strPrev);
next = _ttol(strNext);
if (prev > next)
return nAsc;
else
return -nAsc;
default:
return _tcscmp(strPrev, strNext) * nAsc;
}
}
只需几步,我们的功能就实现了,哦对了,还有这个结构
/// ListCtrl排序用的结构
typedef struct SortData
{
int nAsc;
//1或-1
CListCtrl *pList;
int nSubItem;
} SORTDATA, * PSORTDATA;
完整的代码在我的资源里面,资源名字叫《ListCtrl分页》,因为同时实现了分页显示和排序的功能
注意!!!!!!
排序有一个问题就是ListCtrl会屏蔽掉内容相同的项,一定要注意这个问题
对ListCtrl排序的总结;
记得还要添加Sort属性(在资源里)
要实现这个功能,首先要调用c_lstRcdData.SetItemData(i,i);遍历每一个元素,
然后就是点击表头的消息处理了,注意:这里非常关键,因为有两个消息都可以响
应表头被点击的的操作,一个标准的是void UCFVDataSel::OnColumnclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult);
但是在排序里面不要用这个,因为它传的第一个参数老是出问题,所有用另一个:
void UCFVDataSel::OnItemclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult);这个虽然看起来不像
点击表头触发的消息,但是它确实是啊,贴一段我完整的关于这个消息处理的函数:
void UCFVDataSel::OnItemclickListRcddata(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMHEADER pNMLV = reinterpret_cast<LPNMHEADER>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
static int sSortColumn = 0;
//让它不显示上下三角
HDITEM hdrItem;
c_lstRcdData.GetHeaderCtrl()->GetItem(sSortColumn, &hdrItem);
hdrItem.mask = HDI_FORMAT;
hdrItem.fmt &= ~(HDF_SORTDOWN | HDF_SORTUP);
c_lstRcdData.GetHeaderCtrl()->SetItem(sSortColumn, &hdrItem);
//点击相同列,排序方式变反。
//点击不同列,升序排列
static int nAsc = 1;
if(sSortColumn == pNMLV->iItem)
{
nAsc = - nAsc;
}
else
{
sSortColumn = pNMLV->iItem;
nAsc = 1;
}
//显示上三角或下三角
c_lstRcdData.GetHeaderCtrl()->GetItem(sSortColumn, &hdrItem);
hdrItem.mask = HDI_FORMAT;
if(nAsc == 1)
{
hdrItem.fmt |= HDF_SORTUP;
hdrItem.fmt &= ~HDF_SORTDOWN;
}
else
{
hdrItem.fmt |= HDF_SORTDOWN;
hdrItem.fmt &= ~HDF_SORTUP;
}
c_lstRcdData.GetHeaderCtrl()->SetItem(sSortColumn, &hdrItem);
PSORTDATA pSortData = new SORTDATA;
pSortData->nAsc = nAsc;
pSortData->pList = &c_lstRcdData;
pSortData->nSubItem = sSortColumn;
c_lstRcdData.SortItems(SortFunc,(DWORD_PTR)pSortData);
*pResult = 0;
}
其它的注释已经很清楚了,大家运行一下就知道是什么了,需要注意看的是倒数第二句代码
c_lstRcdData.SortItems(SortFunc,(DWORD_PTR)pSortData);这就是API,第一个是回调函数,第二个参数是
回调函数的参数,我把完整的回调函数也贴出来了
///////////////////////////////////////////////////////
/// \brief
/// 自定义排序函数
///
/// \param lParam1
/// 第一行数据
///
/// \param lParam2
/// 第二行数据
///
/// \param lParamSort
/// 自定义数据结构SortData类型变量,SortItems()函数的第二个参数
///
/// \return
/// 第一个数据大于第二个数据返回正数,否则返回负数
int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
PSORTDATA pSortData = (PSORTDATA) lParamSort;
CListCtrl *pList = pSortData->pList;
int nSubItem = pSortData->nSubItem;
int nAsc = pSortData->nAsc;
//find item index
LVFINDINFO findInfo;
findInfo.flags = LVFI_PARAM;
findInfo.lParam = lParam1;
//1st index
int nPrevIndex = pList->FindItem(&findInfo, -1);
findInfo.lParam = lParam2;
//2nd index
int nNextIndex = pList->FindItem(&findInfo, -1);
//get item string
CString strPrev = pList->GetItemText(nPrevIndex, nSubItem);
CString strNext = pList->GetItemText(nNextIndex, nSubItem);
int prev = 0, next = 0;
switch ( nSubItem )
{
case 0:
prev = _ttol(strPrev);
next = _ttol(strNext);
if (prev > next)
return nAsc;
else
return -nAsc;
case 1:
strPrev.Replace( _TEXT("/"),_TEXT("") );
strNext.Replace( _TEXT("/"),_TEXT("") );
strPrev.Replace( _TEXT(":"),_TEXT("") );
strNext.Replace( _TEXT(":"),_TEXT("") );
strPrev.Replace( _TEXT(" "),_TEXT("") );
strNext.Replace( _TEXT(" "),_TEXT("") );
prev = _ttol(strPrev);
next = _ttol(strNext);
if (prev > next)
return nAsc;
else
return -nAsc;
default:
return _tcscmp(strPrev, strNext) * nAsc;
}
}
只需几步,我们的功能就实现了,哦对了,还有这个结构
/// ListCtrl排序用的结构
typedef struct SortData
{
int nAsc;
//1或-1
CListCtrl *pList;
int nSubItem;
} SORTDATA, * PSORTDATA;
完整的代码在我的资源里面,资源名字叫《ListCtrl分页》,因为同时实现了分页显示和排序的功能
注意!!!!!!
排序有一个问题就是ListCtrl会屏蔽掉内容相同的项,一定要注意这个问题
相关文章推荐
- 控件ListCtrl 点击表头排序
- jQuery数据表格(点击表头排序,有点问题)
- bootstrap点击表头实现排序功能
- easyUI扩展datagrid支持按列点击表头自定义排序
- ClistCtrl用法及总结(由怎样隐藏ListCtrl列表头的排序小三角形这个bug学习到的知识)
- javascript-jquery-tablesorter的问题:如果表头是多行的,点击排序好像就不正确了
- js对table排序(类似点击Excel表头排序)
- 实现Repeater控件点击表头排序功能
- 点击表头排序
- ClistCtrl用法及总结(由怎样隐藏ListCtrl列表头的排序小三角形这个bug学习到的知识)
- 点击表头排序(ASP)
- GridView之点击表头排序篇
- 禁止DataGridView点击表头进行排序(WinForm)
- asp.net 点击表头排序及分页代码
- C# ListView中点击表头ColumnClick实现对相应列的排序
- 点击表头排序时,"分组"及"分组明细"的数据层次关系不变
- 转《QT中Qtableview视图表格中点击表头进行排序》
- Js-点击表头进行排序