using System;
using System.ComponentModel;
using System.Windows.Forms;
using System.Globalization;
namespace Aga.Controls{
/// <summary>
/// Restricts the entry of characters to digits, the negative sign,
/// the decimal point, and editing keystrokes (backspace).
/// It does not handle the AltGr key so any keys that can be created in any
/// combination with AltGr these are not filtered
/// </summary>
public class NumericTextBox : TextBox
{
private const int WM_PASTE = 0x302;
private NumberStyles numberStyle = NumberStyles.AllowDecimalPoint | NumberStyles.AllowLeadingSign;
/// <summary>
/// Restricts the entry of characters to digits, the negative sign,
/// the decimal point, and editing keystrokes (backspace).
/// It does not handle the AltGr key
/// </summary>
/// <param name="e"></param>
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
e.Handled = invalidNumeric(e.KeyChar);
}
/// <summary>
/// Main method for verifying allowed keypresses.
/// This does not catch cut paste copy ... operations.
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
private bool invalidNumeric(char key)
{
bool handled = false;
NumberFormatInfo numberFormatInfo = CultureInfo.CurrentCulture.NumberFormat;
string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
string negativeSign = numberFormatInfo.NegativeSign;
string keyString = key.ToString();
if (Char.IsDigit(key))
{
// Digits are OK
}
else if (AllowDecimalSeparator && keyString.Equals(decimalSeparator))
{
if (Text.IndexOf(decimalSeparator) >= 0)
{
handled = true;
}
}
else if (AllowNegativeSign && keyString.Equals(negativeSign))
{
if (Text.IndexOf(negativeSign) >= 0)
{
handled = true;
}
}
else if (key == '\b')
{
// Backspace key is OK
}
else if ((ModifierKeys & (Keys.Control)) != 0)
{
// Let the edit control handle control and alt key combinations
}
else
{
// Swallow this invalid key and beep
handled = true;
}
return handled;
}
/// <summary>
/// Method invoked when Windows sends a message.
/// </summary>
/// <param name="m">Message from Windows.</param>
/// <remarks>
/// This is over-ridden so that the user can not use
/// cut or paste operations to bypass the TextChanging event.
/// This catches ContextMenu Paste, Shift+Insert, Ctrl+V,
/// While it is generally frowned upon to override WndProc, no
/// other simple mechanism was apparent to simultaneously and
/// transparently intercept so many different operations.
/// </remarks>
protected override void WndProc(ref Message m)
{
// Switch to handle message...
switch (m.Msg)
{
case WM_PASTE:
{
// Get clipboard object to paste
IDataObject clipboardData = Clipboard.GetDataObject();
// Get text from clipboard data
string pasteText = (string)clipboardData.GetData(
DataFormats.UnicodeText);
// Get the number of characters to replace
int selectionLength = SelectionLength;
// If no replacement or insertion, we are done
if (pasteText.Length == 0)
{
break;
}
else if (selectionLength != 0)
{
base.Text = base.Text.Remove(SelectionStart, selectionLength);
}
bool containsInvalidChars = false;
foreach (char c in pasteText)
{
if (containsInvalidChars)
{
break;
}
else if (invalidNumeric(c))
{
containsInvalidChars = true;
}
}
if (!containsInvalidChars)
{
base.Text = base.Text.Insert(SelectionStart, pasteText);
}
return;
}
}
base.WndProc(ref m);
}
public int IntValue
{
get
{
int intValue;
Int32.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out intValue);
return intValue;
}
}
public decimal DecimalValue
{
get
{
decimal decimalValue;
Decimal.TryParse(this.Text, numberStyle, CultureInfo.CurrentCulture.NumberFormat, out decimalValue);
return decimalValue;
}
}
private bool allowNegativeSign;
[DefaultValue(true)]
public bool AllowNegativeSign
{
get { return allowNegativeSign; }
set { allowNegativeSign = value; }
}
private bool allowDecimalSeparator;
[DefaultValue(true)]
public bool AllowDecimalSeparator
{
get { return allowDecimalSeparator; }
set { allowDecimalSeparator = value; }
}
}
}
|