Sorting the list when user clicks on column header


Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame

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;
                        bSortAscending = TRUE;

                nSortedCol = phdn->iItem;
                SortTextItems( nSortedCol, bSortAscending );

        *pResult = 0;


  • The HDN_ITEMCLICK is not sent to the CMyListCtrl, why?

    Posted by cwgk_zc on 07/02/2006 10:45pm

    I do it following the steps above. I derive a class CMListCtrl from CListCtrl and then go as the steps. At last, I declare a variable CMyListCtrl m_list which is from resource. I insert three columns but when I click the headers, nothing happened. Can anyone tell me the reason? If send me the source code, this is very good.

    • It's sent to the parent (us. a dialog) instead

      Posted by Mr. X on 10/03/2007 06:36pm

      The notification is sent to the parent - usually a dialog. You'll need to read up on the reflection mechanism (the MFC one, not the .NET one).

  • SortTextItems?

    Posted by mathieu1975 on 05/01/2006 08:46pm

    What is the SortTextItems doing? how do you sort the list? (manually? do a predefined method exist already?)

    • SortTextItems

      Posted by Mr. X on 10/04/2007 03:41pm

      I just call my method RefreshList(), which I use in several places.  It does the following:
      1. creates a Clist of any selected items
      2. Clears the CListCtrl
      3. Requests & populates list data afresh
      4. Uses the CList from 1. to restore the selected items
      5. Calls my method - SortList()
      SortList() is just a switch which sets a function pointer to the appropriate compare-function to sort based on the selected column.  It then calls CListCtrl::SortItems - the CListCtrl's built-in sort method:
      void CMyDlg::SortList()
      	PFNLVCOMPARE pfnCompare = NULL;	// Pointer to compare function
      	switch( m_nSortedCol )
      	case COLUMN_PROMPT_ID:		// Sort by ID
      		pfnCompare = CMyDlg::CompareIds;
      	case COLUMN_PROMPT_NAME:	// Sort by file name
      		pfnCompare = CMyDlg::CompareNames;
      	case COLUMN_PROMPT_TIME:	// Sort by date-time
      		pfnCompare = CMyDlg::CompareTimes;
      	m_ctrListFailedPrompts.SortItems( pfnCompare, (LPARAM)this );

  • Nice and Simple.Great!!!

    Posted by Legacy on 12/12/2003 08:00am

    Originally posted by: Danushka Menikkumbura

    This helped me a lot.Nice work.Thanks a lot.

  • It worked! Thank you!

    Posted by Legacy on 06/04/2003 07:00am

    Originally posted by: zhangyi

    int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort);



    BEGIN_MESSAGE_MAP(CListSort, CListCtrl)
    // NOTE - the ClassWizard will add and remove mapping macros here.
    ON_NOTIFY(HDN_ITEMCLICKA, 0, OnHeaderClicked)
    ON_NOTIFY(HDN_ITEMCLICKW, 0, OnHeaderClicked)


    // CListSort message handlers
    void CListSort::OnHeaderClicked(NMHDR* pNMHDR, LRESULT* pResult)
    HD_NOTIFY *phdn = (HD_NOTIFY *) pNMHDR;
    if( phdn->iButton == 0 )
    if( phdn->iItem == m_nSortedCol )
    m_fAsc = !m_fAsc;
    m_fAsc = TRUE;
    m_nSortedCol = phdn->iItem;
    SortItems( ListCompare, (DWORD)this );

    typedef struct tagNMHEADER{
    NMHDR hdr;
    int iItem;
    int iButton;
    HDITEM FAR* pItem;}
    NMHDR structure that contains information about the notification message.
    Zero-based index of the header item that is the focus of the notification message.
    Index of the mouse button used to generate the notification message. It is one of the following values:
    int CALLBACK ListCompare(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
    CListSort* pV=(CListSort*)lParamSort;
    DEMO_DATA* pInfo1=strAllData+lParam1;
    DEMO_DATA* pInfo2=strAllData+lParam2;
    CString szComp1,szComp2;
    int iCompRes;
    if(pInfo1->iAge == pInfo2->iAge)iCompRes = 0;
    iCompRes=(pInfo1->iAge < pInfo2->iAge)?-1:1;
    return iCompRes;
    return iCompRes*-1;

  • Thanx for the Info....very helpful

    Posted by Legacy on 05/14/2003 07:00am

    Originally posted by: Vikas Hegde

    Thank you Zafir...The callback function gave me problems....This saved a lot of my time.A very useful aricle.

  • Anyone got a work around for this to work with Integer columns

    Posted by Legacy on 04/25/2003 07:00am

    Originally posted by: LizardKing

    This works great for String or Character based columns however numeric based columns get sorted incorrectly ( I know that this was pointed out in article) - Just wondering has anyone modified it to work on Integer based columns and if so , could they share the knowledge :)



  • Thanks a lot!

    Posted by Legacy on 04/10/2003 07:00am

    Originally posted by: Ligh56t

    It's a good idea to make a message entry by myself.
    Thank you to let me know that
    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.

  • dang

    Posted by Legacy on 10/09/2002 07:00am

    Originally posted by: amit gupta

    its very good but we want complete FAQ in a proper sequence

  • It Worked

    Posted by Legacy on 07/29/2002 07:00am

    Originally posted by: Sheethal Shneoy

    Thanks Zafirji,Works absolutel fine.

  • Thanks. But This sample only sort the ListView or ListCTrl by char .not Integer data.

    Posted by Legacy on 04/09/2002 07:00am

    Originally posted by: WilliamXu


  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date