Формы, не отвечающие на события KeyDown
Я работал некоторое время на моем проекте Windows Forms, и я решил поэкспериментировать с быстрыми клавишами. После небольшого чтения я решил, что должен просто написать обработчик событий и связать его с формой события KeyDown:
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.Alt && e.KeyCode == Keys.O)
{
MessageBox.Show("Ctrl+Alt+O: magic!");
}
}
Я сделал это, чтобы открыть панель свойств конструктора Visual Studio, затем дважды щелкнув событие KeyDown моей формы, чтобы сгенерировать обработчик события Form1_KeyDown
. Но при тестировании моего приложения форма вообще не отвечает на комбинацию клавиш Ctrl + Alt + O. Дизайнер Visual Studio действительно создал код для привязки обработчика события к форме:
private void InitializeComponent()
{
// ...
this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.Form1_KeyDown);
// ...
}
Итак, я попробовал добавить вызов Console.WriteLine()
к обработчику, чтобы проверить, что он вообще вызван, но также не повезло.
Кроме того, я попытался установить точку останова на вызове привязки события (показан выше) и обнаружил, что программа достигает этой точки останова только штрафом. Но любые точки останова, установленные в самом определении метода, никогда не достигаются.
Чтобы убедиться, что я делал первые несколько шагов правильно, я попытался повторить их с помощью:
-
Новая форма в том же решении.
Такая же проблема: форма не отвечает, когда я нажимаю клавишу Ctrl + Alt + O, и отладчик даже не вступает в обработчик событий. Пробовал это снова и он работает.
-
Новое решение WinForms.
Он отлично работает: появляется диалоговое окно сообщения (также работает вызов Console.WriteLine()
).
Итак, я совсем потерялся. Что мешает всем формам в этом проекте получать события KeyDown?
Ответы
Ответ 1
Имеет ли ваша форма свойство KeyPreview значение true?
Свойство Form.KeyPreview
Получает или задает значение, указывающее, получит ли форма ключ события до того, как событие будет передано элементу управления с фокусом.
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.keypreview.aspx
Ответ 2
Наиболее распространенный совет по этой проблеме в StackOverflow и MSDN 1, 2 (включая принятый ответ здесь) быстро и просто:
KeyDown
события запускаются на Form
, пока его свойство KeyPreview
установлено на true
Это адекватно для большинства целей, но это рискованно по двум причинам:
-
KeyDown
обработчики не видят всех ключей. В частности, "вы не можете видеть типы нажатий клавиш, которые используются для навигации. Подобно клавишам курсора и Tab, Escape и Enter для диалога".
-
Существует несколько способов перехвата ключевых событий, и все они происходят последовательно. KeyDown
обрабатывается последним. Следовательно, KeyPreview
не является большим количеством предварительного просмотра, и событие может быть отключено на несколько остановок на этом пути.
(кредит для @HansPassant для этих точек.)
Вместо этого переопределите ProcessCmdKey
в Form
:
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
if (keyData == Keys.Up)
{
// Handle key at form level.
// Do not send event to focused control by returning true.
return true;
}
return base.ProcessCmdKey(ref msg, keyData);
}
Таким образом, все ключи видны методу, и метод сначала находится в строке, чтобы увидеть событие.
Обратите внимание, что вы все еще имеете контроль над тем, контролировали ли сфокусированные элементы управления событие KeyDown
. Просто верните true
, чтобы заблокировать последующее событие KeyDown
, вместо установки KeyPressEventArgs.Handled
в true
, как это было бы в обработчике события KeyDown
. Здесь - статья с более подробной информацией.
Ответ 3
Попробуйте установить для свойства KeyPreview
в вашей форме значение true. Это работало для меня для регистрации нажатий клавиш.