Components

A TextBox for double and float values.

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

The Double/Float TextBox

    public partial class DoubleTextBox : 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
        //  Establish range limits
        private Double MaxDoubleValue = Double.MaxValue;
        private Double MinDoubleValue = Double.MinValue;

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

        public Double DoubleValue
        {
            //  Only double values
            get
            {
                try
                {
                    //  Filter off conversionsx
                    Double reply = Convert.ToDouble(this.NumBox.Text);
                    this.NumBox.Text = reply.ToString(System.Globalization.CultureInfo.CurrentCulture.NumberFormat);
                    return reply;
                }
                catch
                {
                    this.NumBox.Text = "Invalid";
                    return 0;
                }
            }
            set
            {
                if (value > MaxDoubleValue) value = MaxDoubleValue;
                else if (value < MinDoubleValue) value = MinDoubleValue;
                try { this.NumBox.Text = Convert.ToString(value); }
                catch { this.NumBox.Text = "Invalid"; }
            }
        }

        public float FloatValue
        {
            //  Float values only. precision from float to 7 decimals.
            get { return (float)DoubleValue; }
            set
            {
                Int32 round_limit = 7;
                if (round_limit > this.NumBox.MaxLength) round_limit = this.NumBox.MaxLength;
                DoubleValue = Math.Round(value, round_limit, MidpointRounding.AwayFromZero);
            }
        }

        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 Double MaximumDoubleValue
        {
            get { return MaxDoubleValue; }
            set
            {
                MaxDoubleValue = value;
                if (MaxDoubleValue < MinDoubleValue) MaxDoubleValue = Double.MaxValue;
                if ((MaxDoubleValue != Double.MaxValue) && (DoubleValue > MaxDoubleValue)) DoubleValue = MaxDoubleValue;
            }
        }

        public Double MinimumDoubleValue
        {
            get { return MinDoubleValue; }
            set
            {
                MinDoubleValue = value;
                if (MinDoubleValue > MaxDoubleValue) MinDoubleValue = Double.MinValue;
                if ((MinDoubleValue != Double.MinValue) && (DoubleValue < MinDoubleValue)) DoubleValue = MinDoubleValue;
            }
        }

        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 double
                String current_text = Text + e.KeyChar.ToString();
                try
                {
                    Double current_value = Convert.ToDouble(current_text);
                    if ((current_value > MaxDoubleValue) || (current_value < MinDoubleValue))
                    {
                        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)) && (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))
            {
                //  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 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 (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 if (e.KeyChar == 'e')
            {
                String current_text = Text;
                //  exponential found. Valid formats
                //  xe, +xe, -xe, xxe, x.xe, xxxe, +x.xe, -x.xe, >= 4 length
                if ((current_text.Length >= 1) && (!current_text.Contains('e'))) return;
                e.Handled = true;
                SystemSounds.Beep.Play();
                return;
            }
            else
            {
                // Consume this invalid key and beep
                e.Handled = true;
                SystemSounds.Beep.Play();
            }
        }
    }

This text box allows number entry in scientific format, with value limits set by the internal Double value. 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();
            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);
            // 
            // DoubleTextBox
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.Controls.Add(this.NumBox);
            this.Name = "DoubleTextBox";
            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.