In my window application I need masked textbox which accept real decmal numbers.
eg.
1) 1.56
2) 22.34
3) 123.34
4) 12312.34
This all value should be valid.
Can anyone tell me how can I do this?
And ya if anyone have better solution for real decimal numbers, instead of this masked TextBox
than I love to see it.
Thanks...
Use a custom control like this one (modify it to fulfill your needs):
using System;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
namespace CustomControls
{
public enum PasteRejectReasons
{
Unknown = 0,
NoData,
InvalidCharacter,
Accepted
}
public class DecimalTextBox : TextBox
{
public const int WM_PASTE = 0x0302;
public event EventHandler<KeyRejectedEventArgs> KeyRejected;
public event EventHandler<PasteEventArgs> PasteRejected;
private bool _DecimalSeparator = false;
private int _Precision;
public new HorizontalAlignment TextAlign
{
get { return base.TextAlign; }
set { base.TextAlign = value; }
}
public int Precision
{
get { return _Precision; }
set { _Precision = value; }
}
public DecimalTextBox()
{
TextAlign = HorizontalAlignment.Right;
Precision = 3;
}
protected override void OnGotFocus(EventArgs e)
{
SelectAll();
base.OnGotFocus(e);
}
protected override void OnKeyDown(KeyEventArgs e)
{
bool validate = true;
if (Text.Contains(".") || Text.Contains(","))
{
int indexSep;
string[] split;
string partiDecimal = "";
if (Text.Contains("."))
indexSep = Text.IndexOf('.');
else
indexSep = Text.IndexOf(',');
split = Text.Split(new char[] { ',', '.' });
partiDecimal += split[1];
if (partiDecimal.Length >= Precision)
if (SelectionStart > Text.Length - (partiDecimal.Length + 1))
validate = false;
}
bool result = true;
bool validateKeys = (e.KeyCode == Keys.Enter);
bool numericKeys = (
((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))
&& e.Modifiers != Keys.Shift
&& validate);
bool ctrlA = e.KeyCode == Keys.A && e.Modifiers == Keys.Control;
bool editKeys = (
(e.KeyCode == Keys.Z && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.X && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.C && e.Modifiers == Keys.Control) ||
(e.KeyCode == Keys.V && e.Modifiers == Keys.Control) ||
e.KeyCode == Keys.Delete ||
e.KeyCode == Keys.Back);
bool navigationKeys = (
e.KeyCode == Keys.Up ||
e.KeyCode == Keys.Right ||
e.KeyCode == Keys.Down ||
e.KeyCode == Keys.Left ||
e.KeyCode == Keys.Home ||
e.KeyCode == Keys.End);
bool decimalSeparator = ((
e.KeyCode == Keys.Decimal ||
e.KeyValue == 190 ||
e.KeyValue == 188)&&
TextLength != 0 &&
SelectionLength == 0);
if (decimalSeparator)
{
if (!_DecimalSeparator)
_DecimalSeparator = true;
else
decimalSeparator = false;
}
if (!(numericKeys || editKeys || navigationKeys || decimalSeparator || validateKeys))
{
if (ctrlA)
SelectAll();
result = false;
}
if (!result)
{
e.SuppressKeyPress = true;
e.Handled = true;
if (!ctrlA)
OnKeyRejected(new KeyRejectedEventArgs(e.KeyCode));
}
else
base.OnKeyDown(e);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (e.KeyChar == ';' || e.KeyChar == '?')
{
if (!(Text.Contains(",") || Text.Contains(".")))
_DecimalSeparator = false;
e.Handled = true;
}
}
protected override void OnTextChanged(EventArgs e)
{
bool invalid = false;
int i = 0;
foreach (char c in Text) // Check for any non digit characters.
{
if (!(char.IsDigit(c) || c == ',' || c == '.'))
{
invalid = true;
break;
}
if (c == ',' || c == '.')
i++;
}
if (i == 0)
_DecimalSeparator = false;
else if (i > 1)
invalid = true;
if (invalid)
{
Text = "";
return;
}
if (Text.Contains(".") || Text.Contains(","))
{
string charSep = "";
string[] split;
string partiEntier = "";
if (Text.Contains("."))
charSep = ".";
else
charSep = ",";
split = Text.Split(new char[] { ',', '.' });
partiEntier += split[0];
if (partiEntier == "")
Text = "0" + charSep + split[1];
}
base.OnTextChanged(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_PASTE)
{
PasteEventArgs e = CheckPasteValid();
if (e.RejectReason != PasteRejectReasons.Accepted)
{
m.Result = IntPtr.Zero;
OnPasteRejected(e);
return;
}
}
base.WndProc(ref m);
}
private PasteEventArgs CheckPasteValid()
{
PasteRejectReasons rejectReason = PasteRejectReasons.Accepted;
string originalText = Text;
string clipboardText = string.Empty;
string textResult = string.Empty;
try
{
clipboardText = Clipboard.GetText(TextDataFormat.Text);
if (clipboardText.Length > 0)
{
textResult = (
Text.Remove(SelectionStart, SelectionLength).Insert(SelectionStart, clipboardText));
foreach (char c in clipboardText)
{
if (!char.IsDigit(c))
{
rejectReason = PasteRejectReasons.InvalidCharacter;
break;
}
}
}
else
rejectReason = PasteRejectReasons.NoData;
}
catch
{
rejectReason = PasteRejectReasons.Unknown;
}
return new PasteEventArgs(originalText, clipboardText, textResult, rejectReason);
}
protected virtual void OnKeyRejected(KeyRejectedEventArgs e)
{
EventHandler<KeyRejectedEventArgs> handler = KeyRejected;
if (handler != null)
handler(this, e);
}
protected virtual void OnPasteRejected(PasteEventArgs e)
{
EventHandler<PasteEventArgs> handler = PasteRejected;
if (handler != null)
handler(this, e);
}
}
}
Instead of using a MaskedTextbox, consider using NumericUpDown
instead. It supports System.Decimal
numbers which supports most real-set numbers you should be caring about.
The NumericUpDown.DecimalPlaces
property supports up to 99 decimal places.