- How do I make custom events?
- How do I get two forms to talk to each other?
- How do properties work?
- I've gotten 50% done, but I didn't plan ahead now I'm stuck. How can I fix this?
So I decided to build a cash-register type application step-by-step and take you along for the ride. In this article we will learn/make use of:
- Enumerations
- Inheritance
- Custom events
- User controls
- Multiple projects in one solution
Planning
Before jumping right in to any project you must PLAN AHEAD. Expect that later in life you will want to make changes to your application. Your boss is going to ask you to add features and so on. So even the simplest of programs need to be modularized. This is one of the tenat of C# and object oriented programming: Lots of little black boxes that have one purpose in life, but can be wired together in various ways to do different things.
What does a cash register UI need, at least to start with:
- A numeric keypad
- A display
- Running total
- Tax calculation
What might get added later, or be a nice feature that we will plan for now, but add later:
- A secondary display (the one that faces the customer)
- Receipt printing
- Barcode reader (for UPC codes on products)
- Audit trail / reporting
Basic UI
Let's start a new Windows Forms project and name it DemoPOS.
This automatically wraps this first project in a solution of the same name. A solution can contain multiple projects if you didn't know already.



Next let's add another project to this solution. This is going to be a Windows Control Library. Name it Display.
Make one more Windows Control Library project and name it Keypad.

Your solution should contain 3 projects and look like this

Planning ahead: There are lots of different kinds of keypads. A cash register pad has different keys and layout than a telephone keypad or a computer keyboard 10-key pad. Wouldn't it be nice if we created a Keypad project, with several different types of Keypads inside it? That way we can re-use our Keypad project in other solutions. Then we just use Keypad.RegisterKeypad or Keypad.TelephoneKeypad as needed. Here is where our inheritance example is going to be used. All of these keypads share a lot of commonality, with just minor changes to GUI. So we will make a generic keypad, then inherit from it for our more specialized keypads. Lots of on-line tutorials do this with animals. First you make an animal, then you inherit a mammal from that, then you inherit a canine from mammal, then a poodle from canine. Whether it be animals, or products or keypads it is the same principal. You start out with the most generic form of the object, and with each inheritance get more specific.
In your Keypad project there is a UserControl named UserControl.cs. Right-click on it and rename it to GenericKeypad.cs

