如何在maskedtextbox中仅允许强制数值?

时间:2012-05-25 17:13:59

标签: c# .net winforms

我对Winforms很新,我想知道如何使用MaskedTextBox来确保用户只输入数值(包括小数)。

我使用“/ ^ [ - +]?[0-9] +(。[0-9] +)?$ /”尝试了屏蔽功能,并且没有成功。即使使用普通的文本框,我想要的只是数字/小数值

4 个答案:

答案 0 :(得分:9)

为什么不使用NumericUpDown?设置最大值和最小值,小数位数,然后离开。

http://msdn.microsoft.com/en-us/library/system.windows.forms.numericupdown%28v=vs.90%29.aspx

答案 1 :(得分:3)

MaskedTextBox的掩码不是正则表达式模式;他们使用自己的语法。

您想要的模式可能类似于“999,990.9999”。这要求用户输入至少一个数字,但是他们可以输入0到999,999.9999之间的任何数字,精度最高为4位小数,并且在需要时会自动插入千位分隔符。

您可以做的另一件事,类似于MaskedTextBox本身所做的,是覆盖OnKeyPress以拒绝任何输入的字符,这会导致Regex不匹配:

public class RegexTextBox:TextBox
{
   [Category("Behavior")]
   public string RegexPattern {get;set;}

   protected override OnKeyPress(KeyPressEventArgs e)
   { 
      if (!Regex.IsMatch(this.Text + e.KeyChar, RegexPattern)) e.Handled = true;
      else base.OnKeyPress(e);
   }
}

定义模式时必须小心,因为只有在目前输入的内容与模式匹配时才会起作用。但是,如果您使用"[0-9]{1,3}((,[0-9]{1,3})*(\.[0-9]*)?"等模式,它将适用于您的情况。

答案 2 :(得分:0)

我调整了这个NumericTextBox控件:http://sanity-free.org/forum/viewtopic.php?pid=1205#p1205

如果你想把它分开你的工具箱,你可能会创建一个基于TextBox的新控件,并将该链接中的代码粘贴到代码部分。

这是我的版本。我不知道我已经修改了多少,因为我已经有很长时间了。

<强> NumericTextBox.Designer.cs:

using System.Windows.Forms;

namespace SeaRisenLib2.Controls
{
    partial class NumericTextBox : TextBox
    {
        /// <summary> 
        /// Required designer variable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary> 
        /// Clean up any resources being used.
        /// </summary>
        /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
        protected override void Dispose(bool disposing)
        {
            if (disposing && (components != null))
            {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Component Designer generated code

        /// <summary> 
        /// Required method for Designer support - do not modify 
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
            components = new System.ComponentModel.Container();
            //this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        }

        #endregion
    }
}

<强> NumericTextBox.cs

// From: http://sanity-free.org/forum/viewtopic.php?pid=1205#p1205
// modified it slightly
//
/******************************************************/
/*          NULLFX FREE SOFTWARE LICENSE              */
/******************************************************/
/*  NumericTextBox Library                            */
/*  by: Steve Whitley                                 */
/*  © 2005 NullFX Software                            */
/*                                                    */
/* NULLFX SOFTWARE DISCLAIMS ALL WARRANTIES,          */
/* RESPONSIBILITIES, AND LIABILITIES ASSOCIATED WITH  */
/* USE OF THIS CODE IN ANY WAY, SHAPE, OR FORM        */
/* REGARDLESS HOW IMPLICIT, EXPLICIT, OR OBSCURE IT   */
/* IS. IF THERE IS ANYTHING QUESTIONABLE WITH REGARDS */
/* TO THIS SOFTWARE BREAKING AND YOU GAIN A LOSS OF   */
/* ANY NATURE, WE ARE NOT THE RESPONSIBLE PARTY. USE  */
/* OF THIS SOFTWARE CREATES ACCEPTANCE OF THESE TERMS */
/*                                                    */
/* USE OF THIS CODE MUST RETAIN ALL COPYRIGHT NOTICES */
/* AND LICENSES (MEANING THIS TEXT).                  */
/*                                                    */
/******************************************************/
/* Changed by Carlos Montiers                         */
/* Decimal separator "." or "," depending on locale   */
/* Constructor for numericTextBox whith or without    */
/* negative range and number of decimals.             */
/* Does not allow the entry of non-numeric character  */
/* through alt + ascii code                           */
/* Permit use of tab key                              */
/* Version: 24-10-2008                                */
/******************************************************/

using System;
using System.Drawing;
using System.Windows.Forms;
using System.Text.RegularExpressions;

namespace SeaRisenLib2.Controls
{
    public partial class NumericTextBox : TextBox
    {
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_PASTE = 0x0302;
        private int decimalNumbers;
        private bool hasNegatives;
        private string format;

        public delegate void D(NumericTextBox sender);
        /// <summary>
        /// Fired when Text changes
        /// </summary>
        public event D Changed = delegate { };

