MFC实现点击列表头排序
1、添加消息处理函数
在列表窗口右键,类向导。选择 IDC_LIST1(我的列表控件的ID),消息选择LVN_COLUMNCLICK。
2、消息映射如下
然后会在 cpp 文件中生成以下函数
void CFLashSearchDlg::OnLvnColumnclickFlashConfigList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
*pResult = 0;
}
3、定义两个全局变量用于存储参数,一个全局静态函数用作比较回调
// 在对应的 cpp 文件中定义
DWORD dwSelColID = 0; // 选择的列
bool bASC = FALSE; // 是否升序
static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); // 点击列表头进行升/降排序的比较函数
4、具体实现消息处理函数
// 点击列表头进行升序或降序排序
void CFLashSearchDlg::OnLvnColumnclickFlashConfigList(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码
if(dwSelColID != pNMLV->iSubItem)
{
dwSelColID = pNMLV->iSubItem;
bASC = bASC;
}
else
bASC = !bASC;
int count = m_flashConfigList.GetItemCount();
for(int i = 0; i < count; ++i)
m_flashConfigList.SetItemData(i, i);
m_flashConfigList.SortItems(&CompareFunc, (LPARAM)(&m_flashConfigList));
*pResult = 0;
}
这段代码是一个消息处理函数,处理了列表控件的列点击消息 LVN_COLUMNCLICK
。
-
首先,通过
reinterpret_cast
将传递给消息处理函数的NMHDR
结构体指针转换为LPNMLISTVIEW
类型,这是因为列表控件的列点击消息LVN_COLUMNCLICK
使用的是NMLISTVIEW
结构体。 -
接着,根据列点击的子项索引
pNMLV->iSubItem
和之前保存的当前列索引dwSelColID
进行比较。如果当前列索引与点击的子项索引不同,则更新当前列索引为点击的子项索引,并保持排序顺序不变(bASC = bASC
)。如果当前列索引与点击的子项索引相同,则切换排序顺序(bASC = !bASC
)。 -
然后,获取列表控件中项的总数,并为每个项设置与其相同的数据,这样在排序后可以保持项的数据与列表控件中的位置对应。
-
最后,调用列表控件的
SortItems
函数对列表进行排序。作为参数传递给SortItems
函数的是静态成员函数CompareFunc
的地址,以及一个参数,即列表控件本身的地址。CompareFunc
函数会根据列点击的子项索引和排序顺序来进行排序。 -
将
pResult
设置为 0,表示消息处理已经完成。
总的来说,这段代码的作用是在列表控件的列点击事件发生时,根据点击的列索引以及当前的排序顺序对列表项进行排序。
5、添加回调函数
// 按列表头升序或逆序比较函数
static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CListCtrl* pListCtrl = (CListCtrl*)lParamSort;
LVFINDINFO findInfo;
findInfo.flags = LVFI_PARAM;
findInfo.lParam = lParam1;
int iItem1 = pListCtrl->FindItem(&findInfo, -1);
findInfo.lParam = lParam2;
int iItem2 = pListCtrl->FindItem(&findInfo, -1);
CString strItem1 = pListCtrl->GetItemText(iItem1, dwSelColID);
CString strItem2 = pListCtrl->GetItemText(iItem2, dwSelColID);
if (bASC)
return strItem1.Compare(strItem2);
else
return strItem2.Compare(strItem1);
}
这段代码是用于比较两个列表项的函数,用于在排序时确定它们的顺序。
-
static int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
: 这是一个静态成员函数,用于比较两个列表项的回调函数。它接受三个参数:lParam1
: 第一个列表项的自定义数据,通常是列表项的索引或其他标识符。lParam2
: 第二个列表项的自定义数据,同样是列表项的索引或其他标识符。lParamSort
: 对列表控件的指针,用于访问列表控件以获取列表项的文本。
-
CListCtrl* pListCtrl = (CListCtrl*)lParamSort;
: 将lParamSort
转换为CListCtrl*
类型的指针,以便在比较函数中访问列表控件。 -
LVFINDINFO findInfo; findInfo.flags = LVFI_PARAM; findInfo.lParam = lParam1; int iItem1 = pListCtrl->FindItem(&findInfo, -1);
: 使用lParam1
和lParam2
查找它们对应的列表项索引。这是通过设置LVFINDINFO
结构体中的lParam
字段来进行的,然后调用FindItem
函数来查找列表中第一个匹配项的索引。 -
CString strItem1 = pListCtrl->GetItemText(iItem1, dwSelColID);
: 使用列表控件指针和列表项索引获取第一个列表项的文本。dwSelColID
是当前选择的列的索引。 -
同样的步骤也适用于第二个列表项,只是使用了
lParam2
来查找索引,并获取其文本。
: 使用列表控件指针和列表项索引获取第一个列表项的文本。dwSelColID
是当前选择的列的索引。
-
同样的步骤也适用于第二个列表项,只是使用了
lParam2
来查找索引,并获取其文本。 -
if (bASC) return strItem1.Compare(strItem2); else return strItem2.Compare(strItem1);
: 根据当前排序顺序决定返回哪个字符串比较结果。如果是升序排序,则直接返回两个字符串的比较结果;如果是降序排序,则将两个字符串的比较结果反转再返回。