Клавиши со стрелками вверх, вниз, влево и вправо не вызывают событие KeyDown - PullRequest
66 голосов
/ 30 октября 2009

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

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

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

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

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

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

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

Ответы [ 10 ]

58 голосов
/ 19 октября 2011

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

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

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

56 голосов
/ 09 апреля 2011
    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;                
        }
    }
16 голосов
/ 24 января 2013

Я использую 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;
        }
    }
16 голосов
/ 30 октября 2009

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


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

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

2 голосов
/ 11 октября 2016

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

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

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

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

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

2 голосов
/ 30 октября 2009

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

0 голосов
/ 18 июня 2019
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);
}
0 голосов
/ 03 января 2017

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

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

0 голосов
/ 20 декабря 2014

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

Чтобы захватить нажатия клавиш в элементе управления 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 #

Вейн

...