Introduction

When you design a user interface using classic Windows Forms, you normally use the .NET MessageBox to give short information feedbacks or let the user make choices. In my latest project, I also needed simple dialogs to display status messages after processing some server operations. These messages were usually quite short, something like "everything was processed successfully". So “why create my own dialog”, I thought and decided to use the standard MessageBox to do the job.

The Problem

Everything worked well and my program kept growing for a while. I added some bigger batch operations which consist of many server operations. Every operation had its – usually quite short – message but also could produce a short error report. All of these messages together could add to quite big “status reports”.

When I first saw the results. they looked like this:

Yes, the MessageBox did resize itself to fit my contents, but I could not see any of my buttons at the bottom, because it was cropped at the bottom. But not enough: Not all contents are reachable, because the vertical scrollbar was missing.

This was not acceptable for me, so I was thinking about creating an own dialog to display my various kinds of messages. The more I thought about it, the less I wanted to design a dialog specially tailored to the application, especially because I did not want to change all usages of MessageBox.Show(…) in my code.

The Solution: A Flexible Messagebox

I was searching for a replacement of my standard MessageBox in the web. But although I found very useful things, none of the solutions made me really happy. I, first of all, wanted a MessageBox-Replacement which should be resizable and no bunch of code, which would have been overdone for me. So I ended up programming a substitution to fit my own needs.

Features

This is an abstract of the features provided by FlexibleMessageBox:

It can be simply used instead of MessageBox since all important staticShow functions are supported

It is small, only one source file, which could be added easily to each solution

It can be resized and the content is correctly word-wrapped

It tries to auto-size the width to show the longest text row

It never exceeds the current desktop working area

It displays a vertical scrollbar when needed

It supports hyperlinks in the text

Appearance

Using the FlexibleMessageBox, the results from above could now look like this:

But the appearance of the FlexibleMessageBox can also look like:

Or using another font like so:

Using the FlexibleMessageBox

Integration Into Your Project

To use the FlexibleMessageBox in your code, the following simple steps are suggested:

Download the FlexibleMessageBox.cs source file (or the demo project).

Add the FlexibleMessageBox.cs source file to your solution.

Add using JR.Utils.GUI.Forms to your source file.

That’s all. Now you can use FlexibleMessageBox like (almost) every other MessageBox.

Usage examples:

FlexibleMessageBox.Show("Just a text");
FlexibleMessageBox.Show("A text", "A caption");
FlexibleMessageBox.Show("Some text with a link: www.google.com",
"Some caption",
MessageBoxButtons.AbortRetryIgnore,
MessageBoxIcon.Information,
MessageBoxDefaultButton.Button2);
var result = FlexibleMessageBox.Show("Know the answer to life the universe and everything?",
"One short question",
MessageBoxButtons.YesNo); //By the way: The answer is 42 :-)

Using the Demo Application

This is just a small Windows Forms application to demonstrate the features of the FlexibleMessageBox:

The leftmost two buttons do show two variations of the FlexibleMessageBox with different parameters. The two buttons in the middle do show a sample for a text with many rows, first time with the .NET MessageBox and in contrast using theFlexibleMessageBox. You can test resizing the FlexibleMessageBox and watch the word wrapping and the vertical scrollbar. On the right side, you can change some static parameters (which are described below) to see how the appearance of all FlexibleMessageBoxes does change. Click the checkbox to use another font. Use the sliders to modify the maximum width and height.

Inside the Code

Decision: Provide the Code in a Single File

I know that I should have to split the code in more than one source file to keep it more readable and for terms of modularization. But I also know that I, for my part, was often annoyed when I wanted to use an external component and have to include many files for a simple component. So I decided to put this component in one single file that can be added to other projects easily.

Clean Interface

You may have noticed that the public interface of the FlexibleMessageBox is very clean:

That’s because all relevant helper functions reside in an inner class FlexibleMessageBoxForm. See below for a short description of this class.

Static Show-Functions

These are the available Show-Functions, which are a subset of those in the original .NET MessageBoxShow-Functions:

Static Parameters

There are a few static variables that contain settings used for all FlexibleMessageBox instances:

MAX_WIDTH_FACTOR

Defines the maximum width for all FlexibleMessageBox instances in percent of the working area.
Allowed values are minimal from 0.2 up to 1.0:

0.2 means: The FlexibleMessageBox can be at most half as wide as the working area.

1.0 means: The FlexibleMessageBox can be as wide as the working area.

The default value is 0.7 which is 70% of the working area width.

MAX_HEIGHT_FACTOR

Defines the maximum height for all FlexibleMessageBox instances in percent of the working area.

Allowed values are minimal from 0.2 up to 1.0:

0.2 means: The FlexibleMessageBox can be at most half as high as the working area.

1.0 means: The FlexibleMessageBox can be as high as the working area.

The default value is 0.9 which is 90% of the working area height.

Font

Defines the font that is used for all FlexibleMessageBox instances. The default value is SystemFonts.MessageBoxFont.

Inner Form Class FlexibleMessageBoxForm

The hidden inner class FlexibleMessageBoxForm is derived from Form and does arrange the needed GUI elements. The text is provided as a RichTextBox. Beyond, there are three buttons and the PictureBox for the icon – nothing magical.

Show-Function

The staticShow function of <code>FlexibleMessageBoxForm is called by all Show-functions of FlexibleMessageBox. It is dealing with all the different given parameters and performs the following operations:

Creates a new instance of the FlexibleMessageBox form

Binds the caption and the message text

Sets the buttons visibilities and texts

Sets a default button

Sets the dialogs icon. When no icon is used: Corrects the placement and width of rich text box

Sets the font for all controls, using the static FONT. When no font is set, it uses the standard SystemFonts.MessageBoxFont

Calculates the dialogs start size by trying to auto-size the width to show the longest text row

Sets the dialogs maximum size, using the statics for MAX_WIDTH_FACTOR and MAX_HEIGHT_FACTOR

Sets the dialogs start position when given. Otherwise, centers the dialog on the current screen

And last but not least: Shows the dialog

Helper Functions and Other Stuff

There are several small helper functions. Please discover them on your own. I tried to document it well and used code regions to increase the readability.

Share

About the Author

I am a freelancer developer since 2005. Prior to that I worked for a small software company beginning in 1998. My origins in the software sector were in 1980s as I programmed assembler on the good old C64 and dreamt of being a game developer.

The default button (set by the "MessageBoxDefaultButton" parameter) is active after showing the FlexibleMessageBox. You can use <enter> to confirm the default button. Or <escape> to exit.
This works in the demo application you can download.

Have you tried version 1.2?
I have made a few bugfixes in this version.

For the localization problem of the buttons, here is another solution which allows for the use of a uniquely named string resource ("FlexibleMessageBoxButtonText") within the current assembly. This resource must include a '|' separated list of 7 strings in the same order as the current strings. For example, the list in Italian would be "OK|Annulla|&Sì|&No|&Interrompi|&Riprova|&Ignora". This will work with multiple localizations and is only expensive on the first fetch after a culture UI change. Using CurrentUICulture, instead of InstalledUICulture, makes sure the buttons match the language of the application's UI. It requires the addition of two static fields and the modification to the GetButtonText method as follows.