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 } }