Sort list (numeric/text/float/date) using callback
Posted
by Max Poliashenko
on August 6th, 1998
////////////////////////////////////////////////////////////////////////
////////
// by Max Poliashenko - rewritten version of class proposed by Iuri Applonio
// This class will sort a List control by a column of text, integer, float or
// date/time type. It could be easily extended for other data types.
// February 11, 1998
//
class CSortClass
{
public:
enum EDataType {dtNULL, dtINT, dtSTRING, dtDATETIME, dtDEC};
CSortClass(CListCtrl * _pWnd, const int _iCol);
virtual ~CSortClass();
void Sort(bool bAsc, EDataType _dtype);
protected:
CListCtrl * pWnd;
static int CALLBACK Compare(LPARAM lParam1, LPARAM lParam2, LPARAM
lParamSort);
struct CSortItem
{
CSortItem(const DWORD _dw, const CString &_txt);
DWORD dw;
CString txt;
};
};
////////////////////////////////////////////////////////////////////////
/////
// CSortClass
CSortClass::CSortClass(CListCtrl * _pWnd, const int _iCol)
{
pWnd = _pWnd;
ASSERT(pWnd);
int max = pWnd->GetItemCount();
DWORD dw;
CString txt;
// replace Item data with pointer to CSortItem structure
for (int t = 0; t < max; t++)
{
dw = pWnd->GetItemData(t); // save current data to restore it later
txt = pWnd->GetItemText(t, _iCol);
pWnd->SetItemData(t, (DWORD) new CSortItem(dw, txt));
}
}
CSortClass::~CSortClass()
{
ASSERT(pWnd);
int max = pWnd->GetItemCount();
CSortItem * pItem;
for (int t = 0; t < max; t++)
{
pItem = (CSortItem *) pWnd->GetItemData(t);
ASSERT(pItem);
pWnd->SetItemData(t, pItem->dw);
delete pItem;
}
}
void CSortClass::Sort(bool _bAsc, EDataType _dtype)
{
long lParamSort = _dtype;
// if lParamSort positive - ascending sort order, negative - descending
if (!_bAsc)
lParamSort *= -1;
pWnd->SortItems(Compare, lParamSort);
}
int CALLBACK CSortClass::Compare(LPARAM lParam1, LPARAM lParam2, LPARAM
lParamSort)
{
CSortItem * item1 = (CSortItem *) lParam1;
CSortItem * item2 = (CSortItem *) lParam2;
ASSERT(item1 && item2);
// restore data type and sort order from lParamSort
// if lParamSort positive - ascending sort order, negative - descending
short sOrder = lParamSort < 0 ? -1 : 1;
EDataType dType = (EDataType) (lParamSort * sOrder); // get rid of sign
// declare typed buffers
COleDateTime t1, t2;
switch (dType)
{
case EDataType::dtINT:
return (atol(item1->txt) - atol(item2->txt))*sOrder;
case EDataType::dtDEC:
return (atof(item1->txt) < atof(item2->txt) ? -1 : 1)*sOrder;
case EDataType::dtDATETIME:
if (t1.ParseDateTime(item1->txt) && t2.ParseDateTime(item2->txt))
return (t1 < t2 ? -1 : 1 )*sOrder;
else
return 0;
case EDataType::dtSTRING:
return item1->txt.CompareNoCase(item2->txt)*sOrder;
default:
ASSERT("Error: attempt to sort a column without type.");
return 0;
}
}
CSortClass::CSortItem::CSortItem(const DWORD _dw, const CString & _txt)
{
dw = _dw;
txt = _txt;
}
==========================================================================
Here is its usage:
void CMyDlg::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
{
static int nSortedCol = -1;
static bool bSortAscending = true;
HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
if( phdn->iButton == 0 )
{
// User clicked on header using left mouse button
if( phdn->iItem == nSortedCol )
bSortAscending = !bSortAscending;
else
bSortAscending = TRUE;
nSortedCol = phdn->iItem;
CSortClass csc(&m_List, nSortedCol);
csc.Sort(bSortAscending, (CSortClass::EDataType)
m_arrColType[nSortedCol]);
}
*pResult = 0;
}
Posted: March, 8, 98
Comments:
- Fantastic! Thanks a million! - Darshan (2003/10/20)
- OnHeaderClicked with RightMouse? - Georg Lensing (2003/09/09)
- Very good code , it's work perfect - Pavel (2003/01/08)
- Compilation Error - Jorge Santos (2002/06/04)
- Help Please!! Using this class with the ReportCtrl by Maarten Hoeben - Jamie Adams (2001/12/14)
- Extact code to get GfxListCtrl.cpp to work - Scott McCulley (2000/09/27)
- Leaving out OnGetDispInfo - Eric Schmidt (1999/12/01)
- Thanks + Question about HD_NOTIFY - Mark Sherman (1999/10/14)
- Text then Image? - Franky (1999/05/21)
- m_arrColType array - Maxim Poliashenko (1999/03/03)
- Sort list (numeric/text/float/date) using callback - Mike Albright (1999/02/26)
- Nice - Gregory Goeppel (1999/01/13)
- A word about differences from this and my article .. - Iuri Apollonio (1998/09/24)

Comments
Elegant work
Posted by turkim on 11/20/2010 05:21pmThanks for your effort .. you really saved me days of work. And thanks also to hanhao who gave us a big help.
Replysolving problem with m_arrColType
Posted by hanhao on 07/05/2005 12:49amafter tons of researching the code and checking it out, i found the correct solution http://www.codeguru.com/forum/showthread.php?p=1186557#post1186557 [CODE]// SortClass.h: interface for the CSortClass class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_SORTCLASS_H__C4FFD42B_9BC4_4084_AA1C_DAA42CDCC697__INCLUDED_) #define AFX_SORTCLASS_H__C4FFD42B_9BC4_4084_AA1C_DAA42CDCC697__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 class CSortClass { public: enum EDataType {dtNULL, dtINT, dtSTRING, dtDATETIME, dtDEC}; CSortClass(CListCtrl * _pWnd, const int _iCol); virtual ~CSortClass(); void Sort(bool bAsc, EDataType _dtype); EDataType m_arrColType[200]; [COLOR=DarkOrange]THIS IS CORRECT![/COLOR] protected: CListCtrl * pWnd; EDataType m_arrColType[200]; [COLOR=Sienna]THIS IS WRONG[/COLOR] static int CALLBACK Compare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort); struct CSortItem { CSortItem(const DWORD _dw, const CString &_txt); DWORD dw; CString txt; }; }; #endif // !defined(AFX_SORTCLASS_H__C4FFD42B_9BC4_4084_AA1C_DAA42CDCC697__INCLUDED_)[/CODE]
-
Reply(2) solving problem with m_arrColType
Posted by hanhao on 07/05/2005 12:51amhttp://www.codeguru.com/forum/showthread.php?p=1186557#post1186557
ReplyWHAT IS m_arrColType!?!??
Posted by hanhao on 06/23/2005 03:17pmWHAT IS m_arrColType!?!??
Reply