Before starting the article, take a look at the renderings to see if you are exactly what you need:
1, Build calculator interface
It takes a lot of effort to build a better calculator interface. When I did this, I also spent two or three hours building this interface.
Its main usage control is the TableLayoutPanel control.
Another small difficulty lies in the display of the content control Textbox. To make the text vertically centered, it took some careful thinking to achieve this effect without rewriting the Textbox control.
Other interfaces are nothing. As for the plus and minus signs, use the special symbols of the input method.
2, Build the open properties of the control
A total of 3 attributes are open, which is not enough for you to add. The three are as follows. You should be able to understand them from the notes:
/// <summary> ///The minimum acceptable value is -3.402823E+38 /// </summary> [Browsable(true)] [Category("Kintai")] [DefaultValue(0)] [Description("The minimum acceptable value is-3.402823E+38")] public float Min { get; set; } = 0; /// <summary> ///The maximum acceptable value is 3.402823E+38 /// </summary> [Browsable(true)] [Category("Kintai")] [DefaultValue(0)] [Description("The maximum acceptable value is 3.402823E+38")] public float Max { get; set; } = 0; /// <summary> ///Set the precision digits of the decimal point. The default is 2 decimal places /// </summary> [Browsable(true)] [Category("Kintai")] [DefaultValue(2)] [Description("Set the precision digits of the decimal point. The default is 2 decimal places")] public int Precision { get; set; } = 2;
3, Control keyboard input
Our purpose is to allow the keypad to input numbers, so we need to prohibit the physical keyboard from entering text letters and other information, and the small number points can only appear once at most. The specific logic is as follows:
/// <summary> ///Triggered when text content is entered using the physical keyboard /// </summary> /// <param name="e"></param> private void OnKeyPressed(KeyPressEventArgs e) { //13 means enter if (e.KeyChar == 13) { this.OnEntered(); e.Handled = true; return; } //48 stands for 0, 57 for 9, 8 for space and 46 for decimal point if ((e.KeyChar < 48 || e.KeyChar >= 57) && (e.KeyChar != 8) && (e.KeyChar != 46)) { e.Handled = true; return; } //Judge that the decimal point is entered multiple times, and only one decimal point is allowed if (e.KeyChar == 46) { this.PointHandle(); this.SetContentFocus(); e.Handled = true; return; } } /// <summary> ///Handle decimal point /// </summary> ///< returns > < see langword = "true" / > indicates that the processing is successful, < see langword = "false" / > indicates that it is not processed < / returns > private bool PointHandle() { string content = this.ContentTextBox.Text; if (content.IndexOf('.') != -1) { return false; } if (string.IsNullOrEmpty(content)) { this.SetContent("0."); return true; } //Take cursor position int index = this.ContentTextBox.SelectionStart; string str = this.ContentTextBox.Text.Substring(0, index); if (str == "+" || str == "-") { return this.SetContent(string.Join(string.Empty, str, "0.", this.ContentTextBox.Text.Substring(index, this.ContentTextBox.Text.Length - index))); } return this.SetContent(string.Join(string.Empty, str, ".", this.ContentTextBox.Text.Substring(index, this.ContentTextBox.Text.Length - index))); }
4, Let the text box handle the focus state and the cursor position
Cursor position. If special processing is required, the cursor position will always move to the end when the default parameter cursorPosition=-1. But in some cases, for example, if you want the cursor to delete or add a few numbers between the numbers, you can't make the cursor automatically run to the end.
/// <summary> ///Get the text box in focus /// </summary> ///< param name = "cursorposition" > whether to reposition the cursor position. The default < see langword = "- 1" / > indicates that it will automatically jump to the end of the text < / param > private void SetContentFocus(int cursorPosition = -1) { if (cursorPosition == -1) { //Position the cursor at the end this.ContentTextBox.Select(this.ContentTextBox.Text.Length, 0); } else { this.ContentTextBox.Select(cursorPosition, 0); } this.ContentTextBox.Focus(); }
5, Realize the function of backspace and clearing content
/// <summary> ///Clear content /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ClearButton_Click(object sender, EventArgs e) { this.SetContent(string.Empty); this.SetContentFocus(); } /// <summary> ///Backspace content /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BackButton_Click(object sender, EventArgs e) { //Take cursor position int index = this.ContentTextBox.SelectionStart; //Cut content string cutStr = this.ContentTextBox.Text.Substring(0, index); //Remaining content string remainStr = this.ContentTextBox.Text.Substring(index, this.ContentTextBox.Text.Length - index); int position = this.SetContent(string.Join(string.Empty, cutStr.Substring(0, cutStr.Length - 1), remainStr)) ? index + 1 : index; this.SetContentFocus(position); }
6, Enter to confirm the result
The principle is realized through events. The code is as follows:
/// <summary> ///Event delegate when the enter button is pressed /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public delegate void EnteredEventHandler(object sender, float e); /// <summary> ///Event when the enter button is pressed /// </summary> public event EnteredEventHandler Entered; /// <summary> ///Event triggered when the mini keypad presses enter /// </summary> protected virtual void OnEntered() { this.Entered?.Invoke(this, Convert.ToSingle(string.IsNullOrEmpty(this.ContentTextBox.Text) ? "0" : this.ContentTextBox.Text)); } /// <inheritdoc cref="OnEntered"/> private void EnterButton_Click(object sender, EventArgs e) { this.OnEntered(); this.SetContentFocus(); }
Finally, attach the source code for free download.
Have a nice meal