Get up to 80 % extra points for free! More info:

Lesson 7 - Drawing on Graphics in C# .NET

In the previous lesson, Birthday Reminder - Storing Data and Conclusion, we finished creating the birthday reminder. We tried the basic form controls on it, as well as bindings and error handling. We are already able to create quite sophisticated applications. In today's C# .NET tutorial we're going to take a look at drawing.

Drawing on Graphics

We'll create an application that takes care of selling cinema tickets. As we know, there are many seats in the cinema hall, and the cinema worker should be able to see in the application which seats are already occupied. You might think of clicking a PictureBox for each seat. However, if the cinema had 15 rows with 30 seats each, we'd have 450 PictureBox. You probably guess there should be a better way than to start typing PictureBox1, PictureBox2, ... And how those would be handled then? In case we need to render something more complex than just one or two pictures, we use Graphics. The principle is we place a single PictureBox on the form and draw what we need on its canvas.

We'll simplify the application considerably, it doesn't need to be complicated. It'll be able to display a single hall only, which will be initially empty. The user will click the seats to make them occupied using the mouse, and then they will press the Save button, which will create a simple text file at the selected location. The file will contain information about the occupancy of the hall. The reason of saving the data is to learn how to work with dialogues.

Form Design

Create a new Windows Forms Application, rename the form to CinemaForm, the title could be Cinema hall booking. Add a PictureBox to cover most of the form and name it as cinemaPictureBox. Below the PictureBox, place a Button with the saveButton name and the Save text. Finally, we'll drag SaveFileDialog onto the form. This control won't be placed directly on the form, but in a bar below it, because it's not an actual form control, but merely a helper component. We'll rename it to cinemaSaveFileDialog. You can play with the anchors as you want. Your form should look like this:

Cinema form in C# .NET - Form Applications in C# .NET Windows Forms

Logic Layer

You're probably not surprised that we'll add a Cinema class. It'll have a single private field, a two-dimensional array of seats. If you haven't worked with a 2D array yet, you can think of it as a table. A one-dimensional (classic) array is just a single row. With the 2D array we work exactly the same as with the one-dimensional array, except that we have to specify two coordinates (X and Y). In many languages, 2D arrays are created as array of arrays, but C# allows us to declare 2D arrays directly as follows:

class Cinema
{
    private bool[,] seats = new bool[30, 15];

}

The seats are of the bool type, because we only care whether it's vacant or occupied. 30 is the width of the array, 15 is the height.

We'll also add 2 private constants to the class, one defining the size of rendered seats in pixels, and the other one defining the space between the seats in pixels. Get used to constants, because when you'll want to resize the seats, you'll just change the value of a constant without having to mess with the rendering code.

private const int size = 16;
private const int space = 2;

We can now move to methods.

Rendering

The cinema hall should be able to render itself. We've already mentioned that we'll draw on a canvas. This canvas is of the Graphics type, and we'll request it as a Draw() method parameter. You need to add using System.Drawing for the Graphics type to use, but it certainly didn't surprise you. We draw on the canvas using its methods. For now, we'll be interested only in the FillRectangle() method, which draws a rectangle filled with a specific color. There are a lot of methods for different geometric shapes, both filled or unfilled. You can check them out, we'll try some of them in following lessons.

In Graphics, there are two types of color - the fill color (Brush) and the outline color (Pen). For the filled rectangle we have to specify a Brush. Already created instances set to certain colors can be found in the static Brushes class (or Pens for outlines, respectively), you can choose. Brushes can also draw patterns or pictures, but that isn't important to us right now.

Using two nested loops, we'll go through all the seats in the array and draw either a green or a red square on the canvas. We'll go through the rows using the outer loop, and through the columns in the current row using the inner loop. We'll determine the color (the brush, more precisely) by whether the seat at the given coordinates is true or false. The method code will be as follows:

public void Draw(Graphics g)
{
    Brush brush;
    for (int j = 0; j < seats.GetLength(1); j++)
    {
        for (int i = 0; i < seats.GetLength(0); i++)
        {
            if (seats[i, j])
                brush = Brushes.Red;
            else
                brush = Brushes.Green;
            g.FillRectangle(brush, i * (size + space), j * (size + space), size, size);
        }
    }
}

Notice that we didn't hard-code the values 30 and 15 in the loops, but we use the GetLength() method instead with parameters 0 and 1. This method is used to get the size of a two-dimensional array. 0 is the width, 1 is the height (of course, it depends on us which dimension we choose to represent the height and which dimension the width). Of course, we don't specify a fixed size because in the future we may increase/decrease the array size, and we don't want to have to look in the entire code to find where we use the values 30 and 15. It's always better to avoid these problems and work with the array length.

It's worth mentioning the rendering of the rectangle itself. The first parameter of the FillRectangle() method is the Brush, which determines the filling color. The other two parameters are the coordinates of the upper left corner of the rectangle. The last two parameters determine its height and width. Since each seat is 16 pixels wide + 2 pixels spaced from each other, we need to multiply its coordinate by that value. For example, if the i value is 2 (i.e. drawing the third column), we're drawing at the X coordinate of 36, instead of 2 :) The same applies for the Y coordinate.

Later, you may try replacing the FillRectangle() method with FillOval(). It works exactly the same, but draws an ellipse. Be sure to try drawing other shapes after we finish the app.

Wiring the Form and Logic

The base of the logic is done, let's wire it with the form. Let's go to the form code and create a private instance of the cinema hall:

private Cinema cinema = new Cinema();

Now we'll click the PictureBox and add it the Paint event handler. You have to do this via the flash icon in the Properties window. The event is called by the system when the window is to be redrawn. This is, of course, when we start the application, but also after maximizing the window, when we move another window over the window of our application, and so on.

In the event handler, we'll call the Draw() method of the cinema instance. The canvas is passed as a property of the event parameter. We'll just pass it to the logic method that will draw on it.

private void cinemaPictureBox_Paint(object sender, PaintEventArgs e)
{
    cinema.Draw(e.Graphics);
}

We certainly don't have to be ashamed of the result:

Drawing shapes on a PictureBox in C# .NET - Form Applications in C# .NET Windows Forms

In the next lesson, Handling Clicks at Coordinates in C# .NET, we'll show how to change the status of a seat by clicking on it, and we'll also implement saving. As always, you can download the project in the attachment below, in case something went wrong.


 

Did you have a problem with anything? Download the sample application below and compare it with your project, you will find the error easily.

Download

By downloading the following file, you agree to the license terms

Downloaded 188x (229.25 kB)
Application includes source codes in language C#

 

Previous article
Birthday Reminder - Storing Data and Conclusion
All articles in this section
Form Applications in C# .NET Windows Forms
Skip article
(not recommended)
Handling Clicks at Coordinates in C# .NET
Article has been written for you by David Capka Hartinger
Avatar
User rating:
1 votes
The author is a programmer, who likes web technologies and being the lead/chief article writer at ICT.social. He shares his knowledge with the community and is always looking to improve. He believes that anyone can do what they set their mind to.
Unicorn university David learned IT at the Unicorn University - a prestigious college providing education on IT and economics.
Activities