Click here to Skip to main content
12,302,376 members (64,198 online)
Click here to Skip to main content
Add your own
alternative version


115 bookmarked

Using comboboxes in the MFC Grid Control

, 8 Jan 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
Explains how to use comboboxes to edit cells in the MFC Grid Control

Sample Image - gridctrl_combo.gif


Since I posted my MFC grid control I've had a lot of requests asking how to use other methods of editing cells in the grid. Ken Bertelson has taken this to the extreme, with his Grid Tree control. For some this was a little too involved, so I've created a demo project that shows how to replace the default editing with a simple combo box.

Previous methods of achieving this required that a new CGridCtrl derived class be created. With the new structure in the 2.X versions of CGridCtrl it's now a lot simpler.

A new cell type

Changing the way cells are edited is simply a matter of deriving a new grid cell class from CGridCellBase (or derivatives such as CGridCell).

I'm using the In-Place list that I used in previous versions. It's not the greatest - but it does demonstrate how to replace the default editing.

The first step is to derive a new class from CGridCell - I call it CGridCellCombo - and override Edit (which initiates editing) and EndEdit (which stops editing). You can find this class in the GridCellCombo.* files.

In Edit I create a CWnd derived class that will perform the actual editing - in this case my CInPlaceList from previous versions of the grid. There are a number of things to be aware of when creating such CWnd derived Edit classes:

  • The control will receive the row and column to be edited, the dimensions and location of the in-place edit control, the style of control to create, the original text in the cell plus the initial character that caused editing to commence (or VK_LBUTTON if the mouse was clicked on the current cell).
  • Your editing control should stop editing when it loses input focus.
  • Your editing object should handle mouse keys in a way that allows the user to navigate between cells while editing. If the control gets an arrow key for instance, it should cancel editing and return the last key it encountered back to the grid via the GVN_ENDLABELEDIT notification message.
    Note that the grid control accepts Ctrl+<arrows> for navigation, so if your in-place edit control needs to use the arrows, you can always reserve Ctrl+<arrows> to move to other cells.
  • Your edit control should pass back information about the last key pressed before editing ended. This allows correct movement among cells

The EndEdit function of your grid cell class should cease editing and destroy the in-place editing window.

If you look at the code you will see that the grid cell derived class is merely a wrapper that creates an instance of a CInPlaceList window and then sits back with the knowledge of a job well done. The actual guts of the grid cell class are as follows:

// Create a control to do the editing
BOOL CGridCellCombo::Edit(int nRow, int nCol, CRect rect, CPoint /* point */,
                          UINT nID, UINT nChar)
    m_bEditing = TRUE;
    // CInPlaceList auto-deletes itself
    m_pEditWnd = new CInPlaceList(GetGrid(), rect, GetStyle(), nID, nRow, nCol, 
                                  m_Strings, GetText(), nChar);

    return TRUE;

// Cancel the editing.
void CGridCellCombo::EndEdit()
    if (m_pEditWnd)

We rely on CGridCell::OnEndEdit to set m_bEditing to FALSE and m_pEditWnd to NULL when editing has finished. CInPlaceList is also self-deleting, which saves a whole line of code in EndEdit.

The CInPlaceList does the actual work, and keeps track of issues such as the last key pressed and it's current focus state. It also has niceties such as ensuring that the drop down list is correctly sized.

The major issue is that the control must pass the necessary data back to the parent grid once editing has been completed. It uses the following code snippet in it's EndEdit method to do this:

