Проверить, была ли нажата кнопка в течение заданного промежутка времени
Я использую устройство, считывающее код с RFID-карточек, моделируя тем самым ситуацию прохождения человека через КПП. После прикладывания карты к этому устройству оно записывает код, хранимый на карте (последовательность из цифр), а затем посылает команду ПК нажатия на клавишу "Enter".
В представленном ниже коде я записываю эту последовательность цифр в переменную code. Когда эта последовательность записана (окончание записи определяется выполнением условия if (e.KeyChar == 13), где 13 - код клавиши "Enter" в таблице ASCII), в программе проделывается часть кода (обращение к БД, извлечение информации и т.д.).
Так вот, мне бы хотелось понять, каким образом после получения этой последовательности цифр выставить условный таймер на какой-то промежуток времени (5/10 секунд, неважно), в течение которого я буду ждать нажатия определённой клавиши. Если эта клавиша будет нажата, то..., иначе...
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == 13)
{
if (SQL.PassChecking(code, out string Name, out string Surname, out string MiddleName, out string PassStatus, out string Action))
{
if (Action == "Выход")
{
//код
}
else
{
//Тут необходимо выставить условный таймер в 5 секунд.
//если в течение этих 5 секунд была нажата определённая клавиша, то
//код
}
//код
}
else if (Name != null && Surname != null && MiddleName != null)
{
//код
}
else
{
//код
}
}
else
{
char PressedKey = e.KeyChar;
code += PressedKey;
}
}
Ответы (3 шт):
Всё-таки удалось прийти к результату. По совету Pekor использовал класс Timer. Добавил, соответственно, его на форму. В событии timer_tick написал незамысловатый код:
private void timer1_Tick(object sender, EventArgs e)
{
if (second <= 0)
{
timer1.Stop();
CardUsed = false;
code = "";
label1.Text = "отмена";
}
second--;
}
Коротко о переменных: second - переменная типа int, для хранения секунд; CardUsed - переменная типа bool для хранения логического значения (была ли карта приложена или нет). (строка label1.Text = "отмена"; - тестовая, чтобы проверить, отрабатывает ли таймер по истечении 5 секунд).
Теперь к основному коду:
private void Form1_KeyPress(object sender, KeyPressEventArgs e)
{
if (CardUsed == false)
{
if (e.KeyChar == 13 && code != "" && code != null)
{
second = 5;
CardUsed = true;
timer1.Start();
}
else if (e.KeyChar != 13)
{
char PressedKey = e.KeyChar;
code += PressedKey;
}
else code = "";
}
else
{
if (e.KeyChar == 101 && second > 0)
{
timer1.Stop();
CardUsed = false;
DataBaseAccessing(code);
}
}
}
Логика следующая: когда я прикладываю карту, в переменную code записывается числовая последовательность, соответствующая коду, хранимому на карте. В этот же момент (поскольку так работает то устройство, о котором я писал в самом начале) срабатывает условие нажатия клавиши Enter, за которым следует установка таймера на 5 секунд, его запуск и изменение значения переменной CardUsed. Теперь у меня есть маленькое окно в виде пяти секунд на то, чтобы нажать на кнопку "e". Как только я на неё нажимаю (строчка в коде - if (e.KeyChar == 101 && second > 0)), при условии, что у меня ещё осталось время, таймер останавливается, "статус" использования карты (переменная CardUsed) меняется на false и посылается запрос в базу данных с считанным с карты кодом.
Понятно, что по ходу дела нужно будет прописать дополнительные условия (например, если я после прикладывания карты нажал не на требуемую клавишу) и т.д. и т.п., но основной вопрос решён.
Вы можете ждать нажатия определенной клавиши, но непонятно, хотите ли вы продолжать в этот момент обрабатывать остальные клавиши?
Вот пример без мам, пап и таймеров. Я останавливаю всю обработку всего на 5 секунд и просто жду энтера, по истечении 5 секунд или если этнер нажмут раньше, я делаю if/else и восстанавливаю все подписки.
class MyForm : Form
{
private Label label;
public MyForm()
{
this.KeyPress += KeyPressed;
label = new Label() { Width = 300, Height = 30, Text = "Waiting for Enter" };
this.Controls.Add(label);
}
private async void KeyPressed(object sender, KeyPressEventArgs args)
{
if (args.KeyChar == (char)Keys.Enter)
{
var pressedTaskSource = new TaskCompletionSource<int>();
KeyPressEventHandler awaiter = null;
awaiter = (obj, e) =>
{
if (e.KeyChar == (char)Keys.Enter)
{
pressedTaskSource.SetResult(0);
this.KeyPress -= awaiter;
}
};
this.KeyPress += awaiter; // подписываемся на нажатие кнопки, чтобы словить когда будет энтер
this.KeyPress -= KeyPressed; // и отписываем основной обработчик, иначе второе нажатие энтера стриггерит второе ожидание
label.Text = "Ok, waiting another enter for 5 seconds!";
await Task.WhenAny(pressedTaskSource.Task, Task.Delay(5000)); // ждем энтер или 5 сек
if (pressedTaskSource.Task.IsCompleted)
label.Text = "You are good boy!";
else
label.Text = "Not waiting anymore!";
this.KeyPress -= awaiter; // надо отписаться от втутреннего обработчика
this.KeyPress += KeyPressed; // подписаться на основной обработчик
}
Console.WriteLine(args.KeyChar);
}
}
проверить можно просто запустив форму
new MyForm().ShowDialog();