65.9K
CodeProject is changing. Read more.
Home

Simple Row Insert for CListCtrl

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.47/5 (24 votes)

Jul 10, 2000

viewsIcon

307808

This simple CListCtrl extension allows easy row insertion when in Report mode.

Ever been annoyed at the amount of code you need just to insert a few rows and their columns' text into a CListCtrl while using the 'Report' style?

This little MFC subclassing tutorial provides a handy little enhancement to the standard CListCtrl, which can make life easier for both beginners and not_so_beginners alike.

The code and text that follows assumes you have generated a typcal Dialog based application with the MFC Application (.exe) Appwizard in MS Visual C++.

Derive a new CListCtrl based class (here CMyListCtrl).  In the VC IDE, this is as simple as selcting 'Add Class...' from the MFC Class wizard then, in the new class dialog, naming the control and selecting CListCtrl as the base class in the drop down list.

To use the new class, start by adding a CListCtrl to the dialog (be sure to select 'Report' in the Styles page of the proprties for the new control) then, in the Member Variables page of the MFC Class Wizard (ctrl+w), add a control variable for the newly created item (IDC_LIST1, or whatever ID you supplied) - but instead of accepting the default CListCtrl as the type, you will be able to select the new CMyListCtrl type. Call the variable m_myList.

Specify

#include "MyListCtrl.h"

in the header of the dialog class (in this case, the main dialog of the app) and you're set.

In the code that VC generates for the new class, add the following: 

// put this into the header file, in the public: section
int InsertRow(int nPos,int nNoOfCols, LPCTSTR pText, ...);
//
// and this into the cpp file, in the public: section
int CMyListCtrl::InsertRow(int nPos,int nNoOfCols, LPCTSTR pText, ...)
{
    va_list argList;
    va_start(argList, pText);

    ASSERT(nNoOfCols >= 1); // use the 'normal' Insert function with 1 argument
    int nIndex = InsertItem(LVIF_TEXT|LVIF_STATE, nPos, pText,0,LVIS_SELECTED,0,0);
    ASSERT(nIndex != -1);
    if (nIndex < 0) return(nIndex);
    for (int i = 1; i < nNoOfCols; i++) {
        LPCSTR p = va_arg(argList,LPCSTR);
        if (p != NULL) {
            SetItemText(nIndex, i, p);    
        }
    }
    va_end(argList);
    return(nIndex);
}
// In your program the list control can now be filled like this:

   myList.InsertRow(0,3,_T("Sample 1"),_T("Column 2 for row 1"),_T("Column 3 for row 1"));
   myList.InsertRow(1,3,_T("Sample 2"),_T("Column 2 for row 2"),_T("Column 3 for row 2"));
   myList.InsertRow(2,3,_T("Sample 3"),_T("Column 2 for row 3"),_T("Column 3 for row 3"));
   myList.InsertRow(3,1,_T("Sample 4")); // nothing for column 2 and 3
   myList.InsertRow(4,3,_T("Sample 5"),_T("Column 2 for row 5"),_T("Column 3 for row 5"));
   myList.InsertRow(5,2,_T("Sample 6"),_T("Column 2 for row 6")); // nothing for column 3

To test, you might add a command button that executes the above code.  Also, this assumes that you have initialized the list with 3 columns - for the sake of this simple example, you might provide the following in the OnInitDialog method of the dialog class:

   // TODO: Add extra initialization here
   m_myList.InsertColumn(0, "Column 1");
   m_myList.InsertColumn(1, "Column 2");
   m_myList.InsertColumn(2, "Column 3");

   m_myList.SetColumnWidth(0, 100);
   m_myList.SetColumnWidth(1, 100);
   m_myList.SetColumnWidth(2, 100);

Enjoy!