int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort;
CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column);
if(sort_column<2)
{
if(method)
{
method=FALSE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
else
{
method=TRUE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
}
return 0;
}为什么只是排序前2项,觉得if中应该来个循环,我想全部排序,应该怎么做,求解?
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort;
CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column);
if(sort_column<2)
{
if(method)
{
method=FALSE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
else
{
method=TRUE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
}
return 0;
}为什么只是排序前2项,觉得if中应该来个循环,我想全部排序,应该怎么做,求解?
{
int listcount = m_list.GetItemCount();
int nColumn =m_list.GetHeaderCtrl()->GetItemCount();
CString temp0,temp1,temp2;
for(int j = 1;j <listcount;j++)
{
for(int i=0;i <listcount-j;i++)
{
temp1 = m_list.GetItemText(i,0); //m_list为控件绑定的变量,根据自己的修改
temp2 = m_list.GetItemText(i+1,0);
//int nRe = StrCmpLogicalW(temp1,temp2); //
int nRe = StrCmpI(temp1,temp2); //
if (m_bSort)
{
if (nRe < 0)
{
for(int n=0;n <nColumn;n++)
{
temp1 = m_list.GetItemText(i,n);
temp2 = m_list.GetItemText(i+1,n);
m_list.SetItemText(i,n,temp2);
m_list.SetItemText(i+1,n,temp1);
}
}
}
if (!m_bSort)
{
if (nRe > 0)
{
for(int n=0;n <nColumn;n++)
{
temp1 = m_list.GetItemText(i,n);
temp2 = m_list.GetItemText(i+1,n);
m_list.SetItemText(i,n,temp2);
m_list.SetItemText(i+1,n,temp1);
}
}
}
}
}
}
这个函数如果是CListCtrl用来排序的回调函数,这样写是对的。
CListCtrl会针对每行记录调用这个函数来排序。不是用来你自己在对话框中调用的。得加上这个void CListCtrlDlg::OnColumnClickDGrid(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView=(NM_LISTVIEW*)pNMHDR; m_lstctlTable.SortItems((PFNLVCOMPARE)MyCompareProc, &m_lstctlTable);
*pResult=0;
}然后点击列表头,就对其中记录按MyCompareProc中的规则,排序了。
用CListCtrl自己的排序,除了实现排序函数,还要满足两个条件:
1. 各行必须有不同的itemdata。
2. 不能只有一列。当然,这两点是10年前发现的,当时用2000多些,现在也许没这问题了。
int CALLBACK CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);
The lParam1 parameter is the 32-bit value associated with the first item that is compared, and the lParam2 parameter is the value associated with the second item. These are the values that were specified in the lParam member of the items' LVITEM structure when they were inserted into the list.也就是说,listctrl传给排序函数的参数lParam1和lParam2,其实不是行索引号,是itemData。
你可以在排序前给每行SetItemData,值就用行索引号,排序后再还原就行了。
void CListCtrlDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
sort_column=pNMLV->iSubItem;
int count=m_ListCtrl.GetItemCount();
for(int i=0;i<count;i++)
m_ListCtrl.SetItemData(i,i);
m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&m_ListCtrl);
*pResult = 0;
}int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort;
CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column);
LVFINDINFO findInfo;
findInfo.flags=LVFI_PARAM;
findInfo.lParam=lParam1;
findInfo.
if(sort_column<2)
{
if(method)
{
method=FALSE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
else
{
method=TRUE;
return strcmp((char*)(LPCTSTR)lp1,(char*)(LPCTSTR)lp2);
}
}
else
{
if(method)
return lp1.CompareNoCase(lp2);
else
return lp2.CompareNoCase(lp1);
}
return 1;
}
这个是我的代码,关键是为什么只是比较前两项,也就是相邻的两项。setItemData也用了,为什么不行?前两项确实可以排序,但后面就不行了。
难道不是响应LVN_COLUMNCLICK 消息?
int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort; CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column); return lp1.CompareNoCase(lp2);
}
void CListCtrlDlg::OnLvnColumnclickList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
sort_column=pNMLV->iSubItem;
int count=m_ListCtrl.GetItemCount();
for(int i=0;i<count;i++)
m_ListCtrl.SetItemData(i,i);
m_ListCtrl.SortItems(MyCompareProc,(DWORD_PTR)&m_ListCtrl);
*pResult = 0;
}int CListCtrlDlg::MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int row1=(int)lParam1;
int row2=(int)lParam2;
CListCtrl *lc=(CListCtrl*)lParamSort;
CString lp1=lc->GetItemText(row1,sort_column);
CString lp2=lc->GetItemText(row2,sort_column); if(sort_column<2)
{
if(method) {
method=FALSE;
return _tcscmp(lp1,lp2);
}
else
{
method=TRUE;
return _tcscmp(lp2,lp1);
} }
else
{
if(method)
return lp1.CompareNoCase(lp2);
else
return lp2.CompareNoCase(lp1);
}
return 0;
}
这个是我全部代码,method是静态全局函数,表示升序或降序。 我想问下,这个函数一直会遍历完整个行,直到遍历完才返回吗?
一般升序降序的状态,可以保存到列头CHeaderCtrl中,可以用item的lParam参数保存,排序时通过回调函数的最后一个参数传进去。如:CHeaderCtrl *pHeardCtrl = GetHeaderCtrl();
HDITEM hdi;
hdi.mask = HDI_LPARAM;
pHeardCtrl->GetItem(pNMLV->iSubItem, &hdi);
BOOL bASC = (hdi.lParam == 0 ? TRUE : FALSE); //当前排序方式和上次相反
hdi.lParam = bASC; //保存当前的升降序状态
pHeardCtrl->SetItem(pNMLV->iSubItem, &hdi);
我把这个源代码发给你,能否帮我修改一下,一直想实现这个功能。我的QQ [email protected]
http://download.csdn.net/detail/iamshuke/3929906