Today, I decided that I needed a new messagebox to communicate with the user in a war-game I'm writing, and that's how I discovered that there were no ready-made buttons for a message box with the text "Charge" or "Cancel Attack" on them. Floundering around a bit to figure out how to get this done, I put a form together, and discovered that I could lock the system until it was either disposed or closed, by setting this form's owner to the calling form. But, closing this message box discarded the value of the reference variable 'reply' which I had passed to it, making it useless.
This, I decided, was a problem. And, after resolving to fix the issue, I came on-line to this site and found a few options that had their own complications, and I got some help from MSDN's C# General Forum which gave me the answer I needed for my war-game (click here), but a more generalized idea was nascent.
In this article, I will explain how to use
classMessagebox, which allows users to easily invoke as many buttons as they want, call them whatever is their fancy, and give each button and/or main text its own font.
The Five-Step Programme
The image above results from the test form's button event handler, shown here:
private void btnTestClassMessageBox_Click(object sender, EventArgs e)
= new classMessageBox("Message Box",
"This is a test",
"Button 1,Button 2,Vote Quimbey");
msgBox.Owner = this;
string reply = msgBox.Reply;
Text = reply;
Points of Interest
Since the label and the array of buttons are both
public in the class, you can change their fonts before calling
ShowDialog(). These objects have event handlers to resize the form when their fonts change so that adding these two lines, for example:
msgBox.btns.Font = new Font("ms sans-serif", 18);
msgBox.lbl.Font = new Font("Lucida Console", 18, FontStyle.Italic);
gives you this:
Your messagebox's reply is the same as the text written on the button which the user pressed. As long as you don't have two buttons with the same text, you'll know what the user wants.
Simple, flexible, and easy to use!
How it Works
There isn't very much in here to explain. It's all pretty straightforward. Really the only part that might be difficult is the
resize() function, but first, let me start from the beginning and give you a brief tour.
The class inherits
Form. It has a label and an empty array of buttons, and it receives three parameters, all of which are strings. The reply is a global variable which is treated like a property with its own '
When you instantiate a messagebox, the first two parameters are simply written where they belong, the first being the heading that goes to the
Form's text proper, and the second parameter is set as the text of our label. You with me so far? Nothing to it.
The third parameter is where the fun starts. This string is split into an array of strings using a comma as a divisor. This array of strings is then run through, one at a time, and the strings are sent as parameters to a function which generates all the buttons, setting these strings as text for each button. Once all the buttons are created, complete with their
Click event-handlers, and included into the global array of buttons, then the resizing begins.
At this point, the resize function is called straight away, and this function then places the buttons left to right, from the left edge of the screen, with their
AutoSize set to
ShrinkAndGrow. Once this is done, we know how wide our form has to be, so we set this value to fit all the buttons onto the form. Then, setting the
AutoSize value to
true, we get a measure of the
Label's width. The
Resize function then calculates how many lines of text this
Label will require if its width is greater than the width of the form. Now, we set the
false, and adjust its height to fit the number of lines we assume it will need (this does not account for any return carriage characters in the
Label's text) by multiplying the number of lines times the
Label's font height. Next, all the buttons have to be shifted down below the
Label, and finally the form's height is set to fit the buttons.
And, we're done resizing this form.
When the font of one of the buttons (or the label) is changed, then that object's size may change as well, throwing our resized form's edge all a quiver. But, if we call
resizeForm straight from the
FontChange event-handler, then that object's size won't have adjusted already, so we have to wait, and calling that object's
Refresh() doesn't solve your problem either; so to get this to work, you have to get the object to adjust its size to fit its new font, and sometimes all we need is time... so out comes the timer. The event handlers call
initResize, which creates a timer and sets the timer's interval to the grand ole' value of 5 milliseconds and trips it to go. Five milliseconds to a computer, of course, is equivalent to something close to eternity, and so this gives your object plenty of time to adjust its size to fit its new font, and the time this timer trips and its
Tick event is handled, the form is ready to be resized.