Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Adding custom dialogs to your applications

0.00/5 (No votes)
16 Oct 2005 1  
The article introduces a base dialog form class, which can be used to create all kinds of OK/Cancel type of dialogs. It also gives the basics of custom control creation and form inheritance.

Sample Image - CustomDialogs.png

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.

  1. Inherit from System.Windows.Forms.Control.
  2. Paint it ourselves.
    protected override void OnPaint(PaintEventArgs e) {
      base.OnPaint(e);
      Redraw(e.Graphics);
    }
  3. Repaint it on resize.
    protected override void OnResize(EventArgs e) {
      base.OnResize(e);
      // height shouldn't change, only length changes
    
      this.Height = 6;
      Redraw(this.CreateGraphics());
    }

Here goes the painting:

private void Redraw(Graphics g) {
  // drawing dark edge of line

  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);
  // drawing bright edge of line

  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.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here