This generic keypad will be our base that we will inherit from for our more specific keypad later. It will contain all the properties and methods that all keypads have in common. Ok... What do all keypads have in common? What do they do? They press keys. That's it. Nothing else. Don't get caught up in the trap of trying to make one control do everything. A keypad is not a calculator. A Keypad does not add. It does not display. It does not record to a database. It presses keys, which in our case means it will raise events to tell any other control/class that a key has been pressed. So we need to make a custom event that other classes can subscribe to, that will tell what key has been pressed/clicked.
Right-click on the GenericKeypad.cs in the Solution Explorer and choose "View Code"
Add the new code shown in bold
namespace Keypad.cs
{
public partial class GenericKeypad : UserControl
{
public GenericKeypad()
{
InitializeComponent();
}
#region Events
public event KeyPressEventHandler ButtonPressed;
#endregion Events
#region Methods
public void RaiseButtonPressed(char WhatToSend)
{
KeyPressEventHandler handler = ButtonPressed;
if (handler != null)
{
handler(this, new KeyPressEventArgs(WhatToSend));
}
}
#endregion Methods
}
Congratulations: Your generic keypad now has a new event named ButtonPressed. Other classes (controls/forms) can subscribe to that and they will 'hear' when a button is pressed and what that button is. You could make your own custom EventArgs but we dodn't need to do that here because the .NET framework already had something we can make use of: The KeyPressEvent and the KeyPressEventArgs. Afterall, isn't that what we are doing? Pressing keys. Except for the actual buttons on the face, you've just built a virtual keyboard, or at least the controller for one.
By now you probably want to see *something* do *anything*. Just to make sure you aren't wasting your time. Fair enough. We are going to make a Keypad that uses the generic pad as a base, then use that to test our event.
INHERITANCE
Now we are going to make an inherited keypad that will become our RegisterKeypad. Right-click on Keypad.cs and choose "Add New.." then choose "UserControl". Name it RegisterKeypad.

Now view the code of this control just as we did earlier. As you can see this control is already an inherited control. We just going to change the base class that it inherits from. See where it says "RegisterKeypad : UserControl"... double-click UserControl to select all of it, then start typing GenericKeypad. Notice that Intellisense starts showing you all the matching options. You can just select from the menu if you like

Open the blank user control in the designer and drag ONE button from the tool box. Resize it so it square. In the example I made mine 64 x 64 pixels. Then copy/paste buttons to make a keypad

Select Button1 with a single left click. Go to the Properties pallet. Select the name property and rename it to "btn1"

Now we can quickly name each of the buttons without too much mouse-ing around. Select Button2 and WITHOUT going to the properties pallet just type "btn2". Notice that since we were already in the name field, its the name that changes. Click on Button3 - type "btn3". Click on Button4 - type btn4 and so on until you have renamed all the buttons. I used button names of "btn0", "btn00", "btnEnter", "btnPlus", "btnMinus" for the extra buttons.
We now use the same technique to change the text on the face. Select btn1. Go to the properties pallet and select the text of "button1" and type '1'
Now you can fast change all the other text. Select btn2 and type '2'. Select btn3 and type '3'
I then selected all the buttons and changed the font size to something larger

The buttons now all have worthwhile names, and meaningful text on the front. We just need to give them methods to run when they are clicked on. Double-click btn1, and you will be taken to the code. Visual Studio will be kind enough to stub-in a handler for the btn1_Click event. Go back to the designer and do the same for all the rest of the buttons, preferably in numeric order so the code is organized with btn1, btn2, btn3 and so on.
Now will give each method some code to raise our KeyPressed event. In the designer just double-click on button 1. Visual Studio will fill in an empty handler for you. Go to the designer and do button 2, 3, ... This way a new handler for every button is put in for you, and they will all be done at the same time and grouped together for your convenience.

I trust you are smart enough to have btn1 send a '1', btn2' send a '2' and so on. For now, fill in code for buttons 0-9. Buttons 00, +, - and Enter will need something more complex and we can update them later
At this point we want to hit function key F5 to cause the project to build and run. The results are boring: A blank Form1. That's ok. The reason we build here is because we need to compile the code for these controls so our toolbox will update. Notice that our two Keypad user controls are now in the toolbox for us to drag onto a form.

Let's do exactly that. Open From 1. Make it bigger so we have some room to work. Then drag a RegisterKeypad onto it. Then just above the keypad drag a textbox to act as our temporary display readout

Select the RegisterKeypad control. In the properties pallet click on the events button (yellow lightning bold) Notice the custom event we created is here: "ButtonPressed"
Any time someone clicks a button (0-9 for now) a ButtonPressed event is going to be raised by the control. Let's give it a handler. double-click in the blank field next to the 'ButtonPressed' label and Visual Studio will once again stub-in a handler for this event, in your code. Add line 12 as shown
namespace DemoPOS
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void registerKeypad1_ButtonPressed(object sender, KeyPressEventArgs e)
{
textBox1.Text += e.KeyChar;
}
}
}
Hit F5 again to run your code. Click any of the 0-9 keys and you should see the the display textbox update

So what is really happening when we click button 'btn1'?
In our RegistryKeypad.cs the handler for btn1 is being executed.
RegisterKeypad.cs runs a method it inherited from its base class (GenericKeypad.cs): RaiseButtonPressed. Giving it the parameter of '1'.
The base-class method then runs, generating an event with that parameter.
Our instance of RegisterKeypad.cs (RegisterKeypad1) on Form1 then hears the event, and runs it's handler for that control (Form1.cs) - adding the passed in parameter to the .Text property of the textbox1.
SAFETY
After you have everything working as it should be, close the solution.
In Windows Explorer go into your Visual Studio projects folder.
Select the POScalc folder.
[Control] C
[Control] V
Rename "POSCalc - copy" to "POScalc - {today's date}" like "POScalc 07feb10 1100hrs"
Now when you re-open the project it doesn't matter how much you break it. You have a functioning backup to this point.
Get used to doing this. The ability to roll back to working versions after completely screwing up a project will have you hours of frustration!
Part 0 - Custom events
Part 1 - Virtual Keypad (inheritance)
Part 2 - The LCD display panel
This post has been edited by JackOfAllTrades: 21 June 2010 - 10:38 AM
Reason for edit:: Remove b code tag from code block






MultiQuote





|