Home

Combo Boxes

    

Introduction to the Combo Box

 

Description

A combo box is a Windows control that holds a list of items. Each item can be a null-terminated string or it can be made of a bitmap and a string. In fact, there are various types of combo boxes.

As far as looks are concerned, there are two types of combo boxes. The most regularly used combo box is made of two sections. The main part is an edit box. On the right of the edit box, there is a button with a down pointing arrow:

Combo Box

To use this type of combo box, the user would click the down pointing arrow button. This causes a list of items to display:

Combo Box

If the user finds the desired item in the list, he or she can click it. The item clicked becomes the selection and it gets in the edit box side of the combo box:

Combo Box

If the user does not find the desired item, he or she can click the down pointing arrow. In this case, no selection is made and the combo box remains as it was before the button was clicked, whether it had an item or not.

A combo box is called "Drop Down" or Drop List if it is made of an edit box and a down pointing arrow, as described above. Another type of combo box is referred to as Simple. This kind displays its items like a list box. The user does not have to click an arrow button to display the list. When a simple combo box displays, the user can locate the desired item in the list and click it. The selected item becomes the value of the edit side.

Combo Box

A combo box is used to display a list of items to the user to select from. A combo box allows the user to select only one item from the list. If the number of items is higher than the allocated space can accommodate, the combo box is equipped with a vertical scroll bar, whether it is a drop type or a simple kind.

A combo box (especially the drop kinds) has the advantage of saving space as it can use only as much space as a combination of an edit box and a small button.

Practical LearningPractical Learning: Introduction to Combo Boxes

  1. Start Microsoft Visual Studio
  2. To start a new application, on the main menu, click File -> New Project...
  3. In the middle list, click MFC Application and set the Name to ClarksvilleIceCream1
  4. Click OK
  5. In the first page of the wizard, click Next
  6. In the second page of the wizard, click Dialog-based and set the Dialog Title to Clarksville Ice Cream
  7. Click Finish
  8. Delete the TODO line and the OK button
  9. Change the caption of the Cancel button to Close
  10. Move the Close button to the bottom-right section of the dialog box

Creating a Combo Box

To visually create a combo box, in the Toolbox, click the Combo Box button Combo Box and click the dialog box.

A combo box is based on the CComboBox class that is derived from CWnd. Therefore, if you want to dynamically create this control, declare a variable or a pointer to CComboBox using its default constructor. To initialize the control, call its Create() member function. Its syntax is:

virtual BOOL Create(DWORD dwStyle,
   		    const RECT& rect,
   		    CWnd* pParentWnd,
   		    UINT nID);

Here is an example of programmatically creating a combo box:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE,
		   CRect(10, 50, 100, 150), this, 0x1448);

    return TRUE; // return TRUE unless you set the focus to a control
}

The Styles of a Combo Box

 

The Drop-Down Combo Box

By default, a newly added combo box is a drop down type. The kind of display is visually controlled by the Type combo box in the Properties window. The default value is Dropdown.

To programmatically create a drop down combo box, add the CBS_DROPDOWN style.

Practical LearningPractical Learning: Creating Combo Boxes

  1. Design the dialog box as follows:
     
    Clarksville Ice Cream
     
    Control Caption ID Other Properties
    Group Box Group Box      
    Static Text Static Text Order &Date:    
    Edit Box Edit Control   IDC_ORDER_DATE Input Template: __/__/____
    Mask: DD DD DDDD
    Static Text Static Text Order &Time:    
    Edit Box Edit Control   IDC_ORDER_TIME Input Template: __:__
    Mask: DD DD
    Static Text Static Text &Flavor:    
    Combo Box Combo Box   IDC_FLAVORS  
    Static Text Static Text &Container:    
    Combo Box Combo Box   IDC_CONTAINERS  
    Static Text Group Box &Ingredients:    
    Combo Box Combo Box   IDC_INGREDIENTS  
    Static Text Group Box &Scoops:    
    Edit Box Edit Control   IDC_SCOOPS Align Text: Right
    Number: True
    Button Button Calculate ID_CALCULATE  
    Static Text Group Box &Order Total:    
    Edit Box Edit Control   IDC_ORDER_TOTAL Align Text: Right
    Static Text Static Text Notes:    
    Edit Box Edit Control   IDC_NOTES Auto HScroll: False
    Auto VScroll: False
    Multiline: True
    Vertical Scroll: True
  2. Right-click each of the edit controls and click Add Variable...
  3. Create the variables as follows:
     
    ID
    Category Type Name
    IDC_ORDER_DATE Value CString m_OrderDate
    IDC_ORDER_TIME Value CString m_OrderTime
    IDC_FLAVORS Control CComboBox m_Flavors
    IDC_FLAVORS Value CString m_Flavor
    IDC_CONTAINERS Control CComboBox m_Containers
    IDC_CONTAINERS Value CString m_Container
    IDC_INGREDIENTS Control CComboBox m_Ingredients
    IDC_INGREDIENTS Value CString m_Ingredient
    IDC_SCOOPS Value int m_Scoops
    IDC_ORDER_TOTAL Value double m_OrderTotal
    IDC_NOTES Value CString m_Notes
  4. To execute and preview the dialog box, press F5
  5. Close the dialog box and return to your programming environment

