江阴市兴劲特种玻璃:MFC中使CListCTrl控件排序_不二周助_太平洋博客
来源:百度文库 编辑:偶看新闻 时间:2024/04/29 14:43:07
MFC中使CListCTrl控件排序
- 阅读:(1191) 评论:(0) 发表时间:2009-
08-24作者:不二周助 - 列表控件(CList
Ctrl)的排序功能 不像其它直接调用AP I就可以完成的功能一 样.它比较复杂.今天 将我的一点体会简单地 谈一下. 列表控件的顶部有一排 按钮,用户可以通过选 择不同的列来对记录进 行排序。但是 CListCtrl并 没有自动排序的功能, 我们需要自己添加一个 用于排序的回调函数来 比较两个数据的大小, 此外还需要响应排序按 钮被点击的消息。回调 函数就好像是一个中断 处理函数,操作系统在 符合你设定的条件时自 动调用。
·CListCtrl提供了用于排序的函数
函数原型为:
BOOL CListCtrl::SortItems ( PFNLVCOMPA RE pfnCompare , DWORD dwData);
其中第一个参数为全局排序函数(它就是回调 函数)的地址,
第二个参数为用户数据,你可以根据你的需要 传递一个数据或是指针 。
该函数返回-1,代表第一项排应在第二项前 面;
返回1代表第一项排应在第二项后面;
返回0代表两项相等。·排序函数原形为:
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
其中第三个参数为调用者传递的数据(即调用 SortItems时 的第二个参数dwDa ta)。
第一和第二个参数为用于比较的两项的Ite mData,你可以通 过DWORD CListCtrl: :GetItemDa ta( int nItem )/
BOOL CListCtrl::SetItemDa ta( int nItem, DWORD dwData )来对每一项的Ite mData进行存取。 在添加项时选用特定的 CListCtrl: :InsertIte m也可以设置该值。由 于你在排序时只能通过 该值来确定项的位置所 以你应该比较明确的确 定该值的含义。
·我们什么时候需要排序(消息映射)呢?
实现这点可以在父窗口中对LVN_COLU MNCLICK消息进 行处理来实现。例子:
//排序回调函数实现
static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
{
// lParamSortcontains a pointer to the list view control.
// The lParam of an item is just its index.
//以第一列为根据排序
CListCtrl*pListCtrl = (CListCtrl *) lParamSort ;
CString strItem1 = pListCtrl->GetItemTe xt(lParam1 , 0);
CString strItem2 = pListCtrl->GetItemTe xt(lParam2 , 0);
//比较两个数
LPCTSTR s1=(LPCTSTR)strItem1 ;
LPCTSTR s2=(LPCTSTR)strItem2 ;
int n1=atoi(s1);
int n2=atoi(s2);if (n1>n2)
return -1;
else
return 1;
}
void C***::OnColumnclickL ist(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListVie w = (NM_LISTVI EW*)pNMHDR ;
// TODO: Add your control notification handler code here //调用排序函数
m_ShowData.SortItems ( MyCompareP roc, (DWORD)&m_ ShowData );
*pResult = 0;}
整个过程是这样的: 当你点击列表控件的表头时,此时它会向父窗 口发送LVN_COL UMNCLICK消息 ,此时响应函数OnC olumnclick List(),在该函 数里面再调用列表控件 的SortItems ()成员函数,它会自 动调用排序函数,完成 排序功能.
首先,要让CListCtrl能响应点击C olumn header的操作, 方法是响应对应的LV N_COLUMNCL ICK消息,然后在对 应的消息处理函数中执 行自己的排序。其方法 是调用CListCt rl 类中的成员函数Sor tItems()函数 ,不过在调用之前,依 据msdn的指示,一 定要对所有需要排序的 行调用CListCt rl的 SetItemDat a( int nItem , DWORD dwData )函数,一般的设置方 法为:
for(int i = 0; i < listCtrl.GetItemCoun t(); ++i)
{
SetItemData(i,i);
}
这样写的原因下面马上就会指出。
接下来就是调用CListCtrl的排序函 数SortItems ( PFNLVCOMPA RE pfnCompare , DWORD dwData ),其中第一个参数为 比较函数(回调函数) ,其函数格式按照ms dn上的说法应该为:
int CALLBACK listCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort );
这里的lParam1和lParam2都是 系统传给这个回调函数 的,具体数值就是上面 SetItemDat a函数中的dwDat a,所以刚才用了 SetItemDat a(i,i)的语句( 至于能否将dwDat a设置成其他的数值, 我认为应该也是没有问 题的,只要你觉得用这 样的参数在回调的排序 函数中使用方便就行了 ) 第二个参数是输入给这 个回调函数的一个参数 ,一般都是对应CLi stCtrl对象的指 针
最后就是实现那个回调函数了,msdn上说 这个函数必须为独立的 函数,或者是某个类中 的静态函数,这点注意 一下即可,以下为一个 具体的回调函数的例子 :
//////////////////// ////////// ////////// ///
//按第六列排序
int CALLBACK listCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort )
{
CListCtrl*pListCtrl = (CListCtrl *)lParamSo rt;
CString strItem1 = pListCtrl->GetItemTe xt(lParam1 ,5);
CString strItem2 = pListCtrl->GetItemTe xt(lParam2 ,5);
LVCOLUMN Vol;
CString csStr("");
TCHAR szCol[MAX_PATH];
Vol.pszText = szCol;
Vol.mask=LVCF_TEXT;
Vol.cchTextMax=sizeo f(szCol);
pListCtrl->GetColumn (0,&Vol);
csStr = CString(Vol.pszText) ;
if (csStr.Right(1) == CString("▼ "))
{
return _tcscmp(strItem2.Get Buffer(MAX _PATH),str Item1.GetB uffer(MAX_ PATH));
}
else if (csStr.Right(1) == CString("▲ "))
{
return _tcscmp(strItem1.Get Buffer(MAX _PATH),str Item2.GetB uffer(MAX_ PATH));
}
else
{
return _tcscmp(strItem1.Get Buffer(MAX _PATH),str Item2.GetB uffer(MAX_ PATH));
}
}
///////////////////
void CManageView::OnColum nclick(NMH DR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListVie w = (NM_LISTVI EW*)pNMHDR ; - 列表控件(CList