Sort columns by the image index of the column



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;
}

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read