List boxes and combo boxes are two types of controls that are used often in Windows programming. The list box often is used to enable a user to select from a large number of possible choices, whereas the combo box is a combination of the list box and edit controls. In this section, you will learn about these controls and use them in simple examples.
CString szMsg;
szMsg.Format("This is loop number %d", nLoopCounter);
int nLoopCounter = 0;
while(nLoopCounter < 10)
{
nLoopCounter++;
AfxMessageBox(szMsg);
}
AfxMessageBox("The loop is finished");
In Listing 7.1, the compound statement following the while loop
is executed as long as nLoopCounter is less than 10. When nLoopCounter
is equal to 10, the condition tested by while becomes false,
and the next statement following the block controlled by while
is executed. In this example, a compound statement is executed; however,
a single statement can also be executed.
Compound statements were discussed in Section 5. A compound statement is a group of statements that are enclosed within curly braces.
#include <iostream>
using namespace std;
int main()
{
char ch;
do{
cout << "\nPress `Q' to exit ->";
cin >> ch;
// Ignore input until a carriage return.
cin.ignore( 120, `\n');
}while( ch != `Q' );
cout << "Goodbye" << endl;
return 0;
}
CString szMsg;
szMsg.Format("This is loop number %d", nLoopCounter);
for(int nLoopCounter = 0; nLoopCounter < 10; nLoopCounter++)
{
AfxMessageBox(szMsg);
}
AfxMessageBox("The loop is finished");
There are four components to every for statement:
for( expression1; expression2; expression3 ) statement1When the for loop begins, expression1 is executed. This is usually where you declare loop counters. As long as expression2 is true, the statement controlled by the loop is executed. After the controlled statement (statement1) has been performed, expression3 is executed. Loop counters are usually incremented in expression3.
Just a Minute: In the example provided in Listing 7.3, the expression nLoopCounter++ was used as a way to increment the value of nLoopCounter by one. To decrement the value, you can use nLoopCounter--.
Time Saver: As a rule of thumb, if the loop is executed a fixed number of times, it's usually easier to use for instead of while. However, if you are waiting for an event to occur, or if the number of loops isn't easily predicted, it's better to use while.
New Term: A single selection list box enables one item to be selected at a time. This is the default style for a list box.
New Term: A multiple selection list box enables multiple items to be selected at one time.
A list box normally is found in a dialog box, control bar, or other window that contains controls. List boxes often are used to contain a large number of items. If some items cannot be displayed, a scrollbar is displayed to help the user navigate through the list.
List boxes are also extremely easy to program. If you have created a list box object, you can add an item to the list box with just one line of code, like this:
listBox.AddString("Gwen");
No other control is as flexible and easy to use for both the programmer
and the user.
Just a Minute: The list box is also the first control you have seen that uses indexes. Whenever an item is selected, inserted, or deleted, a zero-based index is used to identify the item. This index can be synchronized with a database index or used to identify the item in other ways.
You can use the MFC CListBox class to manage and interact with the list box control. Like other control classes, CListBox is derived from CWnd, and most CWnd functions can be used with CListBox objects. You will see more details about the CListBox later, in the section, "Using the CListBox Class."
Adding a list box to IDD_LISTBOX_DIALOG, the main dialog box, is just like adding a button or edit control. Either drag and drop a list box control from the control palette to the main dialog box, or select the list box control on the tool palette using the mouse, and click the desired position in the main dialog box. Figure 7.1 shows the IDD_LISTBOX_DIALOG with a list box control.
The main dialog box used in the ListBox sample program.
Open the Properties dialog box for the list box by right-clicking the control and selecting Properties from the shortcut menu. Change the resource ID to IDC_LIST. Set all other properties to their default values.
2. Select the CDialog-derived class that manages the dialog box; in this case, CListBoxDlg.
3. Select the Member Variables tab.
4. Select the control ID representing the control associated with the new member variable; in this case, IDC_LIST.
5. Click the button labeled Add Variable. An Add Member Variable dialog box appears. Enter the control's name, category, and variable type; then click OK. For this example, use the values from Table 7.1.
| Control ID | Variable Name | Category | Type |
| IDC_LIST | m_listBox | Control | CListBox |
m_listBox.AddString( "Rene'" );
m_listBox.InsertString( 0, "Alex" );
// TODO: Add extra initialization here m_listBox.AddString( "Foo" ); m_listBox.AddString( "Bar" ); m_listBox.AddString( "Baz" );To determine the number of items currently in a list box, use the GetCount member function:
nItems = listBox.GetCount();
CAUTION: The GetCount function returns the total number of items in a list box, not the value of the last valid index. If a list box contains five items, GetCount returns five, but the last valid index is four.
listBox.DeleteString(8);This line removes the item in the ninth position of the list box. Remember, all list box position indexes start from zero. The return value from the DeleteString member function is the number of items remaining in the list box, or LB_ERR if any errors occur. The return value can be used like this:
int nItems = listBox.GetCount(); while(nItems > 3 && nItems != LB_ERR ) nItems = listBox.DeleteString(nItems - 1);This code removes the contents of a list box, except for the first three items. To clear a list box completely, use the ResetContent function:
listBox.ResetContent();The ResetContent function returns void.
The steps to add message-handling functions for any of the controls used in Windows are very similar. To create a message-handling function for the LBN_DBLCLK notification message, follow these steps:
2. Select the CListBoxDlg class and the IDC_LIST Object ID.
3. Select LBN_DBLCLK, and click the Add Function button.
4. Accept the suggested function name CListBoxDlg::OnDblclkList.
5. Click the button labeled Edit Code.
6. Add the source code from Listing 7.5 to the CListBoxDlg::OnDblclkList function.
void CListBoxDlg::OnDblclkList()
{
int nSelection = m_listBox.GetCurSel();
if( nSelection != LB_ERR )
{
CString szSelection;
m_listBox.GetText( nSelection, szSelection );
AfxMessageBox( szSelection );
}
}
Compile and run the ListBox project and then double-click any of the list
box items. The LBN_DBLCLK message is sent to the CListBoxDlg::OnDblclkList
function, and a message box is displayed with information about the selected
item.
You can determine the currently selected item in the list box by using the CListbox::GetCurSel member function, as shown in Listing 7.5. The GetCurSel member function returns the position of the currently selected item, with the first item position starting at zero. If no item is selected, or if the list box has the multiple-selection property, LB_ERR is returned.
Combo boxes are quite useful when a user is not limited to selecting only the items presented in a list box. The list box portion of the combo box can be used to display recent selections, giving the user the freedom to enter a new selection in the edit control.
There are three types of combo boxes:
Just a Minute: Combo boxes also are used when space in a dialog box is at a premium. A large number of choices in a combo box can be hidden until the combo box is opened, enabling more controls to be placed in a smaller area than that required for a list box.
You use the MFC CComboBox class to manage and interact with the combo box control, and it contains many of the member functions that are available in the CListBox and CEdit classes. For example, you can use GetCurSel to get the currently selected item from the list box part of a combo box.
comboBox.AddString( "Riley" );or
comboBox.InsertString( 0, "Mitch" );All positions in a combo box are numbered beginning with zero, just like list boxes. However, if an error occurs, CB_ERR is returned instead of LB_ERR. If an item cannot be added due to insufficient space, CB_ERRSPACE is returned.
To determine the number of items currently in a combo box, CComboBox includes the GetCount member function:
nItems = comboBox.GetCount();Remember, CB_ERR is returned instead of LB_ERR when using a CComboBox object.
2. Add a drop-down combo list to the IDD_COMBOLIST_DIALOG resource, as you did for the list box earlier in this section.
3. Give the combo box the resource ID IDC_COMBO. Use the default values for all other properties.
4. Add a static-text control to the dialog box, and give it the resource ID IDC_RESULT. This text control will be used to display information about messages received from the combo box.
5. Using ClassWizard, add a member variable to the CComboListDlg class named m_comboList. Set the Category to Control.
6. Using ClassWizard, add a message-handling function for the IDOK control BN_CLICKED message to the CComboListDlg class.
7. Using ClassWizard, add message-handling functions for IDC_COMBO control messages to the CComboListDlg class. Add functions to handle CBN_CLOSEUP and CBN_EDITUPDATE messages.
// In OnInitDialog... // TODO: Add extra initialization here m_comboList.AddString( "Foo" ); m_comboList.AddString( "Bar" ); m_comboList.AddString( "Baz" );
void CComboListDlg::OnOK()
{
CString szCombo;
m_comboList.GetWindowText( szCombo );
AfxMessageBox( szCombo );
int nChoice = m_comboList.GetCurSel();
szCombo.Format( "The current selection is %d", nChoice );
AfxMessageBox( szCombo );
CDialog::OnOK();
}
void CComboListDlg::OnCloseupCombo()
{
CString szChoice;
CString szResult;
int nChoice;
// Get current selections from edit and list-box controls
m_comboList.GetWindowText( szChoice );
nChoice = m_comboList.GetCurSel();
if( nChoice != CB_ERR )
{
// If a valid choice was made from the list box, fetch
// the item's text string.
m_comboList.GetLBText( nChoice, szChoice );
szResult = "Closing after selecting " + szChoice;
}
else if( szChoice.IsEmpty() == TRUE )
{
// No choice was made from the list box, and the edit
// control was empty.
szResult = "No choice selected";
}
else if( m_comboList.FindStringExact(-1, szChoice) != CB_ERR )
{
// The string from the edit control was found in the
// list box.
szResult = "Closing after selecting " + szChoice;
}
else
{
// The edit control contains a new string, not currently
// in the list box. Add the string.
m_comboList.AddString( szChoice );
szResult = "Adding " + szChoice + " to list";
}
// Get a pointer to the static-text control, and display an
// appropriate result message.
CWnd* pWnd = GetDlgItem( IDC_RESULT );
ASSERT( pWnd );
if( pWnd )
pWnd->SetWindowText( szResult );
}
The CComboListDlg::OnCloseupCombo function collects the contents
from the edit control section of the combo box and the selected item from
the list box section of the combo box. If a selection has been made in
the list box, the item's string is retrieved and displayed. Otherwise,
if a string was entered in the edit control, it is displayed. The string
is not currently in the list box; it is added to it.
Add the source code provided in Listing 7.9 to the CComboListDlg::OnEditupdateCombo member function. CBN_EDITUPDATE is received when the user types inside the edit control. When the CBN_EDITUPDATE message is received, the contents of the edit control are displayed on the IDC_RESULT text control.
void CComboListDlg::OnEditupdateCombo()
{
CString szChoice;
CString szResult;
m_comboList.GetWindowText( szChoice );
szResult = "Choice changed to " + szChoice;
CWnd* pWnd = GetDlgItem( IDC_RESULT );
ASSERT( pWnd );
if( pWnd )
pWnd->SetWindowText( szResult );
}
Compile and run the ComboList project. Experiment by adding new entries
to the combo box and by expanding and closing the combo box. Other messages
sent to the combo box can be trapped and displayed just as CBN_EDITUPDATE
was handled in Listing 7.9.
A The only way to display a bitmap in a list box is to create an owner-drawn list box, where you take responsibility for drawing each item in the list box. You can easily achieve a similar effect by using a list view control, which is discussed in Section 18, "List View Controls."
Q When should I use a combo box drop list, and when is a list box more appropriate?
A A drop list is appropriate when space on your dialog box is at a premium. A list box is more appropriate when the user must see more than one item without clicking on the control.
2. What message is sent to your dialog box when a user double-clicks a dialog box?
3. What functions are used to add items to a list box control?
4. What function is used to retrieve the number of items in a list box control?
5. What function is used to retrieve the currently selected index in a list box?
6. What are the three styles used for list box controls?
7. What are the three types of loops used in C++ programs?
8. Which MFC class is used to manage combo boxes?
9. What function is used to add an item to a combo box at a specific index?
10. What are the three styles used for combo boxes?
Download Sample Programs - EditList.zip , ComboList.zip
|
|
|
|