Подтвердить что ты не робот

Формы, не отвечающие на события 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?

4b9b3361

Ответ 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. Это работало для меня для регистрации нажатий клавиш.