Click here to Skip to main content
15,896,542 members
Articles / Desktop Programming / MFC

CListCtrl and sorting rows

Rate me:
Please Sign up or sign in to vote.
4.43/5 (26 votes)
21 Aug 2008CPOL6 min read 134.6K   6.4K   63  
Examples of how to sort rows in the MFC list control.
#include "stdafx.h"

#include "CListCtrl_SortItems.h"

BEGIN_MESSAGE_MAP(CListCtrl_SortItems, CListCtrl)
	ON_NOTIFY_REFLECT_EX(LVN_GETDISPINFO, OnGetDispInfo)	// Text Callback
	ON_NOTIFY_REFLECT_EX(LVN_COLUMNCLICK, OnHeaderClick)	// Column Click
END_MESSAGE_MAP()

BOOL CListCtrl_SortItems::OnGetDispInfo(NMHDR* pNMHDR, LRESULT* pResult)
{
	NMLVDISPINFO* pNMW = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);
	int nItem = pNMW->item.iItem;
	int nSubItem = pNMW->item.iSubItem;

	if (nItem< 0 || nItem >= GetItemCount())
		return FALSE;	// requesting invalid item

	if (nSubItem < 0 || nSubItem >= GetHeaderCtrl()->GetItemCount())
		return FALSE;	// requesting invalid column

	int col = GetColumnData(nSubItem);
	size_t rowId = (size_t)GetItemData(nItem);

	if(pNMW->item.mask & LVIF_TEXT)
	{
		// Request text
		const string& result = m_DataModel.GetCellText(rowId, col);
		_tcsncpy(pNMW->item.pszText, result.c_str(), pNMW->item.cchTextMax);
	}

	return FALSE;	// Let parent-dialog get chance
}

namespace {
	struct PARAMSORT
	{
		PARAMSORT(const CListCtrl_DataModel& datamodel, int columnData, bool ascending)
			:m_DataModel(datamodel)
			,m_ColumnData(columnData)
			,m_Ascending(ascending)
		{}

		const CListCtrl_DataModel& m_DataModel;
		int  m_ColumnData;
		bool m_Ascending;
	};

	// Comparison extracts values from the DataModel
	int CALLBACK SortFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
	{
		PARAMSORT& ps = *(PARAMSORT*)lParamSort;

		const string& left = ps.m_DataModel.GetCellText((size_t)lParam1, ps.m_ColumnData);
		const string& right = ps.m_DataModel.GetCellText((size_t)lParam2, ps.m_ColumnData);

		if (ps.m_Ascending)
			return _tcscmp( left.c_str(), right.c_str() );	
		else
			return _tcscmp( right.c_str(), left.c_str() );					
	}
}

bool CListCtrl_SortItems::SortColumn(int columnIndex, bool ascending)
{
	if (GetItemCount()!=m_DataModel.GetRowIds())
		return false;

	int columnData = GetColumnData(columnIndex);
	PARAMSORT paramsort(m_DataModel, columnData, ascending);
	SortItems(SortFunc, (DWORD_PTR)&paramsort);
	return true;
}

void CListCtrl_SortItems::LoadData()
{
	if (GetHeaderCtrl()->GetItemCount()==0)
	{
		// Create Columns
		for(int col = 0; col < m_DataModel.GetColCount() ; ++col)
		{
			const string& title = m_DataModel.GetColTitle(col);
			VERIFY( InsertColumn(col, title.c_str(), LVCFMT_LEFT, 100) != -1 );
		}
	}
	else
	{
		// Empty list-control and force refresh
		DeleteAllItems();
		ResetSortOrder();
		Invalidate();
		UpdateWindow();
	}

	// Insert data with callback
	SetRedraw(FALSE);	// Disable redraw as InsertItem becomes so much faster
	int nItem = 0;
	for(size_t rowId = 0; rowId < m_DataModel.GetRowIds() ; ++rowId)
	{
		nItem = InsertItem(++nItem, "");	// Fastest to insert at the end
		VERIFY(nItem!=-1);
		VERIFY(SetItemData(nItem, rowId));
		for(int col = 0; col < m_DataModel.GetColCount() ; ++col)
		{
			VERIFY(SetItemText(nItem, col, LPSTR_TEXTCALLBACK));
		}
	}
	SetRedraw(TRUE);
	Invalidate();
	UpdateWindow();
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Denmark Denmark
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions