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

Клавиши "Вверх", "Вниз", "Влево" и "Вправо" не запускают событие KeyDown

Я создаю приложение, в котором все входные данные ключа должны обрабатываться самими окнами.

Я устанавливаю tabstop в false для каждого элемента управления, который может захватить фокус, кроме панели (но я не знаю, имеет ли он эффект).

Я устанавливаю KeyPreview в true, и я обрабатываю событие KeyDown в этой форме.

Моя проблема в том, что иногда клавиша со стрелками больше не реагирует:

  • Событие keydown не запускается, когда я нажимаю только клавишу со стрелкой.

  • Событие keydown запускается, если я нажимаю клавишу со стрелкой с помощью модификатора элемента управления.

У вас есть идея, почему моя стрелочная клавиша внезапно прекращает стрельбу?

4b9b3361

Ответ 1

    protected override bool IsInputKey(Keys keyData)
    {
        switch (keyData)
        {
            case Keys.Right:
            case Keys.Left:
            case Keys.Up:
            case Keys.Down:
                return true;
            case Keys.Shift | Keys.Right:
            case Keys.Shift | Keys.Left:
            case Keys.Shift | Keys.Up:
            case Keys.Shift | Keys.Down:
                return true;
        }
        return base.IsInputKey(keyData);
    }
    protected override void OnKeyDown(KeyEventArgs e)
    {
        base.OnKeyDown(e);
        switch (e.KeyCode)
        {
            case Keys.Left:
            case Keys.Right:
            case Keys.Up:
            case Keys.Down:
                if (e.Shift)
                {

                }
                else
                {
                }
                break;                
        }
    }

Ответ 2

У меня была такая же проблема. Я рассмотрел ответ @Snarfblam; однако, если вы прочитали документацию в MSDN, метод ProcessCMDKey предназначен для переопределения ключевых событий для пунктов меню в приложении.

Недавно я наткнулся на эту статью от Microsoft, которая выглядит довольно многообещающе: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx. Согласно microsoft, лучше всего установить e.IsInputKey=true; в событии PreviewKeyDown после обнаружения клавиш со стрелками. Это приведет к срабатыванию события KeyDown.

Это работало довольно хорошо для меня и было менее хакерским, чем переопределение ProcessCMDKey.

Ответ 3

См Родольфо Нойбер ответ для лучшего ответа


(Мой оригинальный ответ):

Получите из класса управления, и вы можете переопределить метод ProcessCmdKey. Microsoft решила исключить эти ключи из событий KeyDown, поскольку они влияют на несколько элементов управления и перемещают фокус, но это очень затрудняет реакцию приложения на эти клавиши любым другим способом.

Ответ 4

Я использую PreviewKeyDown

    private void _calendar_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e){
        switch (e.KeyCode){
            case Keys.Down:
            case Keys.Right:
                //action
                break;
            case Keys.Up:
            case Keys.Left:
                //action
                break;
        }
    }

Ответ 5

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

  • Как указано в @Snarfblam, вы можете переопределить метод ProcessCmdKey, который сохраняет возможность разбора нажатий клавиш со стрелками.
  • Как принятый ответ из этого вопроса говорится, что XNA имеет встроенный метод Keyboard.GetState(), который позволяет использовать входы со стрелкой. Однако WinForms этого не имеет, но это можно сделать с помощью P/Invoke или с помощью с помощью класс, который помогает с ним.

Я рекомендую попробовать использовать этот класс. Это довольно просто:

var left = KeyboardInfo.GetKeyState(Keys.Left);
var right = KeyboardInfo.GetKeyState(Keys.Right);
var up = KeyboardInfo.GetKeyState(Keys.Up);
var down = KeyboardInfo.GetKeyState(Keys.Down);

if (left.IsPressed)
{
//do something...
}

//etc...

Если вы используете это в сочетании с событием KeyDown, я думаю, вы можете надежно выполнить свою цель.

Ответ 6

У меня была аналогичная проблема при вызове окна WPF из WinForms.

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.Show();

Однако, показывая окно как диалог , он работал

var wpfwindow = new ScreenBoardWPF.IzbiraProjekti();
    ElementHost.EnableModelessKeyboardInterop(wpfwindow);
    wpfwindow.ShowDialog();

Надеюсь, что это поможет.

Ответ 7

Чтобы зафиксировать нажатия клавиш в элементе управления Forms, вы должны получить новый класс, основанный на классе элемента управления, который вы хотите, и вы переопределите ProcessCmdKey().

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //handle your keys here
}

Пример:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    //capture up arrow key
    if (keyData == Keys.Up )
    {
        MessageBox.Show("You pressed Up arrow key");
        return true;
    }

    return base.ProcessCmdKey(ref msg, keyData);
}

Полный источник... Клавиши со стрелками на С#

Вейн

Ответ 8

Лучший способ сделать, я думаю, - это обработать его, как сказал MSDN http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx

Но справитесь с этим, как вам это действительно нужно. Мой способ (в приведенном ниже примере) - поймать каждый KeyDown; -)

    /// <summary>
    /// onPreviewKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnPreviewKeyDown(PreviewKeyDownEventArgs e)
    {
        e.IsInputKey = true;
    }

    /// <summary>
    /// onKeyDown
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyDown(KeyEventArgs e)
    {
        Input.SetFlag(e.KeyCode);
        e.Handled = true;
    }

    /// <summary>
    /// onKeyUp
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyUp(KeyEventArgs e)
    {
        Input.RemoveFlag(e.KeyCode);
        e.Handled = true;
    }

Ответ 10

protected override bool IsInputKey(Keys keyData)
{
    if (((keyData & Keys.Up) == Keys.Up)
        || ((keyData & Keys.Down) == Keys.Down)
        || ((keyData & Keys.Left) == Keys.Left)
        || ((keyData & Keys.Right) == Keys.Right))
        return true;
    else
        return base.IsInputKey(keyData);
}