简单数字文本框
一个只接受数字的 WinForms 文本框。
概述
这是 System.Windows.Forms.TextBox
组件的一个简单扩展/限制。只有数字可以输入到控件中。粘贴也会被检查,如果文本包含其他字符,则会被取消。我在各个网站上找到了许多示例,但没有一个适合我的目的。它们要么允许或强制执行我不想要的东西(参见下面的“我没有做的事情”),要么没有完全处理所有标准的键盘和鼠标功能(参见下面的“这肯定很简单”),例如,允许 Home 键或 Shift+End 等。
语言
源代码使用 C#,.NET 2.0, VS2008。我包含了已编译的 DLL,因此 VB 用户可以使用此控件。
我没有做的事情
我没有添加任何范围或边界控制 - 这是一个文本框,而不是 int/double/decimal... 框。不支持数字分隔符、货币符号,甚至 - 符号。我的实现不需要它们。如果您想添加它们,应该不会太难。
这肯定很简单,你只需要...
我也是这么想的,直到开始编写代码两分钟后!实际上,我们一直在使用文本框做很多事情,但从未仔细考虑过。除了数字之外,我们还需要允许编辑键组合和导航/选择键和组合。粘贴可以通过键盘或鼠标操作完成,因此仅处理键盘事件是不够的。
代码
代码中有趣的部分在重写的 OnKeyDown
和私有的 CheckPasteValid
方法中。
OnKeyDown
我只是为数字键、编辑键和导航键构建了 bool
s,这样我可以测试每个组的一个值。 Ctrl+A 有时需要单独处理,所以我为此也创建了一个。
protected override void OnKeyDown(KeyEventArgs e)
{
bool result = true;
bool numericKeys = (
((e.KeyCode >= Keys.D0 && e.KeyCode <= Keys.D9) ||
(e.KeyCode >= Keys.NumPad0 && e.KeyCode <= Keys.NumPad9))
&& e.Modifiers != Keys.Shift);
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);
if (!(numericKeys || editKeys || navigationKeys))
{
if (ctrlA)
// Do select all as OS/Framework
// does not always seem to implement this.
SelectAll();
result = false;
}
if (!result) // If not valid key then suppress and handle.
{
e.SuppressKeyPress = true;
e.Handled = true;
if (ctrlA) { } // Do Nothing!
else
OnKeyRejected(new KeyRejectedEventArgs(e.KeyCode));
}
else
base.OnKeyDown(e);
}
CheckPasteValid
当收到粘贴消息时,它会在重写的 WndProc
中捕获,然后调用此方法。根据结果,如果必要,它会在不调用基类的 WndProc
的情况下返回,从而取消该消息。 CheckPasteValid
的代码如下所示。设置默认值后,我们尝试从剪贴板获取文本。如果出现错误或没有有效文本,则会设置相应的拒绝原因并返回。如果一切正常,我们然后从当前文本和剪贴板的文本构建一个字符串。最后一步是检查剪贴板的文本是否包含任何非数字字符,并设置所需的拒绝原因。
private PasteEventArgs CheckPasteValid()
{
// Default values.
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) // Does clipboard contain text?
{
// Store text value as it will be post paste assuming it is valid.
textResult = (
Text.Remove(SelectionStart,
SelectionLength).Insert(SelectionStart, clipboardText));
foreach (char c in clipboardText) // Check for any non digit characters.
{
if (!char.IsDigit(c))
{
rejectReason = PasteRejectReasons.InvalidCharacter;
break;
}
}
}
else
rejectReason = PasteRejectReasons.NoData;
}
catch
{
rejectReason = PasteRejectReasons.Unknown;
}
return new PasteEventArgs(originalText, clipboardText, textResult, rejectReason);
}
新内容
事件
KeyRejected
- 当KeyDown
事件被阻止时发生。PasteRejected
- 当粘贴尝试被禁止时发生。
属性
DefaultText
- 没有值时使用的字符串(不能为 null 或空)。
嵌套类
有两个嵌套的事件参数类。
KeyRejectedEventArgs
每次阻止按下键时都会创建此实例。它只有一个属性
Key
- 被拒绝的键 (System.Windows.Forms.Keys
)。
PasteEventArgs
每次收到粘贴消息时都会创建此实例。它在内部使用,但其主要目的是作为 PasteRejected
事件中的事件参数。它有四个属性
OriginalText
- 粘贴之前(如果被拒绝,仍然是)的文本。ClipboardText
- 尝试粘贴的文本。TextResult
- 粘贴的结果(或本来是)的文本。RejectReason
- 一个枚举 (PasteRejectReasons
),指示被拒绝的原因(如果被拒绝),或者用于内部使用的PasteRejectReasons
.Accepted(如果粘贴 OK)。
历史
- 2008 年 11 月 7 日:初始版本。