## Table of Contents

The purposes of this project was to create an OOP Calculator. More precisely, the Requirements Specification is:

The user should be able to implement a calculation consisting of performing a mathematical operation on two numbers and retrieve a result.

# The Core Application

The words underlined were:

• Calculation - The Core classes of the application should include a Calculation class used for communicating between the core classes and the GUI.
• Operation - The Operator would consist of a one character variable in the Calculation class and there is no reason to make it a class.
• Two numbers - The two numbers involved in the calculation would both be represented by an instance of a Number class as it is appropriate  to represent each number by a Decimal value and a String value, mainly due to the method of inputting numbers. It would also be useful to have methods to append and remove digits in this class.
• Result - As with the Operator there is no reason to make this a class, but also in this case it is not necessary even as a variable either.

Figure 1. The method used for saving
the result allows long strings of multiple calculations.

So after analyzing the project requirements the core application consists of just two classes.

Figure 1.1. The distinct core classes

A Calculation class with several properties used in differentiating between various input values, with one Public function the push method which is used for passing and retrieving values to and from the GUI. The Calculation class has three notable properties, two to represent Number class instances and an [Operator] property. I haven't posted the Calculation class in this article, but it's available in the download.

This shows the instances of the classes and the Relationship between them:

Figure 1.2. Instances and Relationship

Figure 1.3. Core classes diagram

The Number class has a Decimal property and a String property, both of which are used to keep track of numbers and two functions for adding and removing digits.

By some juggling of the two Number classes property values it's possible to perform long strings of multiple calculations (see Figure 1).

### The Number class:

`Public` `Class` ``` Number```

`#Region "     properties"`

`    ``Private` `_value ``As` `Decimal`
`    ``Public` `Property` ``` value() ````As` ``` Decimal```
`        ``Get`
`            ``Return` `_value`
`        ``End` `Get`
`        ``Set``(``ByVal` `value ``As` `Decimal``)`
`            ``_value = value`
`        ``End` `Set`
`    ``End` `Property`

`    ``Private` `_valueString ``As` `String` ``` = ````""`
`    ``Public` `Property` ``` valueString() ````As` ``` String```
`        ``Get`
`            ``If` `_valueString.StartsWith(``"."````) ````Then`
`                ``Return` `"0"` `& _valueString`
`            ``End` `If`
`            ``Return` `_valueString`
`        ``End` `Get`
`        ``Set``(``ByVal` `value ``As` `String``)`
`            ``_valueString = value`
`            ``If` `_valueString <> ``"."` `AndAlso` ``` _valueString <> ````""` ``` AndAlso``` `_valueString <> ``"-"` `Then`
`                ``Me````.value = ````CDec``(_valueString)`
`            ``Else`
`                ``Me``.value = 0D`
`            ``End` `If`
`        ``End` `Set`
`    ``End` `Property`

`#End Region`

`#Region "     functions"`

`    ``''' <summary>`
`    ``''' handles parsing button input to decimal`
`    ``''' </summary>`
`    ``''' <param name="aValue">the button text</param>`
`    ``''' <returns></returns>`
`    ``Public` `Function` ``` appendDigit(aValue ````As` `String````) ````As` ``` String```
`        ``If` `aValue = ``"."` ``` Then```
`            ``If` `Not` ``` Me````.valueString.Contains(``"."````) ````Then`
`                ``Me``.valueString &= aValue`
`            ``End` `If`
`        ``Else`
`            ``Me``.valueString &= aValue`
`        ``End` `If`
`        ``If` `Not` ``` valueString = ````"."` ``` AndAlso``` `_valueString <> ``"-"` `Then`
`            ``Me````.value = ````CDec``(valueString)`
`        ``Else`
`            ``Me``.value = 0`
`        ``End` `If`

`        ``Return` `Me``.valueString`
`    ``End` `Function`

`    ``''' <summary>`
`    ``''' handles removing digits with the backspace button,`
`    ``''' then parsing the remaining digits as decimal`
`    ``''' </summary>`
`    ``''' <returns></returns>`
`    ``Public` `Function` ``` backSpace() ````As` ``` String```
`        ``If` `Me````.valueString.Length > 0 ````Then`
`            ``Me````.valueString = ````Me``.valueString.Substring(0, valueString.Length - 1)`
`        ``End` `If`
`        ``If` `Not` ``` Me````.valueString = ``"."` `AndAlso` ``` Not``` `Me````.valueString = ````""` ``` AndAlso``` `Not` ``` Me````.valueString = ``"-"` `Then`
`            ``Me````.value = ````CDec``(``Me``.valueString)`
`        ``Else`
`            ``Me``.value = 0`
`        ``End` `If`

`        ``Return` `Me``.valueString`
`    ``End` `Function`

`#End Region`

`End` `Class`

# The GUI

Figure 2. The GUI.

In terms of component controls the GUI consists of a Panel, 18 Buttons, an extended TextBox, and a Label. At runtime the TextBox and the Label appear as one control (see Figure 1.). The TextBox is restricted to allow no other input except the programmatic input from the Core classes.

The Form code is limited to handling the Panel_Paint event where it draws a border around the Label and TextBox, handling all of the Button click events in one handler, and capturing keyboard input. The 18 Buttons are the only Controls that respond to user input, either through mouseclicks or by typing the number, operator, or controlchar keys.

### This is the Form code:

`Public` `Class` ``` calcForm```

`    ``''' <summary>`
`    ``''' this is the calculator object`
`    ``''' </summary>`
`    ``Private` `calc ``As` `New` ``` Calculation```

`    ``''' <summary>`
`    ````''' the textbox is actually a textbox with a label above it. ```
`    ``''' this draws a border around both controls to give the appearance of one control`
`    ``''' </summary>`
`    ``''' <param name="sender"></param>`
`    ``''' <param name="e"></param>`
`    ``Private` `Sub` ``` Panel1_Paint(sender ````As` `Object````, e ````As` ``` PaintEventArgs) ````Handles` `Panel1.Paint`
`        ``Dim` `r ``As` `New` ``` Rectangle(TextBox1.Left - 1, Label1.Top - 1, Label1.Width + 2, Label1.Height + TextBox1.Height + 2)```
`        ``ControlPaint.DrawBorder3D(e.Graphics, r, Border3DStyle.SunkenInner)`
`    ``End` `Sub`

`    ``''' <summary>`
`    ``''' this sets up the buttons for keyboard or mouseclick input`
`    ``''' </summary>`
`    ``''' <param name="sender"></param>`
`    ``''' <param name="e"></param>`
`    ``Private` `Sub` ``` Form1_Load(sender ````As` ``` Object````, e ``As` `EventArgs) ``Handles` `MyBase``.Load`
`        ``Me````.KeyPreview = ````True`
`        ``For` `Each` ``` b ````As` ``` Button ````In` ``` Panel1.Controls.OfType(Of Button)```
`            ``AddHandler` `b.Click, ``AddressOf` `button_clicked`
`        ``Next`
`    ``End` `Sub`

`    ``''' <summary>`
`    ``''' onclick the button's text is sent to the calculator object's push method`
`    ``''' which handles all input, and returns the textual output for the textbox and the label`
`    ``''' </summary>`
`    ``''' <param name="sender"></param>`
`    ``''' <param name="e"></param>`
`    ``Private` `Sub` ``` button_clicked(sender ````As` `Object````, e ````As` ``` EventArgs)```
`        ``Dim` `output() ``As` `String` ``` = calc.push(````DirectCast``(sender, Button).Text)`
`        ``TextBox1.Text = output(0)`
`        ``Label1.Text = output(1)`
`    ``End` `Sub`

`    ``''' <summary>`
`    ``''' this converts keyboard input into button clicks`
`    ``''' </summary>`
`    ``''' <param name="sender"></param>`
`    ``''' <param name="e"></param>`
`    ``Private` `Sub` ``` Form1_KeyPress(sender ````As` `Object````, e ````As` ``` KeyPressEventArgs) ````Handles` `Me``.KeyPress`
`        ``If` `e.KeyChar = Chr(Keys.Back) ``Then`
`            ``Button1.PerformClick()`
`        ``Else`
`            ``Dim` `btn ``As` `Button = Panel1.Controls.OfType(Of Button).FirstOrDefault(``Function``(b) b.Text.ToLower = e.KeyChar)`
`            ``If` `Not` ``` btn ````Is` ``` Nothing``` `Then`
`                ``btn.PerformClick()`
`            ``End` `If`
`        ``End` `If`
`    ``End` `Sub`

`End` `Class`

The extended TextBox assigns a new empty ContextMenuStrip to the TextBox, which has the effect of removing the right click menu. The Cut, Copy, Paste, Clear, and Undo keyboard shortcuts are also detected and nullified.

### This is the restrictedTextBox code:

`''' <summary>`
`''' removes the textbox contextmenustrip and disables keyboard shortcuts`
`''' </summary>`
`Public` `Class` ``` restrictedTextBox```
`    ``Inherits` `TextBox`

`    ``Const` `WM_CUT ``As` `Integer` ``` = &H300```
`    ``Const` `WM_COPY ``As` `Integer` ``` = &H301```
`    ``Const` `WM_PASTE ``As` `Integer` ``` = &H302```
`    ``Const` `WM_CLEAR ``As` `Integer` ``` = &H303```
`    ``Const` `WM_UNDO ``As` `Integer` ``` = &H304```

`    ``Public` `Sub` ``` New````()`
`        ``Me````.ContextMenuStrip = ````New` ``` ContextMenuStrip```
`    ``End` `Sub`

`    ``Protected` `Overrides` ``` Sub``` `WndProc(``ByRef` `m ``As` `Message)`
`        ``Dim` `disabledOperations() ``As` `Integer` ``` = {WM_CUT, WM_COPY, WM_PASTE, WM_CLEAR, WM_UNDO}```
`        ``If` `disabledOperations.Contains(m.Msg) ``Then` `Return`
`        ``MyBase``.WndProc(m)`
`    ``End` `Sub`

`End` `Class`

Download here...