Click here to Skip to main content
11,932,168 members (49,697 online)
Click here to Skip to main content
Add your own
alternative version


155 bookmarked

Tree control and Buttons for MFC Grid control

, 25 Apr 2001 CPOL
Rate this:
Please Sign up or sign in to vote.
A set of classes derived from CGridCtrl that embed a tree control, button controls, and virtual cells within the grid
<!-- Article Starts -->

Grid w/ Tree + Buttons

Implement IE-Style Option Dialog


This example demonstrates how to embed a tree and add button cells to Chris Maunder's MFC Grid control (derived from CWnd).

The example derives classes from CGridCellBase that implement different types of cells. The types of cells are as follows:

  • Cells that draw a tree
  • Cells that draw one or more controls
  • Cells that draw a tree + controls
  • Virtual cells - data not stored in each cell

By working with CGridCellBase, you can create all sorts of effects without altering the MFC Grid source files. The example avoids deriving a new grid class. Instead, it dynamically replaces cells within a basic CGridGtrl instance. This should minimize the pain of adding capabilities to your existing grid implementations.

(Note that users of the Grid control are bound by Chris' copyright requirements detailed on his web page.)


The example consists of a number of files stored in various directories:

  BtnDataBase.* A single instance holds common cell properties for all cells of type CGridBtnCell and CGridBtnCellCombo
  GridBtnCell.* The example uses instances of these cells in columns 3 thru 6 to draw buttons
  GridBtnCellCombo.* Column 7 has instances of these. Uses InPlaceList for editing. It is derived from CGridBtnCell
  GridBtnCellBase.* Base class. CGridBtnCell derived from this.
  InPlaceList.* Used by GridBtnCellCombo to provide drop-down list control for editing
  *.* Copy of MFC Grid source code
  GridTreeBtnCell.* Tree + control cell combination. Used by "Options" Dialog. It is derived from CGridTreeCell and contains an instance of CGridBtnCell
  GridTreeCell.* The example uses instances of these cells in column 2 to draw a tree
  GridTreeCellBase.* Base class. CGridTreeCell derived from this.
  TreeColumn.* A single instance holds common cell properties for all cells of type CGridTreeCellBase. Manages a collection of CGridTreeCellBase's in a grid column to form an embedded tree

How to Use

Each type of grid requires a slightly different setup. (See the MFC Grid page for information on how to use the MFC grid.)

To Setup Cells that Draw a Tree

Add an instance of the following to the header file of the CDialog or CView that will host the grid:

// (.h file)

    CGridCtrl m_Grid;           // the grid
    CTreeColumn m_TreeColumn;   // provides tree column support

In the CDialog or CView implementation, setup an array of UCHARs that define the tree indentation level. 1=root, 2=first branch off root, etc.

// (.cpp file)

    unsigned char ucPatternAry[] = { 1,2,3,4,4,5,5,3,3,4,2,3,4};

In the CDialog or CView implementation, specify grid column information, then use CTreeColumn::TreeSetup() to define grid rows tree placement. For CDialog, you may want to do this in the OnInitDialog() member.

// (.cpp file)

    m_Grid.SetColumnCount( 4);
    m_Grid.SetFixedColumnCount( 1);

    m_TreeColumn.TreeSetup( &m_Grid, // tree acts on a column in this grid
                        2,           // which column has tree
                        sizeof( ucPatternAry), // total number of rows in the
                                               //  tree if totally expanded
                        1,           // Set fixed row count now, too
                                     //  Grid total rows=aiTotalRows+aiFixedRowCount
                        ucPatternAry,// Tree Level data array --
                                     //  must have aiTotalRows of entries
                        TRUE,        // T=show tree (not grid) lines; F=no tree lines
                        TRUE);       // T=use 1st 3 images from already set image list
                                     //  to display folder graphics

You can modify the existing tree structure with calls to CTreeColumn's InsertTreeBranch() and DeleteTreeBranch(). (Calling TreeSetup() with different tree configurations was the only way to change the tree structure with the original implementation, but had the disadvantage of destroying cell contents.)

The example demonstrates the inserting and deleting of branchs and some additional capabilites of the tree. See CTreeColumn's member functions for more information.

To Setup Cells that Draw Buttons

Add an instance of the following to the header file of the CDialog or CView that will host the grid:

// (.h file)

    CGridCtrl m_Grid;           // the grid
    CBtnDataBase m_BtnDataBase; // holds common properties for button cells

Associate the grid with the cell property holder in the implementation file of the CDialog or CView.

// (.cpp file)

    m_BtnDataBase.SetGrid( &m_Grid);

You may want to copy an existing cell's properties to act as the model for all button cells. You could do this just one time.

// (.cpp file)

    // retain old cell properties
    CGridBtnCell GridCellCopy;
    GridCellCopy.SetBtnDataBase( &m_BtnDataBase);
    CGridCellBase* pCurrCell = m_Grid.GetCell( row, col);
    if (pCurrCell)
        GridCellCopy = *pCurrCell;  // data will be stored in m_BtnDataBase

After the grid's window created, replace default cells with button cells as required. The following code is called in CDialog::OnInitDialog().

// (.cpp file)

    m_Grid.SetCellType( row, col, RUNTIME_CLASS(CGridBtnCell) );
    CGridBtnCell* pGridBtnCell = (CGridBtnCell*)m_Grid.GetCell( row, col);

    // tell new cell where to get its property data
    pGridBtnCell->SetBtnDataBase( &m_BtnDataBase);

Setup controls within new button cell. The example implementation allows up to 4 buttons within a cell.

// (.cpp file)

        0,                  // zero-based index of image to draw
        DFC_BUTTON,         // type of frame control to draw e.g. DFC_BUTTON
        DFCS_BUTTONPUSH,    // like DrawFrameControl()'s nState  e.g. DFCS_BUTTONCHECK
                            // horizontal alignment of control image
        0,                  // fixed width of control or 0 for size-to-fit
        FALSE,              // T=btn is member of a radio group
        "Btn Text" );       // Text to insert centered in button; if NULL no text

How to Enable / Disable Buttons in Cells

Here's how to use MFC's ON_UPDATE_COMMAND_UI mechanism to "automatically" enable and disable buttons in the grid. This example is for grids that are placed in an MFC SDI or MDI window. CDialog-based grids can adapt code shown within the OnIdleUpdateCmdUI() function at the end of this section to "manually" enable and disable buttons.

Add an instance of the following to the header file of your CFormView derived class that hosts the grid:

// (.h file)

    unsigned long m_ulTicksLast; // for avoiding 100% CPU usage
    CGridCtrl m_Grid;            // the grid

    afx_msg LRESULT OnIdleUpdateCmdUI(WPARAM wParam, LPARAM);

Define macro for MFC's message passing scheme in the implementation file of your CFormView derived class:

// (.cpp file)


Implement button enabling / disabling in the general user interface updating routine that is called by MFC during idle-processing time:

// (.cpp file)

    // You'll use 100% cpu if you update the buttons continually
    unsigned long ulTicksNow = GetTickCount();
    if( ulTicksNow - m_ulTicksLast < 500 ) // <- nbr represents millisecs
        return 0L;
    m_ulTicksLast = ulTicksNow;

    if( !::IsWindow( m_Grid.m_hWnd ) )
        return 0L;  // gotta exist

    CCellRange VisibleRange;
    VisibleRange = m_Grid.GetVisibleNonFixedCellRange();
        // (yes, you could include fixed cells in your implementation)

    // for all visible cells that have a button
    int iRow, iCol;
    for( iRow=VisibleRange.GetMinRow(); iRow <= VisibleRange.GetMaxRow(); iRow++)
        for( iCol=VisibleRange.GetMinCol(); iCol <= VisibleRange.GetMaxCol(); iCol++)
            if( m_Grid.GetRowHeight( iRow) > 0
                && m_Grid.GetColumnWidth( iCol) > 0 )
                CGridBtnCellBase* pGridBtnCellBase
                            = (CGridBtnCellBase*)m_Grid.GetCell( iRow, iCol);
                ASSERT( pGridBtnCellBase != NULL);
                if( pGridBtnCellBase->IsKindOf( RUNTIME_CLASS(CGridBtnCellBase) ) )
                    // here's where you add logic specific to your implementation...
                    BOOL bEnable = TRUE; // or = FALSE;
                    // In this example, just assume that there's one button
                    //  in a cell
                    UINT uiState = pGridBtnCellBase->GetDrawCtlState( 0);
                    if( bEnable)
                        uiState &= ~DFCS_INACTIVE;
                        uiState |= DFCS_INACTIVE;
                    pGridBtnCellBase->SetDrawCtlState( 0, uiState);
                    m_Grid.RedrawCell( iRow, iCol);

    return 0L;

You May Place the Tree in a Fixed Grid Column

Want to try it? Change the following line defined at the top of GridTreeCtrlDemoDlg.cpp:

#define FIXED_COLUMN_COUNT      1


#define FIXED_COLUMN_COUNT      3

Rebuild. The tree will be in a fixed column. You can increase the number to 4 or 5 to try out button cells as fixed, too.


Many thanks to Chris Maunder for his encouragement and suggestions.

