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