How are Windows Forms Controls Created and Rendered Onto a Form?

In order to answer this question, I will use a project that I created in a previous demo. This demo is available here https://win-forms.com/2020/08/16/shapes-objects-and-lists-with-windows-forms/. You may clone the repository or download the code from here https://github.com/dwarwick/Shapes.

This post will cover how Windows Forms, or winforms for short, handles drawing controls on the forms. Examples of controls are text boxes, labels, list boxes, combo boxes, etc.

When you create a winforms project, a single windows form is created. The name of the form is Form1 by default, but you can, and should, rename it. You can also add as many additional forms to your project as you need.

Form Files

Each form consists of 3 files by default. For the purposes of this discussion, we will assume the name of the form is MainForm.

MainForm.cs is a file that normally contains all of the logic code behind the form. This file contains code that interacts with the controls on the form and the algorithms that make the program do what it is supposed to do.

MainForm.Designer.cs is a file that actually creates the controls, sets the initial property values of the controls, and renders the controls onto the form. This is what we will be diving into for this post.

MainForm.resx contains resources that are used by the form. We will not be discussing this today.

Identifying the 3 Files that Are a Form

We can browse to our solution folder to view these files on our hard drive as well. With MainForm.cs selected, you can view the path to the file in the properties window.

Finding File Location Using Properties Window

Lets open our File Explorer and navigate to the folder to view the form files.

File Explorer View of Project Files

In the File Explorer view, you can see 3 distinct files named MainForm.cs, MainForm.Designer.cs, and MainForm.resx. Close the File Explorer window and go back to Visual Studio.

Design View of Form

In the Solution Explorer, double click MainForm.cs. You will see the form open in Design View.

Form Open in Design View

This form was created by dragging and dropping each control onto the form and setting properties on each control using the properties window. See the Shapes Demo for more details on this.

Designer File Code

Open the MainForm.Designer.cs file to view the code that is used to create all of these controls and set the property values for each control.

Designer File Control Variables

In the image above, you can see that there are several variables that are declared. Each variable is named for one of the controls that are being used on our form. There are variables of type TextBox, Button, and Label. Each variable has of course been declared and given a Name such as txtBox_X. Each time a new control is dragged onto the form, Visual Studio creates a new variable in the designer file for you.

Now expand the plus sign next to the words Windows Form Designer generated code if you have not already expanded it.

You may see other plus signs that need to be expanded to view the full code in this file.

Plus Sign

The code in the image above simply declares a variable that represents a control. It does not actually create the control or define any properties.

InitializeComponent Method

Notice that there is a method named InitalizeComponent. This method is responsible for initializing all new controls and setting the properties on those controls.

As I stated before, when you drop a control on the form, a new variable is created for the control. At the same time, Visual Studio adds a new line of code to create a new instance of the control and sets some default property values for the control such as Name and TabIndex. And depending on where you drop the control and what size you make it, it sets the Location and Size properties as well.

Scroll down to the bottom of the InitializeComponent method.

Form Properties

Here you can see that our textboxes, labels, and button are actually added to the Controls Collection of the form. The controls are not actually associated with the form until they are part of the form Controls Collection. Next the Layout is performed and the form will be loaded with the controls positioned according to their assigned properties. This is the end of the InitializeComponent method.

The InitializeComponent method is called from the constructor of the MainForm class. Right click MainForm.cs and select View Code.

Initialize Component Method Called from Form Constructor

When we start debugging a form, the constructor runs before any other code in the MainForm class. The constructor runs the InitializeComponent method to load and position the controls onto the form.

Any changes that are made to a control on the form in design view are automatically updated in the designer file. If you change the color of a text box, or resize it, or set it to disabled, or make any other changes to it, those properties are updated automatically in the designer file.

Events

Events are also associated with their methods in the designer file. Have a look at the button properties in the designer file.

Button Click Event in Designer File

Here you can see that btnDraw Click event is associated with a method named btnDraw_Click. This line is added when you either double click a button in the form design view, or double click the click row for the button in the property window, or when you use the property window to browse to a button event method that has already been created in MainForm.cs.

If you enjoyed this post, please Like it so that you will be notified of new posts as I create them. I also have several other posts about Windows Forms available on my blog home page at https://win-forms.com.

If you have questions, comments, or suggestions, please leave a comment below.

Working with Buttons in Windows Forms

Buttons allow users to interact with a winforms application. The most popular event that is used for buttons is the click event.

