Components

A TextBox limited to integer values.

This is a C# component, so first of all create an UserControl class called NumericalTextBox. 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 NumericalTextBox.cs class, a Designer.cs and a resource NumericalTextBox.resx file. Now just substitute the code with that listed here.

The Integer Numerical TextBox

    public partial class NumericalTextBox : UserControl
    {
        private Boolean allowSpace = 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;
        //  By default Integer Decimal (Base 10) arithmetic is used
        private Boolean allowDecimal = false;
        private Boolean allowHex = false;
        private Boolean allowBinary = false;
        private Boolean allowOctel = false;
        private Boolean allowNibble = false;
        private Boolean bPad = false;
        //  Establish range limits
        private Int32 MaxIntValue = Int32.MaxValue;
        private Int32 MinIntValue = Int32.MinValue;
        private Int32 padTo = 0;

        public NumericalTextBox()
        {
            InitializeComponent();
            this.NumBox.Text = "0";
        }

        public Boolean AllowNegativeSign
        {
            get { return allowNegativeSign; }
            set
            {   //  Only allow - if decimal system, otherwise use two's complement
                if (value && (!allowHex) && (!allowBinary) && (!allowOctel) && (!allowNibble)) allowNegativeSign = true;
                else allowNegativeSign = false;
            }
        }

        public Boolean AllowPlus
        {
            get { return allowPlus; }
            set
            {   //  Only allow + if decimal system
                if (value && (!allowHex) && (!allowBinary) && (!allowOctel) && (!allowNibble)) allowPlus = true;
                else allowPlus = false;
            }
        }
        //  the numerical system is exclusive
        public Boolean AllowHex
        {
            get { return allowHex; }
            set
            {
                if (value)
                {
                    allowHex = true;
                    allowDecimal = false;
                    allowBinary = false;
                    allowOctel = false;
                    allowNibble = false;
                    if (MaxIntValue < 0) MaxIntValue = Int32.MaxValue;
                    if (MinIntValue < 0) MinIntValue = 0;
                    allowNegativeSign = false;
                    allowPlus = false;
                }
                else
                {
                    allowHex = false;
                    if ((!allowBinary) && (!allowNibble) && (!allowOctel)) allowDecimal = true;
                }
            }
        }

        public Boolean AllowBinary
        {
            get { return allowBinary; }
            set
            {
                if (value)
                {
                    allowHex = false;
                    allowDecimal = false;
                    allowBinary = true;
                    allowOctel = false;
                    allowNibble = false;
                    if (MaxIntValue < 0) MaxIntValue = Int32.MaxValue;
                    if (MinIntValue < 0) MinIntValue = 0;
                    allowNegativeSign = false;
                    allowPlus = false;
                }
                else
                {
                    allowBinary = false;
                    if ((!allowNibble) && (!allowOctel) && (!allowHex)) allowDecimal = true;
                }
            }
        }

        public Boolean AllowOctel
        {
            get { return allowOctel; }
            set
            {
                if (value)
                {
                    allowHex = false;
                    allowDecimal = false;
                    allowBinary = false;
                    allowOctel = true;
                    allowNibble = false;
                    if (MaxIntValue < 0) MaxIntValue = Int32.MaxValue;
                    if (MinIntValue < 0) MinIntValue = 0;
                    allowNegativeSign = false;
                    allowPlus = false;
                }
                else
                {
                    allowOctel = false;
                    if ((!allowBinary) && (!allowNibble) && (!allowHex)) allowDecimal = true;
                }
            }
        }

        public Boolean AllowNibble
        {
            get { return allowNibble; }
            set
            {
                if (value)
                {
                    allowHex = false;
                    allowDecimal = false;
                    allowBinary = false;
                    allowOctel = false;
                    allowNibble = true;
                    if (MaxIntValue < 0) MaxIntValue = Int32.MaxValue;
                    if (MinIntValue < 0) MinIntValue = 0;
                    allowNegativeSign = false;
                    allowPlus = false;
                }
                else
                {
                    allowNibble = false;
                    if ((!allowBinary) && (!allowOctel) && (!allowHex)) allowDecimal = true;
                }
            }
        }

        public Boolean AllowDecimal
        {
            get { return allowDecimal; }
            set
            {
                if (value)
                {
                    allowHex = false;
                    allowDecimal = true;
                    allowBinary = false;
                    allowOctel = false;
                    allowNibble = false;
                }
                else
                {
                    allowDecimal = false;
                    if ((!allowBinary) && (!allowNibble) && (!allowOctel)) allowHex = true;    //  The choosen alternative
                }
            }
        }

        //  The values depend upon base system in use. All systems are converted to Int32 or Decimal, could be over-range
        public Int32 IntValue
        {
            get
            {
                Int32 iValue = 0;
                try
                {
                    String sValue = this.NumBox.Text;
                    if (allowDecimal) iValue = Convert.ToInt32(sValue, 10);
                    else if (allowHex) iValue = Convert.ToInt32(sValue, 16);
                    else if (allowOctel) iValue = Convert.ToInt32(sValue, 8);
                    else if (allowBinary) iValue = Convert.ToInt32(sValue, 2);
                    //  the nibble format is not in Convert
                    else if (allowNibble) iValue = ConvertNibbleToInt32(sValue);
                    else iValue = 0;
                }
                catch { return 0; }
                return iValue;
            }
            set
            {   //  Convert to string in correct base value
                // The value assigned cannot be out of the min/max range set
                if (value > MaxIntValue) value = MaxIntValue;
                else if (value < MinIntValue) value = MinIntValue;
                try
                {
                    //  The bPad and padTo control the insertion of 0 padding to set a minimum text length. Cannot result in excessive length
                    if (allowDecimal) this.NumBox.Text = Convert.ToString(value, 10);
                    else if (allowHex) this.NumBox.Text = Convert.ToString(value, 16);
                    else if (allowOctel) this.NumBox.Text = Convert.ToString(value, 8);
                    else if (allowNibble) this.NumBox.Text = Convert.ToString(value, 4);
                    else if (allowBinary) this.NumBox.Text = Convert.ToString(value, 2);
                    else this.NumBox.Text = "Invalid";
                    if (bPad && (this.NumBox.Text != "Invalid"))
                    {
                        if (this.NumBox.Text.Length < padTo)
                        {
                            String sText = ";
                            for (Int32 i = 0; i < (padTo - this.NumBox.Text.Length); i++) sText += "0";
                            //  Now add on actual text
                            sText += this.NumBox.Text;
                            this.NumBox.Text = sText;
                        }
                    }
                }
                catch { this.NumBox.Text = "Invalid"; }
            }
        }

        public static Int32 ConvertNibbleToInt32(String sValue)
        {
            //  No standard Convert available for this
            Int32 iValue = 0;
            if (sValue == null) return iValue;
            if (sValue.Length < 1) return iValue;
            for (Int32 i = 0; i < sValue.Length; i++)
            {
                iValue += (Byte)sValue[i] * ((Int32)Math.Pow(8, (sValue.Length - (i + 1))));
            }
            return iValue;
        }


        public new String Text { get { return this.NumBox.Text; } }

        public HorizontalAlignment AlignText { get { return this.NumBox.TextAlign; } set { this.NumBox.TextAlign = value; } }

        public Size SizeTextBox
        {
            get { return this.NumBox.Size; }
            set
            {
                this.NumBox.Size = value;
                this.Size = value;
                this.MaximumSize = value;
                this.MinimumSize = value;
                this.NumBox.MaximumSize = value;
                this.NumBox.MinimumSize = value;
            }
        }

        public Boolean TextPad { get { return bPad; } set { bPad = value; } }

        public Int32 TextPadTo
        {
            get { return padTo; }
            set
            {
                //  Cannot be more than MaxStringLength
                if (value > this.NumBox.MaxLength) padTo = this.NumBox.MaxLength;
                else padTo = value;
            }
        }

        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 Int32 MaximumIntegerValue
        {
            get { return this.MaxIntValue; }
            set
            {   //  Cannot be negative unless allowDecimal set
                //  Default value cannot be > maximum value, if != 0,  so compare with actual value
                if (value >= 0) MaxIntValue = value;
                else if (allowDecimal) MaxIntValue = value;
                else MaxIntValue = Int32.MaxValue;
                if (MaxIntValue < MinIntValue) MaxIntValue = Int32.MaxValue;
                if ((MaxIntValue != Int32.MaxValue) && (IntValue > MaxIntValue)) IntValue = MaxIntValue;
            }
        }

        public Int32 MinimumIntegerValue
        {
            get { return this.MinIntValue; }
            set
            {   //  Cannot be negative unless allowDecimal set
                //  Default value cannot be < minimum value, if !=0, so compare with actual value
                if (value >= 0) MinIntValue = value;
                else if (allowDecimal) MinIntValue = value;
                else MinIntValue = Int32.MinValue;
                if (MinIntValue > MaxIntValue) MinIntValue = Int32.MinValue;
                if ((MinIntValue != Int32.MinValue) && (IntValue < MinIntValue)) IntValue = MinIntValue;
            }
        }


        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 (allowHex)
            {
                if (e.KeyChar == 'A') e.KeyChar = 'a';
                else if (e.KeyChar == 'B') e.KeyChar = 'b';
                else if (e.KeyChar == 'C') e.KeyChar = 'c';
                else if (e.KeyChar == 'D') e.KeyChar = 'd';
                else if (e.KeyChar == 'E') e.KeyChar = 'e';
                else if (e.KeyChar == 'F') e.KeyChar = 'f';
            }

            if ((Char.IsDigit(e.KeyChar)) || (allowHex && ((e.KeyChar == 'a') || (e.KeyChar == 'b') || (e.KeyChar == 'c') || (e.KeyChar == 'd') || (e.KeyChar == 'e') || (e.KeyChar == 'f'))))
            {
                //  The digit limit depends upon the base in use eg: octel limit is 0-7
                Boolean bLimitFail = false;
                Byte digit = (Byte)(e.KeyChar - 0x30);
                if (allowOctel && (digit >= 8)) bLimitFail = true;
                else if (allowNibble && (digit >= 4)) bLimitFail = true;
                else if (allowBinary && (digit >= 2)) bLimitFail = true;
                //  if out side limit we consume the digit
                if (bLimitFail)
                {
                    e.Handled = true;
                    SystemSounds.Beep.Play();
                    return;
                }
                // Digits are OK. Also check the maximum value here if either decimal or Integer are non-zero.
                // Care for Integer or decimal.
                // Note the current value does not include the last key pressed. The parsed value depends upon the base in use
                //  Must be an integer
                String current_text = Text + e.KeyChar.ToString();
                //  Get current value from the current text using current base
                Int32 current_value = CurrentValue(current_text);
                if (MaxIntValue != 0)
                {
                    if (current_value > MaxIntValue)
                    {
                        e.Handled = true;
                        SystemSounds.Beep.Play();
                        return;
                    }
                }
                if (MinIntValue != 0)
                {
                    if (current_value < MinIntValue)
                    {
                        e.Handled = true;
                        SystemSounds.Beep.Play();
                        return;
                    }
                }
            }
            else if ((keyInput.Equals(negativeSign)) && (allowNegativeSign))
            {
                //  Can only be at 1st char position ie keyInput at text length = 0
                if (Text.Length < 1) return;
                else
                {
                    // Consume this invalid key and beep
                    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 == '+'))
            {
                //  Can only be at 1st char position ie keyInput at text length = 0
                if (Text.Length < 1) return;
                else
                {
                    // Consume this invalid key and beep
                    e.Handled = true;
                    SystemSounds.Beep.Play();
                    return;
                }
            }
            else
            {
                // Consume this invalid key and beep
                e.Handled = true;
                SystemSounds.Beep.Play();
            }
        }

        private Int32 CurrentValue(String sValue)
        {
            Int32 iValue = 0;
            try
            {
                if (allowDecimal) iValue = Convert.ToInt32(sValue, 10);
                else if (allowHex) iValue = Convert.ToInt32(sValue, 16);
                else if (allowOctel) iValue = Convert.ToInt32(sValue, 8);
                else if (allowBinary) iValue = Convert.ToInt32(sValue, 2);
                //  the nibble format is not in Convert
                else if (allowNibble) iValue = ConvertNibbleToInt32(sValue);
                else iValue = 0;
            }
            catch { return 0; }
            return iValue;
        }
    }
}

The base types are mutually exclusive. It is an option to use + or - signs but only for base 10 usage. If a negative number is required for other base formats the two's complementary should be used.

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.TabIndex = 0;
                    this.NumBox.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.NumBox_KeyPress);
                    // 
                    // NumericalTextBox
                    // 
                    this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
                    this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
                    this.Controls.Add(this.NumBox);
                    this.Name = "NumericalTextBox";
                    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.