This is a C# component, so first of all create an UserControl class called DecimalTextBox. This most commonly done within a ComponentLibrary project. Pull a generic TextBox from the toolbox on to the component design form. We now have the DecimalTextBox.cs class, a Designer.cs and a resource DecimalTextBox.resx file. Now just substitute the code with that listed here.
public partial class DecimalTextBox : UserControl { private Boolean allowSpace = false; // Group seperator allows decimal nnn,nnn etc seperation of decimal numbers private Boolean allowGroupSeperator = false; // Negative numbers require a different treatment to get to the two's complementary format // so + and - are only allowed for Decimal numbers private Boolean allowNegativeSign = false; private Boolean allowPlus = false; // Establish range limits private Decimal MaxDecValue = Decimal.MaxValue; private Decimal MinDecValue = Decimal.MinValue; public DecimalTextBox() { InitializeComponent(); this.NumBox.Text = "0.0"; } public Boolean AllowNegativeSign { get { return allowNegativeSign; } set { allowNegativeSign = value; } } public Boolean AllowPlus { get { return allowPlus; } set { allowPlus = value; } } public Boolean AllowGroupSeperator { get { return allowGroupSeperator; } set { allowGroupSeperator = value; } } public Decimal DecimalValue { // Only decimal values get { try { // Filter off conversions like nn,.n and replace correct format on the text box Decimal reply = Convert.ToDecimal(this.NumBox.Text); if (allowGroupSeperator) this.NumBox.Text = reply.ToString(System.Globalization.CultureInfo.CurrentCulture.NumberFormat); else this.NumBox.Text = Convert.ToString(reply); return reply; } catch { this.NumBox.Text = "Invalid"; return 0; } } set { NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; if (value > MaxDecValue) value = MaxDecValue; else if (value < MinDecValue) value = MinDecValue; try { if (allowGroupSeperator) this.NumBox.Text = Convert.ToString(value, numberFormatInfo); else this.NumBox.Text = Convert.ToString(value); } catch { this.NumBox.Text = "Invalid"; } } } public new String Text { get { return this.NumBox.Text; } } public bool AllowSpace { set { this.allowSpace = value; } get { return this.allowSpace; } } public Color Text_Background { get { try { return NumBox.BackColor; } catch { return Color.AntiqueWhite; } } set { NumBox.BackColor = value; } } public Int32 MaxDigit { get { return NumBox.MaxLength; } set { NumBox.MaxLength = value; } } public Decimal MaximumDecimalValue { get { return MaxDecValue; } set { MaxDecValue = value; if (MaxDecValue < MinDecValue) MaxDecValue = Decimal.MaxValue; if ((MaxDecValue != Decimal.MaxValue) && (DecimalValue > MaxDecValue)) DecimalValue = MaxDecValue; } } public Decimal MinimumDecimalValue { get { return MinDecValue; } set { MinDecValue = value; if (MinDecValue > MaxDecValue) MinDecValue = Decimal.MinValue; if ((MinDecValue != Decimal.MinValue) && (DecimalValue < MinDecValue)) DecimalValue = MinDecValue; } } private void NumBox_KeyPress(object sender, KeyPressEventArgs e) { // Restricts the entry of characters to digits (including hex), the negative sign, // the decimal point, and editing keystrokes (backspace). NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat; String decimalSeparator = numberFormatInfo.NumberDecimalSeparator; String groupSeparator = numberFormatInfo.NumberGroupSeparator; String negativeSign = numberFormatInfo.NegativeSign; string keyInput = e.KeyChar.ToString(); e.Handled = false; if (Char.IsDigit(e.KeyChar)) { // Note the current value does not include the last key pressed // This is a fractioned decimal String current_text = Text + e.KeyChar.ToString(); try { Decimal current_value = Convert.ToDecimal(current_text); if ((current_value > MaxDecValue) || (current_value < MinDecValue)) { e.Handled = true; SystemSounds.Beep.Play(); return; } } catch { e.Handled = true; SystemSounds.Beep.Play(); return; } } else if (keyInput.Equals(decimalSeparator)) { String current_text = Text; // if already > 2 length we are OK provided there is no '.' already if (current_text.Length > 2) { if (!current_text.Contains(decimalSeparator)) return; } // Cannot be 1st position or 2nd position if first is + or - else if ((current_text.Length == 2) && (current_text[0] != '+') && (current_text[0] != '-')) return; else if ((current_text.Length == 1) && (Char.IsDigit(current_text[0]))) return; e.Handled = true; SystemSounds.Beep.Play(); return; } else if ((keyInput.Equals(groupSeparator)) && (allowGroupSeperator) && (Text.Length >= 1)) { // Cannot allow decimal seperator before group seperator String current_text = Text; if (!current_text.Contains(decimalSeparator)) return; e.Handled = true; SystemSounds.Beep.Play(); return; } else if ((keyInput.Equals(negativeSign)) && (allowNegativeSign)) { // Only in first position if (Text.Length < 1) return; e.Handled = true; SystemSounds.Beep.Play(); return; } else if (e.KeyChar == '\b') { return; } // else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0) // { // // Let the edit control handle control and alt key combinations // } else if (this.allowSpace && e.KeyChar == ' ') { return; } else if ((allowPlus) && (e.KeyChar == '+')) { // Only in first position or immediately after e if (Text.Length < 1) return; if (Text[(Text.Length - 1)] == 'e') return; e.Handled = true; SystemSounds.Beep.Play(); return; } else { // Consume this invalid key and beep e.Handled = true; SystemSounds.Beep.Play(); } } }
The text box has been sized for "normal" numbers by default, if a full definition is required, then a re-size will be needed. Optionally a group seperator for the thousands etc can be used. Note: if on evaluation the text is found to contain a contary format then the text will be modified when the value is read back.
The MaxDigit method refers to the maximum length of the text that can be entered in the box and the NumBox_KeyPress function handles all the text I/O.
private void InitializeComponent() { this.NumBox = new System.Windows.Forms.TextBox(); this.SuspendLayout(); // // NumBox // this.NumBox.AcceptsReturn = true; this.NumBox.BackColor = System.Drawing.SystemColors.Window; this.NumBox.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.NumBox.Location = new System.Drawing.Point(0, 0); this.NumBox.Margin = new System.Windows.Forms.Padding(0); this.NumBox.Name = "NumBox"; this.NumBox.Size = new System.Drawing.Size(100, 20); this.NumBox.TabIndex = 0; this.NumBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.NumBox_KeyPress); // // DecimalTextBox // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.NumBox); this.Name = "DecimalTextBox"; this.Size = new System.Drawing.Size(100, 25); this.ResumeLayout(false); this.PerformLayout(); } private System.Windows.Forms.TextBox NumBox; }
The designer can be copied or the equivalent generated by hand by changing the properties of the designer form. The properties must coincide with that required by the .cs code.