XListCtrl
The use of list controls is becoming very common now, and is used by many apps with the need for some sort of list display. I have used list controls in many projects, and naturally have developed my own classes to display different colors, fonts, and progress bars in list control.
Recently I needed a list control with a checkbox like Hotmail. With a list like Hotmail you have checkbox in column header, and checkboxes in each subitem in that column. To set a check in every subitem, you check the checkbox in the column header. Similarly, if you uncheck one of the subitems, then the checkbox in the column header also gets unchecked.
What's New in 1.6.1
New Features
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
|
![]() |
Please see the Revision History for more changes.
XListCtrl Features
The new CXListCtrl list control class supports these features:
- Text and background colors may be specified for each subitem.
- One or more subitem text may be displayed as normal or bold font.
- One or more subitems may be switched from displaying text to displaying a progress bar, and then back again to text.
- Custom text may be specified for progress bar, instead of just displaying usual 10%, 20%, etc. Also, there is option to display no text for progress bar, just the bar itself.
- One or more subitems may contain checkbox, with or without text.
- One or more subitems may contain combobox control.
- One or more subitems may contain edit control.
- One or more subitems may contain button.
- A row may be disabled, so that checkboxes are unclickable.
- All user input can be disabled.
- The header is displayed flat like Outlook.
- Alignment of subitems is independent of header.
XListCtrl Demo
The demo project provides a sample app that shows what the various features look like. Press the Start button and the list control is filled with data.

- Columns 1, 2, 3, 5, and 6 show header items with custom color (blue)
- The second column shows subitem with different background color
- The second column shows subitem with bold text
- The third column contains progress bar in row 2
- The fourth column shows header item with custom color (red)
- The fifth column shows subitem with different background color
- The sixth column contains buttons and text
- First column is specified with checkboxes
- The second column shows combobox
- The sixth row is disabled
- The fourth column also contains checkboxes
- The fifth column shows edit control
- The sixth column shows subitem with different text and background colors
How To Use
To integrate XListCtrl into your own app, you first need to decide if you want to include XListCtrl code into your own exe (using XListCtrl static link library), or if you want to link to XListCtrl DLL. Using DLL version of XListCtrl makes sense if you plan to use XListCtrl in several apps. The XListCtrl DLL is an MFC extension DLL, so your app must also be MFC-based.
If you plan to use and distribute DLL version of XListCtrl, do not put DLL in Windows directory. This could cause conflicts with other apps that use XListCtrl, and some future version of XListCtrl may not be compatible with the one that you distribute.
To use static XListCtrl library, define symbol XLISTCTRLLIB_STATIC before including header file XListCtrl.h. Otherwise, DLL version of XListCtrl will be linked to your app. Regardless of which version you link with, you must change your app's build environment as follows:
- Go to Project | Settings | C/C++ | Preprocessor and add the XListCtrl source directory to Additional include directories. Also, on the left side of the Settings dialog, choose All Configurations. Click OK to save this setting.

- Go to Project | Settings | Link | Input and add the XListCtrl library directory to Additional library path. Again, on the left side of the Settings dialog, choose All Configurations. Click OK to save this setting.