        /// <summary>
        /// Constructor of a NumericTextBox, with negative number and 2 decimals.
        /// </summary>
        public NumericTextBox()
            : this(2, true)
        {
        }

        /// <summary>
        /// Constructor with parameters
        /// </summary>
        /// <param name="decimalNumbers">number of decimals</param>
        /// <param name="hasNegatives">has negatives</param>
        public NumericTextBox(int decimalNumbers, bool hasNegatives)
            : base()
        {
            InitializeComponent();
            DecimalNumbers = decimalNumbers;
            HasNegatives = hasNegatives;
            Format = Format;
        }

        /// <summary>
        /// Property of decimalNumbers
        /// </summary>
        public int DecimalNumbers
        {
            get
            {
                return decimalNumbers;
            }
            set
            {
                decimalNumbers = value > 0 ? value : 0;
            }
        }

        /// <summary>
        /// Bindable Decimal Text
        /// </summary>
        public decimal DecimalText
        {
            get {
                if(string.IsNullOrEmpty(Text))
                    return 0;

                return Convert.ToDecimal(Text);
            }
            set { Text = value.ToString(); }
        }

        /// <summary>
        /// The string text value of the numeric text, use DecimalText to get the numeric value.
        /// </summary>
        public override string Text
        {
            get { return base.Text; }
            set
            {
                base.Text = value;
                Changed(this);
            }
        }

        /// <summary>
        /// Property of hasNegatives
        /// </summary>
        public bool HasNegatives
        {
            get
            {
                return hasNegatives;
            }
            set
            {
                hasNegatives = value;
            }
        }

        /// <summary>
        /// Property of format
        /// </summary>
        public string Format
        {
            get
            {
                return format;
            }
            set
            {
                format = "^";
                format += HasNegatives ? "(\\" + getNegativeSign() + "?)" : "";
                format += "(\\d*)";
                if (DecimalNumbers > 0)
                {
                    format += "(\\" + getDecimalSeparator() + "?)";
                    for (int i = 1; i <= DecimalNumbers; i++)
                    {
                        format += "(\\d?)";
                    }
                }
                format += "$";
            }
        }

        /// <summary>
        /// Method PreProcessMessage
        /// </summary>
        /// <param name="msg">ref Message</param>
        /// <returns>bool</returns>
        public override bool PreProcessMessage(ref Message msg)
        {
            if (msg.Msg == WM_KEYDOWN)
            {
                Keys keys = (Keys)msg.WParam.ToInt32();

                bool numbers = ModifierKeys != Keys.Shift
                                && (keys >= Keys.D0 && keys <= Keys.D9
                                    || (keys >= Keys.NumPad0 && keys <= Keys.NumPad9));


                bool dec = ModifierKeys != Keys.Shift
                            && (keys == Keys.Decimal
                                || keys == Keys.Oemcomma
                                || keys == Keys.OemPeriod);

                bool negativeSign = (keys == Keys.OemMinus && ModifierKeys != Keys.Shift)
                                    || keys == Keys.Subtract;

                bool home = keys == Keys.Home;
                bool end = keys == Keys.End;

                bool ctrlZ = keys == Keys.Z && ModifierKeys == Keys.Control;
                bool ctrlX = keys == Keys.X && ModifierKeys == Keys.Control;
                bool ctrlC = keys == Keys.C && ModifierKeys == Keys.Control;
                bool ctrlV = keys == Keys.V && ModifierKeys == Keys.Control;

                bool del = keys == Keys.Delete;
                bool bksp = keys == Keys.Back;

                bool tab = keys == Keys.Tab;

                bool arrows = keys == Keys.Up
                              || keys == Keys.Down
                              || keys == Keys.Left
                              || keys == Keys.Right;

                if (numbers || del || bksp || arrows || home || end
                    || ctrlC || ctrlX || ctrlV || ctrlZ)
                {
                    return false;
                }
                else
                {
                    if (dec)
                    {
                        return DecimalNumbers <= 0;
                    }
                    else
                    {
                        if (negativeSign)
                        {
                            return !HasNegatives;
                        }
                        else
                        {
                            if (tab)
                            {
                                return base.PreProcessMessage(ref msg);
                            }
                            else
                            {
                                return true;
                            }
                        }
                    }
                }
            }
            else
            {
                return base.PreProcessMessage(ref msg);
            }
        }