Thanks to all who have submitted feedback and bug fixes. Special thanks to Michael A. Barnhart for his work on the insert / delete tree branches feature.


  • 17 Mar 2000 - Initial Release
  • 30 Jul 2000 - Updated to work with v2.20 of the grid control
  • 26 Apr 2001
    • Can dynamically insert and delete branches of the tree. Press these buttons:
      Insert/Delete Branches to try it. (Michael A. Barnhart)
    • The column with the tree may be a fixed column, now. Button cells may be in a fixed column, too.
    • If you clicked-down on a control embedded in a cell (e.g. push button, check box, etc.) then dragged you mouse away before releasing your mouse button, the control would remain in a state of limbo. Fixed. NOTE: This fix required a slight change in Chris' grid control code. (Search for "//." in GridCtrl.cpp to review the changes.) I've asked Chris to consider these changes for a future release.
    • Tree line drawing problem fixed. (Matthew Strawbridge; Hal DeVore)
    • Corrected tree image drawing when (nbr of fixed rows) != (nbr of fixed columns). (Andrey Babchenko)
    • Updated to work with v2.22 grid control.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Ken Bertelson
Web Developer
United States United States
No Biography provided

You may also be interested in...

Comments and Discussions

GeneralMy vote of 5 Pin
AnOldog12-Aug-13 2:05
memberAnOldog12-Aug-13 2:05 
QuestionBugs: The code available in the demo project does not run in vc++ 2010. Pin
konarkuppal904-Jul-12 3:40
memberkonarkuppal904-Jul-12 3:40 
AnswerRe: Bugs: The code available in the demo project does not run in vc++ 2010. Pin
Ken Bertelson5-Jul-12 11:48
memberKen Bertelson5-Jul-12 11:48 
GeneralRe: Bugs: The code available in the demo project does not run in vc++ 2010. Pin
konarkuppal9013-Jul-12 4:32
memberkonarkuppal9013-Jul-12 4:32 
QuestionLicence? Pin
F_DJacobs3-Oct-11 7:16
memberF_DJacobs3-Oct-11 7:16 
AnswerRe: Licence? Pin
F_DJacobs3-Oct-11 10:56
memberF_DJacobs3-Oct-11 10:56 
AnswerRe: Licence? Pin
Ken Bertelson3-Oct-11 10:58
memberKen Bertelson3-Oct-11 10:58 
AnswerTree columns have shared attributes (e.g. background color) grude solution Pin
MarkoAP15-Sep-11 4:31
memberMarkoAP15-Sep-11 4:31 
Questionproblem with MFC GridCtrl v2.27 Pin
Manmohan2930-Aug-11 3:57
memberManmohan2930-Aug-11 3:57 
QuestionHow set tree in column number 0? Pin
GAJERA3-Nov-10 1:56
memberGAJERA3-Nov-10 1:56 
GeneralMy vote of 5 Pin
GAJERA2-Nov-10 0:33
memberGAJERA2-Nov-10 0:33 
Questionhow to know the state of checkbox? Pin
yinglai30-May-10 22:19
memberyinglai30-May-10 22:19 
QuestionIssue test in vs 2008 Pin
Wyxxenlin1-Feb-10 21:31
memberWyxxenlin1-Feb-10 21:31 
QuestionHOW to delete treeColumn Pin
xieji6-Aug-08 1:20
memberxieji6-Aug-08 1:20 
GeneralHave any body has idea on how to merge the cells. I m badly need of it. Pin
ravi.code22-May-08 13:16
memberravi.code22-May-08 13:16 
QuestionHow to populate the grid with an existing tree Pin
luther1311-Dec-07 0:57
memberluther1311-Dec-07 0:57 
QuestionExtra checkbox Pin
mensfort24-Oct-07 5:13
membermensfort24-Oct-07 5:13 
Questionwhich root has been expanded ? Pin
amit_007_bond14-Mar-07 18:52
memberamit_007_bond14-Mar-07 18:52 
Questioncheck tree is expanded using plus button(hasbutton property) Pin
Member #381532413-Mar-07 21:42
memberMember #381532413-Mar-07 21:42 
General&#22909;&#21464;&#24577;&#30340;&#21151;&#33021;.... Pin
gxpotato4-Mar-07 10:01
membergxpotato4-Mar-07 10:01 
GeneralRe: &#22909;&#21464;&#24577;&#30340;&#21151;&#33021;.... Pin
xdchen263-Nov-11 22:59
memberxdchen263-Nov-11 22:59 
Generalresize column width to expanded tree Pin
Virtuality9621-Dec-06 4:35
memberVirtuality9621-Dec-06 4:35 
QuestionIs it compatible with v2.25 Pin
WinCEdep7-Nov-06 19:35
memberWinCEdep7-Nov-06 19:35 
AnswerRe: Is it compatible with v2.25 Pin
Bob Farrell31-Jan-07 13:50
memberBob Farrell31-Jan-07 13:50 
GeneralOnly printing check boxes in top level branch [modified] Pin
crazydave2219-Oct-06 21:25
membercrazydave2219-Oct-06 21:25 

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.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.151126.1 | Last Updated 26 Apr 2001
Article Copyright 2000 by Ken Bertelson
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid