Sorting the list when user clicks on column header


If you dont want to allow the users to sort the list
by clicking on the header, you can use the style LVS_NOSORTHEADER. However,
if you do want to allow sorting, you do not specify the LVS_NOSORTHEADER.
The control, though, does not sort the items. You have to handle the HDN_ITEMCLICK
notification from the header control and process it appropriately. In the
code below, we have used the sorting function SortTextItems() developed
in a previous section. You may choose to sort the items in a different
manner.


Step 1: Add two member variables


Add two member variables to the CListCtrl. The first variable to track
which column has been sorted on, if any. The second variable to track if
the sort is ascending or descending.

       
int nSortedCol;


       
BOOL bSortAscending;


 


Step 2: Initialize them in the constructor.


Initialize nSortedCol to -1 to indicate that no column has been sorted
on. If the list is initially sorted, then this variable should reflect
that.

 

       
nSortedCol = -1;


       
bSortAscending = TRUE;


 


Step 3: Add entry in message map to handle HDN_ITEMCLICK


Actually you need to add two entries. For HDN_ITEMCLICKA and HDN_ITEMCLICKW.
Do not use the class wizard to add the entry. For one, you need to add
two entries whereas the class wizard will allow you only one. Secondly,
the class wizard uses the wrong macro in the entry. It uses ON_NOTIFY_REFLECT()
instead of ON_NOTIFY(). Since the HDN_ITEMCLICK is a notification from
the header control to the list view control, it is a direct notification
and not a reflected one.
    ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)

    ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)

 Note that we specify the same function for both the notification.
Actually the program will receive one or the other and not both. What notification
it receives will depend on the OS. The list view control on Windows 95
will send the ANSI version and the control on NT will send the UNICODE
version.

Also, note that the second argument is zero. This value filters for
the id of the control and we know that header control id is zero.


Step 4: Write the OnHeaderClicked() function


Heres where you decide what to do when the user clicks on a column header.
The expected behaviour is to sort the list based on the values of the items
in that column. In this function we have used the SortTextItems() function
developed in a previous section. If any of the columns displays numeric
or date values, then you would have to provide custom sorting for them.

 

void CMyListCtrl::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult) 
{
        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;
                SortTextItems( nSortedCol, bSortAscending );

        }
        *pResult = 0;
}

 

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read