        /// <summary>
        /// Method WndProc
        /// </summary>
        /// <param name="m">ref Message</param>
        protected override void WndProc(ref Message m)
        {
            if (m.Msg == WM_PASTE)
            {
                IDataObject obj = Clipboard.GetDataObject();
                string input = (string)obj.GetData(typeof(string));
                string pasteText = getPosibleText(input);

                if (!isValidadFormat(pasteText))
                {
                    m.Result = (IntPtr)0;
                    return;
                }
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// Method OnKeyPress
        /// </summary>
        /// <param name="e">KeyPressEventArgs</param>
        protected override void OnKeyPress(KeyPressEventArgs e)
        {
            base.OnKeyPress(e);
            string keyInput = e.KeyChar.ToString();
            string inputText = getPosibleText(keyInput);

            if (Char.IsDigit(e.KeyChar)
                || keyInput.Equals(getDecimalSeparator())
                || keyInput.Equals(getNegativeSign()))
            {
                e.Handled = !isValidadFormat(inputText);
            }
            else if (e.KeyChar == '\b'
                    || e.KeyChar == '\t'
                    || keyInput.Equals(Keys.Delete.ToString())
                    || keyInput.Equals(Keys.Home.ToString())
                    || keyInput.Equals(Keys.End.ToString()))
            {
                //Allow backspace, tab, delete, home, end
            }
            else if (e.KeyChar == 26
                     || e.KeyChar == 24
                     || e.KeyChar == 3
                     || e.KeyChar == 22)
            {
                // 26 : Allow Ctrl+Z | 24 : Allow Ctrl+X
                //  3 : Allow Ctrl+C | 22 : Allow Ctrl+V
            }
            else
            {
                //Disallow
                e.Handled = true;
            }
        }

        /// <summary>
        /// Method OnTextChanged
        /// </summary>
        /// <param name="e">System.EventArgs</param>
        protected override void OnTextChanged(System.EventArgs e)
        {
            if (getFloatValue() < 0)
            {
                this.ForeColor = Color.Red;
            }
            else
            {
                this.ForeColor = Color.Black;
            }

            //If the decimal point is preceded by a no number is added zero
            if (this.Text.StartsWith(getNegativeSign() + getDecimalSeparator()))
            {
                this.Text = getNegativeSign() + "0" + this.Text.Substring(1);
                this.Select(3, 0);
            }
            else
            {
                if (this.Text.StartsWith(getDecimalSeparator()))
                {
                    this.Text = "0" + this.Text;
                    this.Select(2, 0);
                }
            }
            base.OnTextChanged(e);
        }

        /// <summary>
        /// Method for validate text with format
        /// </summary>
        /// <param name="text">text</param>
        /// <returns>is valid format</returns>
        private bool isValidadFormat(string text)
        {
            return Regex.IsMatch(text, Format);
        }

        /// <summary>
        /// Method for get deciamal separator
        /// </summary>
        /// <returns>Decimal Separator of current culture</returns>
        private string getDecimalSeparator()
        {
            return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
        }

        /// <summary>
        /// Method for get negative sign
        /// </summary>
        /// <returns>Negative Sign of current culture</returns>
        private string getNegativeSign()
        {
            return System.Globalization.CultureInfo.CurrentCulture.NumberFormat.NegativeSign;
        }

        /// <summary>
        /// Method for get posible resulting text for input text
        /// </summary>
        /// <param name="text">string with input text</param>
        /// <returns>posible text</returns>
        private string getPosibleText(string text)
        {
            string rText;
            rText = this.Text.Substring(0, SelectionStart);
            rText += text;
            rText += this.Text.Substring(SelectionStart + SelectionLength);
            return rText;
        }

        /// <summary>
        /// Method for get int value of text
        /// </summary>
        /// <returns>int value</returns>
        public int getIntValue()
        {
            try
            {
                return (int)getFloatValue();
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// Method for get round int value of text
        /// </summary>
        /// <returns>round int value</returns>
        public int getIntRoundValue()
        {
            try
            {
                return (int)Math.Round(getFloatValue());
            }
            catch
            {
                return 0;
            }
        }

        /// <summary>
        /// Method for get float value of text
        /// </summary>
        /// <returns>float value</returns>
        public float getFloatValue()
        {
            try
            {
                return float.Parse(this.Text);
            }
            catch
            {
                return 0;
            }
        }


    }
}

答案 3 :(得分:0)

谢谢,下面的工作代码。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace System.Windows.Forms {
    public class RegexTextBox : TextBox {
        [Category("Behavior")]
        public string RegexPattern { get; set; }
        private bool DelOrBack = false;
        protected override void OnKeyDown(KeyEventArgs e) {
            base.OnKeyDown(e);
            if (e.KeyCode == Keys.Back || e.KeyCode == Keys.Delete) {
                DelOrBack = true;
            }
        }

        protected override void OnKeyPress(KeyPressEventArgs e) {
            if (!Regex.IsMatch(this.Text + e.KeyChar, RegexPattern) && !DelOrBack) {
                e.Handled = true;               
            }
            else {
                base.OnKeyPress(e);
            }

            DelOrBack = false;
        }
    }

    public class NumericTextBox : RegexTextBox {
        public NumericTextBox() {
            RegexPattern = "^[0-9]+$";
        }
    }
}