Как лучше всего заблокировать использование определенных клавиш ввода в TextBox без блокировки специальных нажатий клавиш, таких как Ctrl-V / Ctrl-C?
Например, позволяя пользователю вводить только подмножество символов или цифр, таких как A, B или C, и ничего больше.





Вы можете использовать событие TextChanged для текстового поля.
private void txtInput_TextChanged(object sender, EventArgs e)
{
if (txtInput.Text.ToUpper() == "A" || txtInput.Text.ToUpper() == "B")
{
//invalid entry logic here
}
}
Я использовал элемент управления Текстовое поле с маской для winforms. По этому поводу есть более подробное объяснение здесь. По сути, он запрещает ввод, который не соответствует критериям для поля. Если вы не хотите, чтобы люди вводили что-либо, кроме цифр, они просто не позволяли бы им вводить что-либо, кроме цифр.
Я бы использовал событие keydown и использовал e.cancel, чтобы остановить ключ, если ключ не разрешен. Если я хочу сделать это в нескольких местах, я бы создал пользовательский элемент управления, наследующий текстовое поле, а затем добавил бы свойство AllowedChars или DisallowedChars, которое обрабатывает его за меня. У меня есть несколько вариантов, которые я использую время от времени: некоторые позволяют форматировать и вводить деньги, некоторые - редактировать по времени и так далее.
Хорошо делать это как пользовательский элемент управления, так это то, что вы можете добавить к нему и превратить его в свое собственное текстовое поле-убийцу. ;)
Вот как я обычно с этим справляюсь.
Regex regex = new Regex("[0-9]|\b");
e.Handled = !(regex.IsMatch(e.KeyChar.ToString()));
Это позволит использовать только числовые символы и возврат. Проблема в том, что в этом случае вам не разрешат использовать клавиши управления. Я бы создал свой собственный класс текстового поля, если вы хотите сохранить эту функциональность.
Я обнаружил, что единственное рабочее решение закончилось предварительной проверкой нажатия клавиши в ProcessCmdKey для Ctrl-V, Ctrl-C, Delete или Backspace, а также дальнейшая проверка, если это не один из этих ключей в событии KeyPress. с помощью регулярного выражения.
Возможно, это не лучший способ, но в моих обстоятельствах он сработал.
protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
// check the key to see if it should be handled in the OnKeyPress method
// the reasons for doing this check here is:
// 1. The KeyDown event sees certain keypresses differently, e.g NumKeypad 1 is seen as a lowercase A
// 2. The KeyPress event cannot see Modifer keys so cannot see Ctrl-C,Ctrl-V etc.
// The functionality of the ProcessCmdKey has not changed, it is simply doing a precheck before the
// KeyPress event runs
switch (keyData)
{
case Keys.V | Keys.Control :
case Keys.C | Keys.Control :
case Keys.X | Keys.Control :
case Keys.Back :
case Keys.Delete :
this._handleKey = true;
break;
default:
this._handleKey = false;
break;
}
return base.ProcessCmdKey(ref msg, keyData);
}
protected override void OnKeyPress(KeyPressEventArgs e)
{
if (String.IsNullOrEmpty(this._ValidCharExpression))
{
this._handleKey = true;
}
else if (!this._handleKey)
{
// this is the final check to see if the key should be handled
// checks the key code against a validation expression and handles the key if it matches
// the expression should be in the form of a Regular Expression character class
// e.g. [0-9\.\-] would allow decimal numbers and negative, this does not enforce order, just a set of valid characters
// [A-Za-z0-9\-_\@\.] would be all the valid characters for an email
this._handleKey = Regex.Match(e.KeyChar.ToString(), this._ValidCharExpression).Success;
}
if (this._handleKey)
{
base.OnKeyPress(e);
this._handleKey = false;
}
else
{
e.Handled = true;
}
}
Эд: Я уже делаю это с помощью Regex, и мне нужно расширить текстовое поле, чтобы разрешить клавиши ctrl. Я обрабатываю Backspace и Delete как особые случаи в событии KeyPress, это событие KeyPress, в правильном месте выполняются ключевые проверки / блоки