Introduction

Microsoft's CListCtrl has support for displaying data in a grid using the report style, but one have to make several changes to implement features like:

This article will demonstrate a customized CListCtrl, which implements all the above features, while maintaining the Windows XP/Vista look.

screenshot.png

Background

There are lots of advanced grid controls that extend the CListCtrl, and one of those is the Enhanced List Control (CGfxListCtrl). This wonderful control provides all the above features, but fails to handle Windows XP and Vista. Finding a good replacement for this control is not very easy:

Want a CListCtrl that is using custom drawing (not owner drawing), and at the same time doesn't try to interfere with the normal item drawing. Hopefully such a CListCtrl will not be broken in case Microsoft extends their CListCtrl.

How to use the CGridListCtrlEx

The CGridListCtrlEx tries to stay true to the CListCtrl, and doesn't try replace anything the CListCtrl already provides. This means one can replace a CListCtrl with CGridListCtrlEx without needing to do anything more.

It is recommended that one doesn't use the CGridListCtrlEx directly, but makes one own class that inherits/derives from CGridListCtrlEx. This will make it easier to migrate any updates there will be to the CGridListCtrlEx class later.

Editing Cells/subitems

By default when inserting columns in the CGridListCtrlEx, then they will be configured as readonly without the ability to be edited. By using CGridListCtrlEx::InsertColumnTrait() then one can provide a CGridColumnTrait class which specifies what type of editor it should use.

    CGridColumnTrait* pTrait = new CGridColumnTraitEdit;
    m_ListCtrl.InsertColumnTrait(nCol, title.c_str(), LVCFMT_LEFT, 100, nCol, pTrait);

When having edited an item, then a standard LVN_ENDLABELEDIT message will be sent to the CListCtrl. When the CGridListCtrlEx receives this message it will automatically call the virtual method CGridListCtrlEx::OnTraitEditComplete(), allowing a derived class to validate the input and maybe update an underlying datamodel.

Editing cells/subitems with combo-box

By using CGridListCtrlEx::InsertColumnTrait() then one can also provide a CGridColumnTrait class which works as an ComboBox.

    CGridColumnTraitCombo* pTrait = new CGridColumnTraitCombo;
    pTrait->AddItem(0, "Hello");
    pTrait->AddItem(1, "Goodbye");
    m_ListCtrl.InsertColumnTrait(nCol, title.c_str(), LVCFMT_LEFT, 100, nCol, pTrait);

One can specify the items of the combo-box when inserting the columns (as shown above). If wanting to provide the combobox items dynamically, then one can override the CGridListCtrlEx::OnTraitEditBegin(), and then either use dynamic_cast<> or use the CGridColumnTraitVisitor to modify the items in the combobox.

Sorting rows

By default the GridListCtrlEx will have sorting enabled for all columns, where it will perform a simple text-comparison. If wanting more advanced sorting, then one can override the CGridListCtrlEx::SortColumn() method. Then it is just a matter of choosing the right way to perform the sorting. See CListCtrl and sorting rows.

Showing tooltip

By default the CGridListCtrlEx will just display the cell contents as tooltip. If wanting to display something different in the tooltip, then one can override the CGridListCtrlEx::GetCellTooltip() method.

Formatting cells/subitems

If wanting to change the foreground/background color or the font style (bold, italic, underline), then one can override the CGridListCtrlEx::GetCellCustomColor() and CGridListCtrlEx::GetCellCustomFont().

How does CGridColumnTrait work

CGridListCtrlEx tries to keep away from all the nasty details about how to display and edit data. Instead this is handled by the CGridColumnTrait class, and if wanting to modify how data is displayed, then it is "just" a matter of creating a new CGridColumnTrait class.

When inserting a column, then one can assign a CGridColumnTrait to the column. The CGridListCtrlEx will activate the appropriate CGridColumnTrait when needing to draw a cell in that column, or edit a cell in the column.

The CGridColumnTrait includes some special members known as meta-data. These members can be used by your own class when it derives from CGridListCtrlEx, so one can easily add extra properties to a column.

When inheriting from CGridColumnTrait, then one must consider the following:

Using the code

The source code includes the following classes:

Things to do

The CGridListCtrlEx is not quite finished, as it still lacks some features:

Only the group-style handling should be part of the CGridListCtrlEx itself, while the other features should be handled with new specialized CGridColumnTrait's.

History