这是一段对List Control进行排序的代码,现在有这个一个问题,对于一些数字型的东西,如"123"和"21",这段代码会认为"123" < "21",我想更正这个错误,谢谢!可以先进行位数上的比较.
BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
{
int i;
int lo = low;
int hi = high;
CString midItem;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi; if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( 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 ) && ( GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( 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( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
lvitemhi.iItem = hi; GetItem( &lvitemlo );
GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
SetItem( &lvitemlo );
} ++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,bIsNumber); // 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,bIsNumber); return TRUE;
}
BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
{
int i;
int lo = low;
int hi = high;
CString midItem;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi; if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( 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 ) && ( GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( 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( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
lvitemhi.iItem = hi; GetItem( &lvitemlo );
GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
SetItem( &lvitemlo );
} ++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,bIsNumber); // 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,bIsNumber); return TRUE;
}
BOOL IsAllNumber(CString str)//这个函数判断某个字符串是不是全是数字
{
int i;
i=atoi(str);
CString strComp;
strComp.Format("%d",i);
if (str==strComp)
return TRUE;
else
return FALSE;
}
BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
{
int i;
int lo = low;
int hi = high;
CString midItem;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi;
if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
//判断:如果全是数字的话,采用数字的比较
if(IsAllNumber(midItem) && IsAllNumber(GetItemText(lo, nCol))
{
if( bAscending )
while( ( lo < high ) && ( atoi(GetItemText(lo, nCol)) < atoi(midItem) ) )
++lo;
else
while( ( lo < high ) && ( atoi(GetItemText(lo, nCol)) > atoi(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 ) && ( atoi(GetItemText(hi, nCol)) > atoi(midItem) ) )
--hi;
else
while( ( hi > low ) && ( atoi(GetItemText(hi, nCol)) < atoi(midItem )) )
--hi; }elseif{//下面是原来的字符串比较
if( bAscending )
while( ( lo < high ) && ( GetItemText(lo, nCol) < midItem ) )
++lo;
else
while( ( lo < high ) && ( 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 ) && ( GetItemText(hi, nCol) > midItem ) )
--hi;
else
while( ( hi > low ) && ( 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( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
lvitemhi.iItem = hi; GetItem( &lvitemlo );
GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
SetItem( &lvitemlo );
} ++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,bIsNumber); // 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,bIsNumber); return TRUE;
}
BOOL IsAllNumber(CString str)
{
int i;
i=atoi(str);
CString strComp;
strComp.Format("%d",i);
if (str==strComp)
return TRUE;
else
return FALSE;
}
BOOL CompString(CString str1,CString str2,BOOL oper)
{
//oper=TRUE是判断大于,否则判断小于
if (IsAllNumber(str1) && IsAllNumber(str2)) {
if ((atoi(str1)>atoi(str2)) && oper ) {
return TRUE;
}
else{
return FALSE;
}
}
if ((str1 > str2) && oper) {
return TRUE;
}
else{
return FALSE; }
}
BOOL CSortFileList::SortTextItems(int nCol, BOOL bAscending, int low, int high,BOOL bIsNumber)
{
int i;
int lo = low;
int hi = high;
CString midItem;
CStringArray rowText;
LV_ITEM lvitemlo, lvitemhi; if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( high == -1 ) high = GetItemCount() - 1; if( hi <= lo ) return FALSE; midItem = GetItemText( (lo+hi)/2, nCol ); // loop through the list until indices cross
while( lo <= hi )
{
// rowText will hold all column text for one row
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( lo < high ) && ( CompString(GetItemText(lo, nCol),midItem,FALSE)) )
++lo;
else
while( ( lo < high ) && ( CompString(GetItemText(lo, nCol),midItem,TRUE)) )
++lo; // find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( hi > low ) && ( CompString(GetItemText(hi, nCol),midItem, TRUE) ) )
--hi;
else
while( ( hi > low ) && ( CompString(GetItemText(hi, nCol), midItem,FALSE )) )
--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( GetItemText(lo, nCol) != GetItemText(hi, nCol))
{
// swap the rows
int nColCount =((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
rowText.SetSize( nColCount );
for( i=0; i<nColCount; i++)
rowText[i] = GetItemText(lo, i);
lvitemlo.mask = LVIF_IMAGE | LVIF_PARAM | LVIF_STATE;
lvitemlo.iItem = lo;
lvitemlo.iSubItem = 0;
lvitemlo.stateMask = LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK; lvitemhi = lvitemlo;
lvitemhi.iItem = hi; GetItem( &lvitemlo );
GetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(lo, i, GetItemText(hi, i)); lvitemhi.iItem = lo;
SetItem( &lvitemhi ); for( i=0; i<nColCount; i++)
SetItemText(hi, i, rowText[i]); lvitemlo.iItem = hi;
SetItem( &lvitemlo );
} ++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,bIsNumber); // 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,bIsNumber); return TRUE;
}
123
21
32
但是格式化的数据为:
0000123
0000021
0000032
这样处理的数据显示肯定没问题*///首先声明全局结构
typedef struct{
CString strFileName;
CString strFileSize;
}ITEMDATA,*PITEMDATA;//在产生列表时填充该结构的实例
sFileSizeSort.Format("%20.0fKB",fFileSize);pData=new ITEMDATA;
pData->strFileName=sFileName;
//用格式化的数据填充全局结构的实例,用来排序(0000123,0000021,0000032)
pData->strFileSize=sFileSizeSort;//同时填充列表
m_lstFileList.AddItem(lFileCnt,0,wfd.cFileName,1);
//用未格式化的数据填充列表(123,21,32)
m_lstFileList.AddItem(lFileCnt,2,sFileSize);
m_lstFileList.SetItemData(lFileCnt,(LPARAM)pData);//在列表的表头发生鼠标单击事件时
{
HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
CListCtrlEx* pList=(CListCtrlEx*)GetDlgItem(IDC_LIST_FILELIST);
static int i;
if(i==0){
pList->SortItems(SortFuncASC,phdn->iItem);
i=1;
*pResult = 0;
return;
}
if(i==1){
pList->SortItems(SortFuncDESC,phdn->iItem);
i=0;
*pResult = 0;
return;
}
}
//升序函数
int CALLBACK SortFuncASC(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int nRtnVal;
PITEMDATA pData1=(PITEMDATA)lParam1;
PITEMDATA pData2=(PITEMDATA)lParam2;
switch(lParamSort)
{
case 0:
nRtnVal=strcmp(pData1->strFileName,pData2->strFileName);
break;
case 2:
nRtnVal=strcmp(pData1->strFileSize,pData2->strFileSize);
break;
default:
break;
}
return nRtnVal;
}
//降序函数
int CALLBACK SortFuncDESC(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
int nRtnVal;
PITEMDATA pData1=(PITEMDATA)lParam1;
PITEMDATA pData2=(PITEMDATA)lParam2;
switch(lParamSort)
{
case 0:
nRtnVal=strcmp(pData2->strFileName,pData1->strFileName);
break;
case 2:
nRtnVal=strcmp(pData2->strFileSize,pData1->strFileSize);
break;
default:
break;
}
return nRtnVal;
}