#c_sharp #winforms #button #клавиатура
Подскажите пожалуйста, как привязать клавишу клавиатуры к button С# form? Событие Click уже занято. А KeyPress не пойму как работает. Пишу калькулятор.
Ответы
Ответ 1
WinForms и клавиатура, довольно веселое сочетание, особенно когда пытаешься их заставить работать согласованно. 1. События Control.Key* Любой контрол умеет реагировать на нажатия клавиш и для этого определены несколько событий: Control.KeyDown, Control.KeyPress, Control.KeyUp. Вроде бы все нормально, подписываемся на события и получаем реакцию на клавиши. Но тут есть один подвох - эти события срабатывают только когда контрол находится в фокусе. Кроме того, многие контролы уже имеют стандартные обработчики клавиш, многие реагируют на пробел как на клик, а TextBox и его родственники перехватывают почти всю клавиатуру. 2. Форма тоже контрол Класс Form также наследуется от контрол, и умеет получать эти события. Вроде бы очевидно, переносим обработку клавиш в события формы и радуемся, она же вроде бы всегда в фокусе. Но и тут не все так просто. Если дочерний контрол настроен на обработку клавиш и находится в фокусе (а если на форме есть дочерние контролы, то один из них обязательно в фокусе), то форма просто игнорирует нажатия на клавиши. Можно вспомнить о свойстве формы Form.KeyPreview, которое предназначено для перехвата событий, тогда события клавиатуры будут сначала передаваться в форму. Это вроде бы рабочий вариант, но если вы не хотите чтобы стандартный функционал контролов все еще работал, то придется не забыть выставить свойство KeyPressEventArgs.Handled = false; чтобы после обработки события клавиатуры на уровне формы, оно было передано в дочерние контролы. Честно говоря, это не самый лучший вариант, т.к. имеет свои ограничения и далеко не все задачи можно решить таким способом. Хотя он вроде для этого и задуман. 3. Нас спасет меню Первый вариант решения проблемы относительно без шаманства - добавить на форму меню в лице MenuStrip. Меню сделано таким образом, что к каждому его элементу, можно привязать хоткей, а для их корректной работы меню перехватывает все события клавиатуры и отдает дальше только те, которые не связаны с нажатиями на заданные клавиши и сочетания. Способ всем хорош, кроме пары моментов: для всех нужных клавиш и сочетаний нужен пункт в меню и необходимо само меню на форме. Если первая проблема еще может быть решена применением скрытых элементов (лично не проверял), то вторая - реально проблема, т.к. не любая форма приложения допускает наличие на ней меню, а добавлять его только ради обработки клавиш... ну вы меня поняли. 4. Универсальное решение Не торопитесь радоваться, все предыдущие пункты требовали только мастерского владения кликом мыши в интерфейс конструктора, а тут потребуется писать код. В форме, как и любом контроле есть виртуальный метод ProcessCmdKey, который отвечает за дефолтную обработку событий клавиатуры, вот его-то и потребуется переопределить в нашей форме для получения ожидаемой и корректной работы с клавиатурой. protected override bool ProcessCmdKey(ref Message msg, Keys keyData) { //ваша логика тут return base.ProcessCmdKey(ref msg, keyData); } Вызов базового метода - не обязателен. За передачу события дочерним контролам отвечает результат работы метода, только логика немного наоборот: true - клавиша обработана, дальнейшая обработка не требуется; false - событие будет передано дочерним контролам, даже если вы выполнили какую-то предварительную обработку. Таким образом вы получаете полный контроль над обработкой событий клавиатуры на уровне формы или кастомного контрола. Преимущество данного метода заключается еще и в том, что вы получаете доступ к параметру keyData, который, в отличие от KeyPressEventArgs содержит не только отображаемый символ, а всю информацию о нажатой клавише, включая скан-код, состояние клавиш-модификаторов и другую полезную информацию. За то, какое именно событие произошло, отвечает параметр msg, который содержит системное сообщение WinAPI. Нас интересуют относящиеся к клавиатуре WM_KEYDOWN и WM_KEYUP. Событие KeyPress - фактически последовательное получение WM_KEYDOWN и WM_KEYUP. 5. Ну и как этим воспользоваться? Да собственно как и обычно. Нажатие на клавишу и клик по кнопке это действие пользователя, которое должно вызвать какую-то реакцию программы. Реакцию описываем отдельным приватным методом, а в обработчики клика кнопки и нажатия на клавишу кладем вызов этого метода. Такой подход избавляет от необходимости копировать код, сводит код обработчиков событий к минимуму, позволяет вызывать заданную реакцию программы любым нужным способом, будь то клик по какому либо контролу, выбор чекбокса или радио-баттона, клавиша или сочетание, пункт меню или все сразу. Код реакции находится в одном месте и при необходимости его изменить не придется думать где еще вы его забыли поправить. Если хватит энтузиазма, позже соберу в этом ответе ссылки на связанные вопросы с хорошими ответами. А пока первое что нашлось по теме без глубокого копания: Как правильно перехватывать нажатия клавиш в Windows Forms (C++)? Обработка нажатий на цифровую клавиатуруОтвет 2
Если я правильно понял вопрос, то вы можете использовать событие KeyDown. При нажатии на кнопку пробел выполнится код кнопки private void button1_KeyDown(object sender, KeyEventArgs e) { if (e.KeyCode == Keys.Space) MessageBox.Show("Hello!"); }
Комментариев нет:
Отправить комментарий