Auto-Scrolling

A drop down combo box allows the user to type a new value if the desired string is not in the list. with this type, the user can click the edit side of the control and start typing. If the user types a string that is longer than the width of the edit box part, the control would cause the computer to start making a beep sound, indicating that the user cannot type beyond the allocated length. If you want the user to be able to type a long string, check or set to True the Auto HScroll property. If you are programmatically creating the control, you can do this by adding the CBS_AUTOHSCROLL style.

The Drop-Down List

If you don't want the user to be able to type a new string, set the Type property to Drop List. To programmatically get the same behavior, add the CBS_DROPDOWNLIST style to the combo box. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST,
		   CRect(10, 10, 140, 150), this, 0x1448);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

With this type, whether the user clicks the edit part or the arrow button, the list would drop. If the user finds the desired value and clicks it, the list retracts and the new selection displays in the edit part of the control. If the user does not find the desired item in the list, he or she can click the edit box or the arrow button. In this case, the selection would not be changed.

A Combo Box With a Simple Style

If you want the list part of the combo box to always display, visually set the Type property to Simple in the Properties window. If you are programming creating the combo box, add the CBS_SIMPLE style. In reality, this is the default set by the operating system. That is, if you are programmatically creating a combo box and add only the default controls styles (WS_CHILD and WS_VISIBLE), the object would be created as a simple combo box.

The Vertical Scroll Bar

As described above, when the list of items is too long for the reserved rectangular area of the list side to display, the control gets automatically equipped with a vertical scroll bar. This is because its Vertical Scroll property is automatically set to True in the Properties window.

If you allow or add this style, if the list is not too long and can be accommodated by the rectangle, no scroll bar would be displayed. If the list is too long and you set this property, then a vertical scroll bar would automatically appear on the control. If you insist on displaying a vertical scroll bar even if the rectangle is long enough to display all items, in the Properties window, set the Disable No Scroll field to True. In this case, if the rectangle can accommodate all items, a disabled vertical scroll bar would appear on the control.

If you want the operating system to decide if or when to equipped the combo box with a vertical scroll bar, in the Properties window, set the Vertical Scrollbar field to True. If you are programmatically creating the control, add the WS_VSCROLL style.

An Owner-Draw Combo Box

The combo boxes we have mentioned so far are responsible for creating and updating their list. You can create a combo box that relies on its owner for all related operations. Such a combo box is referred to as owner draw.

When an owner is responsible for drawing the items of a combo box, it can set the value of each item as it sees fit. For example, different items of the same list can use different fonts. They can display different types of items and they can even draw anything on their line.

The ability to feature a combo box as owner draw or not is specified using the Owner Draw combo box of the Properties window. Its default value is No. To create an owner draw combo box where all items have the same height, set this property to the Fixed value. This is equivalent to adding the CBS_OWNERDRAWFIXED style to a dynamic combo box. On the other hand, if you want items to have different heights, set the Owner Draw value to Variable or create the control with a CBS_OWNERDRAWVARIABLE style.

 
 
 

Operations on the Strings of a Combo Box

 

Introduction to Combo Box Messages and Events

When you add or create a combo box, an amount of space is allocated and during the lifetime of your application, the combo box uses some memory to perform its assignments. If at one time there is not enough memory for a processing, the combo box sends an ON_CBN_ERRSPACE message. The event related to this message doesn't take an argument.

Like any control, for the user to use the combo box, it must first have focus. This can be done by the user clicking its edit part, its list part (for a Simple combo box) or its down pointing arrow (for a drop-type combo box). When the combo box receives focus, it sends the ON_CBN_SETFOCUS message. The event related to this message doesn't take an argument.

Once the control has focus, if the user clicks or had clicked the edit control side of the combo box that already had a selected item, if the user starts typing, which would modify the string of the item that was already selected, the combo box would send the ON_CBN_EDITCHANGE message (remember that the user can change the string only if the combo box was not created as Drop List). The event related to this message doesn't take an argument.

If the user finishes typing or changing the string, just before the altered string is validated, the combo box sends the ON_CBN_EDITUPDATE message. The event related to this message doesn't take an argument.

Adding a String to a Combo Box

After adding a combo box, if you want to immediately create its strings, in the Properties window, click the Data field. To create the list of items, type the items separated by a semi-colon. An example would be:

Small;Medium;Large;Jumbo

To let you programmatically add a string to a combo box, the CComboBox class is equipped with a member function named AddString. Its syntax is:

int AddString(LPCTSTR lpszString);

This member function takes one argument as the string to be added to the combo box. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    SetIcon(m_hIcon, TRUE); // Set big icon
    SetIcon(m_hIcon, FALSE); // Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE,
		   CRect(10, 50, 100, 150),
		   this, 0x1448);

    Majors->AddString(L"Accounting");
    Majors->AddString(L"Art Education");
    Majors->AddString(L"Finance");
    Majors->AddString(L"Biology");

    return TRUE; // return TRUE unless you set the focus to a control
}

This would produce:

Combo Box

To let you know the number of items in a combo box, the CComboBox class is equipped with the GetCount() member function. Its syntax is:

int GetCount() const;

ApplicationTopic Applied: Adding Strings to a Combo Box

  1. To create a list of items, on the dialog box, click the Flavors combo box (the combo box on the right side of the Flavor static text)
  2. In the Properties window, click Data and type Other;Vanilla;Butter Pecan;Cream of Cocoa;Chocolate Chip;Organic Strawberry;Banana Coconut
  3. On the dialog box, click the Containers combo box
  4. In the Properties window, click Data and type Cone;Cup;Bowl;Other
  5. On the dialog box, click the Ingredients combo box
  6. In the Properties window, click Data and type None;M & M;Cookies;Peanuts;Mixed Nuts

Inserting a String

You can insert a string inside the list of items of a combo box. You will have to provide the 0-based position of the new string and its value. To support this, the CComboBox class is equipped with the InsertString() member function. Its syntax is:

int InsertString(int nIndex, LPCTSTR lpszString);

The first argument represents the index of the second argument. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE,
		   CRect(10, 10, 160, 120),
		   this, 0x1448);

    Majors->AddString(L"Accounting");
    Majors->AddString(L"Art Education");
    Majors->AddString(L"Finance");
    Majors->AddString(L"Biology");

    Majors->InsertString(1, L"Journalism");

    return TRUE;  // return TRUE  unless you set the focus to a control
}

This would produce:

Combo Box

Sorting the Strings of a Combo Box

By default, the strings of a combo box are added to the list in a sequential order. If you want, you can make the control re-order its list. To do this visually, after adding the control to a dialog box, in the Properties window, set the value of the Sort field.

If you are programmatically creating the control and you want to sort its items, add the CBS_SORT style. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE | CBS_SORT,
		   CRect(10, 10, 160, 120),
		   this, 0x1448);

    Majors->AddString(L"Biology");
    Majors->AddString(L"Accounting");
    Majors->AddString(L"Art Education");
    Majors->AddString(L"Finance");

    return TRUE;  // return TRUE  unless you set the focus to a control
}

This would produce:

Combo Box

If add some strings to a combo box, then programmatically sort the list, the items would be sorted. If you add a new item, it would be added to the end of the list. If you insert an item, it would be put in the position you indicated, ignoring the sorting. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE | CBS_SORT,
		   CRect(10, 10, 160, 120),
		   this, 0x1448);

    Majors->AddString(L"Biology");
    Majors->AddString(L"Accounting");
    Majors->AddString(L"Art Education");
    Majors->AddString(L"Finance");

    Majors->InsertString(1, L"Journalism");

    return TRUE;  // return TRUE  unless you set the focus to a control
}

This would produce:

Combo Box

Practical LearningPractical Learning: Unsorting a Combo Box

  1. On the dialog box, click the top dialog box
  2. In the Properties window, double-click Sort to change its value to False
  3. In the same way, set the Sort field to False for the other combo boxes

Selecting an Item

To select an item from the list, the user can click it. To let you programmatically select an item, the CComboBox class is equipped with a member function named SetCurSel. Its syntax is:

int SetCurSel(int nSelect);

This function takes as argument the 0-based index of the item you want to select. Here is an example:

BOOL CExerciseDlg::OnInitDialog()
{
    CDialogEx::OnInitDialog();

    // Set the icon for this dialog.  The framework does this automatically
    //  when the application's main window is not a dialog
    SetIcon(m_hIcon, TRUE);			// Set big icon
    SetIcon(m_hIcon, FALSE);		// Set small icon

    // TODO: Add extra initialization here
    CComboBox *Majors = new CComboBox;

    Majors->Create(WS_CHILD | WS_VISIBLE | CBS_SORT,
		   CRect(10, 10, 165, 120),
		   this, 0x1448);

    Majors->AddString(L"Biology");
    Majors->AddString(L"Accounting");
    Majors->AddString(L"Art Education");
    Majors->AddString(L"Finance");
    Majors->InsertString(1, L"Journalism");

    Majors->SetCurSel(2);

    return TRUE;  // return TRUE  unless you set the focus to a control
}

This would produce:

Combo Box

As mentioned already, to select an item from a drop type combo box, the user usually clicks the down pointing arrow button to display the control's list. When the user clicks that button, just before the list displays, the control sends the ON_CBN_DROPDOWN message. The event related to this message takes no argument.

After this click and this message, the list part of a drop combo box displays and the user must make a decision:

  • If the user finds the desired item in the list, he or she must let the combo box know. This is done by highlighting it. To do this, the user can either click (with the mouse) or press the arrow keys (on the keyboard) to indicate his or her choice. When this highlighting occurs, the combo box sends the ON_CBN_SELCHANGE message, notifying the application that the combo box's selection may be changed soon. The event related to this message doesn't take an argument
  • Once the user has found the desired item and has possibly highlighted it, if using the mouse, he or she can click to select it. If using the keyboard, after locating the item, the user can press Enter. Clicking the desired item or pressing Enter on the highlighted string means that the user has made a definite selection. This causes the control to send an ON_CBN_SELENDOK message, notifying the application that the user has made his or her decision. The event related to this message doesn't take an argument
  • If the user did not find the desired item, he or she may want to dismiss the combo box without making a selection. There are three main ways the user can invalidate a selection. If the user clicks another control or another application, if the list was displaying, it would retract and no selection would be made, event if the user had already highlighted an item. If the user clicks either the edit box part of the combo box of a Drop List type or the down pointing button, the selection is dismissed and if the list of a drop type was displaying, it would retract. If the user presses Esc, the selection would be dismissed.
    Any of these actions causes the selection to be dismissed or the user to cancel the selection action. This causes the combo box to send an ON_CBN_SELENDCANCEL message. The event related to this message doesn't take an argument

Once the user has clicked an item or pressed Enter to validate a selection, if the combo box was created not as Simple, the list part of the control retracts to hide itself. At this time, the combo box sends an ON_CBN_CLOSEUP message. The event related to this message doesn't take an argument.

If the user finishes using the combo box and moves to another control, the combo box sends an ON_CBN_KILLFOCUS message, notifying the application that it (the combo box) has lost focus. The event related to this message doesn't take an argument.

