数字控件NumberText

在日常中,很多地方输入需要限制输入数字,甚至是阿拉伯数字,为了各处代码的统一,写了个数字控件,效果如图

主要原理是在数字控件中重写OnKeyPress事件,判断当前输入的字符是否为数字(if (!char.IsDigit(e.KeyChar))),不是的话就放弃输入。

 

实现源代码如下:

   /// <summary>
    /// 文件:LiuYun.Beanver.UI.Control.LyNumber
    /// 说明:数字控件,增加小数点、负数处理
    ///       事前处理模式:做录入操作时屏蔽非数字字符
    ///       参考 http://blog.youkuaiyun.com/hulihui/article/details/3055907
    /// 创建者    操作    日期
    /// liuyun        新建    2013/2/21
    /// </summary>
    [ToolboxBitmap(typeof(TextBox))]//使用系统工具箱里的图片
    public class LyNumber : TextBox
    {
        private const int WM_CHAR = 0x0102;  // 字符消息
        private const int WM_PASTE = 0x0302;  // 上下文菜单"粘贴"消息
        public LyNumber()
        {
           
        }

        public LyNumber(IContainer container)
            : this()
        {
            container.Add(this);
        }

        protected override void Dispose(bool disposing)
        {
            base.Dispose(disposing);
        }

        private bool _isScientificNotation =false;

        [Browsable(true)]
        [EditorBrowsable(EditorBrowsableState.Always)]
        [Category("数字控件")]
        [Description("是否使用科学计数,默认不使用")]

        public bool IsScientificNotation
        {
            get { return _isScientificNotation; }
            set { _isScientificNotation = value; }
        }

        #region 重写事件
        bool isError = false;//当前的text值是否是数值型

        /// <summary>
        /// 重写获取值,因在值中有分号分隔
        /// </summary>
        /// <returns>在控件中显示的文本。</returns>
        public override string Text
        {
            get
            {
                string str = base.Text;
                if (str.Contains(',')&&_isScientificNotation)//去除分号
                    str.Replace(",","");
                return str;
            }
            set
            {
                if (_isScientificNotation)
                {
                    bool isPositiveNumber;//正数
                    if (string.IsNullOrEmpty(value))
                        return;
                    double num;
                    //判断数字格式是否正确
                    isError = !Double.TryParse(value.Replace(",", ""), out num);
                    if (!isError)//格式正确,是数值型
                    { 
                        //判断数值正负
                        if (num < 0)
                            isPositiveNumber = false;
                        else
                            isPositiveNumber = true;
                        value = Math.Abs(num).ToString();
                        //数值拆分为整数和小数部分,分别用分隔符分隔
                        string[] strs = value.Split('.');
                        value = GetSeparateStr(strs[0]);
                        if (strs.Length == 2)
                        {  
                            if (string.IsNullOrEmpty(value))
                                value = "0";
                            value += "." + GetSeparateStr(strs[1]);

                        }
                        //最后为负数值加上负号
                        if (!isPositiveNumber)
                            value = "-" + value;
                    }
                }
                
                base.Text = value;
            }
        }

        /// <summary>
        /// 得到分隔后的字符串
        /// </summary>
        /// <param name="str">The STR.</param>
        /// <returns></returns>
        private string GetSeparateStr(string str)
        {
            if (!string.IsNullOrEmpty(str)&&!str.Equals("0"))
            {
                int length = 3;
                string[] intStrs = new string[(int)Math.Ceiling((float)str.Length / 3)];
                for (int i = 0; i < intStrs.Length; i++)
                {
                    if (i == intStrs.Length - 1)
                        length = str.Length % 3;
                    if (length == 0)
                        length = 3;
                    intStrs[i] = str.Substring(0, length);
                    str = str.Remove(0, length);
                }
                str = string.Empty;
                for (int i = 0; i < intStrs.Length; i++)
                {
                    if (i == 0)
                        str += intStrs[i];
                    else
                        str += "," + intStrs[i];
                }

            }//end if (!string.IsNullOrEmpty(str)&&!str.Equals("0"))
            return str;
        }

        /// <summary>
        /// 捕获Mouse的Paste消息
        /// </summary>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_PASTE)  // 选择上下文菜单的"粘贴"操作
            {
                this.ClearSelection();
                SendKeys.Send(Clipboard.GetText());  // 模拟键盘输入
            }
            else
                base.WndProc(ref m);
        }

        /// <summary>
        /// 捕获Ctrl+V快捷键操作
        /// </summary>
        protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
        {
            if (keyData == (Keys)Shortcut.CtrlV)  // 快捷键 Ctrl+V 粘贴操作
            {
                this.ClearSelection();

                string text = Clipboard.GetText();
                for (int k = 0; k < text.Length; k++) // can not use SendKeys.Send
                {
                    // 通过消息模拟键盘输入, SendKeys.Send()静态方法不行
                    SendCharKey(text[k]);
                }
                return true;
            }
            return base.ProcessCmdKey(ref msg, keyData);
        }

        /// <summary>
        /// 屏蔽非数字键
        /// </summary>
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);

            if (this.ReadOnly)
                return;

            // 特殊键, 不处理
            if ((int)e.KeyChar <= 31)
                return;

            
            // 非数字键, 放弃该输入
            if (!char.IsDigit(e.KeyChar))
            {
                //防止重复输入特殊符号
                if ((e.KeyChar == 46 && this.Text.Contains('.')) || (e.KeyChar == 45 && (this.Text.Contains('-'))))
                {
                    e.Handled = true;
                    return;
                }
                switch (e.KeyChar)
                {
                    case '.'://小数点
                        if (this.Text.Length == 0)
                        {
                            this.Text = "0.";
                            e.Handled = true;
                            //控制光标在小数点之后
                            this.SelectionStart += 2;
                            this.SelectionLength = 0;
                            return;
                        }
                        else 
                            break;
                    case '-'://负数
                        if (this.Text.Length > 0)
                        {
                            e.Handled = true;
                            return;
                        }
                        else
                            break;
                    default :
                        e.Handled = true;
                        return;
                }//end switch
            }//end if (!char.IsDigit(e.KeyChar))

            #region 科学计数
            if (_isScientificNotation)
            {
                //增加科学计数,每3位“,”分隔
                if (this.Text.Length > 2)
                {
                    double num;
                    bool isAdd = false;//是否加分号
                    string currentText;
                    //判断数字格式是否正确
                    isError = !Double.TryParse(Text.Replace(",", ""), out num);
                    if (!isError)//格式正确,是数值型
                    {
                        currentText = Math.Abs(num).ToString();
                        if (!currentText.Contains('.'))//整数
                        {
                            if (currentText.Length % 3 == 0)
                                isAdd = true;
                            else
                                isAdd = false;
                        }
                        else
                        {
                            int i=currentText.IndexOf('.');
                            currentText = currentText.Substring(i+1, currentText.Length - i-1);
                            if (currentText.Length % 3 == 0)
                                isAdd = true;
                            else
                                isAdd = false;
                        }
                    }

                    if (isAdd)
                    {
                        this.Text += "," + e.KeyChar;
                        this.SelectionStart += this.Text.Length;
                        this.SelectionLength = 0;
                        e.Handled = true;
                    }//end if (isAdd)
                }//end if (this.Text.Length > 2)
            }//end if (_isScientificNotation)
            #endregion

        }


        /// <summary>
        /// 通过消息模拟键盘录入
        /// </summary>
        private void SendCharKey(char c)
        {
            Message msg = new Message();

            msg.HWnd = this.Handle;
            msg.Msg = WM_CHAR;
            msg.WParam = (IntPtr)c;
            msg.LParam = IntPtr.Zero;

            base.WndProc(ref msg);
        }

        /// <summary>
        /// 清除当前TextBox的选择
        /// </summary>
        private void ClearSelection()
        {
            if (this.SelectionLength == 0)
                return;

            int selLength = this.SelectedText.Length;
            this.SelectionStart += this.SelectedText.Length;  // 光标在选择之后
            this.SelectionLength = 0;

            for (int k = 1; k <= selLength; k++)
            {
                this.DeleteText(Keys.Back);
            }
        }

        /// <summary>
        /// 删除当前字符, 并计算SelectionStart值
        /// </summary>
        private void DeleteText(Keys key)
        {
            int selStart = this.SelectionStart;

            if (key == Keys.Delete)  // 转换Delete操作为BackSpace操作
            {
                selStart += 1;
                if (selStart > base.Text.Length)
                    return;
            }

            if (selStart == 0 || selStart > base.Text.Length)  // 不需要删除
                return;

            if (selStart == 1 && base.Text.Length == 1)
            {
                base.Text = "";
                base.SelectionStart = 0;
            }
            else  // selStart > 0
            {
                base.Text = base.Text.Substring(0, selStart - 1) +
                    base.Text.Substring(selStart, base.Text.Length - selStart);
                base.SelectionStart = selStart - 1;
            }

        }
        #endregion
    }

 

注:有些地方可能还不是很完善,欢迎批评指正。

转载于:https://www.cnblogs.com/liuyun969/archive/2013/05/08/3066797.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值