1。 在 父窗口添加消息响应函数,及映射。
void CStatisticCtrl::OnListNotify( NMHDR * pNotifyStruct, LRESULT * result )
{
NM_LISTVIEW * plv = (NM_LISTVIEW *)pNotifyStruct;
int cnt = m_list.GetItemCount();
for( int i =0 ;i <cnt ; i++ )
m_list.SetItemData(i,i);
info.m_list= &m_list;info.col = plv->iSubItem;
static std::map<int,int> hashtable ;
std::map<int,int>::iterator itor;
if((itor = hashtable.find(plv->iSubItem)) != hashtable.end()){
info.basc = ! ( itor->second) ;
hashtable.erase(itor);
hashtable.insert(std::map<int,int>::value_type(plv->iSubItem,info.basc));
}else
{
info.basc = 1 ;
hashtable.insert(std::map<int,int>::value_type(plv->iSubItem,info.basc));
}
m_list.SortItems(ListCompare,(LPARAM)&info);
}
这是消息相应函数
ON_NOTIFY(LVN_COLUMNCLICK,1403,OnListNotify) 这是消息映射,1403 是CListCtrl的ID。
然后添加响应的比较函数
typedef struct INFOTAG{
CListCtrl * m_list;
int basc;
int col;
}INFO;
INFO info;
int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
INFO * info = (INFO*) lParamSort ;
CString data1,data2 ;
switch(info->basc){
case 0 :
switch(info->col)
{
case 0:
data1 = info->m_list->GetItemText(lParam1,0);
data2 = info->m_list->GetItemText(lParam2,0);
if(data1 > data2 ) return 1 ;
if(data1 < data2 ) return -1 ;
break;
case 1:
data1 = info->m_list->GetItemText(lParam1,1);
data2 = info->m_list->GetItemText(lParam2,1);
if(data1 > data2 ) return 1 ;
if(data1 < data2 ) return -1 ;
break;
case 2:
data1 = info->m_list->GetItemText(lParam1,2);
data2 = info->m_list->GetItemText(lParam2,2);
if(atoi((LPCTSTR) data1) > atoi((LPCTSTR)data2) ) return 1 ;
if(atoi((LPCTSTR)data1)< atoi((LPCTSTR)data2) ) return -1 ;
break;
}
break;
case 1:
switch(info->col)
{
case 0:
data1 = info->m_list->GetItemText(lParam1,0);
data2 = info->m_list->GetItemText(lParam2,0);
if(data1 < data2 ) return 1 ;
if(data1 > data2 ) return -1 ;
break;
case 1:
data1 = info->m_list->GetItemText(lParam1,1);
data2 = info->m_list->GetItemText(lParam2,1);
if(data1 < data2 ) return 1 ;
if(data1 > data2 ) return -1 ;
break;
case 2:
data1 = info->m_list->GetItemText(lParam1,2);
data2 = info->m_list->GetItemText(lParam2,2);
if(atoi((LPCTSTR)data1) < atoi((LPCTSTR)data2) ) return 1 ;
if(atoi((LPCTSTR)data1)> atoi((LPCTSTR)data2) ) return -1 ;
break;
}
break;
}
return 0 ;
}
/
列表控件(CListCtrl)的顶部有一排按钮,用户可以通过选择不同的列来对记录进行排序。但是 CListCtrl并没有自动排序的功能,我们需要自己添加一个用于排序的回调函数来比较两个数据的大小,此外还需要响应排序按钮被点击的消息。下面讲述一下具体的做法。
CListCtrl提供了用于排序的函数,函数原型为:BOOL CListCtrl::SortItems( PFNLVCOMPARE pfnCompare, DWORD dwData )。其中第一个参数为全局排序函数的地址,第二个参数为用户数据,你可以根据你的需要传递一个数据或是指针。该函数返回-1代表第一项排应在第二项前面,返回1代表第一项排应在第二项后面,返回0代表两项相等。
用于排序的函数原形为:int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort),其中第三个参数为调用者传递的数据(即调用SortItems时的第二个参数dwData)。第一和第二个参数为用于比较的两项的ItemData,你可以通过DWORD CListCtrl::GetItemData( int nItem )/BOOL CListCtrl::SetItemData( int nItem, DWORD dwData )来对每一项的ItemData进行存取。在添加项时选用特定的CListCtrl::InsertItem也可以设置该值。由于你在排序时只能通过该值来确定项的位置所以你应该比较明确的确定该值的含义。
最后一点,我们需要知道什么时候需要排序,实现这点可以在父窗口中对LVN_COLUMNCLICK消息进行处理来实现。