1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
4 using System
.ComponentModel
;
5 using System
.Windows
.Forms
;
6 using System
.Globalization
;
12 /// Restricts the entry of characters to digits, the negative sign,
13 /// the decimal point, and editing keystrokes (backspace).
14 /// It does not handle the AltGr key so any keys that can be created in any
15 /// combination with AltGr these are not filtered
17 public class NumericTextBox
: TextBox
19 private const int WM_PASTE
= 0x302;
20 private NumberStyles numberStyle
= NumberStyles
.AllowDecimalPoint
| NumberStyles
.AllowLeadingSign
;
23 /// Restricts the entry of characters to digits, the negative sign,
24 /// the decimal point, and editing keystrokes (backspace).
25 /// It does not handle the AltGr key
27 /// <param name="e"></param>
28 protected override void OnKeyPress(KeyPressEventArgs e
)
32 e
.Handled
= invalidNumeric(e
.KeyChar
);
37 /// Main method for verifying allowed keypresses.
38 /// This does not catch cut paste copy ... operations.
40 /// <param name="key"></param>
41 /// <returns></returns>
42 private bool invalidNumeric(char key
)
46 NumberFormatInfo numberFormatInfo
= CultureInfo
.CurrentCulture
.NumberFormat
;
47 string decimalSeparator
= numberFormatInfo
.NumberDecimalSeparator
;
48 string negativeSign
= numberFormatInfo
.NegativeSign
;
50 string keyString
= key
.ToString();
52 if (Char
.IsDigit(key
))
56 else if (AllowDecimalSeparator
&& keyString
.Equals(decimalSeparator
))
58 if (Text
.IndexOf(decimalSeparator
) >= 0)
63 else if (AllowNegativeSign
&& keyString
.Equals(negativeSign
))
65 if (Text
.IndexOf(negativeSign
) >= 0)
72 // Backspace key is OK
74 else if ((ModifierKeys
& (Keys
.Control
)) != 0)
76 // Let the edit control handle control and alt key combinations
80 // Swallow this invalid key and beep
88 /// Method invoked when Windows sends a message.
90 /// <param name="m">Message from Windows.</param>
92 /// This is over-ridden so that the user can not use
93 /// cut or paste operations to bypass the TextChanging event.
94 /// This catches ContextMenu Paste, Shift+Insert, Ctrl+V,
95 /// While it is generally frowned upon to override WndProc, no
96 /// other simple mechanism was apparent to simultaneously and
97 /// transparently intercept so many different operations.
99 protected override void WndProc(ref Message m
)
101 // Switch to handle message...
106 // Get clipboard object to paste
107 IDataObject clipboardData
= Clipboard
.GetDataObject();
109 // Get text from clipboard data
110 string pasteText
= (string)clipboardData
.GetData(
111 DataFormats
.UnicodeText
);
113 // Get the number of characters to replace
114 int selectionLength
= SelectionLength
;
116 // If no replacement or insertion, we are done
117 if (pasteText
.Length
== 0)
121 else if (selectionLength
!= 0)
123 base.Text
= base.Text
.Remove(SelectionStart
, selectionLength
);
126 bool containsInvalidChars
= false;
127 foreach (char c
in pasteText
)
129 if (containsInvalidChars
)
133 else if (invalidNumeric(c
))
135 containsInvalidChars
= true;
139 if (!containsInvalidChars
)
141 base.Text
= base.Text
.Insert(SelectionStart
, pasteText
);
157 Int32
.TryParse(this.Text
, numberStyle
, CultureInfo
.CurrentCulture
.NumberFormat
, out intValue
);
162 public decimal DecimalValue
166 decimal decimalValue
;
167 Decimal
.TryParse(this.Text
, numberStyle
, CultureInfo
.CurrentCulture
.NumberFormat
, out decimalValue
);
173 private bool allowNegativeSign
;
175 public bool AllowNegativeSign
177 get { return allowNegativeSign; }
178 set { allowNegativeSign = value; }
181 private bool allowDecimalSeparator
;
183 public bool AllowDecimalSeparator
185 get { return allowDecimalSeparator; }
186 set { allowDecimalSeparator = value; }