A control is a child window that belongs to a predefined or application-defined window class and that gives the user a method of supplying input to the application. A dialog box can contain any number and any types of controls. Examples of controls are push buttons and edit controls. Most dialog boxes contain one or more controls of the predefined class. The number of controls, the order in which they should be created, and the location of each in the dialog box are defined by the control statements given in the dialog box template.
Every control in a dialog box needs a unique control identifier, or ID, to distinguish it from other controls. Because all controls send information to the dialog box procedure through WM_COMMAND messages, the control identifiers are essential for the dialog box to determine which control sent a given message.
Each control in the dialog box must have a unique identifier. If a dialog box has a menu bar, there must be no conflict between menu-item identifiers and control identifiers. Because Windows sends menu input to a dialog box procedure as WM_COMMAND messages, conflicts with menu and control identifiers can cause errors. Menus in dialog boxes are not recommended.
The dialog box procedure usually identifies each dialog box control by using its control identifier. Occasionally the dialog box procedure requires the window handle that was given to the control when it was created. The dialog box procedure can retrieve this window handle by using the GetDlgItem function.
The WS_TABSTOP style specifies that the user can move the input focus to the given control by pressing the TAB key or SHIFT+TAB keys. Typically, every control in the dialog box has this style, so the user can move the input focus from one control to the other. If two or more controls are in the dialog box, the TAB key moves the input focus to the controls in the order in which they have been created. The SHIFT+TAB keys move the input focus in reverse order. For modal dialog boxes, the TAB and SHIFT+TAB keys are automatically enabled for moving the input focus. For modeless dialog boxes, the IsDialogMessage function must be used to filter messages for the dialog box and to process these keystrokes. Otherwise, the keys have no special meaning and the WS_TABSTOP style is ignored.
The WS_GROUP style specifies that the user can move the input focus within a group of controls by using the arrow keys. The first control in a group of controls must have the WS_GROUP style. The next control that has the WS_GROUP style marks the bottom boundary of the group; the input focus cannot be moved to this control by using the arrow keys. The DOWN ARROW and RIGHT ARROW keys move the input focus to controls in the order in which they have been created. The UP ARROW and LEFT ARROW keys move the input focus in reverse order. For modal dialog boxes, the arrow keys are automatically enabled for moving the input focus. For modeless dialog boxes, the IsDialogMessage function must be used to filter messages for the dialog box and to process these keystrokes. Otherwise, the keys have no special meaning and the WS_GROUP style is ignored.
Buttons are the principal interface of a dialog box. Almost all dialog boxes have at least one push button, and most have one default push button (a push button having the BS_DEFPUSHBUTTON style) and one or more other push buttons. Many dialog boxes have collections of radio buttons enclosed in group boxes or have lists of check boxes.
Most modal or modeless dialog boxes that use the special keyboard interface
have a default push button whose control identifier is set to IDOK so that the
action the dialog box procedure takes when the button is chosen is identical to the action taken when the ENTER key is pressed. There can be only one button with the default style; however, an application can assign the default style to any button at any time. Most dialog boxes that use the special keyboard interface can also set the control identifier of another push button to IDCANCEL so that the action of the ESC key is duplicated by choosing that button.
When a dialog box first starts, the dialog box procedure can set the initial state of each button by using the CheckDlgButton function, which sets or clears the button state. This function is most useful when used to set the state of radio buttons or check boxes. If the dialog box contains a group of radio buttons in which only one button should be set at any given time, the dialog box procedure can use the CheckRadioButton function to set the appropriate radio button and automatically clear any other radio button.
Before a dialog box terminates, the dialog box procedure can check the state of each button control by using the IsDlgButtonChecked function, which returns the current state of the button. A dialog box typically saves this information to initialize the buttons the next time the dialog box is created.
Many dialog boxes have edit controls that let the user supply text as input. Most dialog box procedures initialize an edit control when the dialog box first starts. For example, the dialog box procedure may place a proposed filename in the control that the user can select, modify, or replace. The dialog box procedure can set the text in an edit control by using the SetDlgItemText function, which copies text from a given buffer to the edit control. When the edit control receives the input focus, the complete text is automatically selected for editing.
Because edit controls do not automatically return their text to the dialog box, the dialog box procedure must retrieve the text before terminating. It can retrieve the text by using the GetDlgItemText function, which copies the edit-control text to a buffer. The dialog box procedure typically saves this text to initialize the edit control later or passes it on to the parent window for processing.
Some dialog boxes use edit controls that let the user enter numbers. The dialog box procedure can retrieve a number from an edit control by using the GetDlgItemInt function, which retrieves the text from the edit control and converts the text to a decimal value. The user enters the number in decimal digits. It can be either signed or unsigned. The dialog box procedure can display an integer by using the SetDlgItemInt function. SetDlgItemInt converts a signed or unsigned integer to a string of decimal digits.
Some dialog boxes display lists, such as a list of filenames, from which the user can select one or more items. To display a list of filenames, a dialog box typically uses a list box and the DlgDirList and DlgDirSelect functions. The DlgDirList function automatically fills a list box with the filenames in the current directory. The DlgDirSelect function retrieves the selected filename from the list box. Together, these two functions provide a convenient way for a dialog box to display a directory listing that makes it possible for the user to select a file without having to type the location and name of the file.
Another method for providing a list of items to a user is by using a combo box. A combo box consists of either a static control or edit control combined with a list box. The list box can be displayed at all times or pulled down by the user. If the combo box contains a static control, that control always displays the current selection (if any) from the list box portion of the combo box. If the combo box uses an edit control, the user can type a selection; the list box highlights the first item (if any) that matches what the user has entered in the edit control. The user can choose the OK button or press ENTER to complete the choice.
List boxes, combo boxes, and buttons can be designated as owner-drawn controls by creating them with the appropriate style. Following are available styles:
Style | Meaning |
LBS_OWNERDRAWFIXED | Creates an owner-drawn list box with items that have the same, fixed height. |
LBS_OWNERDRAWVARIABLE | Creates an owner-drawn list box with items that have different heights. |
CBS_OWNERDRAWFIXED | Creates an owner-drawn combo box with items that have the same, fixed height. |
CBS_OWNERDRAWVARIABLE | Creates an owner-drawn combo box with items that have different heights. |
BS_OWNERDRAW | Creates an owner-drawn button. |
When a control has the owner-drawn style, Windows handles the user's interaction with the control as usual, performing such tasks as detecting when a user has chosen a button and notifying the button's owner of the event. However, because the control is owner-drawn, the owner of the control is completely responsible for the visual appearance of the control. Owner-drawn list boxes and combo boxes can control the display of only the individual elements within a list box or combo box, not the entire list box or combo box.
When Windows first creates a dialog box containing owner-drawn controls, it sends the owner a WM_MEASUREITEM message for each owner-drawn control. The lParam parameter of this message contains a pointer to a MEASUREITEMSTRUCT structure. When the owner receives the message for a control, the owner fills in the appropriate members of the structure and returns. This informs Windows of the dimensions of the control or of its items so that Windows can appropriately detect the user's interaction with the control. If a list box or combo box is created with the LBS_OWNERDRAWVARIABLE or CBS_OWNERDRAWVARIABLE style, the WM_MEASUREITEM message is sent to the owner for each item in the control, because each item can differ in height. Otherwise, this message is sent once for the entire owner-drawn control.
Whenever an owner-drawn control needs to be redrawn, Windows sends the WM_DRAWITEM message to the owner of the control. The lParam parameter of this message contains a pointer to a DRAWITEMSTRUCT structure that contains information about the drawing required for the control. Similarly, if an item is deleted from a list box or combo box, Windows sends the WM_DELETEITEM message containing a pointer to a DELETEITEMSTRUCT structure that describes the deleted item.
Many controls recognize predefined messages that, when sent to the control, cause it to carry out some action. A dialog box procedure can send a message to a control by supplying the control identifier and using the SendDlgItemMessage function, which is identical to the SendMessage function except that it uses a control identifier instead of a window handle to identify the control that is to receive the message.