C # пытается перехватить событие KeyDown в форме

Я создаю небольшую игру, игра печатается на панели в форме окна. Теперь я хочу захватить событие нажатия клавиш, чтобы увидеть, были ли нажаты клавиши со стрелками, однако проблема в том, что я могуКажется, я это понял.

Позвольте мне объяснить, в форме у меня есть 4 кнопки и различные другие элементы управления, и если пользователь, например, нажимает одну из кнопок (для запуска игрового события), то кнопка имеет фокус, и я могу 'захватить движения с помощью клавиш со стрелками.

Я пробовал что-то вроде

private void KeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Left)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.E);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Right)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.W);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Up)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.N);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Down)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.S);
            game.DrawObjects(panel1.CreateGraphics());
        }
    }

а затем, когда была нажата кнопка формы вниз, я использовал это

private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
        KeyDown(e);
    }

Я также добавил keydown для кнопок и различных других элементов управления в форме окна, но я не получаю никакого ответа. Я установил точку останова внутри функции, чтобы увидеть, если этоВызывается, но эта точка останова никогда не срабатывает?

Есть идеи?

Наиболее оптимальным было иметь общее событие KeyDown, которое запускается (независимо от того, какой элемент управления в данный момент имеет фокус), а затем вызывает метод KeyDown.

Ответы на вопрос(3)

KeyPreview свойство формы дляtrue? Это заставит форму получить "Первый взгляд" на ключевых событиях.

Обновить: заставить это работать правильно, когдаButton имеет фокус, кажется, немного сложнее. Элемент управления Button перехватывает нажатия клавиш со стрелками и перемещает фокус на следующий или предыдущий элемент управления в порядке вкладок таким образом, чтобыKeyDownKeyUp а такжеKeyPress события не поднимаются. Тем не менееPreviewKeyDown событие инициируется, так что можно использовать:

private void Form_KeyDown(object sender, KeyEventArgs e)
{
    e.Handled = ProcessKeyDown(e.KeyCode);
}

// event handler for the PreViewKeyDown event for the buttons
private void ArrowButton_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
    ProcessKeyDown(e.KeyCode);

}

private bool ProcessKeyDown(Keys keyCode)
{
    switch (keyCode)
    {
        case Keys.Up:
            {
                // act on up arrow
                return true;
            }
        case Keys.Down:
            {
                // act on down arrow
                return true;
            }
        case Keys.Left:
            {
                // act on left arrow
                return true;
            }
        case Keys.Right:
            {
                // act on right arrow
                return true;
            }
    }
    return false;
}

Тем не менее, фокус перемещается довольно уродливо ...

 Fredrik Mörk19 авг. 2009 г., 14:56
@ Патрик: да, у клавиш со стрелками и кнопки управления, похоже, очень тесные отношения. Я обновил свой ответ, делая шаг вперед.
 Patrick19 авг. 2009 г., 12:03
Это'С полуработкой, теперь я получаю событие нажатия клавиш, но когда я нажимаю кнопки, они все еще становятся сфокусированными, и затем он перестает работать, пока я не нажму верхнюю клавишу со стрелкой, пока она не пройдет через все их, и они не потеряют фокус.
Решение Вопроса

IsInputKey поведение

Вы должны переопределитьIsInputKey поведение, информирующее о том, что вы хотите, чтобы клавиша со стрелкой вправо рассматривалась как InputKey, а не как специальная клавиша поведения. Для этого вы должны переопределить метод для каждого из ваших элементов управления. Я бы посоветовал вам создать ваши выигранные кнопки, давайтескажиMyButton

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

    public partial class MyButton : Button
    {
        protected override bool IsInputKey(Keys keyData)
        {
            if (keyData == Keys.Right)
            {
                return true;
            }
            else
            {
                return base.IsInputKey(keyData);
            }
        }
    }

После этого вы можете обработать событие события keyDown в каждой отдельной кнопке или в самой форме:

В пуговицах Метод KeyDown попытайтесь установить эти свойства:

private void myButton1_KeyDown(object sender, KeyEventArgs e)
{
  e.Handled = true;
  //DoSomething();
}

-- ИЛИ ЖЕ --

обрабатывать обычное поведение в форме: (не устанавливатьe.Handled = true; в кнопках)

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    //DoSomething();
}
 Luis Filipe19 авг. 2009 г., 15:23
Как вы ловитеKeys.Left» а также "Keys.Right» События KeyDown?
 bentsai30 сент. 2010 г., 21:34
Это все еще говорит "UseInputKey».
 Luis Filipe19 авг. 2009 г., 15:44
Я отредактировал свой ответ для ссылки на метод IsInputKey
 Luis Filipe26 нояб. 2010 г., 16:43
@bentsai: спасибо .. каким-то образом я могуне исправить их все .. тамs всегда один отсутствует :)
 Patrick19 авг. 2009 г., 12:46
Это'С полуработкой, теперь я получаю событие нажатия клавиш, но когда я нажимаю кнопки, они все еще становятся сфокусированными, и затем он перестает работать, пока я не нажму верхнюю клавишу со стрелкой, пока она не пройдет через все их, и они не потеряют фокус.

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

Ваш маленький игровой пример можно переписать так:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.Left)
    {
        MoveLeft(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Right)
    {
        MoveRight(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Up)
    {
        MoveUp(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Down)
    {
        MoveDown(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else
        return base.ProcessCmdKey(ref msg, keyData);
}
 Singlet20 янв. 2011 г., 13:05
Это'отлично, но клавиша пробела не обрабатывается
 Kibbee08 июл. 2011 г., 04:20
Отличное решение. Захватывает все нажатия клавиш. Даже Космос.
 Dean Seo07 янв. 2014 г., 09:36
Это самый простой способ решения этих проблем, и он отлично сработал для меня.

Ваш ответ на вопрос