|
<ul class="download"><li>
<a href="CListCtrl_ToolTip/ListCtrl_Tooltip.zip">Download source code - 200 KB</a>
</li></ul>
<h2>Introduction</h2>
<p>Microsoft's <code>CListCtrl</code> has support for displaying data in a grid,
but also supports grouping of data. This article will demonstrate how we can
activate the grouping functionality of <code>CListCtrl</code>.</p>
<p>The demo application allows you to experience the how grouping can be used. Just
right-click a column header, to group the data according to that header. </p>
<p><img height="254" width="471" alt="screenshot.png" src="CListCtrl_Grouping/screenshot.png" /></p>
<h2>Background</h2>
<p>Microsoft extended the <code>CListCtrl</code> with support for grouping with the release of
Windows XP, the new feature wasn't promoted that much and was also limited in
functionality (No collapsing of groups). The implementation was later extended
with more functionality when Windows Vista was released (Collapsing, Footer,
Subtitle and more).</p>
<p>
There are already some .NET articles describing how to use grouping in Windows
XP:</p>
<ul><li>
<a href="../../KB/list/GroupListView.aspx">ListView Grouping
XP Style</a>
</li><li>
<a href="../../KB/list/GroupableListView.aspx">Groupable
ListView</a></li></ul>
<p>There is also <a title="MSDN Magazine August 2007" href="http://msdn.microsoft.com/en-us/magazine/cc163384.aspx">
MSDN - Windows Vista Control Enhancements</a>, which describes some of the
new stuff in Windows Vista.
</p>
<p>The first time I actually saw an useful application make use of this grouping
feature was with <a href="http://tortoisesvn.tigris.org/tsvn_1.5_releasenotes.html#changelist-support">
TortoiseSVN 1.5</a>.</p>
<h2>How to activate grouping in CListCtrl</h2>
<p>Before grouping can be activated, then some things has to be in order:</p>
<ul><li>
The operating system must support common controls ver. 6 (Windows XP/Vista and
newer)
</li><li>
The application must enable common controls ver. 6 through its manifest
</li><li>
The application must be compiled with <code>_WIN32_WINNT</code> set to at least <code>0x0501</code></li></ul>
<p>When the above requirements are met, then one can create group like this:</p>
<pre lang="C++">LRESULT CListCtrl_Category_Groups::CreateSingleGroup(int nIndex, int nGroupId, const CString& strHeader)
{
EnableGroupView( TRUE );
LVGROUP lg = {0};
lg.cbSize = sizeof(lg);
lg.iGroupId = nGroupId;
lg.state = LVGS_NORMAL;
lg.mask = LVGF_GROUPID | LVGF_HEADER | LVGF_STATE | LVGF_ALIGN;
lg.uAlign = LVGA_HEADER_LEFT;
// Header-title must be unicode (Convert if necessary)
lg.pszHeader = strHeader.GetBuffer();
lg.cchHeader = strHeader.GetLength();
nGroupId = InsertGroup(nIndex, &lg );
if (nGroupId==-1)
return nGroupId;
// Insert all current items into this group
for(int nRow = 0; nRow < GetItemCount(); ++nRow)
{
LVITEM lvItem = {0};
lvItem.mask = LVIF_GROUPID;
lvItem.iItem = nRow;
lvItem.iSubItem = 0;
lvItem.iGroupId = nGroupID;
return SetItem( &lvItem );
}
}
</pre>
<p>
The above example code create a new group with the following properties:</p>
<ul><li>
The group will be inserted at <code>nIndex</code> in the <code>CListCtrl</code> internal list of groups.
</li><li>
The group will get the external identifier <code>nGroupId</code>.
</li><li>
The group headline will become the text-string <code>strHeader</code>.</li></ul>
<h2>Limititations in Windows XP</h2>
<p>When working with groups on Windows XP, then one will discover the following is
missing:</p>
<ul><li>
It is not possible to ask how many groups there are in the <code>CListCtrl</code> internal
list of groups. Instead it is recommended to keep track of the created groups
ourselves.
</li><li>
It is not possible to iterate over the groups in the <code>CListCtrl</code> internal list of
groups. Instead it is recommended to keep track of the created groups
ourselves.
</li><li>
It is not possible to ask the <code>CListCtrl</code> if the mouse cursor is currently over a
group. Instead one have to do a lot of guessing.
</li><li>
It is not possible to change the group state, so it become collapsed.</li></ul>
<p>These limitations have been solved with Windows Vista, and at the same time the
following features have been added:</p>
<ul><li>
Can attach a task-link to the group,
</li><li>
Can provide a subtitle-text that is placed just below the header-text
</li><li>
Can provide a footer-text to the group</li></ul>
<h2>Using the source code</h2>
<p>The source code provided demonstrates how to activate the different grouping
features:</p>
<ul><li>
<strong><code>InsertGroupHeader()</code></strong> - Creates a new group. Wrapper around
<code>CListCtrl::InsertGroup()</code>.
</li><li>
<strong><code>SetRowGroupId()</code></strong> - Adds a row to an existing group. Wrapper around
<code>CListCtrl::SetItem()</code> with <code>LVIF_GROUPID</code>.
</li><li>
<strong><code>GroupByColumn(int nCol)</code></strong> - Creates a new group for each unique cell text in the
specified column.
</li><li>
<strong><code>SortColumn(int nCol)</code></strong> - Sorts the groups generated from the specified column.
Wrapper around <code>CListCtrl::SortGroups()</code>. </li><li>
<strong><code>GroupHitTest(const CPoint& point)</code></strong> - Attempts to find the group below the
given mouse point.
</li><li>
<strong><code>CheckEntireGroup()</code></strong> - When having the <code>CListCtrl</code> extended style <code>LVS_EX_CHECKBOXES</code>
enabled, then this method will change the check box state of an entire
group. </li></ul>
<p>It also demonstrates how to use some of the new Windows Vista features:</p>
<ul><li>
<strong><code>CollapseAllGroups()</code></strong> - Loops through all the groups and makes them collapse.
Wrapper around <code>CListCtrl::SetGroupInfo()</code> with <code>LVGS_STATE</code>.
</li><li>
<code><strong>SetGroupTask()</strong></code><strong></strong> - Changes the task-link of a group. When the user clicks the
task link then it will generate a <code>LVN_LINKCLICK</code> message.
</li><li>
<code><strong>SetGroupSubtitle()</strong></code><strong></strong> - Changes the subtitle of a group.
</li><li><strong>
</strong><code><strong>SetGroupFooter()</strong></code> - Changes the footer of a group.</li></ul>
<h2>History</h2>
<ul><li>
<strong>2008-09-16</strong> - First release of the article.</li></ul>
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.