A Multi Column Sort listview
Download Source Code and Example
This class handles sorting of multiple columns in a listctrl at the same time. The way it works is simple. When you click on a column, the column number is stored in an array, the array is cleared each time you click on a column without holding control. Telling the sort routine that only 1 column needs to be sorted. If you press control while clicking another column that second column is appended to the array and the columns are sorted in reverse order. Accomplishing a "subsort".
One other thing it does is save column widths for each instance of the listctrl. To acheive this though you must call SetUniqueName. Each instance needs a unique name to know where to save and retreive column widths.
Usage:
You generally should not use this class directly, though it is possible. You need to do two things to use it directly. Set m_strUniqueName to someting, and set m_strColumnWidthSection to where you want the column widths to be saved. m_strColumnWidthSection by default is set to "ColumnWidths".
The purpose of m_strUniqueName is to allow for saving of multiple instances of listview objects. So obviously you would need to set this differently for each instance. SetUniqueName must be called before calling InsertColumn() or LoadColumnWidths().
If you are deriving from this class, you need to do the following: Add a class to your project derived from CListView, then go into the header file and include MultiColumnSortListView.h and change all references to CListView to CMultiColumnSortListView. Then in the .cpp file of your class, change all the message maps to CMultiColumnSortListView instead of CListView. That should do it.
Functions you must call:
A sample CreateView:
< CMyListView is derived from CMultiColumnSortListView >
m_wndSplitter.CreateView( 0, 0, RUNTIME_CLASS( CMyListView ), CSize( 0, 200 ), pContext );
CMyListView *pView = (CMyListView *) m_wndSplitter.GetPane( 0, 0 );
pView->SetUniqueName( "MYVIEW1" );
Functions you dont need to call but may find useful:
- SetColumnNumeric:
This function tells the sorting routine that this column will contain only numeric data. It will not crash if there are string inside the column, it just wont sort them correctly.
CMyListView *pView = GetTheListView(); pView->SetColumnNumeric(2); pView->SetColumnNumeric(3); - IsSorting:
This function will tell you if the listctrl is in the middle of being sorted.
if( pView->IsSorting() ) MessageBox("Cannot sort, i am already sorting");
Miscellaneous utility functions are also provided:
- void CMultiColumnSortListView::DeleteAllColumns()
Utility function to get rid of all the columns
- void CMultiColumnSortListView::DeleteAllItems()
Utility function to get rid of all items.
- UINT CMultiColumnSortListView::GetColumnCount()
Utility function to get the number of columns written by Zafir Anjum
- const int CMultiColumnSortListView::IsControlPressed() const
Utility function to tell you if the control key is being pressed
- const SORT_STATE CMultiColumnSortListView::GetItemSortState( int iItem ) const
Utility function to get you the sort state of a column
- void CMultiColumnSortListView::SetItemSortState(int iItem, SORT_STATE bSortState)
Utility function to set the sort state of a column
- const int CMultiColumnSortListView::GetRegColumnWidth( int iColumn ) const
Utility function to look up a columns width in the registry.
- void CMultiColumnSortListView::AutoSizeAllColumns()
Utility function to Autosize all columns in the case there is no registry entry.
- void CMultiColumnSortListView::SetColumnWidth( int nCol )
Utility function to set the width on the column based on the registry value and a set minimum column width.
Most of the functions have very descriptive names.
Compiling:
One problem you will have is finding IDB_ARROWUP and IDB_ARROWDOWN. Those bitmaps will be included with this set of classes, You should add them to your project or add your own bitmaps named correctly. These are the bitmaps that show the sort order on the header control.
I hope this is simple enough, kind of a pain to get started but after that it should be cake and hopefully it will be useful.
Things to be aware of:
Multithreading:
If you delete all the items from another thread
in the middle of a sort, it will crash. This is the only
bug i have found.
Column Widths:
MINCOLWIDTH - Minimum width a column can be.
MAXCOLWIDTH - Maximum width a column can be.
These are hard coded in the header file. Be aware.
MAXCOLUMNS - The most columns you can have right now is 64, that is only because im using __int64 to hold the column sort states. Who needs more than 64 columns anyway? If you do, you can change it to CUIntArray, i just didnt see the need for a whole int when all i needed was a bit.
Credits:
- Iuri Apollonio -- Sorting Class ( great class )
- Zafir Anjum -- CMultiColumnSortListView::GetColumnCount
- Roger Onslow -- CMultiColumnSortListView::AutoSizeColumns
- Zafir Anjum -- CSortableHeaderCtrl::SetSortImage
- Me -- The Rest, I think.
Last updated: 12 July 1998

Comments
Does it works with ownerdata
Posted by Legacy on 12/18/2003 12:00amOriginally posted by: PoperoH
Is there a way to work it with ownerdata??
ReplyExcellant Class! Question about ListCtrl
Posted by Legacy on 05/15/2003 12:00amOriginally posted by: Charles M. Curtis Jr.
This Class is excellant and it works great. I would like to know if you can tell me. Is the ListCtrl a single list control or is it in fact two seperate ListCtrl's? If it is Seperate is there a way to Seperate them and use them independently of one another? I.E. is it possible to set one list with one set of data and the other with something different?
Thanks for any help and Thanks for a Great ListCtrl!
ReplyNeed the Same in VB
Posted by Legacy on 08/21/2002 12:00amOriginally posted by: Deepak
Hi,
ReplyCould you please tell where I can find similar control to use in VB6.0.
Regards
Deepak.
How do i Increase Height ?
Posted by Legacy on 06/11/2002 12:00amOriginally posted by: rivaldo
hi, how do i increase the Height of the each Row in the listctrl. how do i do that?
Replyany help .... or any source...
pl. help me..
Inserting subitems doesn't work
Posted by Legacy on 01/19/2001 12:00amOriginally posted by: Daniel Benmergui
When i try to add a subitem in the function OnUpdate
the subitems aren't drawn on screen...how can it be fixed?
Thanks.
ReplyDaniel.
Minor Bug and Warning Solution
Posted by Legacy on 09/13/2000 12:00amOriginally posted by: Ariel Benary
A truly great class!!
The Warning about SORT_STATE is solved easily, just fix the following line :
in SortColumn (multisort class) change :
csc.Sort(ssEachItem);
to :
csc.Sort(ssEachItem == DESCENDING);
Also, in DeleteAllItems the function should call
Replythe function DeleteAllItems of its base class, since
the current situation results in an endless recursion
Problem when setting HDS_FILTERBAR to header control
Posted by Legacy on 01/17/2000 12:00amOriginally posted by: Rob Davidson
ReplyA simple algorithm for sorting multiple columns
Posted by Legacy on 09/15/1999 12:00amOriginally posted by: Rick Shide
ReplyThere's a problem when the number of colums to sort exceds 2
Posted by Legacy on 08/27/1999 12:00amOriginally posted by: Nuno
When the number of columns exceds 2 the third one don't do nothing, neither sort ascending nor descending.
ReplyI will try to fix this problem, but if there's anyone that already do this please tell me.
A minor bug in function : MoveItemInCombinedSortedListToEnd
Posted by Legacy on 06/03/1999 12:00amOriginally posted by: Frank Chen
ReplyLoading, Please Wait ...