Here is a simple standalone Winforms custom control, derived from the standard TextBox, that allows only System.Int32 input (it could be easily adapted for other types such as System.Int64, etc.). It supports copy/paste operations and negative numbers:
public class Int32TextBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;
string c = e.KeyChar.ToString();
if (char.IsDigit(c, 0))
return;
if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
return;
// copy/paste
if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
&& ((ModifierKeys & Keys.Control) == Keys.Control))
return;
if (e.KeyChar == '\b')
return;
e.Handled = true;
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_PASTE = 0x0302;
if (m.Msg == WM_PASTE)
{
string text = Clipboard.GetText();
if (string.IsNullOrEmpty(text))
return;
if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
return;
int i;
if (!int.TryParse(text, out i)) // change this for other integer types
return;
if ((i < 0) && (SelectionStart != 0))
return;
}
base.WndProc(ref m);
}
Update 2017: My first answer has some issues:
- you can type something that’s longer than an integer of a given type (for example 2147483648 is greater than Int32.MaxValue);
- more generally, there’s no real validation of the result of what has been typed;
- it only handles int32, you’ll have to write specific TextBox derivated control for each type (Int64, etc.)
So I came up with another version that’s more generic, that still supports copy/paste, + and — sign, etc.
public class ValidatingTextBox : TextBox
{
private string _validText;
private int _selectionStart;
private int _selectionEnd;
private bool _dontProcessMessages;
public event EventHandler<TextValidatingEventArgs> TextValidating;
protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (_dontProcessMessages)
return;
const int WM_KEYDOWN = 0x100;
const int WM_ENTERIDLE = 0x121;
const int VK_DELETE = 0x2e;
bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
{
DontProcessMessage(() =>
{
_validText = Text;
_selectionStart = SelectionStart;
_selectionEnd = SelectionLength;
});
}
const int WM_CHAR = 0x102;
const int WM_PASTE = 0x302;
if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
{
string newText = null;
DontProcessMessage(() =>
{
newText = Text;
});
var e = new TextValidatingEventArgs(newText);
OnTextValidating(this, e);
if (e.Cancel)
{
DontProcessMessage(() =>
{
Text = _validText;
SelectionStart = _selectionStart;
SelectionLength = _selectionEnd;
});
}
}
}
private void DontProcessMessage(Action action)
{
_dontProcessMessages = true;
try
{
action();
}
finally
{
_dontProcessMessages = false;
}
}
}
public class TextValidatingEventArgs : CancelEventArgs
{
public TextValidatingEventArgs(string newText) => NewText = newText;
public string NewText { get; }
}
For Int32, you can either derive from it, like this:
public class Int32TextBox : ValidatingTextBox
{
protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
{
e.Cancel = !int.TryParse(e.NewText, out int i);
}
}
or w/o derivation, use the new TextValidating event like this:
var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);
but what’s nice is it works with any string, and any validation routine.
Здравствуйте, очень часто начинающие программисты задают вопрос, как вводить в TextBox только цифры или другие необходимые им символы, игнорируя все остальные. В этой статье мы рассмотрим несколько самых простых и полезных способ решения этой проблемы.
Для этого мы создадим тестовый проект для наглядного примера с одним лишь текстбоксом, у нас он вот такой:
Перво-наперво нам необходимо найти событие, благодаря которому сможем отследить нажатие определенных клавиш. Таким событием является KeyPress. Оно будет происходить всегда, когда пользователь нажимает на любую кнопку на клавиатуре. Чтобы перейти к нему, надо для начала выделить TextBox, один раз щёлкнув на него левой кнопкой мыши.
Затем следует найти в правой стороне рабочей области Visual Studio окно «Свойства» и перейти в нём на вкладку событий (значок в виде молнии):
Примечание: если вы не нашли «Свойства», то просто кликните правой кнопкой мыши по текстбоксу и выберете в появившемся меню соответствующую вкладку.
Далее мы ищем событие KeyPress и дважды нажимаем на него левой кнопкой мыши. Нас перенесет к коду этого события. Далее мы рассмотрим несколько вариантов решения проблемы с вводом определенных символов в TextBox. Сначала будут идти варианты только с выводом цифр, а затем и другие (с Backspace, пробелом, запятой и проч.)
Использование в TextBox только цифр.
Способ первый — самый быстрый.
Внутри этой области кода мы запишем всего несколько строк:
char number = e.KeyChar; if (!Char.IsDigit(number)) { e.Handled = true; } |
Вот и всё решение нашей проблемы! Теперь если запустить проект и попробовать что-нибудь написать в нашем TextBox’e, то в него не попадёт ни один другой символ кроме цифр.
Так что же мы тут сделали?
В самой первой строке мы объявили символьную переменную, назвав её number.Благодаря параметру e.KeyChar программа заносит в нашу переменную символ введенной клавиши. Нажали на клавишу «+», в переменную запишется «+», нажали на клавишу «в», в переменную запишется «в» и т.д.
Далее идёт условие !Char.IsDigit(number), которое можно словесно интерпретировать как «если символ из переменной number не относится к категории десятичных цифр» (а нам как раз такие и нужны). А вывод из условия e.Handled = true интерпретируется как «тогда не обрабатывать введенный символ (и, следовательно, не выводить его в TextBox). Иными словами, мы проверяем, является ли любой символ, введенный пользователем десятичной цифрой. Если нет — отбрасываем его, если является — обрабатываем и выводим в TextBox. Легко, просто, быстро!
Способ второй — с кодировкой ASCII.
Однако далеко не всегда можно обойтись только способом, описанным выше. Нам в TextBox’e могут понадобиться и другие символы и клавиши, например, клавиша удаления Backspace, запятая или пробел. В таком случае нам придётся пользоваться помощью таблицей ASCII-кодов. Это совсем несложно. Но для начала разберемся,что вообще такое ASCII.
ASCII — это специальная кодировка, которая присваивает всем используемым в компьютере символам соответствующий числовой код.
Таблицу большинства ASCII-кодов можно просмотреть ниже (кликабельно).
Теперь попробуем написать аналогичный код для вывода только цифр используя коды ASCII. Итак, ищем в таблице, под какими номерами расположены наши цифры. Видимо, что нам необходимы коды с 48 по 57 — цифры от 0 до 9. Значит наш код в событии KeyPress будет таким:
char number = e.KeyChar; if (e.KeyChar <= 47 || e.KeyChar >= 58) { e.Handled = true; } |
Интерпретировать его можно так: «если ASCII-код записанного в переменную number символа будет меньше или равен 47 (все символы в кодировке до цифры «0») или больше или равен 58 (все символы в кодировке после цифры «9»), то не обрабатывать такие символы. При этом оставшиеся символы (как раз все наши цифры) не будут подходить под этот фильтр и поэтому выведутся в TextBox’e.
Ниже приведены коды с различными фильтрациями клавиш и символов, не ограничивающихся только лишь одними цифрами.
Использование в TextBox цифр и клавиши Backspace.
Код, приведенный ниже, дает возможность использовать в TextBox’e не только цифры, но и клавишу удаления Backspace. В нашем варианте мы смешали оба описанных выше способа, но также можно использовать и только второй способ.
char number = e.KeyChar; if (!Char.IsDigit(number) && number != // цифры и клавиша BackSpace { e.Handled = true; } |
Использование в TextBox цифр, запятой и клавиши Backspace.
Если нам потребуется вводить десятичные дроби, то для этой цели понадобится ещё и запятая. Приведем пример кода, на этот раз основанного на ASCII кодировке:
char number = e.KeyChar; if ((e.KeyChar <= 47 || e.KeyChar >= 58) && number != 8 && number != 44) //цифры, клавиша BackSpace и запятая а ASCII { e.Handled = true; } |
Альтернативный вариант:
char number = e.KeyChar; if (!Char.IsDigit(number) && number != 8 && number != 44) // цифры, клавиша BackSpace и запятая { e.Handled = true; } |
Использование в TextBox цифр, запятой, основных математических знаков и клавиши Backspace.
Если есть необходимость в создании, например, калькулятора, то может потребоваться отфильтровать не только цифры, но и некоторые другие математически знаки. Пример кода со знаками умножения, деления, сложения и вычитания, а также со скобками можно увидеть ниже:
char number = e.KeyChar; if ((e.KeyChar <= 47 || e.KeyChar >= 58) && number != 8 && (e.KeyChar <= 39 || e.KeyChar >= 46) && number != 47 && number != 61) //калькулятор { e.Handled = true; } |
Сравнив использованные числовые коды с таблицей ASCII можно легко понять, какой символ соответствует каждому коду.
Вот и всё! Мы рассмотрели самые простые способы ввода в TextBox одних цифр или других необходимых символов на языке C#.
Можно скачать исходный код программы, приведенной в статье со всеми перечисленными вариантами использования.
Скачать исходник
В скором времени мы разберем, как можно создавать вывод в TextBox только букв английского и русского алфавитов, а также знаков препинания. Удачного программирования!
Here is a simple standalone Winforms custom control, derived from the standard TextBox, that allows only System.Int32 input (it could be easily adapted for other types such as System.Int64, etc.). It supports copy/paste operations and negative numbers:
public class Int32TextBox : TextBox
{
protected override void OnKeyPress(KeyPressEventArgs e)
{
base.OnKeyPress(e);
NumberFormatInfo fi = CultureInfo.CurrentCulture.NumberFormat;
string c = e.KeyChar.ToString();
if (char.IsDigit(c, 0))
return;
if ((SelectionStart == 0) && (c.Equals(fi.NegativeSign)))
return;
// copy/paste
if ((((int)e.KeyChar == 22) || ((int)e.KeyChar == 3))
&& ((ModifierKeys & Keys.Control) == Keys.Control))
return;
if (e.KeyChar == '\b')
return;
e.Handled = true;
}
protected override void WndProc(ref System.Windows.Forms.Message m)
{
const int WM_PASTE = 0x0302;
if (m.Msg == WM_PASTE)
{
string text = Clipboard.GetText();
if (string.IsNullOrEmpty(text))
return;
if ((text.IndexOf('+') >= 0) && (SelectionStart != 0))
return;
int i;
if (!int.TryParse(text, out i)) // change this for other integer types
return;
if ((i < 0) && (SelectionStart != 0))
return;
}
base.WndProc(ref m);
}
Update 2017: My first answer has some issues:
- you can type something that’s longer than an integer of a given type (for example 2147483648 is greater than Int32.MaxValue);
- more generally, there’s no real validation of the result of what has been typed;
- it only handles int32, you’ll have to write specific TextBox derivated control for each type (Int64, etc.)
So I came up with another version that’s more generic, that still supports copy/paste, + and — sign, etc.
public class ValidatingTextBox : TextBox
{
private string _validText;
private int _selectionStart;
private int _selectionEnd;
private bool _dontProcessMessages;
public event EventHandler<TextValidatingEventArgs> TextValidating;
protected virtual void OnTextValidating(object sender, TextValidatingEventArgs e) => TextValidating?.Invoke(sender, e);
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (_dontProcessMessages)
return;
const int WM_KEYDOWN = 0x100;
const int WM_ENTERIDLE = 0x121;
const int VK_DELETE = 0x2e;
bool delete = m.Msg == WM_KEYDOWN && (int)m.WParam == VK_DELETE;
if ((m.Msg == WM_KEYDOWN && !delete) || m.Msg == WM_ENTERIDLE)
{
DontProcessMessage(() =>
{
_validText = Text;
_selectionStart = SelectionStart;
_selectionEnd = SelectionLength;
});
}
const int WM_CHAR = 0x102;
const int WM_PASTE = 0x302;
if (m.Msg == WM_CHAR || m.Msg == WM_PASTE || delete)
{
string newText = null;
DontProcessMessage(() =>
{
newText = Text;
});
var e = new TextValidatingEventArgs(newText);
OnTextValidating(this, e);
if (e.Cancel)
{
DontProcessMessage(() =>
{
Text = _validText;
SelectionStart = _selectionStart;
SelectionLength = _selectionEnd;
});
}
}
}
private void DontProcessMessage(Action action)
{
_dontProcessMessages = true;
try
{
action();
}
finally
{
_dontProcessMessages = false;
}
}
}
public class TextValidatingEventArgs : CancelEventArgs
{
public TextValidatingEventArgs(string newText) => NewText = newText;
public string NewText { get; }
}
For Int32, you can either derive from it, like this:
public class Int32TextBox : ValidatingTextBox
{
protected override void OnTextValidating(object sender, TextValidatingEventArgs e)
{
e.Cancel = !int.TryParse(e.NewText, out int i);
}
}
or w/o derivation, use the new TextValidating event like this:
var vtb = new ValidatingTextBox();
...
vtb.TextValidating += (sender, e) => e.Cancel = !int.TryParse(e.NewText, out int i);
but what’s nice is it works with any string, and any validation routine.
Learn how to prevent the input from non numeric characters inside a textbox in Winforms.
To create an input element on your Windows Form that only accepts numbers, you have 2 options:
A. Use a NumericUpDown control
If you want to create an input that only accepts number, the first thing that you need to think in is the NumericUpDown control. This controls represents a Windows spin box (also known as an up-down control) that displays exclusively numeric values.
You can simply drag and drop this control from your Toolbox in the All Windows Forms components:
Or you can add it dinamically using code:
// Create a new numericupdown control
NumericUpDown numbox = new NumericUpDown();
// Some location on the form
numbox.Location = new Point(10, 50);
numbox.Visible = true;
// Append to the form
Controls.Add(numbox);
To retrieve its value you can simply access the Value attribute of the control, for example:
// Retrieve numeric up down value
decimal value = numericUpDown1.Value;
// Show in an alert
MessageBox.Show(value.ToString());
Note that the value is returned in decimal type, so you can format it into an integer, string or whatever you need. This field by itself doesn’t allow non-numeric characters inside.
B. With a real textbox
In case you aren’t able to use a NumericUpDown
control for some reason, like the usage of a UI framework that only offers a textbox, you can still filter the input by handling properly its KeyPress
event. The first you need to do is to add a function to the KeyPress event of your input by adding automatically the event with Visual Studio selecting your textbox and in the Properties toolbox (right bottom corner of VS), then selecting the events tab and double clicking the KeyPress option:
This will automatically add the KeyPress function on your class that will be empty, then you need to modify it with the following code to prevent the input from non-numeric characters:
private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
// Verify that the pressed key isn't CTRL or any non-numeric digit
if (!char.IsControl(e.KeyChar) && !char.IsDigit(e.KeyChar) && (e.KeyChar != '.'))
{
e.Handled = true;
}
// If you want, you can allow decimal (float) numbers
if ((e.KeyChar == '.') && ((sender as TextBox).Text.IndexOf('.') > -1))
{
e.Handled = true;
}
}
To retrieve its value, you would need only to convert the string to a number by using the desired type:
string textboxValue = textBox1.Text;
// Retrieve as decimal
decimal valueDec = decimal.Parse(textboxValue);
// Retrieve as integer
int valueInt = Int32.Parse(textboxValue);
Happy coding !
8 / 8 / 4 Регистрация: 08.10.2009 Сообщений: 103 |
|
1 |
|
23.06.2011, 00:11. Показов 119628. Ответов 8
Что написать и в каком событии, что бы в textBox вводились только цифры?
1 |
Programming Эксперт 94731 / 64177 / 26122 Регистрация: 12.04.2006 Сообщений: 116,782 |
23.06.2011, 00:11 |
Ответы с готовыми решениями: TextBox ввод только цифр Ввод только цифр в TextBox Ввод в TextBox только цифр Ввод в TextBox только цифр 8 |
Петррр 6277 / 3562 / 898 Регистрация: 28.10.2010 Сообщений: 5,926 |
||||
23.06.2011, 00:33 |
2 |
|||
Сообщение было отмечено Памирыч как решение Решение Зачем отверстие сверлить молотком? Если очень сильно нужно:
5 |
8 / 8 / 4 Регистрация: 08.10.2009 Сообщений: 103 |
|
23.06.2011, 01:06 [ТС] |
3 |
А как добавить еще ноль и бекспейс?
0 |
_Vladimir_ 57 / 55 / 10 Регистрация: 27.07.2010 Сообщений: 279 |
||||
23.06.2011, 04:50 |
4 |
|||
Сообщение было отмечено как решение Решение
А как добавить еще ноль и бекспейс?
19 |
GENDALF_ISTARI 16 / 33 / 19 Регистрация: 20.08.2013 Сообщений: 740 |
||||
15.03.2015, 02:06 |
5 |
|||
По ascii.pdf это диапазон 47 по 58 теперь можно вводить цифры с 0-9 все остальное запрещено
5 |
UPicorn 3 / 3 / 0 Регистрация: 27.11.2017 Сообщений: 7 |
||||
27.11.2017, 00:55 |
6 |
|||
3 |
insider1 0 / 0 / 0 Регистрация: 18.01.2016 Сообщений: 5 |
||||||||
31.01.2019, 16:17 |
7 |
|||||||
Не совсем по теме, но тоже интересный случай — если нужно вводить в TextBox число с плавающей точкой
Этот метод, в отличие от вышеуказанных, позволяет вводить разделитель целой и дробной части (,). Также, если недопустимо, чтобы значение осталось пустым, можно добавить
Тогда, при некорректном вводе значение поменяется на «1» (нужно указать наиболее приемлемое значение по умолчанию). Поведение TextBox`a становится немного «странным», но защитит от пустых и некорректных значений.
0 |
Rutik777 0 / 0 / 1 Регистрация: 11.11.2015 Сообщений: 13 |
||||
19.01.2020, 00:11 |
8 |
|||
Приветствую всех тех кто еще в этой теме. Я пишу программу для практики, возникла у меня стоянка в коде. Хочу реализовать ввод в textBox, так что бы были только десятичные цифры и первое значения не было нулем например что бы не 02 или 04 и. т. а нормальные от 1 до 99. Вот кусок кода из события KeyPress.
В этом куске кода возникает исключение потому что пишу if (Convert.ToInt32(textBox1.Text) <= 0 || Convert.ToInt32(textBox1.Text) > 99) до return; и получается в textBox1.Text значения пустой строки. Как можно обойти эту проблему что бы можно было предотвратить ввод первого значения «0» либо размер числа больше 99 до того как будет нажата кнопка для обработки данных из textBox.
0 |
Skf74 0 / 0 / 0 Регистрация: 13.01.2019 Сообщений: 25 |
||||
16.06.2022, 22:52 |
9 |
|||
Кто-нибудь может подсказать как доработать код, чтобы ещё работали DEL, enter и стандартные сочетания (ctrl+v, ctrl+a, ctrl +c, ctrl +z, shift +home, shift+end и шифт + стрелки влево/вправо). В общем много всего)
0 |