This code is based on the articls
“Sorting the list based on text in any column” &
“Sorting list on Numeric Column”.
The follwing code combines both articals and adds a new sort type Date/Time
sort.
#include// MFC Ole #include // Ole TimeData something...
Add function
// Compare two string by their column types // // returns: // Zero if the strings are identical, // < 0 if cstL is less than cstR, // > 0 if cstL is greater than cstR. // int CMyListCtrl::CmpItems(CString cstL, CString cstR, int nCol) { switch (nCol) { //Date time column(s) //*********************** case 0: COleDateTime odtL; COleDateTime odtR; odtL.ParseDateTime(cstL); odtR.ParseDateTime(cstR); COleDateTimeSpan spanElapsed = odtL - odtR; if (spanElapsed.GetStatus() == COleDateTimeSpan::invalid ) { // Invalid Date time. ASSERT(FALSE); return(0); } return((int)spanElapsed.GetTotalSeconds()); } //Numbers column(s) //*********************** case 1: case 4: return(atoi(cstL) - atoi(cstR)); // Strings column(s) //*********************** //*********************** default: return (cstL.Compare(cstR)); } }
Modified lines ==> /*!!!*/
bool CMyListCtrl::SortNumericItems( int nCol, BOOL bAscending,int low/*=0*, int high/*=-1* ) { if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() ) return FALSE; if( high == -1 ) high = GetItemCount() - 1; int lo = low; int hi = high; CString midItem; 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 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 ) && (atoi(GetItemText(lo, nCol)) < midItem ) ) /*!!!* while( ( lo < high ) && ( CmpItems( GetItemText(lo, nCol) , midItem, nCol) < 0 ) ) ++lo; else //while( ( lo < high ) && (atoi(GetItemText(lo, nCol)) > midItem ) ) /*!!!* while( ( lo < high ) && ( CmpItems( GetItemText(lo, nCol) , midItem, nCol) > 0 ) ) ++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)) > midItem ) ) /*!!!* while( ( hi > low ) && ( CmpItems(GetItemText(hi, nCol) , midItem, nCol ) > 0 ) ) --hi; else //while( ( hi > low ) && (atoi(GetItemText(hi, nCol)) < midItem ) ) /*!!!* while( ( hi > low ) && ( CmpItems(GetItemText(hi, nCol) , midItem, nCol ) < 0 ) ) --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(atoi(GetItemText(lo, nCol)) != atoi(GetItemText(hi, nCol)) ) /*!!!* if( CmpItems (GetItemText(lo, nCol) , GetItemText(hi, nCol), Col ) != 0) { // swap the rows LV_ITEM lvitemlo, lvitemhi; int nColCount = ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount(); rowText.SetSize( nColCount ); int i; 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 ) SortNumericItems( 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 ) SortNumericItems( nCol, bAscending , lo, high ); return TRUE; }