/// This method is part of the dialog.
static public DialogResult ShowDialog(string title,
// Call the private constructor so the users only need to call this
// function, which is similar to MessageBox.Show.
// Returns a standard DialogResult.
using (BetterDialog dialog = new BetterDialog(title, largeHeading,
smallExplanation, leftButton, rightButton, iconSet))
DialogResult result = dialog.ShowDialog();
/// This is the calling convention of the above method.
/// Use this to show a custom dialog in your source code.
private void ExampleCall()
DialogResult result = BetterDialog.ShowDialog("Reset Journal Settings",
"Settings will be erased permanently",
"This will not affect any of the text content in the database.",
"Reset", "Cancel", Properties.Resources.DialogWarningXP);
if (result == DialogResult.OK)
Console.WriteLine("User accepted the dialog");
Logic. This code implements the basic logic, but lacks some details. We can see some of the logic and method calls used and the general technique.
Detail It uses CreateGraphics to get a Graphics object on the form. It MeasureString and attempts to lay out the dialog.
Note I had to find values that would lay out and position the elements properly. A table layout simplifies the design.
Detail The layout is done with 2 TableLayoutPanels, with a white background so that it can better match Windows' themes.
Detail It can hide or show various parts. It will hide buttons you specify as null, and it will hide the text if it is empty.
/// Use this with the above static method.
private BetterDialog(string title,
// Set up some properties.
this.Font = SystemFonts.MessageBoxFont;
this.ForeColor = SystemColors.WindowText;
this.Width = 350;
this.Height = 150;
// Do some measurements with Graphics.using (Graphics graphics = this.CreateGraphics())
if (string.IsNullOrEmpty(smallExplanation) == false)
// Note: at this point, we could detect that the OS is Vista
// and do some customizations. That logic is in the download.
// The code here does some measurements.
label1.Font = new Font(SystemFonts.MessageBoxFont.FontFamily.Name, 8.0f,
smallSize = graphics.MeasureString(smallExplanation, this.Font,
bigSize = graphics.MeasureString(largeHeading, label1.Font,
this.Height = (int)smallSize.Height + 166;
double bigger = (smallSize.Width > bigSize.Width) ?
smallSize.Width : bigSize.Width;
this.Width = (int)bigger + 100;
// We have a null "smallExplanation", so we have a single message
// dialog. Do some different changes. Code omitted for brevity (you
// can find the logic in the download if you want to see it).
// Establish a minimum width.
if (this.Width < 260)
this.Width = 260;
// Set the title, and some Text properties.
this.Text = title;
label1.Text = largeHeading;
label2.Text = string.IsNullOrEmpty(smallExplanation) ?
string.Empty : smallExplanation;
// Set the left button, which is optional.
if (string.IsNullOrEmpty(leftButton) == false)
this.buttonLeft.Text = leftButton;
this.AcceptButton = buttonRight;
this.buttonLeft.Visible = false;
this.buttonRight.Text = rightButton;
// Set the PictureBox and the icon.
pictureBox1.Image = iconSet;
Properties. This dialog has some special attributes. The custom dialog has these properties, many of which are not in the default MessageBox in Windows Forms.
Detail It uses the proper fonts—this means the Segoe UI font on newer Windows operating systems.