Introduction

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.)

Files

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

GridBtnCell_src

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

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.

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:

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

// (.cpp file)
pGridBtnCell->SetupBtns(
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
CGridBtnCellBase::CTL_ALIGN_CENTER,
// 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:

Acknowledgements

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.

History

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:
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.

I have seen here lot of questions about not been able to set individual attributes on grid cell on a tree column. And this is true because one CTreeColumn-object is shared between all the cell's in the same tree-column. This CTreeColumn-object has the foreground and background colors and other attributes. CGridTreeCellBase-class uses this object to return attributes e.g.

In my opinion, if you want to have unique attributes in different tree column cells, you have override some functionality in CGridTreeCellBase-class same way as they are done in CGridCell-class. I needed to be able to set background color and I did the following in the CGridTreeCellBase-class:

I just came across this also, after updating the MFC Grid Control from 2.22 to 2.25. Chris Maunder changed some of the functions in the CGridCellBase class to be pure virtual, requiring derived classes to provide overrides. I was able to get it to build with two small changes:

GridBtnCellBase.h: In class CGridBtnCellBase, add the following line in the public section:virtual BOOL IsDefaultFont() const { ASSERT( FALSE); return FALSE; }

GridTreeCellBase.h: In class CGridTreeCellBase, add the following line in the public section:virtual CWnd* GetEditWnd() const { ASSERT( FALSE); return NULL; }

Note that these are just work-arounds and if you try to call these, they'll assert. Also note that these edits are the definitions of these functions from the 2.22 version of the CGridCellBase class in the Grid Control library.

There may or may not be more required edits in the sample program or in any other application you write. These were the ones I had to fix in my application that used these two libraries.