Sort List Control
Sort List Control
Introduction
First thing, I would like to apologize for any grammar/spelling mistakes in the article. Since English isn't my native language, I tend to do a lot of mistakes while typing.
CListViewCtrl
is a nice control, used mainly in report mode. You can see it filled with files when using Windows Explorer. The control also supports sorting mechanism using the SortItems
function. The main problem is that there is no sorting indicator.
Background
When looking at some articles at Code Project, you can find two solutions. The first solution is to provide two additional resources of bitmaps - indicating the arrows for the header control. The second solution is an owner drawn header control which is capable of drawing the appropriate arrow.
Why bother? How does Microsoft draw its arrows? How does Window Explorer draw itself?
Loading Bitmaps
After looking at some files, I found out the solution. There are two bitmaps, located in shell32.dll. The up arrow is 133, while the down arrow is 134.
To load the appropriate bitmap, we use the LoadImage
function. Since most of the applications link themselves to shell32.dll, we can use the GetModuleHandle
function to retrieve the module handle. If our application doesn't link itself to shell32.dll, we can use LoadLibrary
instead.
After loading the bitmaps, we can draw them on the header control just as we draw other bitmaps.
Sorting
To sort using the list control, we need to define a callback function. To avoid doing it manually, I've created a wrapper for a structure, which my list control can use.
Using the code
Since the report mode is some kind of a structure, we need to create our class to hold the relevant information. The class must inherit from CSortListViewCtrlItem
, and specify its class name as the template parameter. We will use a file structure which represents a single file:
class CFileStruct : public CSortListViewCtrlItem<CFileStruct>
{
public:
enum Field
{
Filename = 0,
Size,
Time
};
CFileStruct(LPCTSTR szFilename,ULONGLONG nSize,FILETIME ftTime);
int Compare(CFileStruct* pItem,int nField);
CString Format(int nField);
protected:
CString m_szFilename;
ULONGLONG m_nSize;
FILETIME m_ftTime;
};
The constructor initializes the structure, while the Format
function simply formats a specific field into a string.
The important function is Compare
. It compares the current structure with another one, depending on the specified field (you can check the implementation in maindlg.cpp).
Second, we need to create the list control object. The CSortListViewCtrl
is a template class which accepts the structure type as its parameter.
CSortListViewCtrl<CFileStruct> m_List;
To subclass the control, we can call SubclassWindow
or simply use the operator =
which wraps the subclassing method.
m_List=GetDlgItem(IDC_LIST1);
To make the control work, we need to create a new structure dynamically (using the new
operator), and attach the structure pointer to the list item using the SetItemData
function. We don't need to delete the structure, since the control will delete it automatically when handling the LVN_DELETEITEM
command.
The control should handle all sorting by itself. If you want to sort it by yourself, you can call the Sort
function.
To implement the control, you must follow these steps:
- Derive your own class from
CSortListViewCtrlItem
and implement theCompare
function. - Create the control object with your own structure as its template parameter, and subclass it to the original list window.
- Reflect notifications from the control's parent using the
REFLECT_NOTIFICATIONS
macro.
Sample application
The sample application creates a list control, and fills it with files from your Windows folder. You can sort the files by their name, size or time stamp. There is also a tooltip support which displays the entire information regarding a single file.
Final notes
The source code is provided as-is. You can use it freely and modify it as you want. If you release any application which uses it, I will appreciate getting an email from you (just for my ego :) ).