ApplicationTopic Applied: Selecting an Item

  1. On the dialog box, click the Flavor combo box (the combo box to the right of Flavor)
  2. In the Properties window, the Control Events button Control Events
  3. Click the right side of CBN_SELCHANGE, then click the arrow of its combo box and select the <Add> item in it
  4. Implement the event as follows:
    void CClarksvilleIceCream1Dlg::OnCbnSelchangeFlavors()
    {
        // TODO: Add your control notification handler code here
        CString Flavors[] =
        {
    	_T(""),
    	_T("Vanilla Extract, Milk, Sugar, Flour, Egg Yolks, Ice Cream Freezer, Salt"),
    	_T("Vanilla Extract, Toasted Chopped Pecan, Light Cream, Brown Sugar, Butter"),
    	_T("Dry Powdered Cocoa, Vanilla, Salt, Sugar, Cornstarch, Milk, Syrup"),
    	_T("Cocoa, Unsweetened Chocolate, Whole Milk, Evaporated Milk, Vanilla, Sugar, Eggs, Salt"),
    	_T("Strawberry, Vanilla, Almond, Sugar, All-Purpose Flour, Salt, Milk, Eggs"),
    	_T("Shredded Coconut, Kosher Gelatin, Guava, Honey, Vanilla Soy Milk, Mashed Bananas"),
        };
    
        m_Notes = Flavors[m_Flavors.GetCurSel()];
        UpdateData(FALSE);
    }
  5. Return to the dialog box
  6. Double-click the Calculate button
  7. Implement the event as follows:
    void CClarksvilleIceCream1Dlg::OnBnClickedCalculate()
    {
        // TODO: Add your control notification handler code here
        UpdateData();
        double PriceContainer = 0.00,
    	   PriceIngredient = 0.00,
               PriceScoops = 0.00,
               OrderTotal = 0.00;
        int NumberOfScoops = 1;
    
        // Find out what container the customer requested
        // The price of a container depends on which one the customer selected
        if( m_Containers.GetCurSel() == 0 )
            PriceContainer = 0.55;
        else if( m_Containers.GetCurSel() == 1)
            PriceContainer = 0.75;
        else
            PriceContainer = 1.15;
    
        // If the customer selected an ingredient, which is not "None", add $.95
        if( m_Ingredients.GetCurSel() != 0 )
            PriceIngredient = 0.95;
    
        // Get the number of scoops
        NumberOfScoops = m_Scoops;
    
        if( NumberOfScoops == 2 )
            PriceScoops = 2.55;
        else if( NumberOfScoops == 3 )
            PriceScoops = 3.25;
        else
            PriceScoops = 1.85;
    
        OrderTotal = PriceScoops + PriceContainer + PriceIngredient;
    
        m_OrderTotal = OrderTotal;
        UpdateData(FALSE);
    }
  8. To execute, press F5
  9. Enter some values and make selections in the combo boxes
  10. Click Calculate. Here is an example:
     
    Clarksville Ice Cream
  11. Close the form and return to your programming environment

Finding a String in the Combo Box

Instead of simply selecting an item from a combo box, the user may want to find out if a certain string exists in the  list. To support this operation, the CComboBox class is equipped with a member function named FindString. Its syntax is:

int FindString(int nStartAfter, LPCTSTR lpszString) const;

This method takes as arguments the index where to start looking for a string. If the item is found in the list, the member function returns its position. If the list does not have that string, the member function return -1.

The FindString() member function performs its operation without regards to case. This means that it would perform the same search for BlindMan, Blindman, blindMan, or BLINDMAN and would produce the same result for them. If you want the case of the characters to be taken into consideration, use the FindStringExact() member function. Its syntax is:

int FindStringExact(int nIndexStart, LPCTSTR lpszFind) const;

This member function proceeds like FindString() method by starting to look for the string from the beginning of the list.

Deleting Strings From a Combo Box

To let you remove a string from a combo box, the CComboBox class is equipped with a member function named DeleteString. Its syntax is:

int DeleteString(UINT nIndex);

To let you delete all items from a combo box, the CComboBox class provides the Clear() member function. Its syntax is:

void Clear();
 
 
   
 

Home Copyright © 2010-2011 FunctionX, Inc.