Click here to Skip to main content
15,883,623 members
Articles / Desktop Programming / MFC
Article

CReportCtrl - An extremely convenient version of report-style CListCtrl

Rate me:
Please Sign up or sign in to vote.
4.79/5 (38 votes)
4 May 20032 min read 258.6K   4.6K   97   42
An MFC CListCtrl derived class specialized in report-style list control manipulation.

Sample Image - CReportCtrl.gif

Introduction

The "report-style" list control is commonly used in various situations, although we can directly use the MFC CListCtrl class and specify it with LVS_REPORT style, but if you ask me, that's just not enough.

First of all, it's sort of inconvenient to use, especially when you need to move a particular item up or down, or swap two items, or do something like "invert selection", you will have to write quite some lines of code. Also, CListCtrl member method SetItemText only accepts string values, which could be burdensome since you must convert every data into string first.

Second, CListCtrl lacks of some necessary features which it really should have had. Item sorting by clicking on column headers, for instance, is always a must in most report-style list controls, yet we need to write our own code, quite complicated code, to achieve it. Another example is "item data", we often use heap pointers as item data in order to associate the list items with some real structures. In that case, it is crucial to remember to cleanup before deletion of any item, because we may not have a chance after an item is deleted. Wouldn't it be nice if there is a call back function which is automatically called when an item is about to be deleted from the list control, regardless of which and when?

Alright, let's take a look at what we can have. CReportCtrl, is an MFC CListCtrl derived class specialized in the report-style list control manipulation. A bunch of methods are implemented or overloaded in this class in order to provide fast, efficient and convenient access and operations. I say this class is all about convenience.

Features

It is no more necessary to convert all other data types into character strings before using SetItemText because this method has been overloaded for all common data types, with precision of float/double numbers being taken into account.

Using heap pointers as list item data has become safer since the user defined CALLBACK function BOOL (*) (DWORD, LPARAM) will be called every time before a list item is actually deleted. Therefore you can perform the cleanup period to the deletion of each item, or abort the deletion anytime during the process of DeleteAllItems if you feel things go wrong.

Item sorting is implemented, the comparing function will figure out how to compare your items according to how the particular sub item texts look like, being those in numeric, string, or date time formats. Your end user simply clicks on list header columns and all items will be sorted in desired manner.

Item selection/unselection, checking/unchecking, and repositioning are extensively implemented for sheer convenience.

Public methods

The CALLBACK function

// The callback function which is
// optionally defined by you, the programmer.
// A very common useage of this function
// is to free item data if they are heap
// pointers, before each list item is deleted.
// The item data will be passed in as
// the first parameter.
// You may return FALSE if you want to
// abort the deletion of current item, if you
// want to proceed, you must return TRUE.

typedef BOOL (CALLBACK *ITEMDATAPROC)(DWORD, LPARAM);

Column attributes & operations

int GetColumnCount() const; // Get the column count.
// Set columns and their formats.
BOOL SetHeadings(UINT uiStringID); 
// Set columns and their formats.
BOOL SetHeadings(const CString& strHeadings); 
// How to use "SetHeadings":
// "strHeadings" can be the following format:
// "column_name, format, width; column_name, format, width; ...", where: 
// "column_name" is the title of the column.
// "format" is format of the column(0=LVCFMT_LEFT,
// 1=LVCFMT_CENTER, 2=LVCFMT_RIGHT),  if you don't specify a format,
// it will be LVCFMT_LEFT by default.
// "width" is width of that column, in pixels.
// For example,
// SetHeadings(_T("ID, 1, 75; Name, 100; Salary, 2, 60"));
// will make the CreportCtrl have 3 columns,
// the first column is "ID" with LVCFMT_CENTER format
// and 75 pixels wide, the second column is "Name" with
// LVCFMT_LEFT format and 100 pixels wide, the third column is
// "Salary" with LVCFMT_RIGHT format and 60 pixels wide.
int InsertColumn(int nCol, const LVCOLUMN* pColumn); // Insert a new column
int InsertColumn(int nCol, LPCTSTR lpszColumnHeading, 
  int nFormat = LVCFMT_LEFT, int nWidth = -1, int nSubItem = -1); 
