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

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

Я создаю небольшую игру, игра печатается на панели в форме окна. Теперь я хочу захватить событие 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.

4b9b3361

Ответ 1


Переопределить поведение 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();
}

Ответ 2

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

Обновление:, чтобы это нормально работало, когда фокус Button кажется немного сложным. Элемент управления Button перехватывает клавишу со стрелкой и перемещает фокус на следующий или предыдущий элемент управления в порядке табуляции таким образом, чтобы события KeyDown, KeyUp и 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;
}

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

Ответ 3

Я считаю, что самый простой способ решить эту проблему - переопределить метод ProcessCmdKey() формы. Таким образом, ваша логика обработки ключей выполняется независимо от того, какой контроль имеет фокус во время нажатия клавиши. Кроме того, вы даже можете выбрать, будет ли сфокусированный элемент управления получать ключ после его обработки (return false) или нет (return 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);
}

Ответ 4

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        KeyPreview = true;
        KeyDown += new KeyEventHandler(Form1_KeyDown);
    }

    void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        System.Diagnostics.Debug.Write(e.KeyCode);
    }
}