Creating a Calculator with C# Part 5: Casting, Handling Events, Getting Input and Useful Methods

My thoughts and prayers go out to every individual who was hurt in the shootings last night in Colorado.

In the last installment of this tutorial, you learned how to use the Windows Forms editor. That’s a big step, but the Windows Forms editor isn’t much help if you don’t know how to use your creation. I saw Spiderman last night (because I didn’t want to stay out until two watching Batman on a day I had to drive for 4 hours), and using the Forms editor without being to write the corresponding code is kind of like inserting lizard DNA into your body when it actually turns you into a lizard – insane.

Now, open up your project and right-click on the form you made. Choose “View Code”. The code editor that you saw with the console application will pop up, but the code will look different. Where’s the main method, you ask? It’s there – but it’s in Program.cs. I suggest you don’t mess with it right now. Anyway, you have a code file that looks like this:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace Calculator
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }
    }
}

This seems a little more complex than the console application, does it not? Just like before, we have using statements (although Windows applications have more by default). We have a namespace and a class and a method. There are two key differences. The first is the “: Form” thing, and the second is that the frmMain() method doesn’t have a return type.

The “: Form” thing means that our class inherits from the class System.Windows.Forms.Form. The Form class provides basic form functionality and lets us put controls on the screen. We can set the size of the form, change the color of the form, move the form, and do pretty much whatever we want with the form. Inheriting from the Form class allows us to get that functionality and add whatever we need onto it.

The latter difference also bears a lot of explaining. It is called a constructor. Constructors are methods that are called whenever a new instance of a class is created. What do I mean by that? Remember how I told you that you can use classes as variables? Each variable contains a different instance of a class, and a class instance is created with the “new” keyword. So a class could contain two variables, v1 and v2, and two variables could be declared with separate instances of the class. v1 and v2 could be 1 and 2 in the first and 5 and 6 in the second, like so:

// Call this from the Main method of a console application.
static void ClassExample()
{
    A a = new A();
    A b = new A();
    b.v1 = 5;
    b.v2 = 6;
 
    Console.WriteLine(a.v1 + " " + a.v2 + " " + b.v1 + " " + b.v2);
}
 
// Put this outside the Program class
public class A
{
    public int v1 = 1;
    public int v2 = 2;
}

The above code will output “1 2 5 6″. Declaring something within a class as static means it does not go with an instance of a class; changing it will affect all instances.

For now, all you need to know is that the constructor runs before the form opens. We’re going to take advantage of that by adding some code to the constructor:

public frmMain()
{
    InitializeComponent();
 
    btn0.Click += new EventHandler(ButtonClickHandler);
}

While you’re add it, add the ButtonClickHandler method to stop the error about ButtonClickHandler not existing in the current context:

private void ButtonClickHandler(object sender, EventArgs e)
{
    throw new NotImplementedException(); // Prevent head-scratching later on.
}

Now I have three more things to explain: the btn0.Click += part, the private keyword and the arguments that ButtonClickHandler requires.

  • btn0.Click is called an event. The event happens when btn0 (the zero button – I’m writing this a full day later and I can figure out what controls do because of my naming convention!) is clicked. += is an operator that appends something, so you are essentially adding the event handler method to the Click event. In other words, when the user clicks the button, that method will be automatically called.
  • The private keyword means a method may only be called by other methods in the same class. There is no sense in making an event handler public; it will only make it easier for outside code to interfere with our program.
  • ButtonClickHandler requires two arguments: sender and e. Sender is whatever raised the event – so when you click btn0, sender is btn0. The EventArgs (e) are the base EventArgs class and don’t do anything useful, but some EventArgs let you do cool things like keep a form from closing when a user presses the X button or getting the location of the mouse.

But John, you said C# is type-safe. The type of btn0 is Button, not object! That should be an error!

I like the way you’re thinking, but remember inheritance? Btn0 is a button. You’re correct about that, but if you go back far enough in the family tree, btn0 is an object because every single class in C# is an object. String is an object. EventHandler is an object. System.Linq.ParallelQuery is an object. So, you can use a cast to convert the object into what it actually is. We’ll get there in a bit. For now, add this event handler to the other nine number buttons.

public frmMain()
{
    InitializeComponent();
 
    btn0.Click += new EventHandler(ButtonClickHandler);
    btn1.Click += new EventHandler(ButtonClickHandler);
    btn2.Click += new EventHandler(ButtonClickHandler);
    btn3.Click += new EventHandler(ButtonClickHandler);
    btn4.Click += new EventHandler(ButtonClickHandler);
    btn5.Click += new EventHandler(ButtonClickHandler);
    btn6.Click += new EventHandler(ButtonClickHandler);
    btn7.Click += new EventHandler(ButtonClickHandler);
    btn8.Click += new EventHandler(ButtonClickHandler);
    btn9.Click += new EventHandler(ButtonClickHandler);
}

Now, whenever you click one of the number buttons, your program will crash because of an unhandled exception! Exciting stuff – you can try it out if you want but we really need more functionality than that. Go to your handler and add this (by the way, my TextBox is named txtDisplay):

private void ButtonClickHandler(object sender, EventArgs e)
{
    Button btn = (Button)sender;
    if (char.IsDigit(btn.Text, 0))
    {
        txtDisplay.Text += btn.Text;
    }
}

WHOA, WHOA, WHOA! I thought this was a basic course on C#! That looks like gibberish! I know it does, but it’s the best I can do to make that work. The way this calculator is going to work is to save ourselves a lot of extra coding, we’re going to have one event handler for all the buttons, and figure out which button we’re working with based on sender. To do so, we create a button variable, and use what is known as a cast to turn sender into a Button. You can’t do that arbitrarily; the classes must be compatible. That is, going back and forth from Button to object is fine, but going from Button to TextBox would cause your program to crash.

The next thing the code does is to look at the button’s text and decide if it is a number. The char.IsDigit method does just that. Since the number buttons only have one digit on them, using char (which represents a character in C#) is fine because one digit means there is only one character. If the character turns out to be a number, we add it to the display with the += operator, which appends it.

I know this was a short tutorial, but I have to get on the road to Bot Blast now. As always, thanks for reading!

2 thoughts on “Creating a Calculator with C# Part 5: Casting, Handling Events, Getting Input and Useful Methods”

  1. Excellent article :) however:-
    At the end of this page, when I press a button is it supposed to add the digit to my txtDisplay textbox yet? Or is it still supposed to crash?

Leave a Reply

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


+ 4 = eleven

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>