BOOL DeleteColumn(int nCol); // Delete a column
BOOL DeleteAllColumns(); // Delete all columns.

Item attributes & operations

// List style operation
void SetGridLines(BOOL bSet = TRUE); // Show grid lines.
void SetFullRowSelect(BOOL bSet = TRUE); // Use full row selection style.
void SetCheckboxes(BOOL bSet = TRUE); // Show checkboxes.
  
// Selection related

// Is item selected?
BOOL IsItemSelected(int nItem) const; 
// How many items are selected?
int GetSelectedItemCount() const; 
// How many items are not selected?
int GetUnselectedItemCount() const; 
// Index of the first selected item.
int GetFirstSelectedItem(int nStartAfter = -1) const; 
// Index of the first unselected item.
int GetFirstUnselectedItem(int nStartAfter = -1) const; 
// Select an item.
BOOL SelectItem(int nItem, 
  BOOL bSelectAdjacentIfNotAvailable = FALSE); 
// Unselect an item.  
BOOL UnSelectItem(int nItem); 
// Select all items.
BOOL SelectAllItems(); 
// Unselect all items.
BOOL UnSelectAllItems(); 
// Unselect all selected items,
// and select those were not. 
BOOL InvertSelect(); 

// Checkbox related

// Is item checked?
BOOL IsItemChecked(int nItem) const; 
// How many items are checked?
int GetCheckedItemCount() const; 
// How many items are not checked?
int GetUncheckedItemCount() const; 
// Index of the first checked item.
int GetFirstCheckedItem(int nStartAfter = -1) const; 
// Index of the first unchecked item. 
int GetFirstUncheckedItem(int nStartAfter = -1) const; 
// Check an item.
BOOL CheckItem(int nItem); 
// Uncheck an item.
BOOL UnCheckItem(int nItem); 
// Check all items.
void CheckAllItems(); 
// Uncheck all items.
void UnCheckAllItems(); 
// Uncheck all checked items, and check those were not.
void InvertCheck(); 
// Item Insertion 
int InsertItem(UINT nMask, int nItem, 
      LPCTSTR lpszItem, UINT nState, 
      UINT nStateMask, int nImage, LPARAM lParam);
int InsertItem(int nItem, LPCTSTR lpszItem, int nImage);
int InsertItem(const LVITEM* pItem);
int InsertItem(int nIndex, LPCTSTR pszText, ...); 
// How to use "InsertItem(int nIndex, LPCTSTR pszText, ...)":
// Take the same example we used to demonstrate "SetHeadings", if we use:
// InsertItem(INT_MAX, _T("001"), _T("John Smith"), _T("52000.00"));
// We are appending(inserting at the last) a new item
// into this CReportCtrl, item text of the first column(ID)
// is "001", item text of the second column(Name)
// is "John Smith", item text of the
// third column(Salary) is "52000.00".
// Item Deletion
// Note: if the item data are heap pointers,
// make sure to free them before calling
// any item deletion methods, or define and pass in callback function
// "ITEMDATAPROC" and do the memory cleanup within.
BOOL DeleteItem(int iItem, BOOL bSelectNextItem = FALSE, 
  ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); // Delete an item.
// Delete all items. Returns number of
// items those are actually deleted.
int DeleteAllItems(ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); 
// Delete all selected items.  
int DeleteAllSelectedItems(ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); 
int DeleteAllUnselectedItems(ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); // Delete all unselected items. 
int DeleteAllCheckedItems(ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); // Delete all checked items.
int DeleteAllUncheckedItems(ITEMDATAPROC lpFunc = NULL, 
  LPARAM lParam = NULL); // Delete all unchecked items.
 
