Introduction

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.

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:

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 'get' routine.

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 FontChange and 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 true and AutoSizeMode 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 Label's 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 Label's AutoSize to 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.

Share

About the Author

Christ Kennedy, published his fourth novel "Cleats of the Counter Revolution" in the summer of 2010. He grew up in the suburbs of Montreal and is a bilingual Quebecois with a bachelor’s degree in computer engineering from McGill University and is currently walking across ontario plotting a new novel, far away from any computer.

Comments and Discussions

sure, you could do that.
if you did then you wouldn't be restricted from using the ',' (comma) in the string which I am using as a string separator in the 'split' call.
only, it would force the programmer to turn a string into an array, which isn't a big deal but is an extra step.

I'm not going to change it, but you're welcome to use this code however you like.
BadButBit