我对Winforms很新,我想知道如何使用MaskedTextBox来确保用户只输入数值(包括小数)。
我使用“/ ^ [ - +]?[0-9] +(。[0-9] +)?$ /”尝试了屏蔽功能,并且没有成功。即使使用普通的文本框,我想要的只是数字/小数值
答案 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]+$";
}
}
}