我的软件做好了,想增加排序功能
我是直接用ListView的,所以网上的CSortListCtrl无法使用
后来找到一个直接将内容排序的代码,发现其中有错
然后干脆自己写,用了冒泡排序,感觉这个算法思想最熟悉,但是效率难以忍受
大家谁给我指点一下下面是网上找到的代码
// http://www.vckbase.com/english/code/listview/sort_on_col.shtml.htm
// SortTextItems - Sort the list based on column text
// Returns - Returns true for success
// nCol - column that contains the text to be sorted
// bAscending - indicate sort order
// low - row to start scanning from - default row is 0
// high - row to end scan. -1 indicates last row
BOOL C102_1View::SortTextItems(int nCol, BOOL bAscending, int low, int high)
{
CListCtrl& lc = GetListCtrl();
CHeaderCtrl* pCtrl = lc.GetHeaderCtrl();
if(nCol >= pCtrl->GetItemCount())
return FALSE;//如果待排序的列超过最大值,返回FALSE if( high == -1 ) high = pCtrl->GetItemCount() - 1; int lo = low;
int hi = high;
CString midItem; if( hi <= lo ) return FALSE; midItem = lc.GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
CStringArray rowText; // find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( lc.GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( lc.GetItemText(lo, nCol) > midItem ) )
++lo; // find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && ( lc.GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( lc.GetItemText(hi, nCol) < midItem ) )
--hi; // if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
if( strcmp(lc.GetItemText(lo, nCol), lc.GetItemText(hi, nCol)) != 0)
//if( lc.GetItemText(lo, nCol) != lc.GetItemText(hi, nCol))
{
// swap the rows//这里省略部分内容
} ++lo;
--hi;
}
} // If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortTextItems( nCol, bAscending , low, hi); // If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortTextItems( nCol, bAscending , lo, high ); return TRUE;}
我是直接用ListView的,所以网上的CSortListCtrl无法使用
后来找到一个直接将内容排序的代码,发现其中有错
然后干脆自己写,用了冒泡排序,感觉这个算法思想最熟悉,但是效率难以忍受
大家谁给我指点一下下面是网上找到的代码
// http://www.vckbase.com/english/code/listview/sort_on_col.shtml.htm
// SortTextItems - Sort the list based on column text
// Returns - Returns true for success
// nCol - column that contains the text to be sorted
// bAscending - indicate sort order
// low - row to start scanning from - default row is 0
// high - row to end scan. -1 indicates last row
BOOL C102_1View::SortTextItems(int nCol, BOOL bAscending, int low, int high)
{
CListCtrl& lc = GetListCtrl();
CHeaderCtrl* pCtrl = lc.GetHeaderCtrl();
if(nCol >= pCtrl->GetItemCount())
return FALSE;//如果待排序的列超过最大值,返回FALSE if( high == -1 ) high = pCtrl->GetItemCount() - 1; int lo = low;
int hi = high;
CString midItem; if( hi <= lo ) return FALSE; midItem = lc.GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
CStringArray rowText; // find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( lc.GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( lc.GetItemText(lo, nCol) > midItem ) )
++lo; // find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && ( lc.GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( lc.GetItemText(hi, nCol) < midItem ) )
--hi; // if the indexes have not crossed, swap
// and if the items are not equal
if( lo <= hi )
{
// swap only if the items are not equal
if( strcmp(lc.GetItemText(lo, nCol), lc.GetItemText(hi, nCol)) != 0)
//if( lc.GetItemText(lo, nCol) != lc.GetItemText(hi, nCol))
{
// swap the rows//这里省略部分内容
} ++lo;
--hi;
}
} // If the right index has not reached the left side of array
// must now sort the left partition.
if( low < hi )
SortTextItems( nCol, bAscending , low, hi); // If the left index has not reached the right side of array
// must now sort the right partition.
if( lo < high )
SortTextItems( nCol, bAscending , lo, high ); return TRUE;}
为什么不先把数据源排序,然后再读入listctrl呢?
static int CALLBACK MyCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{ int iReture = 0;//返回值
int i=0;//字符编号
CString str1;
CString str2;
unsigned long lIP1;
unsigned long lIP2; str1 = pCheckBoxListCtrl->GetItemText((int)lParam1, (int)lParamSort);
str2 = pCheckBoxListCtrl->GetItemText((int)lParam2, (int)lParamSort); WCHAR *pChar1 = str1.GetBuffer(str1.GetLength());
WCHAR *pChar2 = str2.GetBuffer(str2.GetLength()); if (lParamSort == 3)//当为ID时进行特殊判断
{
char Buf1[255];
char Buf2[255];
WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)pChar1, -1, Buf1, sizeof(Buf1), NULL, NULL);
WideCharToMultiByte(CP_UTF8, 0, (LPCWSTR)pChar2, -1, Buf2, sizeof(Buf2), NULL, NULL);
lIP1 = inet_addr(Buf1);
lIP2 = inet_addr(Buf2); if (((lIP1 > lIP2) * s_bSign) > 0)
{
iReture = 1;
}
else if (((lIP1 < lIP2) * s_bSign) < 0)
{
iReture = -1;
}
else iReture = 0;
}
else
{
int nSize = min(str1.GetLength(),str2.GetLength());
while (pChar1[i] == pChar2[i])
{
if (i == nSize -1) break;
i++;
} if (i == nSize - 1)
{
iReture = str1.GetLength() - str2.GetLength();
}
else
{
iReture = pChar1[i] - pChar2[i];
} } str1.ReleaseBuffer();
str2.ReleaseBuffer(); return (s_bSign * iReture);
}
void CCheckBoxListCtrl::OnLvnColumnclick(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLISTVIEW pNMLV = reinterpret_cast<LPNMLISTVIEW>(pNMHDR);
// TODO: 在此添加控件通知处理程序代码 int nSize = this->GetItemCount();
for (int i = 0; i<nSize; i++)
{
SetItemData(i,i);//动态更改编号
}
s_bSign *= -1;//点击变换排序顺序
SortItems((PFNLVCOMPARE)MyCompareProc, pNMLV->iSubItem); *pResult = 0;
}
这里有个现成的类,你可以直接用他就可以了