Dialogs


A dialog is a popup window that contains control windows. The size and placement of the control windows are generally specified in a dialog template. An example dialog template specification is shown below.

DialogIdentity DIALOG  20, 20, 160, 80
 STYLE WS_POPUP | WS_DLGFRAME
{
 CTEXT "About1"                           -1,   0, 12, 160,  8
 ICON  "About1"                           -1,   8,  8,   0,  0
 CTEXT "About Box Demonstration Program"  -1,   0, 36, 160,  8
 CTEXT "i++ for windows"                  -1,   0, 48, 160,  8
 DEFPUSHBUTTON "ok"                     IDOK,  64, 60,  32, 14, WS_GROUP
} 

The application discussed in this section displays the dialog specified above and shown below.

The application is composed of:

A modal dialog like this one can extend beyond the boundaries of the client. The client is the owner of the dialog, but the parent of the dialog is the desktop window. The dialog template shown above may be contained in a resource file directly (that is, a file with the extension .rc) or it may be contained in a separate file with the extension .dlg. If the template is in a separate file, that file may be included in the resource compilation via a statement of the following form.

rcinclude filename.dlg

The dialog template may be coded manually or it may be manufactured through a dialog box editor. The first two lines of the above specification are shown below.

DialogIdentity DIALOG  20, 20, 160, 80
 STYLE WS_POPUP | WS_DLGFRAME

The parameter DialogIdentity is the name of the dialog and in this case it is a numeric value defined in the resource header. The name may also be specified as a string. The name is followed by the keyword "DIALOG" which is then followed by four integers. The first two integers are the x and y coordinates (respectively) of the upper-left corner of the dialog relative to the client area of the owner of the dialog. The second two integers are the width and height (respectively) of the dialog.

Dialog Units

The units of specification of positions and sizes for a dialog are dialog units. x-coordinates within the dialog unit system are expressed in units of 1/4 of the average character width of the dialog's font. y-coordinates within the dialog unit system are expressed in units of 1/8 of the height of characters in the dialog's font. Unless otherwise specified, the font of the dialog is the system font. Given this, a width of 160 and a height of 80 implies that the dialog is 40 characters wide and 10 characters high. This coordinate system is designed so that the dialogs appear approximately the same for different display resolutions. The width and height of the system font varies according to the display resolution. Because the height of the system font is usually twice the width, the dimensions of the x and y axes of the dialog coordinate system represent the same number of pixels in either direction.

The function get_dialog_base_units allows for the determination of the dimensions of the system font that is currently being used. For XGA resolution, the horizontal dialog base unit is 10 and the vertical dialog base unit is 20. This implies that each dialog unit is 2.5 pixels. For VGA, the horizontal dialog base unit is 8 and the vertical dialog base unit is 16, which implies that each dialog unit is 2 pixels. These formulae are valid provided that the dialog uses the system font. If a font other than the system font is provided (dialog_style::set_font), the function map_dialog_rectangle should be used instead of get_dialog_base_units.

Dialog Styles

The dialog style accounts for the second line in the above specification of the dialog. The keyword "STYLE" commences the specification of dialog styles. Styles bits then follow; where, they are combined with the C++ or (|) symbol. Styles particular to dialogs may be found in the enumeration dialog_style. Standard window styles may also be present. Unfortunately, the resource compiler is incapable of reading C++ enumerated types. This implies that the standard headers must be used instead of the i++ headers when performing resource compilations.

The styles "WS_POPUP" and "WS_DIALOGFRAME", are standard window styles (style::Popup and style::DialogFrame in i++). The "WS_" prefix stands for "window style". These two styles are fairly normal for dialogs; although, some other styles will be discussed later in this chapter.

Dialog Control Windows

Once the dialog itself has been defined, the control windows may then be incorporated (between the braces - as shown below).

DialogIdentity DIALOG  20, 20, 160, 80
 STYLE WS_POPUP | WS_DLGFRAME
{
  ....   <==== child window control statements go here.
}

For the dialog template at hand, three types of controls are declared: CTEXT (centered text), ICON (an icon) and DEFPUSHBUTTON (a default push button). all of the above control statements have the same overall form, as shown below.

control-type "text" identity, xPosition, yPosition, xWidth, yheight

The identifiers "CTEXT", "ICON" and "DEFPUSHBUTTON" are only used in resource specifications. They are shorthand for a particular window class with a particular style. For example, CTEXT is a control window of class "static" (that is, a display control) and the implied style is shown below.

style::child | style::visible | style::group | display_style::center

For the icon specification:

 ICON  "About1"  -1,   8,  8,   0,  0

the text identifies the resource name of the icon. The keyword "ICON" is also an abbreviation of the static (display) control.

A push button is also present in the dialog, and its specification is repeated below.

DEFPUSHBUTTON "ok" IDok,  64, 60,  32, 14, WS_GROUP

The keyword DEFPUSHBUTTON gives rise to a window of the class "button" which includes the style button_style::push_button_default. For default push buttons, the text field is the text that occurs inside the button itself. The style "WS_GROUP" implies that the button is in its own group. Groups are used to influence the keyboard behaviour of controls within a dialog. This style will be discussed later in the chapter.

For each of the control statements, the identity of the control is given, followed by four numeric values. The four numeric values are the x and y coordinates of the control, followed by the width and height of the control. all of these values are expressed in dialog units. The width and height parameters are ignored for the ICON statement.

The identity that precedes the dimension parameters is the window identity ascribed to the control. This is the window identity used when creating the child window (as previously mentioned in chapter 8). The dialog distinguishes between its various child controls using this identity. An identity of -1 is used for all controls that do not send notifications to their owner. Such controls include display type controls (that is CTEXT and ICON). The pushbutton notifies its owner when selected, so it is given the identity IDok (which is defined in the Win32 headers as 1 and in the i++ headers as item_identity::ok).

Creating a dialog

To create a modeless dialog, the function create_dialog is called. To create a modal dialog, the function dialog_box is called. A modal dialog is a dialog that does not return until it is dismissed. This is achieved via a modal loop. The function dialog_box gets and dispatches messages separately from the main message loop of the program. Modal dialogs disable the owner and its descendants (that is, the owner and descendants may not receive input whilst the modal dialog is active). Despite this, the owner may receive messages other than input messages (such as paint or command messages). A modeless dialog acts more like a standard window, and its messages are processed through the main message loop. The function create_dialog returns as soon as the dialog has been created. The owner of a modeless dialog is not input disabled.

When creating either a modal or modeless dialog, a dialog procedure is required. A dialog procedure looks a bit like a window procedure; however, it is not a window procedure. The window procedure for a dialog is defined within the operating system and it calls the specified dialog procedure with many of the messages it receives. The overall form of a dialog procedure is shown below.

bool standard dialog_procedure(handle DialogHandle,
                              unsigned identity,
                              parameter parameter1,
                              parameter parameter2)
{
 switch (identity)
  {
   case message::initialize_dialog:
    ....
    return true;

   case message::command:
     ....
     break;
   }
 return false;
}

A dialog procedure differs from a window procedure in that:

  1. a window procedure returns the type result whereas a dialog procedure returns the type bool,

  2. a window procedure calls default_window_procedure when it does not process a message; whereas, a dialog procedure returns true when it processes a message and false otherwise,

  3. a dialog procedure does not need to process the messages message::paint and message::destroy and a dialog procedure does not receive the message message::create but receives the message message::initialize_dialog instead.

For the application of this section, when the client window receives the notification message::command, it creates and displays a modal dialog as shown below.

case message::command:
 switch (low_part(parameter1))
  {
   case MenuItemAbout:
    dialog_box(get_module_handle<character>(0),
              DialogIdentity,
              window_handle,
              About);
    break;
  }
 break;

The dialog procedure intercepts the notification message::command and performs as shown below.

bool standard About(handle DialogHandle,
                    unsigned identity,
                    parameter parameter1,
                    parameter parameter2)
{
 switch (identity)
  {
   case message::initialize_dialog:
    return true;

   case message::command:
    switch (low_part(parameter1))
     {
      case item_identity::ok:
       end_dialog(DialogHandle,0);
       return true;
     }
     break;
   }
 return false;
}

When the standard item identity item_identity::ok is received, the dialog is dismissed (ended). The value of item_identity::ok is 1, which matches the value given to the default pushbutton within the dialog template.