Introduction
Dialogs are one of the most widely used types of UI windows. One can hardly imagine Windows application without dialogs. Some of them are easy enough like message boxes with several buttons. Their functionality is pretty much covered by the .NET MessageBox
class. Some are more complex, like file save/load dialogs or printer settings. These also have their corresponding .NET classes. But what if we need some other form of dialog, not covered by MessageBox
or standard dialog controls? In real life applications, the need for custom dialogs arises far too often. Of course, this is a simple matter of putting the necessary controls on the form, adding OK and Cancel buttons, and voila! But why do the same chore over and over again? Let's make the base dialog class and reuse it through inheritance. Isn't it what the OOP is all about?
BaseDialog class
In the beginning, let's ask ourselves what we want of the basic dialog.
First, we need it to have OK and Cancel buttons. Let's put them to the bottom left of the form.
Second, let's draw a line separating them from the rest of the form. Oops, there is no line control in .NET. Never mind, we will make this control ourselves, and learn the basics of custom control creation in the process.
Third, we need to update the layout of these controls in case of resizing of the inheriting form.
protected override void OnLoad(EventArgs e) {
base.OnLoad (e);
OnResize(e);
}
protected override void OnResize(EventArgs e) {
base.OnResize (e);
Line1.Location = new Point(6, this.Size.Height - 64);
Line1.Size = new Size(this.Size.Width - 18, 2);
int okx = this.Size.Width - cbOk.Size.Width - 14;
if(cbCancel.Visible && this.Visible)
okx -= cbCancel.Size.Width + 4;
cbOk.Location = new Point(okx, this.Size.Height - cbOk.Size.Height - 32);
cbCancel.Location = new Point(this.Size.Width -
cbCancel.Size.Width - 14,
this.Size.Height - cbCancel.Size.Height - 32);
}
And, finally, the most important thing. The inheritors should be able to add some custom actions when the dialog completes, either with DialogResult.Ok
or DialogResult.Cancel
. These could be some validating actions, with the ability to prevent dialog completion. protected
virtual methods with boolean return value will serve this purpose just nice.
private void cbOk_Click(object sender, System.EventArgs e) {
ExitOk();
}
private void cbCancel_Click(object sender, System.EventArgs e) {
ExitCancel();
}
protected void ExitOk() {
if(cbOk.Enabled==true) {
if(OnOk()) {
this.DialogResult = DialogResult.OK;
this.Close();
}
}
}
protected void ExitCancel() {
if(cbCancel.Enabled==true) {
if(OnCancel()) {
this.DialogResult = DialogResult.Cancel;
this.Close();
}
}
}
protected virtual bool OnOk() {
return true;
}
protected virtual bool OnCancel() {
return true;
}
Line Control
That one is easy as 1-2-3.
- Inherit from
System.Windows.Forms.Control
.
- Paint it ourselves.
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
Redraw(e.Graphics);
}
- Repaint it on resize.
protected override void OnResize(EventArgs e) {
base.OnResize(e);
this.Height = 6;
Redraw(this.CreateGraphics());
}
Here goes the painting:
private void Redraw(Graphics g) {
Pen pen = new Pen(SystemColors.ControlDark, 1);
Point p1 = new Point(1, 2);
Point p2 = new Point(this.Width - 2, 2);
g.DrawLine(pen, p1, p2);
pen = new Pen(SystemColors.ControlLightLight, 1);
p1 = new Point(1, 3);
p2 = new Point(this.Width - 2, 3);
g.DrawLine(pen, p1, p2);
p1 = new Point(this.Width - 2, 2);
g.DrawLine(pen, p1, p2);
}
How to use
Now dialog creation becomes a pleasure. Add an inherited form to your project (choose BaseDialog
to inherit from). Add necessary controls and code. Don't forget to make a good use of the Anchor
property for added controls. Resize the form to the preferred size. Override OnOk
and OnCancel
methods to add validation code if necessary.
Add the calling code to the application form. For example:
private void button1_Click(object sender, System.EventArgs e) {
SampleDialog sd = new SampleDialog();
if(sd.ShowDialog()==DialogResult.OK) {
}
}
Now some exercises:
- Try to make a dialog without a Cancel button.
- Try to make a Yes/No dialog.
- Try to hide a line and put your controls in a groupbox instead.
All this can be done without making any changes to BaseDialog
.
History
- 16th October 2005 - article submitted.