This code was contributed by Mark Findlay.
// This is a simple modification of the text sorting routine by
// Zafir Anjum. (See "Sorting the list based on text in any column")
//
// It sorts the list based on the image index of the column being
// sorted. You must only call this function when sorting a column
// that has an image associated with it.
//
// I added an additional helper function GetItemImageIndex() which
// simply returns the image index for the row and column specified.
//
//////////////////////////////////////////////////////////
//**************************************************
// GetItemImageIndex
// return the image index of the selected row and col
int CMyListCtrl::GetItemImageIndex(int nRow, int nCol/*=0*)
{
LV_ITEM lv = {0};
lv.mask = LVIF_IMAGE;
lv.iItem = nRow;
lv.iSubItem = nCol;
GetItem( &lv );
return lv.iImage;
}
////////////////////////////////////////////////////////////////////
// Sort by image index of column
//
// This function is a simple modification of the text sorting function
// written by Zafir Anjum.
//
// SortInImageOrder - Sort the list based on image index of column
// Returns - Returns true for success
// nCol - column that contains the text to be sorted
// bAscending - indicate sort order
// nLow - row to start scanning from - default row is 0
// nHigh - row to end scan. -1 indicates last row
BOOL CMyListCtrl::SortInImageOrder(int nCol, BOOL bAscending, int nLow/*=0*, int nHigh/*=-1*)
{
BOOL bRet = FALSE;
if( nCol >= ((CHeaderCtrl*)GetDlgItem(0))->GetItemCount() )
return FALSE;
if( nHigh == -1 ) nHigh = GetItemCount() - 1;
int nLo = nLow;
int nHi = nHigh;
int nMidItem;
if( nHi <= nLo )
return FALSE;
nMidItem = GetItemImageIndex( (nLo+nHi)/2, nCol );
// loop through the list until indices cross
while( nLo <= nHi )
{
// arrsRowText will hold all column text for one row
CStringArray arrsRowText;
// find the first element that is greater than or equal to
// the partition element starting from the left Index.
if( bAscending )
while( ( nLo < nHigh ) && (GetItemImageIndex(nLo, nCol) < nMidItem ) )
++nLo;
else
while( ( nLo < nHigh ) && (GetItemImageIndex(nLo, nCol) > nMidItem ) )
++nLo;
// find an element that is smaller than or equal to
// the partition element starting from the right Index.
if( bAscending )
while( ( nHi > nLow ) && (GetItemImageIndex(nHi, nCol) > nMidItem ) )
--nHi;
else
while( ( nHi > nLow ) && (GetItemImageIndex(nHi, nCol) < nMidItem ) )
--nHi;
// if the indexes have not crossed, swap
// and if the items are not equal
if( nLo <= nHi )
{
// swap only if the items are not equal
if(GetItemImageIndex(nLo, nCol) != GetItemImageIndex(nHi, nCol) )
{
// swap the rows
LV_ITEM lvitemlo = {0};
LV_ITEM lvitemhi = {0};
// Get the column count
int nColCount =
((CHeaderCtrl*)GetDlgItem(0))->GetItemCount();
arrsRowText.SetSize( nColCount );
// Load string array with text items of Lo row
int i;
for( i=0; i < nColCount; i++)
arrsRowText[i] = GetItemText(nLo, i);
// Setup Lo item structure
lvitemlo.mask = LVIF_IMAGE | LVIF_STATE;
// lParam only avail on col zero
if (nCol == 0)
lvitemlo.mask |= LVIF_PARAM;
lvitemlo.iItem = nLo;
lvitemlo.iSubItem = nCol; // 10/29/97 0;
lvitemlo.stateMask =
LVIS_CUT | LVIS_DROPHILITED |
LVIS_FOCUSED | LVIS_SELECTED |
LVIS_OVERLAYMASK | LVIS_STATEIMAGEMASK;
// duplicate to hi item except for iItem index
lvitemhi = lvitemlo;
lvitemhi.iItem = nHi;
lvitemhi.iSubItem = nCol; // 10/29/97
// get the current lo and hi items
GetItem( &lvitemlo );
GetItem( &lvitemhi );
// set item text of lo to item text of hi
for( i=0; i< nColCount; i++)
SetItemText(nLo, i, GetItemText(nHi, i) );
// save hi item
lvitemhi.iItem = nLo;
bRet = SetItem( &lvitemhi );
_ASSERTE(bRet);
// set item text of hi to item text of lo
for( i=0; i< nColCount; i++)
SetItemText(nHi, i, arrsRowText[i]);
// save lo item
lvitemlo.iItem = nHi;
lvitemhi.iSubItem = nCol; // 10/29/97
bRet = SetItem( &lvitemlo );
_ASSERTE(bRet);
}
++nLo;
--nHi;
}
}
// If the right index has not reached the left side of array
// must now sort the left partition.
if( nLow < nHi )
SortInImageOrder( nCol, bAscending , nLow, nHi);
// If the left index has not reached the right side of array
// must now sort the right partition.
if( nLo < nHigh )
SortInImageOrder( nCol, bAscending , nLo, nHigh );
return TRUE;
}