Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / MFC

Custom ComboBox

4.80/5 (21 votes)
4 May 2006CPOL4 min read 3   7.7K  
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)