列表控制有一个特殊的功能,当以详细资料方式显示时,列表顶部的表头可以当作按钮来使用,这可以通过列表控制创建时的风格来控制。当鼠标点击列表头名称时,列表控制就会向其父窗口发送一个LNV_COLUMNCLICK消息,利用类导向中列表控制IDC_LISTCTRL对应的LNV_COLUMNCLICK消息加入相应处理函数,就可将表列按照特定顺序进行排列。其函数使用方法见程序,其中iSort为排序的表列索引号,(PFNLVCOMPARE)CompareFunc为进行具体排序的回调函数,也就是说,通过鼠标点击表头实现的排序过程是由第三方开发的专用排序函数来实现的,排序函数只是实现表项的具体比较操作,而整个排序过程是由SortItemS属性通过不断调用这个函数来实现的。正常的排序过程是升序方式,通过调换排序函数中的参数值,就可实现降序排列,即将PARAM1与PARAM2调换位置。这个回调函数的前两个参数为表列中表项的索引号,第三个参数为排序的表列索引号。
IDC_LIST1 控件添加 LVN_COLUMNCLICK消息,对应CRecordingDlg::OnColumnclickList1方法
/*此为传递数据的结构体,可在头文件中定义*/
typedef struct _Item
{
CListCtrl *mlist;
int Isub; //排序列
}Item;
static int nSortOrder = 1; // 排序的方式,1升序,-1降序。
/*
回调函数
*/
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
// 得到排序方式
Item* pV=(Item*)lParamSort;
// 得到两个列的排序信息
CString sz1 = pV->mlist->GetItemText(lParam1,pV->Isub);
CString sz2 = pV->mlist->GetItemText(lParam2,pV->Isub);
if(nSortOrder == 1)
{
return sz1.Compare(sz2);
}
else
{
return -sz1.Compare(sz2);
}
}
/*
点击list表头事件。
*/
void CRecordingDlg::OnColumnclickList1(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
static int ncurSortCol = -1; // 保存当前的排序列。
// 一开始表示为-1,表示尚未按任何列排序。
/* 若当前排序列与点击列相同,则更改增、减序的排序方式。
若点击列与当前排序列不同的列,则改变排序序,并将排序方式改为增序。*/
if (ncurSortCol == pNMListView->iSubItem)
{
if (nSortOrder == 1)
{
nSortOrder = -1;
}
else
{
nSortOrder = 1;
}
}
else
{
ncurSortCol = pNMListView->iSubItem;
nSortOrder = 1;
}
Item mItem;
mItem.mlist = &m_List;
mItem.Isub = pNMListView->iSubItem;
for(int i=0;i < m_List.GetItemCount();i++)
{
m_List.SetItemData(i,i);
}
m_List.SortItems(CompareFunc,(LPARAM)&mItem);
*pResult = 0;
}