Click here to Skip to main content
15,880,956 members
Articles / Desktop Programming / MFC
Article

Custom ComboBox

Rate me:
Please Sign up or sign in to vote.
4.80/5 (21 votes)
4 May 2006CPOL4 min read 227.3K   7.6K   122   31
A combo box control with a custom popup control.

Classic ComboBox control

ComboBox with ListView control

ComboBox with MFCGrid control

ComboBox with popup dialog

Overview

This article describes how you can implement a combo box with various popup controls, including a dialog containing any kind of control. The article also shows the implementation of a combo box with the CListCtrl control, MFCGrid control, and a combo box with a popup dialog. As we already know, the combo box control contains two controls inside. The edit control which you can type text into, and a list box control containing string items which you can choose to appear in the edit area of the combo box.

Using the CCstmComboBox class

The CCstmComboBox class is derived from the MFC CComboBox class, and supports dialog data exchange and validation with DDX_CBString for CString and DDX_CBIndex for int variables like the ordinary CComboBox MFC class.

CCstmComboBox data members

enum e_popup_type
{
__CCB_STANDARD  = 0,
__CCB_LIST_CTRL = 1,
__CCB_MFC_GRID  = 2,
__CCB_DLGIALOG  = 4,
};

e_popup_type contains all the available types of popup controls.

protected:

//Height of a popup control
UINT             m_nHeight;
//Combo box information struct
PCOMBOBOXINFO    m_pcbInfo;
//Pointer to Popup Control
CWnd*            m_lstPopup;
//Subclassed edit control of a combo box control
CCstmEditCombo   m_wndEditCombo;
//Enabling/disabling autocompletion
bool             m_bAutoComplete;

CCstmComboBox Implementation

bool SetCustomPopupCtrl(
    e_popup_type _type
)
Description:Changes the classic popup list box control with the control of the specified type.
Parameter:

e_popup_type

Enumeration of the available popup controls.

Returns:true if change is successful, otherwise false.
CWnd* GetPopupCtrl(
    void
)
Description:Returns the current popup control. Not available for classic combo box.
Parameter:None.
Returns:Returns the window of the current popup control.
int SetDroppedHeight(
    UINT nHeight
)
Description:Sets the height of the popup control.
Parameter:

hHeight

Height in pixels.

Returns:nHeight of the popup control, otherwise CB_ERR.
void EnsureVisible(
    int nItem
)
Description:Ensures that an item of the popup control is visible.
Parameter:

nItem

Index of the item that is to be visible.

Returns:Nonzero if successful; otherwise zero.

Combo box class members

The following list also contains members of the MFC combo box. Details of them can be found in the MSDN documentation.

  • GetCount

    Retrieves the number of items in the popup control of a combo box.

  • GetCurSel

    Retrieves the index of the currently selected item, if any, in the popup control of a combo box.

  • GetDroppedControlRect

    Retrieves the screen coordinates of the visible (dropped-down) popup control of a drop-down combo box.

  • GetLBText

    Gets a string from the popup control of a combo box.

  • GetLBTextLen

    Gets the length of a string in the popup control of a combo box.

  • SetCurSel

    Selects a string in the popup control of a combo box.

  • SetDroppedWidth

    Sets the minimum allowable width for the drop-down popup control portion of a combo box.

  • AddString

    Adds a string to the end of the list in the list box of a combo box, or at the sorted position for list boxes with the CBS_SORT style. Only applicable for yje classic combo box.

  • DeleteString

    Deletes a string from the popup control of a combo box.

  • Dir

    Adds a list of filenames to the list box of a combo box. Only applicable for the classic combo box.

  • FindString

    Finds the first string that contains the specified prefix in the popup control of a combo box.

  • FindStringExact

    Finds the first popup control string (in a combo box) that matches the specified string.

  • InsertString

    Inserts a string into the list box of a combo box. Available only for the classic combo box.

  • SelectString

    Searches for a string in the popup control of a combo box and, if the string is found, selects the string in the popup control and copies the string to the edit control.

  • ResetContent

    Removes all items from the popup control and edit control of a combo box.

Popup Control (CListCtrl, CGridCtrl, CDialog)

Each popup control has common members which interact with a combo box.

  • bool CreatePopupCtrl(CWnd* pOwner);

    Creates a popup control. Returns true if successful, otherwise false.

  • int GetCount(void) const;

    Retrieves the number of items in the popup control of a combo box.

  • int GetCurrentSelection(void) const;

    Retrieves the index of the currently selected item.

  • int SetCurrentSelection(int nSelect);

    Sets the currently selected item.

  • void GetItemText(int nIndex,CString& rString) const;

    Gets the string of the selected item of the popup control.

  • int DeleteItem(UINT nIndex);

    Deletes an item from the popup control.

  • int FindString(int nStartAfter, LPCTSTR lpszString) const;

    Finds the first string that contains the specified prefix in the popup control.

  • int FindStringExact(int nStartAfter, LPCTSTR lpszString) const;

    Finds the first popup control string that matches the specified string.

  • void RemoveAllItems();

    Removes all items from the popup control.

Hot to use CCstmComboBox

Using CCstrmComboBox is the same as using a standard combo box.

In OnInitDilog, you have to call SetCustomPopupCtrl(e_popup_type _type) with the right enum type.

Populating a popup control

To populate a popup control, call GetPopupCtrl, and cast it based on the type of control you specified in the previous function call. Populating the popup control is specific and depends on the control implementation.

Populating the CListCtrl popup control

The code below shows populating the ListCtrl popup control.

//Combo with ListCtrl 
if(!m_cmbWithListCtrl.SetCustomPopupCtrl(
          CCstmComboBox::__CCB_LIST_CTRL))
   return FALSE;
m_cmbWithListCtrl.SetDroppedWidth(337);
m_cmbWithListCtrl.SetDroppedHeight(148);
CPopupListCtrl* pPopup = 
  (CPopupListCtrl*)m_cmbWithListCtrl.GetPopupCtrl();
pPopup->InsertColumn(0,_T("Column 1"), 
                    LVCFMT_LEFT, 150);
pPopup->InsertColumn(1, _T("Column 2"), 
                     LVCFMT_LEFT, 150);

for (int i = 0 ; i < 160; i++)
{
  CString item;
  item.Format(_T("Item %i,0"), i);
  int nItem = pPopup->InsertItem(pPopup->GetItemCount(), item);
  item.Format(_T("SubItem %i,1"), i);
  pPopup->SetItemText(nItem, 1, item);
}

Populating CGridCtrl (Chris Maunder's Grid control) popup control

This code populates the MFC Grid control:

//Combo with MFCGrid Ctrl
if(!m_cmbWithMFCGrid.SetCustomPopupCtrl(
          CCstmComboBox::__CCB_MFC_GRID))
    return FALSE;
m_cmbWithMFCGrid.SetDroppedWidth(337);
m_cmbWithMFCGrid.SetDroppedHeight(148);
CPopupMFCGid* pPopupMFC = 
   (CPopupMFCGid*)m_cmbWithMFCGrid.GetPopupCtrl();
m_ImageList.Create(MAKEINTRESOURCE(IDB_IMAGES), 
            16, 1, RGB(255,255,255));

pPopupMFC->SetImageList(&m_ImageList);
pPopupMFC->EnableDragAndDrop(TRUE);
pPopupMFC->GetDefaultCell(FALSE, 
           FALSE)->SetBackClr(RGB(0xFF, 0xFF, 0xE0));
pPopupMFC->SetFixedRowCount(1);
pPopupMFC->SetFixedColumnCount(1);
pPopupMFC->SetRowCount(10);
pPopupMFC->SetColumnCount(5);
pPopupMFC->SetAutoSizeStyle();

TRY {
   pPopupMFC->SetRowCount(16);
   pPopupMFC->SetColumnCount(6);
   pPopupMFC->SetFixedRowCount(1);
   pPopupMFC->SetFixedColumnCount(1);
}
CATCH (CMemoryException, e)
{
   e->ReportError();
   return FALSE;
}
END_CATCH

// fill rows/cols with text
for (int row = 0; row < pPopupMFC->GetRowCount(); row++)
{
    for (int col = 0; col < 
         pPopupMFC->GetColumnCount(); col++)
    {  
        CString str;
        GV_ITEM Item;
        Item.mask = GVIF_TEXT;
        Item.row = row;
        Item.col = col;

        if (row < pPopupMFC->GetFixedRowCount())
            str.Format(_T("Column %d"),col);
        else if (col < pPopupMFC->GetFixedColumnCount()) 
            str.Format(_T("Row %d"), row);
        else 
            str.Format(_T("%d"),row*col);
            Item.strText = str;

        if (rand() % 10 == 1)
        {
            COLORREF clr = RGB(rand()%128 + 128, 
                     rand()%128 + 128, rand()%128 + 128);
            Item.crBkClr = clr; 
            Item.crFgClr = RGB(255,0,0); 
            Item.mask |= (GVIF_BKCLR|GVIF_FGCLR);
        }

        if (col < pPopupMFC->GetFixedColumnCount())
        {
           Item.iImage = rand()%m_ImageList.GetImageCount();
           Item.mask |= (GVIF_IMAGE);
        }
        pPopupMFC->SetItem(&Item);
    }
}

Update History

  • 1.0.0.202 April 19. 2006 - First release version.

License

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


Written By
Software Developer (Senior)
Bosnia and Herzegovina Bosnia and Herzegovina
Bahrudin Hrnjica holds a Ph.D. degree in Technical Science/Engineering from University in Bihać.
Besides teaching at University, he is in the software industry for more than two decades, focusing on development technologies e.g. .NET, Visual Studio, Desktop/Web/Cloud solutions.

He works on the development and application of different ML algorithms. In the development of ML-oriented solutions and modeling, he has more than 10 years of experience. His field of interest is also the development of predictive models with the ML.NET and Keras, but also actively develop two ML-based .NET open source projects: GPdotNET-genetic programming tool and ANNdotNET - deep learning tool on .NET platform. He works in multidisciplinary teams with the mission of optimizing and selecting the ML algorithms to build ML models.

He is the author of several books, and many online articles, writes a blog at http://bhrnjica.net, regularly holds lectures at local and regional conferences, User groups and Code Camp gatherings, and is also the founder of the Bihac Developer Meetup Group. Microsoft recognizes his work and awarded him with the prestigious Microsoft MVP title for the first time in 2011, which he still holds today.

Comments and Discussions

 
Question非常需要帮助和指导 Pin
Member 1399966027-Sep-18 21:43
Member 1399966027-Sep-18 21:43 
QuestionThis sample can not work with specifying Unicode character set Pin
bfm896-Jun-13 22:27
bfm896-Jun-13 22:27 
GeneralMy vote of 5 Pin
maplewang8-Aug-12 3:15
maplewang8-Aug-12 3:15 
GeneralCCstmComboBox::OnChildNotify failed receiving CBN_DROPDOWN ... messages Pin
kjt11-Jan-11 11:04
kjt11-Jan-11 11:04 
GeneralRe: CCstmComboBox::OnChildNotify failed receiving CBN_DROPDOWN ... messages Pin
bfm895-Jun-13 16:35
bfm895-Jun-13 16:35 
GeneralHelp getting the demo to work Pin
tim_fischer8-Dec-10 7:58
tim_fischer8-Dec-10 7:58 
GeneralRe: Help getting the demo to work Pin
tim_fischer8-Dec-10 8:22
tim_fischer8-Dec-10 8:22 
GeneralGreat Work Pin
sebilkullan16-Dec-09 22:16
sebilkullan16-Dec-09 22:16 
GeneralBuilding on VC 6.0 error Pin
maivantai15-Oct-08 17:53
maivantai15-Oct-08 17:53 
GeneralDropList-Problem Too Pin
JacMax9-Feb-08 8:11
JacMax9-Feb-08 8:11 
GeneralRe: DropList-Problem Too Pin
丁兵兵25-Mar-13 19:21
丁兵兵25-Mar-13 19:21 
QuestionDrop list problem Pin
kammi20-Sep-07 16:28
kammi20-Sep-07 16:28 
Generalcan,t work with xpstyle app Pin
ericdk18-Jun-07 19:06
ericdk18-Jun-07 19:06 
GeneralRe: can,t work with xpstyle app Pin
dragonhead72-Jul-07 16:46
dragonhead72-Jul-07 16:46 
GeneralRe: can,t work with xpstyle app Pin
ericdk2-Jul-07 23:48
ericdk2-Jul-07 23:48 
QuestionHow do you subclass the CListBox to your custom control? Pin
sshhit18-Apr-07 0:02
sshhit18-Apr-07 0:02 
AnswerRe: How do you subclass the CListBox to your custom control? Pin
Jon Feider29-May-07 21:55
Jon Feider29-May-07 21:55 
GeneralDoesn't work with XP themes Pin
GeorgDuroy20-Dec-06 23:08
GeorgDuroy20-Dec-06 23:08 
GeneralCan't work on MDI Pin
pjmvn_codeproject19-Sep-06 17:15
pjmvn_codeproject19-Sep-06 17:15 
GeneralRe: Can't work on MDI Pin
Bahrudin Hrnjica20-Sep-06 21:09
professionalBahrudin Hrnjica20-Sep-06 21:09 
GeneralLVS_OWNERDATA & ListCtrl Pin
Raffaele Eugenelo10-May-06 0:05
Raffaele Eugenelo10-May-06 0:05 
GeneralRe: LVS_OWNERDATA & ListCtrl Pin
Bahrudin Hrnjica10-May-06 10:50
professionalBahrudin Hrnjica10-May-06 10:50 
As you already know,list box sends LVN_GETDISPINFO to its parent. Scince the parent window of the PopupListCtrl is Desktop window, you cannot get notification.
GeneralRe: LVS_OWNERDATA & ListCtrl Pin
GeorgDuroy20-Dec-06 23:04
GeorgDuroy20-Dec-06 23:04 
GeneralThanks Pin
pgiustinoni5-May-06 12:56
pgiustinoni5-May-06 12:56 
GeneralRe: Thanks Pin
Bahrudin Hrnjica6-May-06 0:17
professionalBahrudin Hrnjica6-May-06 0:17 

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.