An event is like a trigger for something to happen in the application. So it is like saying, “when this event happens, do this …”. So in this case, the event is that a button was clicked.

For our demonstration, we will create a simple winforms application that increments or decrements a counter (integer) that is displayed on a form.

A video of the demo is provided here, followed by step by step instructions.

Video of this Demo

Setup Your Environment

The first step is to launch Microsoft Visual Studio. If you do not have Visual Studio, see my post here, https://win-forms.com/2020/07/25/create-a-hello-world-winforms-application/ to learn how to download and install Microsoft Visual Studio and create your first Hello World application using Windows Forms.

Once Visual Studio is open, create a new project.

Create A new Project

Choose Windows Forms App (.Net Framework) C# as the template. Filter on C# Windows Desktop as shown in the image below.

Selecting Windows Forms type of Project

After you have selected the Windows Forms template, select Next. Name your project as ButtonDemo. I will be using .Net Framework 4.7.2 for this demo.

Name the Project

Click the Create Button. Once your project has been created, you will be presented with the blank Windows Forms template .

Blank Windows Forms Template

Rename our Form

Notice that our form gets the default name of Form1. It is good practice to name this to something more meaningful. When you start working on projects that contain several forms, you will have a hard time trying to keep track of each form and what they are used for if they are named Form1, Form2, Form3, etc.

Let’s name our form as MainForm to indicate that this is the form that will load when the application starts up. Right click Form1 in the Solution Explorer and click Rename. After you rename the form, press Enter.

Renaming Form1 to MainForm

Rename the Form Heading

Showing Form1 in Form Heading

Let’s change the heading for MainForm to display Main Form. Select the form by click on the form in design view. When the form is selected, you will see sizing handles on the form border and MainForm will be displayed at the top of the properties window.

Indications that Form1 is Selected

When MainForm is selected, you can find the Text property of the form in the properties window, as shown above, and change the text from Form1 to Main Form as shown below.

Form1 Text Property Now Displays Main Form

Add Controls to the Form

Open the Toolbox, which should be on the upper left edge of Visual Studio.

Location of the Toolbox in Visual Studio

The Toolbox contains all of the controls that are available in our chosen Framework, which is .Net Framework 4.7.2 in our case.

When the toolbox is open, drag 2 buttons and a label out onto the approximate middle of the form.

Label and Button in the Toolbox
Buttons and Label on the Form

Set Properties on the Controls

Now we need to change the Text Property of button1 and the Name Property of button1. Select button1 on the form by left clicking it 1 time. You will see sizing handles around the button when it is selected and you will see button1 at the top of the properties window.

button1 Selected and the Default Properties

With button1 selected, change the Text Property to -, the hyphen or minus symbol. Change the Name property to btnDecrement. btn means button. When we reference the button in code by the Name property, it will be easy for us to recognize that it is a button because the name begins with btn.

button1 Changed to Correct Properties

Now select button2 and make similar changes. Change the Tex Property to +, the plus symbol. Change the Name Property to btnIncrement.

btnIncrement Properties

Select the label1 control. Change the Name property to lblValue. Change the Text property to 0, the number zero. When the form first loads, we want it to display a default value of 0.

lblValue Properties
Completed Form Design

Click Events for the Buttons

An event is basically something that triggers some code to run. A click event “fires” when the user clicks the mouse on a control. a Key Down event fires when the user presses a key down. A Key Up event fires when the key is released. There are many other events that can be “Trapped“. If you want to execute some code when a particular event happens on a particular control, then you create an Event Listener. There are a few different ways to create an event listener. I will show you the 2 easiest ways to create button click event event listeners.

Create Button Click Events Method 1

Buttons are meant to accept clicks. The Click event is the default event for the button control. Double-Click btnDecrement on the form designer. You should see the MainForm code file open and you should see an empty click event method for btnDecrement.

Empty btnDecrement_Click Event Handler

Code that we want to execute when someone clicks btnDecrement belongs inside this method. What do we want to happen when someone clicks the decrement button? We want to decrement an integer by 1. To make it somewhat interesting, let’s add a condition that says our integer cannot go less than 0.

The first thing that we need is a variable to hold our integer value. We need to be able to access this variable from anywhere in our MainForm class. The reason for this is that we are going to be manipulating this variable from 2 different methods. One of the methods is the decrement button click event handler method. The other place is the increment button click event handler. I have not introduced you to passing variables from method to method yet, so we will make the integer variable accessible to the entire class for our demo.

In order for a variable to be accessible to the entire class, we need to declare it directly inside the class curly braces.

namespace ButtonDemo
{
    public partial class MainForm : Form
    {
        //This is where class level variables belong

        public MainForm()
        {
            InitializeComponent();
        }

        //You could also declare them here

        private void btnDecrement_Click(object sender, EventArgs e)
        {
            
        }

        //You could also declare them here
    }
}

I have added comments to indicate where class level variables normally go, but also to show alternate locations. Basically, as long as you do not declare them inside methods or constructors, you are usually OK.

public partial class MainForm : Form
    {
        //This is where class level variables belong
        int m_iValue;

        public MainForm()
        {
            InitializeComponent();
        }

        //You could also declare them here

        private void btnDecrement_Click(object sender, EventArgs e)
        {
            
        }
        //You could also declare them here
    }

We have declared an integer variable at the class level called m_iValue. The m means that it is a member of the class. This distinguishes it from local variables, which would be declared inside of methods. The i means that it is an integer. This way, even if I have hundreds or thousands of variables of various types in an application, I can instantly recognize that this variable is an integer. That is important because I need to know the type in order to know how to use it in various places in code.

Add Code to the Button Click Events

private void btnDecrement_Click(object sender, EventArgs e)
{
    if (m_iValue > 0)
    {
         m_iValue--;
    }
    lblValue.Text = m_iValue.ToString();
}

Every time someone clicks the btnDecrement button, the code in the btnDecrement click event handler will run. By default, the value of a newly declared integer is 0. So when we first run our program, the value of m_iValue will be 0. Since m_iValue is not greater than 0, m_iValue will not decrement. In order for the code inside the if statement to execute, the condition inside the parenthesis has to evaluate to true. Therefor, m_iValue must be greater than 0 in order for m_iValue to be decremented. m_iValue– means decrement the value of m_iValue by 1. Our if statement prevents m_iValue from going negative.

Next, lblValue.Text = m_iValue.ToString(); populates the Text property of the label on our form with the text version of the integer value. We must convert the integer value to a string. A string is a text data type as opposed to numbers. The Text property can only be assigned a text value. This is why we have to use ToString().

Go back to the form designer. We are going to use a different technique to create the click event for btnIncrement. Single click btnIncrement to select it. Now click the lightning bolt icon on the properties window.

btnIncrement Event Listing Arranged by Category

Notice in the image above that I have selected the lightning bolt. These are the events that are available for the button. Also notice that my view is by category instead of alphabetical (Green circle on the left). So in this view, the default event (Click) is at the top of the list. Double click the word Click or the empty space to the right of the word Click. A new empty event will be created in the MainForm class code file.

public partial class MainForm : Form
{
   //This is where class level variables belong
   int m_iValue;

   public MainForm()
   {
      InitializeComponent();
   }

   //You could also declare them here

   private void btnDecrement_Click(object sender, EventArgs e)
   {
      if (m_iValue > 0)
      {
         m_iValue--;
      }
      lblValue.Text = m_iValue.ToString();
   }

   private void btnIncrement_Click(object sender, EventArgs e)
   {

   }

   //You could also declare them here
}

Now we just need to add our code for the btnIncrement event handler. It will be similar to the decrement event handler. We will enforce a rule that the value cannot go above 10.

private void btnIncrement_Click(object sender, EventArgs e)
{
   if (m_iValue < 10)
   {
      m_iValue++;
   }
   lblValue.Text = m_iValue.ToString();
}

We check to ensure that the value of m_iValue is less than 10. If that condition is true, the code inside the if statement will run, which means the value of the variable will increment by 1. Then the Text property of the label will be set to the value of the m_iValue variable (converted to a string).

Lets Run Our Program

Run the Program

Click the green Start Arrow or press F5 on your keyboard to run our program. After a few seconds to a few minutes, depending on your computer, you should see your form pop up. If not, go back and double check your code against this tutorial. You should not have anything underlined in red in your code. If you do, those red underlines are where the problem is. You may have forgotten a semi-colon or a brace or a parenthesis, or the some code may not be in the proper case. It is all case sensitive.

Full Code

If you did not see any errors and your form loaded, try clicking the buttons to ensure that you see a value incrementing and decrementing.

Application Running

If you have any questions or comments, please comment below and I will get back to you.

Powered by WordPress.com.

Up ↑

%d bloggers like this: