Dialog Boxes

A dialog box is a form used to solicit input from a user. Dialog boxes, or simply “dialogs,” as they are often called, come in two styles: modal and modeless. When a modal dialog is displayed, its owner, which is typically the application’s main form, is temporarily disabled. The Open File dialog featured in countless Windows applications is an example of a modal dialog. Modeless dialogs don’t disable their owners; users are free to “click back” to the main form at any time. The Find and Replace dialog in Microsoft Word is an example of a modeless dialog.

To a developer versed in programming Windows using the Windows API, dialog boxes are special creatures that are just different enough from ordinary windows to be a bit of a nuisance. In Windows Forms, dialog boxes are nothing special; they’re just forms. Literally. In fact, just three characteristics differentiate a dialog box from an ordinary form:

Experienced Windows developers are often shocked to find that Windows Forms dialogs create their controls programmatically. Traditional Windows applications use dialog resources that enable a dialog to be created, controls and all, with a simple function call. Windows Forms doesn’t use dialog resources, so every dialog class contains code to create each and every control that it hosts.

Windows features an assortment of so-called “system dialogs” or “common dialogs” that developers can use to display Open File dialogs, Print dialogs, and other types of dialogs that are commonly found in Windows applications. The FCL wraps the common dialogs with easy-to-use classes. The following table lists the common dialog classes. All are defined in System.Windows.Forms. You’ve seen one of these dialogs—OpenFileDialog—already in this chapter’s ImageView application. Use these classes whenever appropriate to save on development time and give your Windows Forms applications a look and feel that is consistent with other Windows applications.

Common Dialog Classes Defined in System.Windows.Forms

Class

Dialog Type

ColorDialog

Color dialog boxes for choosing colors

FontDialog

Font dialog boxes for choosing fonts

OpenFileDialog

Open File dialog boxes for choosing files

PageSetupDialog

Page Setup dialog boxes for entering page setup parameters

PrintDialog

Print dialog boxes for entering print parameters

SaveFileDialog

Save File dialog boxes for entering file names

The DialogDemo Application

Figure 4-22 contains the source code for a simple Windows Forms application that displays a dialog box in response to a menu command. To display the dialog, select the Edit Ellipse command from the Options menu. In the dialog are controls that you can use to change the width and height of the ellipse in the application’s main form. (See Figure 4-21.) You can also select the system of units—inches, centimeters, or pixels—that the width and height are measured in.

DialogDemo’s dialog class is named MyDialog. Code in the class constructor initializes the dialog’s properties. The first statement sizes the dialog:

ClientSize?=?new?Size?(296,?196);

The second statement sets the dialog’s StartPosition property to FormStartPosition.CenterParent, which centers the dialog in the parent form each time it’s displayed:

StartPosition?=?FormStartPosition.CenterParent;

The next statement gives the dialog a “fixed dialog” border, which prevents the dialog from being resized:

FormBorderStyle?=?FormBorderStyle.FixedDialog;

The next two statements remove the minimize and maximize buttons that appear in the dialog’s title bar by default, and the statement after that sets the text in the dialog’s title bar:

MaximizeBox?=?false;
MinimizeBox?=?false;
Text?= "Edit?Ellipse";

The final statement prevents the dialog from causing a button to appear in the system’s task bar:

ShowInTaskbar?=?false;

Top-level forms should appear in the task bar, but dialog boxes should not.

Most of the remaining code in MyDialog’s constructor creates the dialog’s controls and adds them to the Controls collection. But notice these two statements:

AcceptButton?=?OKButton;
CancelButton?=?NotOKButton;

AcceptButton and CancelButton are properties that MyDialog inherits from Form. AcceptButton identifies the dialog’s OK button; CancelButton identifies the Cancel button. OK and Cancel buttons are special because they dismiss the dialog box—that is, cause it to disappear from the screen. The statements above identify the OK and Cancel buttons to the framework so that it can dismiss the dialog when either button is clicked.

The following statements instantiate and display the dialog:

MyDialog?dlg?=?new?MyDialog?();
??.
??.
??.
if?(dlg.ShowDialog?(this)?==?DialogResult.OK)?{

The dialog appears on the screen when ShowDialog is called. ShowDialog is a blocking call; it doesn’t return until the dialog is dismissed. Its return value tells you how the dialog was dismissed. DialogResult.OK means the user clicked the OK button. DialogResult.Cancel means the user clicked Cancel. Most applications ignore what was entered into the dialog if the Cancel button is clicked. DialogDemo discards the input if ShowDialog’s return value is anything other than DialogResult.OK, which means the user can cancel out of the dialog without affecting the ellipse in any way.

MyDialog exposes the input that the user enters through public properties named UserWidth, UserHeight, and UserUnits. When read, these properties extract data from the dialog’s controls. When written to, they transfer data to the controls. Before calling ShowDialog to display the dialog, DialogDemo initializes the dialog’s controls by initializing the corresponding properties:

dlg.UserWidth?=?MyWidth;
dlg.UserHeight?=?MyHeight;
dlg.UserUnits?=?(int)?MyUnits;

And when the dialog is dismissed (provided it’s dismissed with the OK button), DialogDemo extracts the user input by reading MyDialog property values:

MyWidth?=?dlg.UserWidth;
MyHeight?=?dlg.UserHeight;
MyUnits?=?(MyForm.Units)?dlg.UserUnits;

Thus, public properties in the dialog class serve as a mechanism for transferring data to and from the dialog’s controls. This mechanism is typically how Windows Forms applications get data in and out of dialogs.

Figure 4-21
DialogDemo in action.
DialogDemo.cs
using?System;
using?System.Windows.Forms;
using?System.Drawing;

class?MyForm?:?Form
{
????enum?Units?{
????????Inches,
????????Centimeters,
????????Pixels
????}

????int?MyWidth?=?400;
????int?MyHeight?=?200;
????Units?MyUnits?=?Units.Pixels;
????MyForm?()
????{
????????//?Set?the?form's?title
????????Text?= "Dialog?Demo";

????????//?Set?the?form's?size
????????ClientSize?=?new?Size?(640,?480);

????????//?Create?a?menu
????????MainMenu?menu?=?new?MainMenu?();
????????MenuItem?item?=?menu.MenuItems.Add?("&Options");
????????item.MenuItems.Add?("Edit?Ellipse...",
????????????new?EventHandler?(OnEditEllipse));
????????item.MenuItems.Add?("-");
????????item.MenuItems.Add?("E&xit",?new?EventHandler?(OnExit));

????????//?Attach?the?menu?to?the?form
????????Menu?=?menu;
????}

????//?Handler?for?the?Edit?Ellipse?command
????void?OnEditEllipse?(object?sender,?EventArgs?e)
????{
????????//?Create?the?dialog
????????MyDialog?dlg?=?new?MyDialog?();

????????//?Initialize?the?dialog
????????dlg.UserWidth?=?MyWidth;
????????dlg.UserHeight?=?MyHeight;
????????dlg.UserUnits?=?(int)?MyUnits;

????????//?Display?the?dialog
????????if?(dlg.ShowDialog?(this)?==?DialogResult.OK)?{
????????????//?If?the?dialog?was?dismissed?with?the?OK?button,
????????????//?extract?the?user?input?and?repaint?the?form
????????????MyWidth?=?dlg.UserWidth;
????????????MyHeight?=?dlg.UserHeight;
????????????MyUnits?=?(MyForm.Units)?dlg.UserUnits;
????????????Invalidate?();
????????}

????????//?Dispose?of?the?dialog
????????dlg.Dispose?();
????}

????//?Handler?for?the?Exit?command
????void?OnExit?(object?sender,?EventArgs?e)
????{
????????Close?();
????}

????//?OnPaint?handler
????protected?override?void?OnPaint?(PaintEventArgs?e)
????{
????????int?multiplier?=?1;

????????switch?(MyUnits)?{

????????case?Units.Inches:
????????????e.Graphics.PageUnit?=?GraphicsUnit.Inch;
????????????break;

????????case?Units.Centimeters:
????????????e.Graphics.PageUnit?=?GraphicsUnit.Millimeter;
????????????multiplier?=?10;
????????????break;

????????case?Units.Pixels:
????????????e.Graphics.PageUnit?=?GraphicsUnit.Pixel;
????????????break;
????????}

????????SolidBrush?brush?=?new?SolidBrush?(Color.Magenta);
????????e.Graphics.FillEllipse?(brush,?0,?0,?MyWidth?*?multiplier,
????????????MyHeight?*?multiplier);
????????brush.Dispose?();
????}

????static?void?Main?()?
????{
????????Application.Run?(new?MyForm?());
????}
}

class?MyDialog?:?Form
{
????Label?WidthLabel;
????Label?HeightLabel;
????TextBox?WidthBox;
????TextBox?HeightBox;
????GroupBox?UnitsGroup;
????RadioButton?InchesButton;
????RadioButton?CentimetersButton;
????RadioButton?PixelsButton;
????Button?OKButton;
????Button?NotOKButton;

????public?int?UserWidth
????{
????????get?{?return?Convert.ToInt32?(WidthBox.Text);?}
????????set?{?WidthBox.Text?=?value.ToString?();?}
????}

????public?int?UserHeight
????{
????????get?{?return?Convert.ToInt32?(HeightBox.Text);?}
????????set?{?HeightBox.Text?=?value.ToString?();?}
????}

????public?int?UserUnits
????{
????????get
????????{
????????????for?(int?i=0;?i<UnitsGroup.Controls.Count;?i++)?{
????????????????RadioButton?button?=
????????????????????(RadioButton)?UnitsGroup.Controls[i];
????????????????if?(button.Checked)
????????????????????return?i;????????????????
????????????}
????????????return?-1;
????????}
????????set
????????{
????????????RadioButton?button?=
????????????????(RadioButton)?UnitsGroup.Controls[value];
????????????button.Checked?=?true;
????????}
????}

????public?MyDialog?()
????{
????????//?Initialize?the?dialog's?visual?properties
????????ClientSize?=?new?Size?(296,?196);
????????StartPosition?=?FormStartPosition.CenterParent;
????????FormBorderStyle?=?FormBorderStyle.FixedDialog;
????????MaximizeBox?=?false;
????????MinimizeBox?=?false;
????????Text?= "Edit?Ellipse";
????????ShowInTaskbar?=?false;

????????//?Create?the?dialog's?controls
????????WidthLabel?=?new?Label?();
????????WidthLabel.Location?=?new?Point?(16,?16);
????????WidthLabel.Size?=?new?Size?(48,?24);
????????WidthLabel.Text?= "Width";

????????HeightLabel?=?new?Label?();
????????HeightLabel.Location?=?new?Point?(16,?48);
????????HeightLabel.Size?=?new?Size?(48,?24);
????????HeightLabel.Text?= "Height";

????????WidthBox?=?new?TextBox?();
????????WidthBox.Location?=?new?Point?(64,?12);
????????WidthBox.Size?=?new?Size?(96,?24);
????????WidthBox.TabIndex?=?1;

????????HeightBox?=?new?TextBox?();
????????HeightBox.Location?=?new?Point?(64,?44);
????????HeightBox.Size?=?new?Size?(96,?24);
????????HeightBox.TabIndex?=?2;

????????UnitsGroup?=?new?GroupBox?();
????????UnitsGroup.Location?=?new?Point?(16,?76);
????????UnitsGroup.Size?=?new?Size?(144,?100);
????????UnitsGroup.Text?= "Units";

????????InchesButton?=?new?RadioButton?();
????????InchesButton.Location?=?new?Point?(16,?24);
????????InchesButton.Size?=?new?Size?(112,?16);
????????InchesButton.Text?= "Inches";

????????CentimetersButton?=?new?RadioButton?();
????????CentimetersButton.Location?=?new?Point?(16,?48);
????????CentimetersButton.Size?=?new?Size?(112,?16);
????????CentimetersButton.Text?= "Centimeters";

????????PixelsButton?=?new?RadioButton?();
????????PixelsButton.Location?=?new?Point?(16,?72);
????????PixelsButton.Size?=?new?Size?(112,?16);
????????PixelsButton.Text?= "Pixels";

????????OKButton?=?new?Button?();
????????OKButton.Location?=?new?Point?(184,?12);
????????OKButton.Size?=?new?Size?(96,?24);
????????OKButton.TabIndex?=?3;
????????OKButton.Text?= "OK";
????????OKButton.DialogResult?=?DialogResult.OK;

????????NotOKButton?=?new?Button?();
????????NotOKButton.Location?=?new?Point?(184,?44);
????????NotOKButton.Size?=?new?Size?(96,?24);
????????NotOKButton.TabIndex?=?4;
????????NotOKButton.Text?= "Cancel";
????????NotOKButton.DialogResult?=?DialogResult.Cancel;

????????AcceptButton?=?OKButton;
????????CancelButton?=?NotOKButton;

????????//?Add?the?controls?to?the?dialog
????????Controls.Add?(WidthLabel);
????????Controls.Add?(HeightLabel);
????????Controls.Add?(WidthBox);
????????Controls.Add?(HeightBox);
????????Controls.Add?(UnitsGroup);
????????UnitsGroup.Controls.Add?(InchesButton);
????????UnitsGroup.Controls.Add?(CentimetersButton);
????????UnitsGroup.Controls.Add?(PixelsButton);
????????Controls.Add?(OKButton);
????????Controls.Add?(NotOKButton);
????}
}
Figure 4-22
The DialogDemo source code.