Draw random rectangles in C#

[random rectangles]

This example simply draws random rectangles on top of each other. It’s mostly straightforward, although it does contain a couple of techniques that are useful if you do a lot of graphics programming.


When it starts, the following code performs a few initialization tasks.

private Bitmap Bm;
private Graphics Gr;

// Make a bitmap to display.
private void Form1_Load(object sender, EventArgs e)
{
    FormBorderStyle = FormBorderStyle.FixedDialog;
    MinimizeBox = false;
    MaximizeBox = false;
    DoubleBuffered = true;
    // Set at design time:
    //      StartPosition = FormStartPosition.CenterScreen;

    Bm = new Bitmap(ClientSize.Width, ClientSize.Height);
    Gr = Graphics.FromImage(Bm);
    BackgroundImage = Bm;
}

This code sets the form’s BorderStyle property to FixedDialog so the user cannot resize it. If the user resized the form, the program would need to worry about drawing on an area that can change size, and that would be more work so I skipped it.

The code also sets the form’s MinimizeBox and MaximizeBox properties to false so the user cannot minimize and maximize the form, respectively. The form’s border style is FixedDialog, so these properties make me wonder, “What part of, ‘do not allow the user to resize the form,’ don’t you understand?”

In this program, if the user minimizes the form, then it has width and height zero. That makes a later calculation will pass a negative value into the Random object’s Next method and that crashes the program. Removing the MinimizeBox prevents that.

If the user maximizes the form, then the Bitmap (described shortly) doesn’t fill the entire form so it is tiled. That’s kind of interesting, but it isn’t what I had in ind and it seems to noticeably hurt performance, so I prevent that, also.

The code also sets the form’s DoubleBuffered property to true. That tells the form to draw its graphics in a secondary piece of memory and only display it when the drawing is complete. This is important for programs that draw a lot of graphics very quickly. If you don’t set this property to true, the program flickers wildly. (Comment out that statement to see. It’s pretty annoying.)

You can set the form’s StartPosition property in the code, but by the time the Load event handler executes, the form has already been positioned, so that has no effect. If you want to change the form’s startup position, you must do it at design time.

Next, the program creates a Bitmap to fit the form’s client area. It also creates an associated Graphics object on which to draw. Finally, it sets the form’s background image to the Bitmap so it will display anything that the program draws on the Bitmap (via the Graphics object).

At design time, I added a Timer that executes the following Tick event handler every 100 milliseconds. (Ten times per second).

private Random Rand = new Random();

private void tmrMakeRectangle_Tick(object sender, EventArgs e)
{
    int x = Rand.Next(ClientSize.Width - 10);
    int y = Rand.Next(ClientSize.Height - 10);
    int width = Rand.Next(ClientSize.Width - x);
    int height = Rand.Next(ClientSize.Height - y);
    Color color = Color.FromArgb(128,
        255 * Rand.Next(2),
        255 * Rand.Next(2),
        255 * Rand.Next(2));
    using (Brush brush = new SolidBrush(color))
    {
        Gr.FillRectangle(brush, x, y, width, height);
    }
    Refresh();
}

The Rand object is declared at the class level so it is created only once and then every call to the event handler uses the same object. That is important. If the event handler created its own Random object, then that object would use the system time to initialize itself. If the event handler executes quickly enough, then some of its executions would use the same time to initialize the object so they would generate the same “random” numbers. that would mean the program would waste time generating the same rectangles multiple times.

This program doesn’t run fast enough to generate too many duplicate rectangles if you create Random objects in that way, but it’s better to use a single Random object if multiple methods will be generating random numbers very quickly. That avoid possible duplication and saves a little time creating, initializing, and destroying the objects.

The Tick event handler uses the Random object to pick X and Y coordinates for a rectangle’s upper left corner. It leaves some space to the right and blow the possible X and Y coordinates so there is room for the rectangle to have a non-zero width and height.

The code then generates a random width and height and a random color. Each off the color’s red, green, and blue components is either 0 or 255. That means the possible colors include:

  • Black (all 0)
  • White (all 255)
  • The primary colors red, green, and blue (one component is 255 and the others are 0)
  • The secondary colors yellow, cyan, and fuchsia (two components are 255 and one is 0)

The color’s alpha (opacity) component is 128, so the color is semi-transparent and rectangles behind other rectangles show through.

After generating the random color, the program fills the random rectangle with it. The form already displays the bitmap Bm as its background image, so the code simply refreshes the form to display the result.

The only other piece to the program is the following KeyDown event handler.

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    if (e.KeyCode == Keys.Escape) Gr.Clear(BackColor);
}

If you press Escape, this event handler clears the form’s background so the drawing starts over.

Download the example and experiment with it. You might try making it draw ellipses instead of rectangles. Or try changing the way the random colors are generated. The program is amazingly simple but produces an interesting result.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in drawing, graphics and tagged , , , , , , , , . Bookmark the permalink.

2 Responses to Draw random rectangles in C#

  1. Ziz says:

    Recent articles a have been useful to me. A question or maybe a future article. If you had 4 dots on the canvas how can I make it draw lines between them to form a square (provided they are in a square)? Obviously I could have more dots and then I would need to say which I want to draw between so almost like join the dots pictures we had as children.

    • RodStephens says:

      You have a couple of options. First, you could simply draw lines between the dots. You would need to know which ones were sides of the square. (Or is that your main question? How to determine which ones make a square?)

      Second, if the dots form a square with sides parallel to the X and Y axes, then you could use them to define a Rectangle object and use the Graphics object’s DrawRectangle method. If you know that the dots form this arrangement, then you can find the minimum X and Y coordinates to get the Rectangle object's upper left corner. Then find the maximum X and Y coordinates and subtract to get the width and height.

      Probably the most general approach would be to put the points in an array and then use the Graphics object's DrawPolygon method. That will work with rotated squares and will make the lines connect nicely, unlike the first approach where the corners may not fit together perfectly depending on the line's properties. (I.e. thickness and the pen's LineJoin property.)

      As for how to figure out which dots make squares, see these posts:

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.