参考多家,终于写出自认为比较好的数值型TextBox

using System;

using System.ComponentModel;

using System.Drawing;

using System.Globalization;

using System.Windows.Forms;



namespace WindowsApplication1

{

    [ToolboxItem(true)]

    [ToolboxBitmap(typeof(TextBox))]

    [DefaultProperty("Value"), DefaultBindingProperty("Value")]

    [DesignTimeVisible]

    public partial class DecimalTextBox : TextBox, ISupportInitialize

    {

        #region 字段



        private static readonly decimal DefaultMaximum = 999999999M;

        private static readonly decimal DefaultMinimum = 0M;

        private static readonly decimal DefaultValue = 0M; //默认值

        private decimal currentValue = DefaultValue; //当前值

        private bool currentValueChanged; //当前值是否改变

        private int decimalPlaces = 2; //要显示的小数位数

        private bool hexadecimal = false; //十六进制

        private bool initializing;

        private Color m_BackColor; //背景色

        private Color m_BackColorWhenReadOnly; //只读背景色

        private decimal maximum = DefaultMaximum; //最大值

        private decimal minimum = DefaultMinimum; //最小值

        private bool thousandsSeparator = true; //千分位分隔符

        private bool userEdit; //用户是否编辑

        private bool m_AllowNegative = true;//负值



        #endregion



        public DecimalTextBox()

        {

            InitializeComponent();

            TextAlign = HorizontalAlignment.Right;

            ForeColor = SystemColors.WindowText;

            Text = "0";

            m_BackColor = base.BackColor; //记录当前背景色

            ReadOnly = true;

            m_BackColorWhenReadOnly = base.BackColor; // 记录只读时的颜色

            ReadOnly = false;

            base.ImeMode = ImeMode.Disable;

        }



        #region 属性



        [Category("扩展属性")]

        [Description("只读背景色")]

        [DefaultValue(typeof(Color), "Control")]

        public Color BackColorWhenReadOnly

        {

            get { return m_BackColorWhenReadOnly; }

            set

            {

                if (m_BackColorWhenReadOnly != value)

                {

                    m_BackColorWhenReadOnly = value;

                    OnBackColorChanged(EventArgs.Empty);

                }

            }

        }



        [Description("背景色")]

        [DefaultValue(typeof(Color), "White")]

        public new Color BackColor

        {

            get { return m_BackColor; }

            set

            {

                if (m_BackColor != value)

                {

                    m_BackColor = value;

                    OnBackColorChanged(EventArgs.Empty);

                }

            }

        }



        [DefaultValue(typeof(SystemColors), "WindowText")]

        public new Color ForeColor

        {

            get { return base.ForeColor; }

            set { base.ForeColor = value; }

        }



        [Description("指示数值是否应以16进制显示"), Category("外观"), DefaultValue(false)]

        public bool Hexadecimal

        {

            get { return hexadecimal; }

            set

            {

                hexadecimal = value;

                UpdateEditText();

            }

        }



        [Description("指示要显示的小数位数"), Category("数据"), DefaultValue(2)]

        public int DecimalPlaces

        {

            get { return decimalPlaces; }

            set

            {

                if (decimalPlaces != value)

                {

                    if ((value < 0) || (value > 0x63))

                    {

                        throw new ArgumentOutOfRangeException("DecimalPlaces", "DecimalPlaces 应介于 0 和 99 之间");

                    }

                    decimalPlaces = value;

                    UpdateEditText();

                }

            }

        }



        [RefreshProperties(RefreshProperties.All), Description("控件的最大值"), Category("数据")]

        public decimal Maximum

        {

            get { return maximum; }

            set

            {

                maximum = value;

                if (minimum > maximum)

                {

                    minimum = maximum;

                }

                Value = Constrain(currentValue);

            }

        }



        [Category("数据"), RefreshProperties(RefreshProperties.All), Description("控件的最小值")]

        public decimal Minimum

        {

            get { return minimum; }

            set

            {

                minimum = value;

                if (minimum > maximum)

                {

                    maximum = value;

                }

                Value = Constrain(currentValue);

            }

        }



        [Category("数据"), DefaultValue(true), Localizable(true), Description("指示是否插入千位分隔符")]

        public bool ThousandsSeparator

        {

            get { return thousandsSeparator; }

            set

            {

                thousandsSeparator = value;

                UpdateEditText();

            }

        }



        [Category("数据"), Description("指示是否允许负值"), DefaultValue(true)]

        public bool AllowNegative

        {

            get { return m_AllowNegative; }

            set

            {

                if (m_AllowNegative != value)

                {

                    m_AllowNegative = value;

                    Text = base.Text;

                }

            }

        }



        [Bindable(true), Category("外观"), Description("控件的当前值")]

        public decimal Value

        {

            get

            {

                if (userEdit)

                {

                    ValidateEditText();

                }

                return currentValue;

            }

            set

            {

                if (value != currentValue)

                {

                    if (!initializing && ((value < minimum) || (value > maximum)))

                    {

                        throw new ArgumentOutOfRangeException("Value", "超过最大值或最小值");

                    }

                    currentValue = value;

                    currentValueChanged = true;

                    UpdateEditText();

                }

            }

        }



        #region 禁用的TextBox属性



        [Browsable(false), Bindable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden),

         EditorBrowsable(EditorBrowsableState.Never)]

        public override string Text

        {

            get

            {

                return base.Text;

            }

            set

            {

                base.Text = value;

            }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new HorizontalAlignment TextAlign

        {

            get { return base.TextAlign; }

            set { base.TextAlign = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new string[] Lines

        {

            get { return base.Lines; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new ImeMode ImeMode

        {

            get { return base.ImeMode; }

            set { base.ImeMode = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new char PasswordChar

        {

            get { return base.PasswordChar; }

            set { base.PasswordChar = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new bool UseSystemPasswordChar

        {

            get { return base.UseSystemPasswordChar; }

            set { base.UseSystemPasswordChar = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new bool Multiline

        {

            get { return base.Multiline; }

            set { base.Multiline = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new AutoCompleteStringCollection AutoCompleteCustomSource

        {

            get { return base.AutoCompleteCustomSource; }

            set { base.AutoCompleteCustomSource = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new AutoCompleteMode AutoCompleteMode

        {

            get { return base.AutoCompleteMode; }

            set { base.AutoCompleteMode = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new AutoCompleteSource AutoCompleteSource

        {

            get { return base.AutoCompleteSource; }

            set { base.AutoCompleteSource = value; }

        }



        [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]

        public new CharacterCasing CharacterCasing

        {

            get { return base.CharacterCasing; }

            set { base.CharacterCasing = value; }

        }



        #endregion



        #endregion



        protected override void OnReadOnlyChanged(EventArgs e)

        {

            base.OnReadOnlyChanged(e);

            OnBackColorChanged(EventArgs.Empty);

        }



        protected override void OnBackColorChanged(EventArgs e)

        {

            base.OnBackColorChanged(e);



            base.BackColor = ReadOnly ? m_BackColorWhenReadOnly : m_BackColor;

            Invalidate();

        }



        protected override void OnLostFocus(EventArgs e)

        {

            base.OnLostFocus(e);

            if (userEdit)

            {

                UpdateEditText();

            }

        }



        protected override void OnKeyPress(KeyPressEventArgs e)

        {

            base.OnKeyPress(e);

            NumberFormatInfo numberFormat = CultureInfo.CurrentCulture.NumberFormat;

            string numberDecimalSeparator = numberFormat.NumberDecimalSeparator;

            string numberGroupSeparator = numberFormat.NumberGroupSeparator;

            string negativeSign = numberFormat.NegativeSign;

            string str4 = e.KeyChar.ToString();



            if (m_AllowNegative)//允许负数

            {

                if (e.KeyChar == '-')

                {

                    if (SelectionStart > 0 || base.Text.IndexOf("-") > 0) // 负号的位置不对或已经存在,负号必须在最前

                    {

                        e.Handled = true;

                    }

                    return;

                }

            }

            else//不允许负数

            {

                if (e.KeyChar == '-')

                {

                    e.Handled = true;

                    return;

                }

            }



            if (decimalPlaces > 0)//允许小数

            {

                if (e.KeyChar == '.')

                {

                    if (base.Text.IndexOf('.') >= 0)// 存在小数点

                    {

                        //SelectionStart = base.Text.IndexOf('.') + 1; //定位到小数点后一位置

                        e.Handled = true;

                        return;

                    }

                }

            }

            else//不允许小数

            {

                if (e.KeyChar == '.')

                {

                    e.Handled = true;

                    return;

                }

            }



            if (((!char.IsDigit(e.KeyChar) && (!str4.Equals(numberDecimalSeparator) && 

                  !str4.Equals(numberGroupSeparator))) && !str4.Equals(negativeSign)) && (e.KeyChar != '\b'))

            {

                if (Hexadecimal)

                {

                    if ((e.KeyChar >= 'a') && (e.KeyChar <= 'f'))

                    {

                        return;

                    }

                    if ((e.KeyChar >= 'A') && (e.KeyChar <= 'F'))

                    {

                        return;

                    }

                }

                if ((ModifierKeys & (Keys.Alt | Keys.Control)) == Keys.None)

                {

                    e.Handled = true;

                }

            }

        }



        protected void ParseEditText()

        {

            try

            {

                if (!string.IsNullOrEmpty(Text) && ((Text.Length != 1) || (Text != "-")))

                {

                    if (Hexadecimal)

                    {

                        Value = Constrain(Convert.ToDecimal(Convert.ToInt32(Text, 0x10)));

                    }

                    else

                    {

                        Value = Constrain(decimal.Parse(Text, CultureInfo.CurrentCulture));

                    }

                }

                else

                {

                    Text = "0";

                }

            }

            catch

            {

            }

            finally

            {

                userEdit = false;

            }

        }



        private decimal Constrain(decimal value) //当超出值的范围,强制为最大值或最小值

        {

            if (value < minimum)

            {

                value = minimum;

            }

            if (value > maximum)

            {

                value = maximum;

            }

            return value;

        }



        private string GetNumberText(decimal num)

        {

            if (Hexadecimal)

            {

                long num2 = (long)num;

                return num2.ToString("X", CultureInfo.InvariantCulture);

            }

            return num.ToString((ThousandsSeparator ? "N" : "F") + DecimalPlaces.ToString(CultureInfo.CurrentCulture), CultureInfo.CurrentCulture);

        }



        protected void UpdateEditText()

        {

            if (!initializing)

            {

                if (userEdit)

                {

                    ParseEditText();

                }

                if (currentValueChanged || (!string.IsNullOrEmpty(Text) && ((Text.Length != 1) || (Text != "-"))))

                {

                    currentValueChanged = false;

                    userEdit = true;

                    Text = GetNumberText(currentValue);

                }

            }

        }



        protected void ValidateEditText()

        {

            ParseEditText();

            UpdateEditText();

        }



        private void ResetMaximum()

        {

            Maximum = DefaultMaximum;

        }



        private void ResetMinimum()

        {

            Minimum = DefaultMinimum;

        }



        private void ResetValue()

        {

            Value = DefaultValue;

        }



        private bool ShouldSerializeMaximum()

        {

            return !Maximum.Equals(DefaultMaximum);

        }



        private bool ShouldSerializeMinimum()

        {

            return !Minimum.Equals(DefaultMinimum);

        }



        private bool ShouldSerializeValue()

        {

            return !Value.Equals(DefaultValue);

        }



        #region ISupportInitialize 成员



        public void BeginInit()

        {

            initializing = true;

        }



        public void EndInit()

        {

            initializing = false;

            Value = Constrain(currentValue);

            UpdateEditText();

        }



        #endregion

    }

}

你可能感兴趣的:(text)