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



Comments

  • bug

    Posted by lincolnfz on 01/13/2006 03:17am

    I have use this code in my program. I found some bugs in this code. If I only have one image type in listctrl it cant sort.

    Reply
  • Bug Report

    Posted by Legacy on 02/07/2002 12:00am

    Originally posted by: eric_chenwei

    I have use this code in my program. I found some bugs in this code. If I only have one image type in listctrl it cant sort.

    Reply
Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Live Event Date: April 22, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Database professionals — whether developers or DBAs — can often save valuable time by learning to get the most from their new or existing productivity tools. Whether you're responsible for managing database projects, performing database health checks and reporting, analyzing code, or measuring software engineering metrics, it's likely you're not taking advantage of some of the lesser-known features of Toad from Dell. Attend this live …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds