Based on the Microsoft Windows standards and
suggestions, a dialog box usually uses constant dimensions. This means that
the user should not change its width and/or height. If you want to give the
user the ability to resize a dialog box, change its Border value to
Resizing. With this type of object, the user can position the mouse on of
its borders or corners, click, hold down the mouse and drag in the desired
direction to change its dimensions. In the resource file, this can also be
done by creating the dialog box with the WS_THICKFRAME style:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | WS_THICKFRAME
CAPTION "Exercise"
A Thin value gives a thin border to the dialog box.
A window is referred to as popup if it can be displayed
on the screen. That is, if it can be "physically" located. To create a popup
dialog box, at design time, select Popup from the Style combo box. In the
resource file, this can be done by adding the WS_POPUP style:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP
CAPTION "Exercise"
If you do not want borders at all on the dialog box, set
its Border value to None. This also removes the title bar and thus the
system buttons:
This is equivalent to using only the WS_POPUP
style:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_POPUP
CAPTION "Exercise"
The Child of a Dialog Box
|
|
A window is referred to as child if its appearance is
dependent of the appearance of another window. All of the objects we will
place on our dialog boxes are child window. As we will see when studying
property sheets and wizards, a dialog box that is designed to be "embedded"
in a property sheet or a wizard must be created as a child. To specify that
a dialog box is a child of another window, at design time, select the Child
value on the Style combo box. This characteristic can be applied by adding
the WS_CHILD style.
A window is called overlapped if it has the following
characteristics:
- It has a title bar equipped with a caption and at least one of the
system buttons (usually at least the system Close button)
- It has borders
To get an overlapped dialog box, at design time, access
the Properties window for the dialog box. Set the Style combo box to the
Overlapped value. This is equivalent to the WS_OVERLAPPED style.
To create a dialog box equipped with a title bar, a
system menu, the ability to pop up, and a border, instead of combining the
WS_CAPTION, the WS_SYSMENU, the WS_POPUP, and the
WS_BORDER styles, use the WS_OVERLAPPEDWINDOW value, which
combines them all.
The Regular Styles of a Dialog Box
|
|
We saw already how to manage the title bar and its
system buttons. If you are creating a strict dialog box, one that is
equipped with only the system close button, if you intend to provide help on
the dialog box, you can add a context-sensitive help button to the left of
the close button. To do this at design time, in the Properties window, set
its Context Help property to True or create it with the DS_CONTEXTHELP
style.
By design, a dialog box has thick borders and cannot be
resized from its borders or corners, even if the system buttons are
available. This characteristic of dialog boxes is controlled by the Border
property. The default border of a dialog box is Dialog Frame. This is the
same as applying the DS_MODALFRAME dialog style:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
CAPTION "Exercise"
In previous versions of MS Windows, namely Windows NT
3.51, to get a 3-dimensional appearance, you needed to apply the
DS_3DLOOK style. At this time, this style is added by default.
The Coordinates of a Dialog Box
|
|
Earlier, when reviewing the techniques of setting the
location of a dialog box, we mentioned that, if the x and the y values, or
the X Pos and the Y Pos properties, are set to 0, the dialog box is
positioned in the middle of the screen. This is because, like all other
objects that can act as children of a parent window, the location of a
dialog box is set according to its parent. That is, the location of a dialog
box is based on its ability to be a client (also called child) of another
window (called a parent). This system is referred to as client coordinate.
If you are creating an application based on a dialog box, that is, an
application whose main or even only container is the dialog box, such a
dialog box does not have a parent. In this case, it does not have a
referential window to base its location on. Consequently, it gets positioned
to the middle of the screen. If you want the location of the dialog box to
be based on the monitor screen, at design time, set its Absolute Align
property to True in the Properties window. In a resource file, this would be
done by adding the DS_ABSALIGN style. This system is referred as the
screen coordinate.
Based on the coordinate system you decide to use, screen
or client, when the dialog box of a dialog-based application comes up, if
you want the dialog to be centered on the monitor screen, even if you are
using the screen coordinate system with the DS_ABSALIGN style, set
its Center property to True in the Properties window. This is also done by
adding the DS_CENTER style. If the dialog box is participating in an
application that is view-based, if you set its Center property to True, it
would be centered with regards to the window that called it.
We have
described how to control the location of the dialog box when it comes up,
depending on the coordinate system you are using, and the DS_CENTER
style. Alternatively, if you want the dialog box to be displayed based on
the location of the user's mouse cursor, at design time, set its Center
Mouse property to True in the Properties window. In this case, when the
dialog box comes up, it would find the mouse pointer and position itself so
the mouse cursor would be in the middle-center of the dialog box. This
ability is also applied by adding the DS_CENTERMOUSE style.
Practical
Learning: Centering a Dialog Box
|
|
- In the Properties window, double-click the Center field to set it to
True
- On the Standard toolbar, click the Save All button
To display its controls, the dialog box uses a
predefined font known as MS Shell Dlg. To change it at design time, in the
Properties window, click Font (Size) to reveal its combo box. Then click its
ellipsis button. This would open the Font dialog box where you can select
the font and its options.
The font characteristics are managed through the
DS_SHELLFONT, the DS_SETFONT, and the DS_FIXEDSYS styles.
The section of the resource file that specifies the general font starts with
the FONT keyword:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
CAPTION "Exercise"
FONT
The FONT keyword is followed by the
characteristics of the font using the following syntax:
FONT size, name, weight, italic, charset
Here is an example:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
CAPTION "Exercise"
FONT 8, “MS Shell Dlgâ€Â, 400, 0, 0x1
If you want to manage the fonts, weights, and colors of
the controls on the dialog box of an MFC application, you must do this
programmatically.
The Background Color of a Dialog Box
|
|
The primary technique used to create a dialog is to
derive a class from CDialog. To enhance it, Microsoft
created a new class named CDialogEx. This class is derived
from CDialog and it added only two characteristics: a color background and a
picture background.
To give you the ability to paint a dialog box with a
color of your choice, the CDialogEx class is equipped with
the SetBackgroundColor() member function. Its syntax is:
void SetBackgroundColor(COLORREF color, BOOL bRepaint = TRUE);
The fist argument, which is required, specifies the
color to apply to the body of the dialog box. The second argument is
optional and it indicates whether the dialog box should be repainted with
this member function is called. Here is an example:
BOOL CExampleDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
SetBackgroundColor(278394);
return TRUE; // return TRUE unless you set the focus to a control
}
The Background Picture of a Dialog Box
|
|
Instead of a color, you may want to paint a dialog box
with a picture. To support this, the CDialogEx class provides the
SetBackgroundImage() member function. It comes in two versions whose
syntaxes are:
void SetBackgroundImage(
HBITMAP hBitmap,
BackgroundLocation location=BACKGR_TILE,
BOOL bAutoDestroy=TRUE,
BOOL bRepaint=TRUE
);
BOOL SetBackgroundImage(
UINT uiBmpResId,
BackgroundLocation location=BACKGR_TILE,
BOOL bRepaint=TRUE
);
In both cases, the first argument is required and it
holds the bitmap to use. The other arguments are optional.
The first version expects a handle to a BITMAP
object. To use it, you must programmatically create a BITMAP or a
CBitmap object and pass it to the function. The second version of
this member function is probably the easier. Before using it, you can first
import a bitmap (a picture with the .bmp extension), and give it an ID. Once
the bitmap is ready, pass its ID to the member function. Here is an example:
BOOL CExample1Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
SetBackgroundImage(IDB_CITY);
return TRUE; // return TRUE unless you set the focus to a control
}
The Extended Styles of a Dialog Box
|
|
Besides the regular Windows styles and the styles
specific to a dialog box, Microsoft Windows provides some extended styles
used to improve the appearance or the role of a dialog box on an
application. To use these styles in the resource file, start a new line with
the EXSTYLE keyword:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
EXSTYLE
CAPTION "Exercise"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
A Dialog Box as a Tool Window
|
|
A tool window is a parent object mostly used to float,
like a toolbar, on a frame of another window. It has a short title bar that
displays its caption. It can neither be minimized nor maximized but it can
be equipped with a circumstantial system menu:
To create a tool window, when designing the dialog box,
set the Tool Window field to True in the Properties window. This can also be
applied by adding the WS_EX_TOOLWINDOW extended style:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Exercise"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
If you want the user to be able to resize the tool
window by dragging its borders or corners, at design time, set its Border
value to Resizing or create it with the WS_THICKFRAME
style. If you do not want the user to be able to resize the tool window, at
design time, set its Border to either Thin or Dialog Frame. In the resource
file, you can also do this by creating it with the WS_CAPTION
and WS_SYSMENU style.
A Dialog Box as an Application Window
|
|
As mentioned already, a window without the system
Minimize button cannot be minimized. This, of course, is the same for a tool
window. Also, by default, a tool window does not display a button on the
task bar. If you are creating a window that will depend on a main window
such as a frame, you should keep that default. If for any reason you want to
display a button on the task bar for the tool window, add the
WS_EX_APPWINDOW extended style.
If you want your window to stay on top of another or
other windows, at design time, set the Topmost field to True in the
Properties window. If you are working from a resource file, add the
WS_EX_TOPMOST extended style to it (if the window you are creating, such
as a dialog box, is being added to a frame-based or a form-based application
and you want that window to always be on top of its parent window, add the
WS_VISIBLE style to it and display it using ShowWindow(SW_SHOW)).
A Client Edge for a Dialog Box
|
|
A window appears sunken when its body is sunk with
regards to its borders. To create a dialog box with a sunken body, at design
time, set its Client Edge field to True in the Properties window. If you are
working from a resource file, add the WS_EX_CLIENTEDGE extended
style.
A Window Edge for a Dialog Box
|
|
A window can have an inside body that appears to be
raised with regards to its borders. To get such an edge, at design time, set
the Window Edge field to True in the Properties window. If you are working
from a resource file, add the WS_EX_WINDOWEDGE extended style.
A Static Edge for a Dialog Box
|
|
To create a window with a 3-dimensional thin border, at
design time, set its Static Edge to True in the Properties window. This is
the same as adding the WS_EX_STATICEDGE extended style.
To create a dialog box that has a raised border and
stays on top of others, which is equivalent to combining the
WS_EX_WINDOWEDGE and the WS_EX_TOPMOST styles, in the resource
file, add the WS_EX_PALETTEWINDOW value in the EXSTYLE line
An Extended Overlapped Window
|
|
A window is referred to as overlapped when it presents a
combination of a sunk and a raised edge. Such a window can be created by
either combining the WS_EX_CLIENTEDGE and the WS_EX_WINDOWEDGE
styles or by using the WS_EX_OVERLAPPEDWINDOW.
A Window that Accepts Files
|
|
If you are creating a dialog box that will be accepting
files dragged from other windows, at design time, set the Accept Files field
to True in the Properties window. You can also do this in the resource file
by adding the WS_EX_ACCEPTFILES extended style.
Creating the Dialog Resource File
|
|
As mentioned already, a dialog box means nothing except
for the objects it hosts. The objects are listed in a section that starts
with the BEGIN and ends with the END
keywords. Here is an example:
IDD_SCHOOL_SURVEY DIALOGEX 0, 0, 340, 268
STYLE WS_CAPTION | WS_SYSMENU | WS_POPUP | DS_MODALFRAME
EXSTYLE WS_EX_TOOLWINDOW
CAPTION "Exercise"
FONT 8, "MS Shell Dlg", 400, 0, 0x1
BEGIN
END
If you design a dialog box and it is the first object of
your application, you must save it before using it. Even if you had decided
to manually create the dialog box as a text file, you must save it before
using it. In both cases, whether saving the dialog box designed or the text
file, saving it results in creating a resource file. This file should have
the .rc extension.
If your resource file is using some identifiers, which
is the case for most or all objects you will use in your application, you
must list them in a header file. This file is traditionally called
Resource.h or resource.h. Each identifier must be listed using the following
syntax:
#define Identifier Constant
When you save the resource file, Microsoft Visual C++
automatically creates the resource header file and names it resource.h
Creating a Class for the Dialog
|
|
After creating the resource for the dialog box, you must
create a class that will be used to handle its assignment(s). To do this,
you must derive a class from CDialog. You have various options. You
can create a header file and a source file for the dialog box. In the header
file of the dialog's class, define an enumeration whose only member is
called IDD and initialize it with the identifier of the dialog box. Because
the identifier is listed in the resource header file, you must include this
resource header in the file in which you are using the dialog's identifier.
Instead of explicitly creating the header and source
files, you can create a class for the dialog box. There are two ways you can
do this:
- While the dialog box has focus, on the main menu, you can click
Project -> Add Class...
- You can right-click the body of the dialog box and click Add
Class...
This would open the MFC Add Class Wizard. In the Class
Name text box, enter the intended name of the class. In the Base Class combo
box, select either CDialog (the default) or another:
When you are ready, click Finish. A header file and a
source file would be created for you. All the necessary ingredients of a
dialog box class will be added in the code for you, including issues we will
study in other lessons.
Practical
Learning: Creating the Dialog's Class
|
|
- Click the Preparation.cpp tab to get to the file
- To create a class for the dialog box, open the Preparation.cpp file
created earlier and add the following:
#include <afxwin.h>
#include <afxdlgs.h>
#include "resource.h"
class CPreparationApp : public CWinApp
{
public:
BOOL InitInstance();
};
class CPreparationDlg : public CDialog
{
public:
enum { IDD = IDD_PREPARATION_DLG };
};
BOOL CPreparationApp::InitInstance()
{
return TRUE;
}
CPreparationApp theApp;
- Save All
A dialog box is based on the CDialog
class. As seen above, when creating your dialog box, you can derive a class
from CDialog. The CDialog class itself provides three
constructors as follows:
CDialog();
CDialog(UINT nIDTemplate, CWnd* pParentWnd = NULL);
CDialog(LPCTSTR lpszTemplateName, CWnd* pParentWnd = NULL);
The default constructor, CDialog(), can be used
to declare a variable whose behavior is not yet known or, for one reason or
another, cannot yet be defined. When creating your class, you should also
declare at least a default constructor.
The identifier of the dialog box, such as IDD_DIALOG1,
can be used as the first argument, nIDTemplate, of a CDialog()
constructor to create a dialog box from an existing resource.
If you are using a Win32 template to create your dialog
box, pass the name of this template as a string to a CDialog()
constructor, lpszTemplateName.
When implementing your default constructor, initialize
the parent CDialog constructor with the IDD enumerator declared in
your class. If your dialog box has an owner, specify it as the pParentWnd
argument. If you set it to NULL, the application will be used as the
dialog's parent.
If you dynamically create objects for your application
using your dialog class, it is a good idea to also declare and define a
destructor. This would be used to destroy such dynamic objects.
Most other methods of a dialog box depend on
circumstances we have not yet reviewed
Practical
Learning: Creating a Dialog Box
|
|
- Declare a default constructor and a destructor for your dialog class
and implement them as follows (in the same file):
class CPreparationDlg : public CDialog
{
public:
enum { IDD = IDD_PREPARATION_DLG };
CPreparationDlg();
~CPreparationDlg();
};
CPreparationDlg::CPreparationDlg()
: CDialog(CPreparationDlg::IDD)
{
}
CPreparationDlg::~CPreparationDlg()
{
}
- Before using the new class, declare a variable of it as follows:
BOOL CPreparationApp::InitInstance()
{
CPreparationDlg Dlg;
m_pMainWnd = &Dlg;
return TRUE;
}
- Save All
There are two types of dialog boxes: modal and modeless.
A Modal dialog box is one that the user must first close in order to have
access to any other framed window or dialog box of the same application.
One of the scenarios in which you use a dialog box is to
create an application that is centered around a dialog box. In this case, if
either there is no other window in your application or all the other windows
depend on this central dialog box, it must be created as modal. Such an
application is referred to as dialog-based
There are two main techniques you can use to create a
dialog-based application: from scratch or using one of Visual C++ wizards.
After creating a dialog resource and deriving a class from CDialog,
you can declare a variable of your dialog class. To display your dialog box
as modal, you can call the CDialog::DoModal() method in
your CWinApp::InitInstance() method. Its syntax is:
virtual int DoModal();
This method by itself does nothing more than displaying
a dialog box as modal. We will learn that you can use this method to find
out how the user had closed such a dialog box.
Practical
Learning: Displaying a Modal Dialog Box
|
|
- To display the dialog box as modal, in the InitInstance()
event of your CWinApp derived class, call the
DoModal() method using your dialog variable:
#include <afxwin.h>
#include <afxdlgs.h>
#include "resource.h"
class CPreparationApp : public CWinApp
{
public:
BOOL InitInstance();
};
class CPreparationDlg : public CDialog
{
public:
enum { IDD = IDD_PREPARATION_DLG };
CPreparationDlg();
~CPreparationDlg();
};
CPreparationDlg::CPreparationDlg()
: CDialog(CPreparationDlg::IDD)
{
}
CPreparationDlg::~CPreparationDlg()
{
}
BOOL CPreparationApp::InitInstance()
{
CPreparationDlg Dlg;
m_pMainWnd = &Dlg;
Dlg.DoModal();
return TRUE;
}
CPreparationApp theApp;
- Execute the application
- Close the dialog box and return to your programming environment
|