Introduction

This tutorial will show how use the CComboBox class in a very basic dialog based application. It will cover the following points:

Adding a CComboBox to your dialog

Changing the height of the Dropdown List

The difference in behaviour of the 3 styles of CComboBox

Inserting/Adding items to the CComboBox

Changing the width of the dropdown list

Using item data

Determining which item is selected

Selecting items

Handling CComboBox messages

Enhancements

A ComboBox is a composite control that consists of an Edit control and a List box control. This tutorial assumes the you are comfortable with creating a dialog based application using the VC++ 6
Class Wizard. If you require information on this topic consult the article A Beginners Guide to Dialog Base Applications - Part 1.

Adding a CComboBox to your dialog

When your dialog-based application is generated, go to the Resources in the Workspace window. Select the dialog
IDD_COMBOBOXTUTORIAL_DIALOG in the Dialog section. To insert the ComboBox control, select it from the Control palette. The cross shaped cursor indicates where the
centre of the edit control portion of the combobox will be placed.

Changing the height of the Dropdown List

Right click on the ComboBox's 'dropdown' button. This will indicate the present size the combo box, including the
extended list box. Then resize it by dragging out the rectangle as you would any other control.

The different in behaviour of the 3 styles of CComboBox

There are three different styles of combo box with different selection properties. To change the style of the combo box Right click on it and select Properties. Then select the Styles tab.

Simple type has a permanently open list box and you are able to type in Edit control.

Dropdown type has a 'closed' list box which can be opened by clicking on the 'drop down' button. The Edit control WILL accept input.

Drop List type has a 'closed' list box which can be opened by clicking on the 'drop down' button. The Edit control will NOT accept any input.

Inserting/Adding items to the CComboBox

It is possible to add items to the combo box at coding time. This is handy for data that will never need to changed. To do this select the Data tab and add the item, one per line. Use Ctrl+Return to go the next line.

It is however more usual and more flexible to load the items into the combo box at run time. This way they can be loaded from resources and be localized or be changed according other user choices.

In the demonstration you will see that Dropdown combo is loaded from string resources, the Drop List initially uses the list that was set up in the Data tab, and the Simple combobox is left empty.

To ensure that the Simple combobox is empty we simply call the CComboBox class ResetContent() function.

m_Simple.ResetContent();

The Dropdown is loaded from string resources by the following for loop, simply call the AddString() member function of the CComboBox class.

If you then click on the Insert Long Text Item check box the string "" will inserted after the 3rd Option in the Drop List combo box.

Firstly the index of the string needs to found, and we simply call the InsertString() member function of the CComboBox class.

int idx = m_DropList.FindString(0, "3rd Option");
CString str;
str.LoadString(IDS_STRING108);
// we add one because we want it after
m_DropList.InsertString(idx+1, str);

The main thing to be careful of when using InsertString() is that index represents the position before it will be inserted. If the index is -1 the insert will at the end of the list. (i.e. the same as AddString())

Changing the width of the dropdown list

It is best to design the dialog so the combo box can be large enough to fully display the longest option. This is not always possible however. In this case it is handy to widen the drop list so that the entire string can be seen while selecting.

The CComboBox class has a function SetDroppedWidth() for this purpose. This function's input parameter is the outside width of the of the drop list in pixels. First you need the Device Context of the combo box. Then check the length of all the strings in pixels to find the longest.

Note we must also allow for the width of the Scroll bar and window border.

You will notice that Class Wizard will only allow you attach an integer variable to a DropList Combo box and a CString variable to the DropDown and Simple Combo boxes.

You can add the Data Exchange entry to attach the alternate variable type manually, but the entry and the variable declaration must be placed outside the AFX_DATA_MAP and AFX_DATA tags so that Class Wizard won't remove them.

Check the string in CBN_SELCHANGE handler after the call to UpdateData().

Selecting items

Selecting an item can be done by setting the index as below. If you use the integer variable call UpdateData(FALSE);

You can use SetCurSel( index )

OR use SelectString( after, str ) where after is the index after which to start searching. As you can see from the demo the items are added in a different order to which they are displayed and the data remains matched.

If you know that the index can never be set to one lager than the number of items in the list the code can be left as it is. If there is a risk of this however then it is wise to check and either set the index to a default item or send a message box to the user waring of the error.

Using item data

A combo box returns a zero based index of the selected item or the string as shown above. Often the program actually uses a value other than the string or the index, and what's more you need to get this value correct whether the items in the list are sorted or not. If the application is to support multiple languages this is even more important because sorting can be different.

To assists with this each item in the list can have a DWORD associated with it, and this remains attached to the string regardless of the sorting.

Use SetItemData( idx, dwData ) and GetItemData( idx ). When setting the data use the index returned by the AddString() or InsertString() functions to ensure you get it right.

Handling CComboBox messages

CBN_ERRSPACE notification message is sent when a combo box cannot allocate enough memory.

CBN_SELCHANGE notification message is sent when the user changes the current selection in the list box of a combo box.

CBN_DBLCLK notification message is sent when the user double-clicks a string in the list box of a combo box.

CBN_SETFOCUS notification message is sent when a combo box receives the keyboard focus.

CBN_KILLFOCUS notification message is sent when a combo box loses the keyboard focus.

CBN_EDITCHANGE notification message is sent after the user has taken an action that may have altered the text in the edit control portion of a combo box.

CBN_EDITUPDATE notification message is sent when the edit control portion of a combo box is about to display altered text.

CBN_DROPDOWN notification message is sent when the list box of a combo box is about to be made visible.

CBN_CLOSEUP notification message is sent when the list box of a combo box has been closed.

CBN_SELENDOK notification message is sent when the user selects a list item, or selects an item and then closes the list.

CBN_SELENDCANCEL notification message is sent when the user selects an item, but then selects another control or closes the dialog box.

The demo handles the CBN_SELCHANGE and CBN_EDITUPDATE messages. The CBN_EDITUPDATE is handy if you like to prevent some characters from being typed.

The code below is for demonstration only and this kind of validation is best carried out by the control itself. This would involve subclassing the control and overriding of some functions. This more complex topic is discussed elsewhere on this site.

A word or two of caution. Validation can also be done in the CBN_KILLFOCUS handler. If you do this take care in the way you change incorrect data back and pop up message boxes that also take focus from the control. The program can finish up in an unfortunate loop of validation and message box display.

Enhancements

Some code you may like to play with, is to vary the number of lines of items displayed in the drop down list. This will prevent empty lines at the end of the list and change the height from what was set in the resource editor. The framework does handle some of these things already but sometimes it good to have the control.

The ENTER key, by default, is only processed by the combo box when the drop list is open, and in this case it has the same effect as a mouse click and makes the selection. A Simple combo box does not process the ENTER key at all and is passed to the parent dialog. If you wish to handle the ENTER key in any other way the combo box will need to be subclassed and handler written for the purpose. You may like to check out Implementing an autocompleting Combobox - By Chris Maunder as a starting point to which the handler can be added.

Conclusion

The Message handlers in this tutorial are the most commonly used and should indicate that they need not be very complex. More complex issues are handled elsewhere on this site.

Happy programming!

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

Started working with computers when I/O was with punched paper tape, using Algol. Then learned Fortran, Basic, various Assemblers, Forth and Postscript. Built a robot in the early '80s. When I finally got a PC I learned C, C++ and more recently worked on a variety of .NET and PHP projects. Senior Software Engineer at MedTech Global in Melbourne, Australia.

I had the same need. I want to have the Edit box but I don't want the user to be able to edit the text but I do want them to be able to select and copy from it. So, if using CBS_DROPDOWNLIST isn't exactly what you wanted, try using GetComboBoxInfo. You'll get a handle to the edit box which you can then send a message to tell it to be ReadOnly like this: