A dialog box can contain any number and any type of controls. 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. 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. Since all controls send information to the dialog function through WM_COMMAND messages, the control identifiers are essential for the dialog box to determine which control sent a given message.
All identifiers for all controls in the dialog box must be unique. If a dialog box has a menu bar, there must be no conflict between menu-item identifiers and control identifiers. Since Windows sends menu input to a dialog function as WM_COMMAND messages, conflicts with menu and control identifiers can cause errors. Menus in dialog boxes are not recommended.
The dialog function usually identifies the dialog-box controls by using their control identifier. Occasionally the dialog function requires the window handle that was given to the control when it was created. The dialog function 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 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 to the given control by using a DIRECTION key. Typically, the first and last controls in a group of consecutive controls in the dialog box have this style, so the user can move the input focus from one control to the other. The DOWN and RIGHT keys move the input focus to controls in the order in which they have been created. The UP and LEFT keys move the input focus in reverse order. For modal dialog boxes, the DIRECTION 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.
Button controls are the principal interface of a dialog box. Almost all dialog boxes have at least one push-button control and most have one default push button and one or more other push buttons. Many dialog boxes have collections of radio buttons enclosed in group boxes, or 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 1 so that the action the dialog function takes when the button is clicked 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. These dialog boxes may also set the control identifier of another push button to 2 so that the action of the ESCAPE key is duplicated by clicking that button.
When a dialog box first starts, the dialog function can set the initial state of the button controls 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 function can use the CheckRadioButton function to set the button and automatically clear any other radio button.
Before a dialog box terminates, the dialog function 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 functions initialize an edit control when the dialog box first starts. For example, the function may place a proposed filename in the control that the user can adapt or modify. The dialog function can set the text in an edit control by using the SetDlgItemText function, which copies text in a given buffer to the edit control. When the edit control receives the input focus, the complete text will automatically be selected for editing.
Since edit controls do not automatically return their text to the dialog box, the dialog function 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 function 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 function can retrieve a number from an edit control by using the GetDlgItemInt function, which retrieves the text of the 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 function can display an integer by using the SetDlgItemInt function. It converts a signed or unsigned integer to a string of decimal digits.
Some dialog boxes display lists, such as filenames, from which the user can select one or more names. Dialog boxes that display a list typically use list-box controls. Dialog boxes that display a list of filenames typically use a list-box control 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 they provide a convenient way for a dialog box to display a directory listing, and let the user select a file without having to type in the name of the directory and file.
Another method for providing a list of items to a user is by means of a combo box. A combo box consists of either a static text field or edit field 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 text field, the text field always displays the current selection (if any) in the list-box portion of the combo box. If it uses an edit field, the user can type in the desired selection; the list box highlights the first item (if any) which matches what the user has entered in the edit field. The user can then select the item highlighted in the list box to complete the choice.
List boxes, combo boxes, and buttons can be designated as owner-draw controls by creating them with the appropriate style:
Style | Meaning |
LBS_OWNERDRAWFIXED | Creates an owner-draw list box with items that have the same, fixed height. |
LBS_OWNERDRAWVARIABLE | Creates an owner-draw list box with items that have different heights. |
CBS_OWNERDRAWFIXED | Creates an owner-draw combo box with items that have the same, fixed height. |
CBS_OWNERDRAWVARIABLE | Creates an owner-draw combo box with items that have different heights. |
BS_OWNERDRAW | Creates an owner-draw button. |
When a control has the owner-draw style, Windows handles the user's interaction with the control as usual, such as detecting when a user has clicked a button and notifying the button's owner of the event. However, because it is an owner-draw control, the owner of the control is completely responsible for the visual appearance of the control.
When Windows first creates a dialog box containing owner-draw controls, it sends the owner a WM_MEASUREITEM message for each owner-draw control. The lParam parameter of this message contains a pointer to a MEASUREITEMSTRUCT data structure. When the owner receives the message for a control, the owner fills in the appropriate fields 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, this message is sent to the owner for each item in the control, since each item can differ in height. Otherwise, this message is sent once for the entire owner-draw control.
Whenever an owner-draw control needs to be redrawn, Windows sends the WM_DRAWITEM message to the owner of the control. The lParam param-eter of this message contains a pointer to a DRAWITEMSTRUCT data 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 data 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 function 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.