void CInPlaceList::EndEdit()
    CString str;
    // Send Notification to parent
    GV_DISPINFO dispinfo;

    dispinfo.hdr.hwndFrom = GetSafeHwnd();
    dispinfo.hdr.idFrom   = GetDlgCtrlID();
    dispinfo.hdr.code     = GVN_ENDLABELEDIT;
    dispinfo.item.mask    = LVIF_TEXT|LVIF_PARAM;
    dispinfo.item.row     = m_nRow;
    dispinfo.item.col     = m_nCol;
    dispinfo.item.strText = str;
    dispinfo.item.lParam  = (LPARAM) m_nLastChar; 
    CWnd* pOwner = GetOwner();
    if (IsWindow(pOwner->GetSafeHwnd()))
        pOwner->SendMessage(WM_NOTIFY, GetDlgCtrlID(), (LPARAM)&dispinfo );
    // Close this window (PostNcDestroy will delete this)
    PostMessage(WM_CLOSE, 0, 0);

I pass the character that initiated editing to the edit control itself so that it can deal with keys appropriately. For instance in the default edit control, if the edit control is passed a normal character or arrow key as the "initiating" key, then it will cease editing when it encounters an arrow key (to allow navigation using the keyboard). If the edit control is passed VK_LBUTTON (meaning editing was initiated by a mouse click) then arrow keys will not cause the editing to cease.

One last thing I do is ensure that the new cell displays a user hint that it is not a normal grid cell. When a cell is selected I override drawing so that a small drop down arrow is shown. The code is quite simple:

BOOL CGridCellCombo::Draw(CDC* pDC, int nRow, int nCol, CRect rect,
                          BOOL bEraseBkgnd /*=TRUE*/)
    // Cell selected?
    DWORD dwState = GetState();
    if ( !(dwState & GVIS_FIXED) && (dwState & GVIS_FOCUSED))
        // Get the size of the scroll box
        CSize sizeScroll(GetSystemMetrics(SM_CXVSCROLL), 

        // enough room to draw?
        if ( < rect.Width() && < rect.Height())
            // Draw control at RHS of cell
            CRect ScrollRect = rect;
            ScrollRect.left   = rect.right -;
            ScrollRect.bottom = +;

            // Do the draw 
            pDC->DrawFrameControl(ScrollRect, DFC_SCROLL, DFCS_SCROLLDOWN);

            // Adjust the remaining space in the cell
            rect.right = ScrollRect.left;

    // drop through and complete the cell drawing using the base class' method
    return CGridCell::Draw(pDC, nRow, nCol, rect,  bEraseBkgnd);

Using the new cell type

Using the new cell is simple. You can either use the Grid control's default cell instantiation method (ie. do nothing) and then call CGridCtrl::SetCellType or you can call CGridCtrl::SetDefaultCellType and then do nothing. The first option changes cells from one type to another, and is good if you only want specific cells to be affected. The second option tells the grid the class type that you want to be used at the outset, and is good if you want all cells in the grid to be of your new type.


Thanks go to Roelf Werkman for his work in extending the CInPlaceList to allow the CBS_DROPDOWN and CBS_SIMPLE styles to be used, and thanks to Fred Ackers for moticating me to finally write this up.


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


About the Author

Chris Maunder
Founder CodeProject
Canada Canada
Chris is the Co-founder, Administrator, Architect, Chief Editor and Shameless Hack who wrote and runs The Code Project. He's been programming since 1988 while pretending to be, in various guises, an astrophysicist, mathematician, physicist, hydrologist, geomorphologist, defence intelligence researcher and then, when all that got a bit rough on the nerves, a web developer. He is a Microsoft Visual C++ MVP both globally and for Canada locally.

His programming experience includes C/C++, C#, SQL, MFC, ASP, ASP.NET, and far, far too much FORTRAN. He has worked on PocketPCs, AIX mainframes, Sun workstations, and a CRAY YMP C90 behemoth but finds notebooks take up less desk space.

He dodges, he weaves, and he never gets enough sleep. He is kind to small animals.

Chris was born and bred in Australia but splits his time between Toronto and Melbourne, depending on the weather. For relaxation he is into road cycling, snowboarding, rock climbing, and storm chasing.

You may also be interested in...

Comments and Discussions

AnswerRe: How to put MFCGridCtrl into a property page. Pin
Hanney Wang15-Mar-03 2:18
memberHanney Wang15-Mar-03 2:18 
GeneralEmpty cell Pin
Gianluca Nastasi28-Feb-03 5:06
sussGianluca Nastasi28-Feb-03 5:06 
GeneralRe: Empty cell Pin
Hanney Wang15-Mar-03 2:42
memberHanney Wang15-Mar-03 2:42 
GeneralRe: Empty cell Pin
xuyuhua20001-Jun-06 17:17
memberxuyuhua20001-Jun-06 17:17 
Questiononly seleting is allowed.but how? Pin
withoutdruck5-Jan-03 1:18
memberwithoutdruck5-Jan-03 1:18 
AnswerRe: only seleting is allowed.but how? Pin
Rolando E. Cruz-Marshall10-Jan-03 9:04
memberRolando E. Cruz-Marshall10-Jan-03 9:04 
General[Code change-proposal] SetOptions(CStringArray) to SetOptions(CTupleArray) Pin
oglimmer25-Nov-02 21:57
memberoglimmer25-Nov-02 21:57 
QuestionHow to use the grid with the new HTML class ? Pin
Appstmd15-Sep-02 7:56
memberAppstmd15-Sep-02 7:56 
GeneralMerging Cells Pin
KP2410-Sep-02 18:50
memberKP2410-Sep-02 18:50 
Ji Gua6-Aug-02 6:39
memberJi Gua6-Aug-02 6:39 
GeneralPlease tell me it can combine multi- cell and ..... Pin
liangzhiguo2-Jun-02 14:43
memberliangzhiguo2-Jun-02 14:43 
QuestionCan this work for WinCE? Pin
Anonymous23-Feb-02 5:06
memberAnonymous23-Feb-02 5:06 
GeneralGrid's row selection Pin
Confused Ai20-Dec-01 3:52
memberConfused Ai20-Dec-01 3:52 
GeneralComboBox OnGridEndEdit Pin
Micah Schehl13-Sep-01 17:12
memberMicah Schehl13-Sep-01 17:12 
GeneralRe: ComboBox OnGridEndEdit Pin
Orhun13-Jun-02 9:54
memberOrhun13-Jun-02 9:54 
GeneralRe: ComboBox OnGridEndEdit Pin
alan9331-Jul-02 7:23
memberalan9331-Jul-02 7:23 
GeneralRe: ComboBox OnGridEndEdit Pin
Orhun Birsoy8-Aug-02 11:28
memberOrhun Birsoy8-Aug-02 11:28 
QuestionHow to change Combox's hight? Pin
Anonymous29-Aug-01 22:30
memberAnonymous29-Aug-01 22:30 
QuestionHow can I get message from CComboBox Pin
Anonymous9-Aug-01 20:43
memberAnonymous9-Aug-01 20:43 
AnswerRe: How can I get message from CComboBox Pin
WRice11-Dec-05 23:29
memberWRice11-Dec-05 23:29 
QuestionHow to cover the background of the grid box with cells completely Pin
Marina Gubina25-Jul-01 10:27
memberMarina Gubina25-Jul-01 10:27 
Generalpassing text from the combo to the grid Pin
abir7-Jul-01 0:05
memberabir7-Jul-01 0:05 
GeneralRe: passing text from the combo to the grid Pin
Mick Jackson21-Aug-01 3:25
memberMick Jackson21-Aug-01 3:25 
Generalcombo-box don't scroll propperly Pin
Ralf Friedrich Hain25-May-01 22:54
memberRalf Friedrich Hain25-May-01 22:54 
GeneralRe: I've solved also this problem Pin
Ralf Friedrich Hain31-May-01 9:02
memberRalf Friedrich Hain31-May-01 9:02 
QuestionCombo and auto-size ? Pin
Ralf Friedrich Hain25-May-01 22:52
memberRalf Friedrich Hain25-May-01 22:52 
AnswerI've solved my problem Pin
Ralf Friedrich Hain30-May-01 10:42
memberRalf Friedrich Hain30-May-01 10:42 
GeneralNeed help just getting the grid to show!! Pin
Codejoy23-May-01 9:50
memberCodejoy23-May-01 9:50 
GeneralRe: Need help just getting the grid to show!! Pin
Anonymous12-Jul-01 3:17
memberAnonymous12-Jul-01 3:17 
GeneralRe: Need help just getting the grid to show!! Pin
Anonymous12-Jul-01 3:18
memberAnonymous12-Jul-01 3:18 
GeneralEditing cell Pin
Petr Jodas25-Apr-01 1:23
memberPetr Jodas25-Apr-01 1:23 
GeneralProblem with CGridCellCombo and ExpandLastColumn in OnSize Pin
Francisco Viella2-Apr-01 7:19
memberFrancisco Viella2-Apr-01 7:19 
GeneralChild Dialog in a Grid Cell Pin
Steffen Albrecht23-Mar-01 4:23
memberSteffen Albrecht23-Mar-01 4:23 
GeneralSelect-Only Combo Box(es) on Grid: CBS_DROPDOWNLIST Pin
Mike Wolfe9-Mar-01 8:17
memberMike Wolfe9-Mar-01 8:17 
GeneralRe: Select-Only Combo Box(es) on Grid: CBS_DROPDOWNLIST Pin
Francisco Viella2-Apr-01 7:15
memberFrancisco Viella2-Apr-01 7:15 
GeneralQuestion about using tab with combobox Pin
RL7-Feb-01 3:18
memberRL7-Feb-01 3:18 
GeneralRe: Question about using tab with combobox Pin
Andreas Jäger-PMC29-Apr-01 22:35
memberAndreas Jäger-PMC29-Apr-01 22:35 
GeneralRe: Question about using tab with combobox Pin
Anonymous11-May-01 2:26
memberAnonymous11-May-01 2:26 
GeneralThe ComboBox doesnt work with the CGridCtrl Ver. 2.22 Pin
Alex Koenig25-Jan-01 1:07
memberAlex Koenig25-Jan-01 1:07 
GeneralRe: The ComboBox doesnt work with the CGridCtrl Ver. 2.22 Pin
Jo Sadler29-Jan-01 5:03
memberJo Sadler29-Jan-01 5:03 
GeneralCapturing ComboBox events in the Application Program Pin
Mel Stober27-Dec-00 7:26
memberMel Stober27-Dec-00 7:26 
GeneralRe: Capturing ComboBox events in the Application Program Pin
D.Raju11-Jun-01 19:26
memberD.Raju11-Jun-01 19:26 
GeneralRe: another method Pin
Kono Kim28-Nov-01 4:40
memberKono Kim28-Nov-01 4:40 
QuestionPossible Memory Leak? Pin
Mel Stober27-Dec-00 7:06
memberMel Stober27-Dec-00 7:06 
AnswerRe: Possible Memory Leak? Pin
Chris Maunder27-Dec-00 20:44
memberChris Maunder27-Dec-00 20:44 
Generalretrieving the selection index of the combo box Pin
jean-pierre Semery19-Dec-00 6:21
memberjean-pierre Semery19-Dec-00 6:21 
GeneralRe: retrieving the selection index of the combo box Pin
Mel Stober27-Dec-00 7:11
memberMel Stober27-Dec-00 7:11 
GeneralRe: retrieving the selection index of the combo box Pin
usha7-Jul-01 0:34
memberusha7-Jul-01 0:34 
GeneralRe: retrieving the selection index of the combo box Pin
Ralf Friedrich Hain15-Jun-01 10:17
memberRalf Friedrich Hain15-Jun-01 10:17 
GeneralRe: retrieving the selection index of the combo box Pin
Anonymous7-Jul-01 1:04
memberAnonymous7-Jul-01 1:04 

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.160530.1 | Last Updated 8 Jan 2013
Article Copyright 2000 by Chris Maunder
Everything else Copyright © CodeProject, 1999-2016
Layout: fixed | fluid