Ожидание нажатия клавиши visual studio

Обновлено: 06.07.2024

Когда пользователь нажимает клавишу, возникает целая серия событий. В таблице эти события перечислены в порядке их возникновения:

Хронология возникновения событий
Имя Тип маршрутизации Описание
PreviewKeyDown Туннелирование Возникает при нажатии клавиши.
KeyDown Пузырьковое распространение То же
PreviewTextInput Туннелирование Возникает, когда нажатие клавиши завершено, и элемент получает текстовый ввод. Это событие не возникает для тех клавиш, которые не "печатают" символы (например, оно не возникает при нажатии клавиш <Ctrl>, <Shift>, <Backspace>, клавиш управления курсором, функциональных клавиш и т.д.)
TextInput Пузырьковое распространение То же
PreviewKeyUp Туннелирование Возникает при отпускании клавиши
KeyUp Пузырьковое распространение То же

Обработка событий клавиатуры отнюдь не так легка, как это может показаться. Некоторые элементы управления могут блокировать часть этих событий, чтобы выполнять свою собственную обработку клавиатуры. Наиболее ярким примером является элемент TextBox, который блокирует событие TextInput, а также событие KeyDown для нажатия некоторых клавиш, таких как клавиши управления курсором. В подобных случаях обычно все-таки можно использовать туннелируемые события (PreviewTextlnput и PreviewKeyDown).

Элемент TextBox добавляет одно новое событие — TextChanged. Это событие возникает сразу после того, как нажатие клавиши приводит к изменению текста в текстовом поле. Однако в этот момент новый текст уже видим в текстовом поле, потому отменять нежелательное нажатие клавиши уже поздно.

Обработка нажатия клавиши

Понять, как работают и используются события клавиатуры, лучше всего на примере. Ниже представлен пример программы, которая отслеживает и протоколирует все возможные нажатия клавиш, когда в фокусе находится текстовое поле. В данном случае показан результат ввода заглавной буквы S.

Этот пример демонстрирует один важный момент. События PreviewKeyDown и KeyDown возникают при каждом нажатии клавиши. Однако событие TextInput возникает только тогда, когда в элементе был "введен" символ. На самом деле это может означать нажатие многих клавиш. В примере, нужно нажать две клавиши, чтобы получить заглавную букву S: сначала клавишу <Shift>, а затем клавишу <S>. В результате получаются по два события KeyDown и KeyUp, но только одно событие TextInput.

Наблюдение за клавиатурой

Каждое из событий PreviewKeyDown, KeyDown, PreviewKey и KeyUp передает объекту KeyEventArgs одну и ту же информацию. Самой важной ее частью является свойство Key, которое возвращает значение из перечисления System.Windows.Input.Key и идентифицирует нажатую или отпущенную клавишу.

Значение Key не учитывает состояние любой другой клавиши — например, была ли прижата клавиша <Shift> в момент нажатия <S>; в любом случае вы получите одно и то же значение Key (Key.S).

Здесь присутствует одна сложность. В зависимости от настройки клавиатуры в Windows, удержание клавиши в прижатом состоянии приводит к повторам нажатия после короткого промежутка времени. Например, прижатие клавиши <S> приведет к вводу в текстовое поле целой серии символов S. Точно так же прижатие клавиши <Shift> приводит к повторам нажатия и возникновению серии событий KeyDown. В реальном примере при нажатии комбинации <Shift+S> текстовое поле сгенерирует серию событий KeyDown для клавиши <Shift>, потом событие KeyDown для клавиши <S>, событие TextInput (или событие TextChanged в случае текстового поля), а затем событие KeyUp для клавиш <Shift> и <S>. Если нужно игнорировать повторы нажатия клавиши <S>, то можно проверить, является ли нажатие результатом прижатия клавиши, с помощью свойства KeyEventArgs.IsRepeat.

События PreviewKeyDown, KeyDown, PreviewKey и KeyUp больше подходят для написания низкоуровневого кода обработки ввода с клавиатуры (что редко бывает нужно — разве что в пользовательских элементах управления) и обработки нажатий специальных клавиш (например, функциональных).

За событием KeyDown следует событие PreviewTextInput. (Событие TextInput не возникает, поскольку элемент TextBox блокирует его.) В этот момент текст еще не отображается в элементе управления.

Событие TextInput обеспечивает код объекта TextCompositionEventArgs. Этот объект содержит свойство Text, которое дает обработанный текст, подготовленный к передаче элементу управления.

В идеале событие PreviewTextInput можно было бы использовать для выполнения проверки в элементах управления наподобие TextBox. Например, если вы создаете текстовое поле для ввода только чисел, можно проверить, не была ли введена при текущем нажатии клавиши буква, и установить флаг Handled, если это так. Увы — событие PreviewTextIlnput не генерируется для некоторых клавиш, которые бывает нужно обрабатывать. Например, при нажатии клавиши пробела в текстовом поле событие PreviewTextInput вообще пропускается. Это означает, что придется обрабатывать также событие PreviewKeyDown.

К сожалению, трудно реализовать надежную логику проверки данных в обработчике события PreviewKeyDown, т.к. в наличии имеется только значение Key, а это слишком низкоуровневый фрагмент информации. Например, в перечислении Key различаются клавиши цифровой клавиатуры (блок, предназначенный для ввода только цифр) и обычной клавиатуры. Это означает, что в зависимости от того, где нажата клавиша с цифрой 9, вы получите или значение Key.D9, или значение Key.NumPad9. Проверка всех допустимых значений как минимум очень утомительна.

Одним из выходов является использование класса KeyConverter, который позволяет преобразовать значение Key в более полезную строку. Например, вызов функции KeyConverter.ConvertToString() с любым из значений Key.D9 и Key.NumPad9 возвращает строковый результат "9". Вызов преобразования Key.ToString() дает менее полезное имя перечисления (либо "D9", либо "NumPad9"):

Однако использовать KeyConverter тоже не очень удобно, поскольку приходится обрабатывать длинные строки (например, "Backspace") для тех нажатий клавиш, которые не приводят к вводу текста.

Наиболее подходящим вариантом является обработка события PreviewTextlnput (где выполняется большая часть проверки) в сочетании с событием PreviewKeyDown для нажатий тех клавиш, которые не генерируют событие PreviewTextInput в текстовом поле (например, пробела).

это стало утомительным, когда мне нужно было создать кучу небольших тестовых программ, и в конце концов я просто положил while(true); В конце на большинстве моих тестовых программ, просто чтобы я мог видеть результаты. Есть ли лучшая функция ожидания, которую я могу использовать?

вы можете потребовать от пользователя нажать enter перед закрытием программы. что-то вроде этого работает.

cin считывает пользовательский ввод и .функция ignore() cin говорит программе просто игнорировать ввод. Программа будет продолжаться, как только пользователь нажмет enter.

обратите внимание, что приведенный выше код был протестирован на Code:: Blocks 12.11 и Visual Studio 2012
на Windows 7.

для принудительной остановки или ожидания вашей программы у вас есть несколько вариантов :

значение должно быть положительным целым числом в миллисекундах. Это означает, что если вы хотите, чтобы ваша программа ждала 2 секунды, введите 2000.

если вы ждете слишком долго, что, вероятно, означает, что параметр в секундах. Поэтому измените его на это:

простой Программа "Hello world" в консольном приложении windows, вероятно, закроется, прежде чем вы сможете что-либо увидеть. Это тот случай, когда вы можете использовать систему("пауза").

тот же результат может быть достигнут с помощью Кин.игнорировать() :

просто не забудьте добавить библиотеку conio.h:

многие люди предложили POSIX sleep , Windows Sleep , Windows system("pause") , C++ cin.get() . есть даже DOS getch() там, примерно с конца 1920-х годов.

пожалуйста не делайте ничего из этого.

ни одно из этих решений не пройдет проверку кода в моей команде. Это означает, что если вы отправили этот код для включения в наши продукты, ваша фиксация будет заблокирована, и вам скажут пойти и найти другое решение. (Один можно утверждать, что все не так серьезно, когда вы просто любитель поиграть, но я предлагаю, что развитие хороших привычек в ваших домашних проектах-это то, что сделает вас ценным профессионалом в бизнес-организации и будет держать вас нанятым.)

держать окно консоли открытым, чтобы вы могли прочитать вывод вашей программы не ответственность вашей программы! Когда вы добавляете wait / sleep / block В конец своей программы, вы нарушаете единственный принцип ответственности, создавая массовую утечку абстракции и уничтожая повторное удобство использования/цепочку вашей программы. Он больше не принимает входной сигнал и не дает выход - он преграждает для переходных причин использования. Это очень нехорошо.

вместо этого вы должны настроить свой окружающая среда чтобы сохранить приглашение открытым после завершения работы программы. ваш пакетный скрипт-обертка-хороший подход! я вижу, как это будет неудобно держать обновление вручную, и вы не можете вызвать его из вашей IDE. вы можете заставить скрипт принять путь к программе для выполнения в качестве параметра и настроить IDE для вызова его вместо вашей программы напрямую.

промежуточный, быстрый старт подход будет измените команду запуска IDE С cmd.exe <myprogram> или <myprogram> , to cmd.exe /K <myprogram> . The /K переключатель cmd.exe делает запрос оставаться открытым после того, как программа по данному пути прекращено. Это будет немного более раздражающим, чем ваше решение пакетного скрипта, потому что теперь вам нужно ввести exit или нажмите на красный "X", когда вы закончите чтение вывода вашей программы, а не просто ударяя пробел.

Я предполагаю использование IDE, потому что в противном случае вы уже вызываете из командной строки, и это не было бы проблемой в первую очередь. Кроме того, я предполагаю использование Windows (на основе деталей данный в вопросе), но этот ответ применим к любой платформе. что, кстати, составляет половину пункта.

появление и исчезновение окна для отображения текста является особенностью того, как вы запускаете программу, а не C++.

выполнить в постоянной среде командной строки или включить поддержку окон на ваша программа или используйте sleep или подождите ввода, как показано в других ответах.

эквивалентом пакетной программы будет

дополнительные строки не PAUSE делает, ждет ввода одного символа

на самом деле, вопреки другим ответам, я считаю, что решение OP является самым элегантным.

вот что вы получаете, используя внешний .bat фантик:

  1. приложения, очевидно, ждет ввода пользователя, поэтому он уже делает то, что вы хотите.
  2. вы не загромождаете код неудобными звонками. Кто должен ждать? main() ?
  3. вам не нужно иметь дело с кросс-платформенными проблемами-посмотрите, сколько людей предложили system("pause") здесь.
  4. без этого, чтобы проверить исполняемый файл в автоматическом режиме в модели тестирования черного ящика, вам нужно имитировать enter нажатие клавиши (если вы не делаете вещи, упомянутые в сноске).
  5. возможно, самое главное-если любой пользователь хочет запустить приложение через терминал ( cmd.exe на платформе Windows), они не хотите подождать, так как они все равно увидят результат. С .bat техника обертки, они могут решить, запускать ли the .bat (или .sh ) wrapper или запустите исполняемый файл напрямую.

фокусируясь на последних двух точках - с любой другой техникой, я ожидал бы, что программа предложит по крайней мере --no-wait переключатель так, что я, как пользователь, можете использовать приложение с разного рода операции, такие как трубопроводы на выходе, сцепление его с другими программами и т. д. Это часть обычного рабочего процесса CLI, и добавление ожидания в конце, когда вы уже внутри терминала, просто мешает и уничтожает пользователя опыт.

по этим причинам, ИМО .bat решение здесь самое приятное.

есть способ сделать это на C++11. Это довольно просто, и я считаю, что это портативный. Конечно, как легкость гонки на орбите указал, вы не должны делать этого, чтобы иметь возможность видеть Привет, Мир в вашем терминале, но есть веская причина использовать функцию ожидания. Без лишних слов,

то, что у вас есть, можно написать проще. Вместо:

системная функция выполняет все, что вы ей даете, как если бы она была написана в командной строке. Он приостанавливает выполнение вашей программы во время выполнения команды, чтобы вы могли делать с ней что угодно, вы даже можете компилировать программы из своей программы cpp.

void sleep (неподписанные секунды);

sleep () приостанавливает выполнение на интервал (секунды). При вызове в спящий режим текущая программа приостанавливается от выполнения на количество секунд, указанное аргументом секунды. Интервал точен только до ближайшей сотой доли секунды или до точности часов операционной системы, в зависимости от того, что менее точно.

этот пример должен дать ясно:

EDIT:

вы также можете использовать winAPI.

просто Примечание, параметр в функции, предоставляемой winapi, находится в миллисекундах, поэтому строка сна в приведенном выше фрагменте кода будет выглядеть так: "Sleep (2000);"

getchar() предоставляет упрощенный ответ (ожидает ввода с клавиатуры). Вызовите Sleep (миллисекунды) для сна перед выходом. функция сна (MSDN)

вы можете использовать sleep () или usleep ().

Ну, это старый пост, но я просто внесу свой вклад в вопрос - кто-то может найти его полезным позже:

добавление ' cin.get (); ' функция непосредственно перед возвращением main (), кажется, всегда останавливает выход программы перед печатью результатов: см. Пример кода ниже:

перед инструкцией return в вас main вставьте этот код:

Это будет держать консоль, пока вы не нажмете клавишу.

второе, что нужно изучить (можно было бы утверждать, что это должно быть первым), - это интерфейс командной строки вашей ОС и флаги и переключатели компилятора/компоновщика.

private Thread cycle;
private ManualResetEvent clickEvent = new ManualResetEvent(false);
private void CycleProc() for (int i = 1; i <= 5; ++i) clickEvent.Reset();
clickEvent.WaitOne(); // ждём сигнала о нажатии

private void Form1_Load(object sender, EventArgs e) cycle = new Thread(CycleProc); // порождаем поток цикла
cycle.Start();
>

private void Form1_FormClosed(object sender, FormClosedEventArgs e) cycle.Abort();
>

private void button1_Click(object sender, EventArgs e) clickEvent.Set(); // сигналим о том, что по кнопке кликнули
>
>
>

