向上,向下,向左和向右箭头键不会触发KeyDown事件

时间:2009-10-29 22:36:48

标签: c# winforms keydown

我正在构建一个应用程序,其中所有键输入必须由Windows本身处理。

我将tabstop设置为false,因为除了面板之外,每个控件都可以抓住焦点(但我不知道它是否有效)。

我将KeyPreview设置为true,我正在处理此表单上的KeyDown事件。

我的问题是,有时箭头键不再响应:

  • 仅按箭头键时不会触发keydown事件。

  • 如果我按下带有控制修饰符的箭头键,就会触发keydown事件。

你知道我的箭头键突然停止发射事件的原因吗?

10 个答案:

答案 0 :(得分:56)

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

答案 1 :(得分:56)

我遇到了完全相同的问题。我考虑了@Snarfblam提供的答案;但是,如果您阅读MSDN上的文档,则ProcessCMDKey方法将覆盖应用程序中菜单项的关键事件。

我最近偶然发现了微软的这篇文章,看起来很有希望:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx。根据微软的说法,最好的办法是在检测到箭头键后在e.IsInputKey=true;事件中设置PreviewKeyDown。这样做会触发KeyDown事件。

这对我来说效果很好,并且比重写ProcessCMDKey要少得多。

答案 2 :(得分:16)

有关最佳答案,请参阅Rodolfo Neuber's reply


(我原来的答案):

从控件类派生,您可以覆盖ProcessCmdKey方法。 Microsoft选择从KeyDown事件中省略这些键,因为它们影响多个控件并移动焦点,但这使得应用程序很难以任何其他方式对这些键做出反应。

答案 3 :(得分:16)

我正在使用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;
        }
    }

答案 4 :(得分:2)

不幸的是,由于KeyDown事件的限制,使用箭头键完成此操作非常困难。但是,有几种方法可以解决这个问题:

  • 正如@Snarfblam所述,您可以覆盖ProcessCmdKey方法,它保留了解析箭头键按下的功能。
  • 作为the accepted answer from this question状态,XNA有一个名为 Keyboard.GetState()的内置方法,它允许您使用箭头键输入。但是,WinForms没有这个,但可以通过P / Invoke 完成,或者可以通过using a class that helps with it 完成。

我建议尝试使用该课程。这样做非常简单:

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事件结合使用,我认为您可以可靠地实现目标。

答案 5 :(得分:2)

从WinForms调用WPF窗口时,我遇到了类似的问题。

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

但是,将窗口显示为对话框,它可以正常工作

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

希望这有帮助。

答案 6 :(得分:0)

为了捕获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);
}

完整来源...... Arrow keys in C#

Vayne

答案 7 :(得分:0)

我认为最好的办法就是像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;
    }

答案 8 :(得分:0)

我遇到了同样的问题,并且已经在所选答案中使用了代码。这个链接是我的答案;也许对其他人来说。

How to disable navigation on WinForm with arrows in C#?

答案 9 :(得分:0)

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