// Item position related 

// Swap two items in the list,
// including texts and item data.
BOOL SwapItems(int nItem1, int nItem2); 
// Move an item up by "nCount" positions.
BOOL MoveUp(int nItem, int nCount = 1); 
// Move an item down by "nCount" positions.
BOOL MoveDown(int nItem, int nCount = 1); 
BOOL MoveToTop(int nItem); // Move an item up to the top.
BOOL MoveToBottom(int nItem); // Move an item down to the bottom.
// Convenient versions of "CListCtrl::SetItemText"
BOOL SetItemText(int nItem, 
  int nSubItem, LPCTSTR lpszText); // String.
BOOL SetItemText(int nItem, int nSubItem, 
  DOUBLE val, int nPrecision = -1); // Double.
BOOL SetItemText(int nItem, int nSubItem, 
  FLOAT val, int nPrecision = -1); // Float.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
China China
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSmall modification to get it more compatible with CListCtrl Pin
Albert Hermann22-Jun-04 2:35
Albert Hermann22-Jun-04 2:35 
GeneralBug fix Pin
galroy14-Feb-04 21:14
professionalgalroy14-Feb-04 21:14 
GeneralRe: Bug fix Pin
J.B.17-Mar-04 16:17
J.B.17-Mar-04 16:17 
GeneralBugs in sorting Pin
Aris Adrianto S14-Feb-04 0:16
Aris Adrianto S14-Feb-04 0:16 
GeneralFindItem method Pin
adrianmichel6-Jan-04 7:07
adrianmichel6-Jan-04 7:07 
Questionhow to implement in a modeles dlg Pin
Akif12-Dec-03 0:36
Akif12-Dec-03 0:36 
GeneralAdd this ! Pin
Juvion25-Aug-03 19:27
Juvion25-Aug-03 19:27 
QuestionCan not be used as a run-time control Pin
Juvion24-Aug-03 18:08
Juvion24-Aug-03 18:08 
that's the problem !
Questionhow about multiline support ? Pin
cider30-Jul-03 22:18
cider30-Jul-03 22:18 
QuestionHow to use with the Create? Pin
Martijn21-Jun-03 23:06
Martijn21-Jun-03 23:06 
AnswerRe: How to use with the Create? Pin
Kirill V. Lyadvinsky7-Sep-06 3:48
Kirill V. Lyadvinsky7-Sep-06 3:48 
GeneralRe: How to use with the Create? Pin
SteveMyatt11-Oct-06 21:57
SteveMyatt11-Oct-06 21:57 
GeneralHeaderBar Loses 3D in VCC V7 Pin
jefflewis15-Jun-03 14:07
jefflewis15-Jun-03 14:07 
Generalconfused Pin
matlin1236-May-03 8:57
matlin1236-May-03 8:57 
GeneralGood work Pin
jhaga30-Apr-03 3:04
professionaljhaga30-Apr-03 3:04 
GeneralRe: Good work Pin
Peter Sjöström5-Jun-03 5:53
Peter Sjöström5-Jun-03 5:53 
GeneralARRRGGG!!! Pin
Nitron26-Apr-03 17:26
Nitron26-Apr-03 17:26 
GeneralRe: ARRRGGG!!! Pin
Abin26-Apr-03 19:09
Abin26-Apr-03 19:09 
GeneralRe: ARRRGGG!!! Pin
Miguel Lopes30-Apr-03 2:40
Miguel Lopes30-Apr-03 2:40 
GeneralRe: ARRRGGG!!! Pin
Peter Sjöström5-Jun-03 5:54
Peter Sjöström5-Jun-03 5:54 
GeneralRe: ARRRGGG!!! Pin
Atlantys26-Apr-03 20:08
Atlantys26-Apr-03 20:08 
GeneralWell, I couldn't get the "code" tags work Pin
Abin26-Apr-03 3:20
Abin26-Apr-03 3:20 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.