Ребят, не поймите неправильно, но у меня похожий вопрос возник про ожидание нажатия, но ваши коды не работают! Там не то что InitializeComponent() нет, там даже Мэйна нет. Я извинясь, но кнопки тоже нигде не упоминаются.. Но даже с добавлением всего недостающего, прога не работает :(

Где можно прочитать про то, как реализовать ожидание нажатия на кнопку? Очень-очень нужно!

Ребят, не поймите неправильно, но у меня похожий вопрос возник про ожидание нажатия, но ваши коды не работают!

Код в студию! :rolleyes:

Ребят, не поймите неправильно, но у меня похожий вопрос возник про ожидание нажатия, но ваши коды не работают!


Ну выложи лог ошибок тогда.


Там не то что InitializeComponent() нет, там даже Мэйна нет. Я извинясь, но кнопки тоже нигде не упоминаются.. Но даже с добавлением всего недостающего, прога не работает :(


Так Main нужен в WF-приложении только чтобы запустить приложение.
Вот например -

using System;
using System.Collections.Generic;
using System.Windows.Forms;


Автор попросил "помогите оформить кпопку" - ну так и дали примеры хэндлеров. А если нужен целиком код приложения - тогда это не в тот раздел, извините.

Где можно прочитать про то, как реализовать ожидание нажатия на кнопку? Очень-очень нужно!


Из книг - думаю, Шилдта и Троелсена. А так - msdn только, по конкретным вещам.

Если вы поставили Visual studio для создания консольного проекта делаем следующее: Меню -> Файл -> Новый проект -> В списке выбираем Console Application (Консольное приложение) -> называем проект и жмем ОК.

Итак, рассмотрим поподробнее. Как же все сложно) Тут есть и пространство имен, и класс, и метод void Main, который принимает какие-то аргументы args, и какой-то using. Всё это требует отдельных тем, поэтому на данный момент воспринимайте это как шаблон, по которому вы будете строить консольные приложения.

Самым важным из них является метод Main. Это точка входа в программу или место, куда вы пишете код для выполнения программы, этакий start. В любом другом месте ваш код не будет выполняться, только если он не вызовется из метода Main.

<> – скобочки указывают на блок кода. < - начало или старт блока, >- конец блока. Аллегория – представьте себе какую-либо цитату. Открывающиеся кавычки указывают на начало цитаты, а закрывающиеся – на конец цитаты. Так и эти скобки указывают, откуда начинается ваш код и где заканчиваются.

static void Main(string[] args)

//Ожидание нажатия клавиши

Текст, обозначенный //однострочный комментарий.

не будет восприниматься компилятором как код, а будет являться комментарием (пояснением кода для вас).

Ну и в конце, просто запускаем программу – Debug->Start Debugging

Это не твое, не надо.

2013 студия в 2019 при бесплатной на сайте? Уроки на пикабу, которые гуглятся там, где они должны гуглиться?

Автор, вы упоролись?

За такое оформление кода надо сразу пальцы ломать.

Ок, вы рассказали, что технически так можно писать, ну так расскажите сразу, что на самом деле так не нужно писать. Никогда.

Иллюстрация к комментарию


Легла в направлении мечты => Пост №2

Легла в направлении мечты => Пост №2 Программирование, Gamedev, Csharp, Самообразование, Обучение

Так же мне посоветовали посмотреть конференции DevGamm. Как раз хорошо совпало, что такая конференция проходила онлайн с 17-19 ноября. Если кому интересно, у них имеется так же ютуб канал, где рассказывают про игры. При чем здесь имеется все: и про арт, и про маркетинг и конечно про сами игры, слушала как разработчики представляют свои работы. Очень интересно!

По английскому языку, больше делаю упор на сайт inSpeak. Так как в комментах подсказали, что лучше делать упор на разговорную речь и понимание что тебе говорят английском языке. Так же начала слушать аудио книги на Английском, их можно скачать на сайте Lelang, очень прикольно. Можно скачать аудио книгу и pdf к ней.

По книгам, добавила в свой список “Грокаем алгоритмы”, думаю к ней смогу приступить как раз после ООП.

Полный список моей программы можно посмотреть в первом посте: Легла в направлении своей мечты

Из того, что тяжело: ни как не могу перейти на режим дня жаворонка, чтобы вставать пораньше и было больше времени на обучение, сейчас даже если и получается встать рано, то целый день ты сидишь вареный, это не хорошо.

Было очень интересно прочитать в комментариях истории у кого всё получилось, и они уже в разработке. Особенно что и после 30 можно попасть в геймдев. Спасибо всем, кто поддерживает. Те, кто считает, что у меня ничего не выйдет и я все брошу, тоже спасибо, вы очень мотивируете писать посты, а не бросать их.

Читайте также: