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


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

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

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

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

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

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

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

9 61

9 ответов:

    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;                
        }
    }

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

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

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

Я использую 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;
        }
    }

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


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

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

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

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

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

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, я думаю, что вы можете надежно достичь своей цели.

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

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

однако, показывая окно как

для захвата нажатий клавиш в элементе управления 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);
}

полный источник...клавиши со стрелками в C#

Вейн

лучший способ сделать, я думаю, это справиться с этим, как сказал 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;
    }

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

Как отключить навигацию на WinForm со стрелками в C#?