More on Defining Controls

In the dialog box template in ABOUT1.RC, we used the shorthand notation CTEXT, ICON, and DEFPUSHBUTTON to define the 3 types of child window controls we wanted in the dialog box. There are 10 others you can use. Each type implies a particular predefined window class and a window style. The following table shows the equivalent window class and window style for each of the 13 control types:

Control Type Window Class Window Style

PUSHBUTTON button BS_PUSHBUTTON | WS_TABSTOP
DEFPUSHBUTTON button BS_DEFPUSHBUTTON | WS_TABSTOP
CHECKBOX button BS_CHECKBOX | WS_TABSTOP
RADIOBUTTON button BS_RADIOBUTTON | WS_TABSTOP
GROUPBOX button BS_GROUPBOX | WS_TABSTOP
LTEXT static SS_LEFT | WS_GROUP
CTEXT static SS_CENTER | WS_GROUP
RTEXT static SS_RIGHT | WS_GROUP
ICON static SS_ICON
EDITTEXT edit ES_LEFT | WS_BORDER | WS_TABSTOP
SCROLLBAR scrollbar SBS_HORZ
LISTBOX listbox LBS_NOTIFY | WS_BORDER | WS_VSCROLL
COMBOBOX combobox CBS_SIMPLE | WS_TABSTOP

The RC resource compiler is the only program that understands this shorthand notation. In addition to the window styles shown above, each of these controls has the style:

WS_CHILD | WS_VISIBLE

For all these control types except EDITTEXT, SCROLLBAR, LISTBOX, and COMBOBOX, the format of the control statement is:

control-type "text", nID, xPos, yPos, xWidth, yHeight, dwStyle

For EDITTEXT, SCROLLBAR, LISTBOX, and COMBOBOX, the format is:

control-type nID, xPos, yPos, xWidth, yHeight, dwStyle

which excludes the text field. In both statements, the dwStyle parameter is optional.

In Chapter 6, I discussed rules for determining the width and height of predefined child window controls. You might want to refer back to that chapter for these rules, keeping in mind that sizes specified in dialog box templates are always in terms of 1/4 the average character width and 1/8 the character height.

The ”style“ field of the control statements is optional. It allows you to include other window style identifiers. For instance, if you wanted to create a check box consisting of text to the left of a square box, you could use:

CHECKBOX "text", nID, xPos, yPos, xWidth, yHeight, BS_LEFTTEXT

While the shorthand notation for child window controls is convenient, it is also incomplete. You can't create a child window edit control without a border, for example. For this reason, the RC resource compiler also recognizes a generalized control statement that looks like this:

CONTROL "text", nID, "class", dwStyle, xPos, yPos, xWidth, yHeight

This statement allows you to create any type of child window control by specifying the window class and the complete window style. For example, instead of using:

PUSHBUTTON "OK", IDOK, 10, 20, 32, 14

you can use:

CONTROL "OK", IDOK, "button", WS_CHILD | WS_VISIBLE |

BS_PUSHBUTTON | WS_TABSTOP, 10, 20, 32, 14

When the resource script is compiled, these two statements are encoded identically in the .RES file and the .EXE file.

When you use CONTROL statements in a dialog box template, you don't need to include the WS_CHILD and WS_VISIBLE styles. Windows includes these in the window style when creating the child windows. The format of the CONTROL statement also clarifies what the Windows dialog manager does when it creates a dialog box. First, as I described earlier, it creates a popup window whose parent is the window handle that was provided in the DialogBox function. Then for each control in the dialog template, the dialog box manager creates a child window. The parent of each of these controls is the popup dialog box. The CONTROL statement shown above is translated into a CreateWindow call that looks like this:

CreateWindow ("button", "OK",

WS_CHILD | WS_VISIBLE | WS_TABSTOP | BS_PUSHBUTTON,

10 * cxChar / 4, 20 * cyChar / 8,

32 * cxChar / 4, 14 * cyChar / 8,

hDlg, nID, hInstance, NULL) ;

where cxChar and cyChar are the width and height of a system font character in pixels. The hDlg parameter is returned from the CreateWindow call that creates the dialog box window. The hInstance parameter is obtained from the original DialogBox call.