Sort - worked example
key : purple - original code / blue - new code
Step 1 :
Continue with the program names.
Step 2 :
Give the columns names. Define these in the header. This makes working with the columns easier and more readable :
// column
order - remember to change column text
const
int COLUMN_TITLE = 1;
const int COLUMN_FIRST_NAME = 2;
const int COLUMN_SECOND_NAME = 0;
and in the original definition :
//
COLUMN_TITLE is a const int defined in the header
listColumn.iSubItem
= COLUMN_TITLE;
listColumn.pszText = arColumns[COLUMN_TITLE];
m_listCtrl.InsertColumn( COLUMN_TITLE, &listColumn );
listColumn.iSubItem = COLUMN_FIRST_NAME;
listColumn.pszText = arColumns[COLUMN_FIRST_NAME];
m_listCtrl.InsertColumn( COLUMN_FIRST_NAME, &listColumn );
listColumn.iSubItem = COLUMN_SECOND_NAME;
listColumn.pszText = arColumns[COLUMN_SECOND_NAME];
m_listCtrl.InsertColumn( COLUMN_SECOND_NAME, &listColumn );
and so on
Step 3 :
Add the LVN_COLUMNCLICK windows message handler to the ListCtrl :
void
CNameListView::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
*pResult = 0;
}
Step 4 :
Add bitwise constants for the combinations :
const
int TITLE_BIT = 1;
const int FIRST_NAME_BIT = 2;
const int SECOND_NAME_BIT = 4;
const int ASC_BIT = 8;
const int DESC_BIT = 16;
Step 6 :
Add new code to the OnColumnClick() function :
void
CNameListView::OnColumnClick(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
CListCtrl& m_listCtrl = GetListCtrl();
int nColumn = pNMListView->iSubItem;
UINT dwData;
// this is a good example of how the bit operator works!!!
static int nCountTitle = 1;
static int nCountFirstName = 1;
static int nCountSecondName = 1;
if( nColumn == COLUMN_TITLE )
{if(nCountTitle%2 == 1)
{dwData = TITLE_BIT | ASC_BIT;
}
else
{dwData = TITLE_BIT | DESC_BIT;
}
// increment this column count - reset the other column counts
nCountTitle++;
nCountFirstName = 1;
nCountSecondName = 1;}
if( nColumn == COLUMN_FIRST_NAME )
{if(nCountFirstName%2 == 1)
{dwData = FIRST_NAME_BIT | ASC_BIT;
}
else
{dwData = FIRST_NAME_BIT | DESC_BIT;
}
nCountFirstName++;
nCountTitle = 1;
nCountSecondName = 1;}
if( nColumn == COLUMN_SECOND_NAME )
{if(nCountSecondName%2 == 1)
{dwData = SECOND_NAME_BIT | ASC_BIT;
}
else
{dwData = SECOND_NAME_BIT | DESC_BIT;
}
nCountSecondName++;
nCountTitle = 1;
nCountFirstName = 1;}
m_listCtrl.SortItems( CompareFunction, dwData );
*pResult = 0;
}
Step 7 :
Add a function to sort the data in the columns :
vint
CALLBACK CNameListView::CompareFunction
(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
CName * pName1 = (CName *)lParam1;
CName * pName2 = (CName *)lParam2;
if( lParamSort & TITLE_BIT )
{CString strName1 = pName1->GetTitle();
CString strName2 = pName2->GetTitle();
if ( lParamSort & ASC_BIT)
return strcmp(strName1, strName2);
else
return strcmp(strName2, strName1);}
else if( lParamSort & FIRST_NAME_BIT )
{CString strName1 = pName1->GetFirstName();
CString strName2 = pName2->GetFirstName();
if ( lParamSort & ASC_BIT)
return strcmp(strName1, strName2);
else
return strcmp(strName2, strName1);}
else if( lParamSort & SECOND_NAME_BIT )
{CString strName1 = pName1->GetSecondName();
CString strName2 = pName2->GetSecondName();
if ( lParamSort & ASC_BIT)
return strcmp(strName1, strName2);
else
return strcmp(strName2, strName1);}
else
return 1;
}
Click here for the basic exercise
Click here for the source code
Click here to return to menu