Automatic Library Selection
Using symbols _AFXDLL, XLISTCTRLLIB_STATIC, _DEBUG, and _UNICODE, the following code in XListCtrlLibDefs.h automatically determines which XListCtrl library to link to your app:
///////////////////////////////////////////////////////////////////////////////
// The first two letters of the library name specify the MFC/XListCtrl
// build configuration as follows:
// MFC MFC XListCtrl XListCtrl
// DLL Static DLL Static
// DD x x
// DS x x
// SS x x
// SD ----------- not provided -----------
//
// The third letter specifies Release/Debug.
// The fourth letter specifies ANSI/UNICODE.
///////////////////////////////////////////////////////////////////////////////
#ifndef XLISTCTRLLIB_NOAUTOLIB
#if defined _AFXDLL && !defined XLISTCTRLLIB_STATIC
// MFC shared DLL with XListCtrl shared DLL
#ifdef _UNICODE
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlDDDU.lib")
#pragma message("Automatically linking with XListCtrlDDDU.lib")
#else
#pragma comment(lib,"XListCtrlDDRU.lib")
#pragma message("Automatically linking with XListCtrlDDRU.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlDDDA.lib")
#pragma message("Automatically linking with XListCtrlDDDA.lib")
#else
#pragma comment(lib,"XListCtrlDDRA.lib")
#pragma message("Automatically linking with XListCtrlDDRA.lib")
#endif
#endif
#elif defined _AFXDLL && defined XLISTCTRLLIB_STATIC
// MFC shared DLL with XListCtrl static lib
#ifdef _UNICODE
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlDSDU.lib")
#pragma message("Automatically linking with XListCtrlDSDU.lib")
#else
#pragma comment(lib,"XListCtrlDSRU.lib")
#pragma message("Automatically linking with XListCtrlDSRU.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlDSDA.lib")
#pragma message("Automatically linking with XListCtrlDSDA.lib")
#else
#pragma comment(lib,"XListCtrlDSRA.lib")
#pragma message("Automatically linking with XListCtrlDSRA.lib")
#endif
#endif
#elif !defined _AFXDLL && defined XLISTCTRLLIB_STATIC
// MFC static lib with XListCtrl static lib
#ifdef _UNICODE
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlSSDU.lib")
#pragma message("Automatically linking with XListCtrlSSDU.lib")
#else
#pragma comment(lib,"XListCtrlSSRU.lib")
#pragma message("Automatically linking with XListCtrlSSRU.lib")
#endif
#else
#ifdef _DEBUG
#pragma comment(lib,"XListCtrlSSDA.lib")
#pragma message("Automatically linking with XListCtrlSSDA.lib")
#else
#pragma comment(lib,"XListCtrlSSRA.lib")
#pragma message("Automatically linking with XListCtrlSSRA.lib")
#endif
#endif
#else
#pragma message(" ")
#pragma message("--------------------------------------------------------------------------")
#pragma message(" The SD build configuration (MFC static, XListCtrl DLL) is not available. ")
#pragma message("--------------------------------------------------------------------------")
#pragma message(" ")
#error This build configuration is not available.
#endif
#endif
XListCtrl Library Naming Conventions
| XListCtrl Library Naming Conventions | ||||||||
|---|---|---|---|---|---|---|---|---|
| Library Name | MFC | XListCtrl | Build | Charset | ||||
| DLL | Static | DLL | Static | Debug | Release | ANSI | UNICODE | |
| XListCtrlDDDA | ||||||||
| XListCtrlDDDU | ||||||||
| XListCtrlDDRA | ||||||||
| XListCtrlDDRU | ||||||||
| XListCtrlDSDA | ||||||||
| XListCtrlDSDU | ||||||||
| XListCtrlDSRA | ||||||||
| XListCtrlDSRU | ||||||||
| XListCtrlSSDA | ||||||||
| XListCtrlSSDU | ||||||||
| XListCtrlSSRA | ||||||||
| XListCtrlSSRU | ||||||||
| XListCtrlSDxx | ——— not built ——— | |||||||
Building XListCtrl Libraries
To build the XListCtrl libraries, go to Build | Batch Build and select the libraries you wish to build:

Then click on Rebuild All and the libraries will be built. By default, the .lib and .dll files are copied to the bin directory.
Tips and Tricks
- TRACE output - TRACE output within XListCtrl is controlled via compiler directives in the file XListCtrlLib\StdAfx.h. To disable the TRACE output, comment out the following line:
#define ENABLE_XLISTCTRL_TRACE
- Checking the target - In a non-trivial application, it is easy to lose track of exactly what compiler options were used. Is it a Release build or Debug? Is it compiled for Unicode or Ansi?
Dependency Walker is a free tool that will quickly answer these questions and others you may have about the product you are building. When used to examine DialogDSRU.exe, this is what Depends shows:
The MFC80U shows that the app was compiled for Unicode (hence the U) and is a Release build (there is no D in the name). Here is what Depends shows for DialogDSDA.exe:
The MFC80D shows that the app was compiled for Ansi (there is no U) and is a Debug build (hence the D).
- Compiling - To compile XListCtrl, you will need the Platform SDK. Otherwise, you will get error for header files uxtheme.h and tmschema.h.
- Unicode vs. Ansi - The demo dialog application projects may be compiled for either Unicode or Ansi. In VS6, this is done by defining the preprocessor symbol
_UNICODE. In VS2005, this is done using a selection on the Properties | C/C++ | General tab:
The XListCtrl projects have the same setting.
Note that – for the dialog demos – you can choose between the Unicode and Ansi builds by using the combobox on the VS2005 toolbar:
- Rebuilding dialog demos - If you rebuild any of the dialog demos, be sure to use Rebuild All command. Reason: the dialog demos all share the same output file directories, and you will get linker errors if you compile only one module, and try to link with modules that were compiled with different set of build options.
- Eliminate flickering - When updating or filling the list control, there is sometimes flickering of list control and/or other controls on dialog. To eliminate this flickering, you may try one of the following methods:
- Use
CListCtrl::LockWindowUpdate()/CListCtrl::UnlockWindowUpdate()to bracket the updating code. - Use
CListCtrl::SetRedraw(FALSE)/CListCtrl::SetRedraw(TRUE)to bracket the updating code.
list.UpdateWindow()to make sure control is updated. If one method doesn't completely eliminate flickering in your application, try other method to determine which works best. - Use
- Using tooltips - You must first call
CListCtrl::EnableToolTips(TRUE). - Using combobox and edit controls - You must set
LVS_EX_FULLROWSELECTstyle. - Using buttons - Buttons require that the row height
be slightly larger than normal. To increase the row height, a 1-pixel wide
image list is created of the desired height. You can override this automatic
behavior by calling
SetItemHeight()yourself.Buttons can be used in any subitem, with or without adjacent text. When there is no adjacent text, the button will be centered. By convention, if there is adjacent text (set with
SetItemText()), the button will be right-aligned. The text itself defaults to the same alignment as the header; this can be overriden by usingSetSubItemAlignment().Normally buttons are sized automatically. Automatic width 
You can control the width of a button by using SetButton()(the fourth parameter is the button width), or by usingSetButtonWidth().Fixed width 
- Using edit boxes - If you use any edit boxes,
you must implement a handler for
LVN_ENDLABELEDIT. Otherwise, the default handler will return 0, meaning that the new text will be rejected. The simplest handler would be:void CMyDlg::OnEndlabeledit(NMHDR* pNMHDR, LRESULT* pResult) { *pResult = 1; // return 1 to accept new text, 0 to reject }The notification messagesLVN_BEGINLABELEDITandLVN_ENDLABELEDITwill always be sent by XListCtrl to its parent; you do not need to set theLVS_EDITLABELSstyle to receive these messages.Anytime after receiving
LVN_BEGINLABELEDITmessage, the parent can sendLVM_GETEDITCONTROLto retrieve theHWNDof the edit control. This can then be used to set additional edit styles, etc. In the demo dialog app, the edit styleES_UPPERCASEis set in theLVN_BEGINLABELEDIThandler. Using one of my favorite programming tools, HPS HwndSpy, I verified that the correctHWNDwas being returned, and also that the edit style was being set:
LVN_ENDLABELEDITwill always be sent to the parent when the edit box closes. If the user pressed the Esc key, or if the parent sent theLVM_CANCELEDITLABELmessage, thepszTextparameter will be NULL; otherwise, thepszTextparameter will not be NULL (however, the string itself may be empty, if the user erased the entry).The
WM_XLISTCTRL_EDIT_ENDmessage is also sent to the parent when the edit box closes, but only if the edit was not cancelled (by the user pressing the Esc key, or by the parent sending theLVM_CANCELEDITLABELmessage).In the demo dialog app,
LVM_CANCELEDITLABELis sent to XListCtrl whenever the subitem at (0,4) is edited. You can see the effect this has by looking at the log output:
If you are planning on using
LVM_CANCELEDITLABELin a VS6 project, you may have to include this line at the beginning of stdafx.h:#define _WIN32_WINNT 0x501
- Customizing the header - There are several
ways that the header can be customized. Here are the APIs that you can use:
EnableHeaderDividerLines()- show/hide divider lines between header itemsSetHeaderAlignment()- set the text alignment (left, center, right) for all header items. Normally, this is set toDT_DEFAULT, which means that the standard column alignment is used.SetHeaderSpacing()- Sets the column spacing. This is the spacing that precedes the text in a column header.SetHeaderItemTextColor(column, color)- Sets the text color for the specified columnSetHeaderItemTextColor(-1, color)- Sets the text color for all columns. This will be overridden ifSetHeaderItemTextColor()is subsequently used for a column.
Revision History
Version 1.6.3 Changes
- Added support for multi-line tooltips (they can now also be greater than 80 characters in length).
- Fixed crash when using scroll wheel to scroll up past top in a closed combobox.
- Fixed problem with horizontal scrolling.
Version 1.6.2 Changes
- Fixed problem with fast-clicking on combobox.
- Fixed problem with vertical scrolling and gridlines.
- Added VS2008 solution; now builds under VS6, VS2005, and VS2008; demo workspace included for each.
Version 1.6.1 Changes
- Fixed several problems with horizontal scrolling and gridlines.
Version 1.6 Changes
- Buttons - thanks to Gregory S Wright for sharing his button implementation.
- Can now set alignment of subitems independent of header.
- Set empty list message and text color; suggested by Allen Rossouw.
- Now builds under both VS6 and VS2005.
- Header now drawn with XP theming; requested by bambou51 and others.
- All checkboxes now drawn with XP theming using
DrawThemeBackground()function from uxtheme.dll. - Can specify color for all header text using
SetHeaderTextColor(), and also for each individual column usingSetHeaderItemTextColor(); requested by zacobi. - Fixed problem with subitem editing when scrolling with mouse wheel, reported by Whilibarj and Eric Jacobsen.
- Removed
GetCheckbox()and renamedGetItemCheckedState()toGetCheckedState(). - Renamed
SetItemCheckedState()toSetCheckedState(); renamed constantsXHEADERCTRL_NO_IMAGE, etc., toXLISTCTRL_NO_CHECKBOX, etc. - Clicking on a checkbox in the header will now generate
the same
WM_XLISTCTRL_CHECKBOX_CLICKEDmessage that is sent when clicking on a list control checkbox, except that thewParamparameter will be -1. ThelParamparameter is the column number (zero based). - New functions
SetAllowUserInput()andGetAllowUserInput()allow you to disable all user input (from buttons, checkboxes, combo, and edit boxes). This is a global setting and applies to all input. There is no visual indication that user input has been disabled. There are corresponding functions for the header control. This was suggested by Tom Watson. - New functions
SaveColumns()andLoadColumns()save and restore column widths. - Implemented notification messages
LVN_BEGINLABELEDITandLVN_ENDLABELEDIT. - Implemented
LVM_CANCELEDITLABELmessage. - Implemented
LVM_GETEDITCONTROLmessage. - Optimized clicking on a column with checkboxes, eliminating flicker from all columns except the one being updated.
- Modified
SetItemColors()to accept -1 for subitem number, meaning apply colors to all columns; suggested by simon heffer. - Added check if combobox exists before attempting to destroy it.
- Fixed orphan combobox when clicking fast.
- Fixed compile problem in AdvComboBox.cpp.
- Fixed compile problem with
CreateEx()function. - Fixed problem with gridlines disappearing in first column.
- Fixed compile errors cause by namespace std in AdvComboBox.
- Fixed problem with combobox leaking.
- Fixed sequence problem where message was being sent to parent before header was updated, reported by larryp.
- Added function
GetCheckboxCount(int nSubItem)to retrieve the number of checkboxes in a column (which may be different from number of items). - Fixed problem where number of items rather than number of checkboxes was being used to determine if header checkbox should be checked, reported by larryp.
- Fixed problem where edit box was not being deleted before a new one is created.
- Fixed problem when using on multiple monitors
- Modified
lParamfor the four registered messages that may be returned by XListCtrl:WM_XLISTCTRL_COMBO_SELECTIONWM_XLISTCTRL_CHECKBOX_CLICKEDWM_XLISTCTRL_EDIT_ENDWM_XLISTCTRL_BUTTON_CLICKED
wParamparameter, andlParamparameter contains subitem number in low order word, and list control ID in high order word.Example:
LRESULT CXListCtrlTestDlg::OnCheckbox(WPARAM wParam, LPARAM lParam) { int nItem = (int) wParam; int nSubItem = (int) LOWORD(lParam); UINT nID = HIWORD(lParam); TRACE(_T("nID=%d\n"), nID); VERIFY(nID == IDC_LIST);This change fixes a problem when there are multiple XListCtrl objects are on dialog. Previously, there was no simple way to determine which object sent message. Reported by simon heffer.INCOMPATIBILITY ALERT The above change to the lParam parameter may break existing code.
Version 1.5 Changes
Unreleased beta.Version 1.4 Changes
- Subitem editing - thanks to Oleg Matcovsky for providing code that I based this implementation on.
- New combo box implementation.
- Skip disabled items - fixed this bug, that allowed disabled item to be selected.
- Set header alignment, text color, and divider lines.
- Set cell padding.
- Reduced flickering.
- Header checkboxes do not require resource bitmap - the file checkboxes.bmp, is still included in download, but it is no longer really necessary.
- Enable ellipsis for text display.
- Get modified flag for subitems.
- More demo build configurations - 1.4 includes both DLL and static link build configurations, with 3 types of demo apps — dialogs, MDI, and property sheet — and 12 versions of the XListCtrl libraries, including both Unicode and ANSI.
- DLL and static library versions - beginning with this version, all XListCtrl code has been organized as libraries that you link with. Table below shows library versions available.
- Many bug fixes!
Version 1.3 Changes
This version includes many bug fixes that have been accumulating. My thanks for all who have reported bugs. Please try this new version and let me know if you find any bugs, or have suggestions for future enhancements.
- Added hot-tracking to combo's listbox.
- Added compile-time option to remove support for comboboxes. (This reduce exe size by about 8 Kb). To remove combobox support, put this line in stdafx.h:
#define DO_NOT_INCLUDE_XCOMBOLIST
If you insert this define, you do not need to include XComboList.cpp or XComboList.h in your project.
- Changed
CXComboList::SetActiveto accept scroll bar width as input parameter. - Fixed bug that caused string to not be displayed when clicking outside item string (reported by James Moore). This also caused problems in property pages and other places.
- Fixed bug that caused some strings not to be selected, when drag-selecting several items quickly (reported by James Moore).
- Fixed several problems with displaying images in header and list control (reported by Scot Brennecke).
- Changed message map macros for
NM_CLICKandLVN_COLUMNCLICKto useON_NOTIFY_REFLECT_EX(), to allow parent to handle message also (suggested by bkupcins). - Fixed problem in
XHeaderCtrlcaused when XP theming is enabled. TheGetHeaderCheckedState()/SetHeaderCheckedState()functions now use 0 = no check box, 1 = unchecked check box, 2 = checked check box. Note: The checkboxes.bmp file has also been updated, and must be replaced in all project that use 1.3XListCtrl. The new definesXHEADERCTRL_NO_IMAGE,XHEADERCTRL_UNCHECKED_IMAGE, andXHEADERCTRL_CHECKED_IMAGEshould be used when setting the image in the header control (see XListCtrlTestDlg.cpp for example). - Replaced calls to
GetSysColor()with class variables that are set in ctor. Class variables are reloaded in response toWM_SYSCOLORCHANGEmessage (suggested by KarstenK). - Added ASSERT if combo boxes are used without
LVS_EX_FULLROWSELECTstyle. - Added two registered messages that
XListCtrlwill send to its parent when combo box selection is changed (WM_XLISTCTRL_COMBO_SELECTION) and when check box is clicked (WM_XLISTCTRL_CHECKBOX_CLICKED). The sample app shows how to handle these new messages. - Added support for tooltips. To enable tooltips, you must call
CListCtrl::EnableToolTips(TRUE). If you #define constantNO_XLISTCTRL_TOOL_TIPS, the tooltip support will not be included. New API's for tooltips:BOOL SetItemToolTipText(int nItem, int nSubItem, LPCTSTR lpszToolTipText); CString GetItemToolTipText(int nItem, int nSubItem); void DeleteAllToolTips();
Version 1.2.1 Changes
- Added build configurations for Unicode.
- Minor code modifications to support Unicode strings.
Version 1.2 Changes
- Comboboxes!!! Now you can specify drop-list combobox for one or more subitem.
- Combobox will be drawn when item is highlighted. Demo now has item hot-tracking.
- Incorporated David Patrick's suggestion on how to subclass header control if
CXListCtrlis created dynamically via Create() instead of via dialog template. See XListCtrlTestDlg.cpp for details on how to convert the demo project to createCXListCtrldynamically. - Tweaked drawing of subitems to make cleaner visually.
- Added API's for
GetCurSelandSetCurSelto make coding easier.
Buy latest version
| Buy XListCtrl 1.6.6 license – $40.00 per developer |






