C# 上、下、左、右方向键不会触发 KeyDown 事件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1646998/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 19:40:04  来源:igfitidea点击:

Up, Down, Left and Right arrow keys do not trigger KeyDown event

c#winformskeydown

提问by Martin Delille

I am building an application where all the key input must be handled by the windows itself.

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

I set tabstop to false for each control witch could grab the focus except a panel (but I don't know if it has effect).

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

I set KeyPreview to true and I am handling the KeyDown event on this form.

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

My problem is that sometimes the arrow key aren't responsive anymore:

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

  • The keydown event is not fired when I pressed only an arrow key.

  • The keydown event is fired if I press an arrow key with the control modifier.

  • 当我只按下一个箭头键时,不会触发 keydown 事件。

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

Have you an idea why my arrow key suddenly stop firing event?

你知道为什么我的箭头键突然停止触发事件吗?

采纳答案by alpha

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

回答by snarf

See Rodolfo Neuber's replyfor the best answer

请参阅Rodolfo Neuber 的回复以获得最佳答案



(My original answer):

(我原来的回答):

Derive from a control class and you can override the ProcessCmdKey method. Microsoft chose to omit these keys from KeyDown events because they affect multiple controls and move the focus, but this makes it very difficult to make an app react to these keys in any other way.

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

回答by Maxim Zaslavsky

Unfortunately, it is quite difficult to accomplish this with the arrow keys, due to restrictions in KeyDown events. However, there are a few ways to get around this:

不幸的是,由于 KeyDown 事件的限制,使用箭头键很难做到这一点。但是,有几种方法可以解决这个问题:

  • As @Snarfblam stated, you can override the ProcessCmdKey method, which retains the ability to parse arrow key presses.
  • As the accepted answer from this questionstates, XNA has a built-in method called Keyboard.GetState(), which allows you to use arrow key inputs. However, WinForms doesn't have this, but it can be done through a P/Invoke, or by using a class that helps with it.
  • 正如@Snarfblam 所说,您可以覆盖 ProcessCmdKey 方法,该方法保留了解析箭头键按下的能力。
  • 正如这个问题的公认答案所述,XNA 有一个名为Keyboard.GetState()的内置方法,它允许您使用箭头键输入。然而,的WinForms没有这一点,但它可以通过一个的P / Invoke来完成,或者通过使用一个类与它帮助

I recommend trying to use that class. It's quite simple to do so:

我建议尝试使用该类。这样做很简单:

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...

If you use this in combination with the KeyDown event, I think you can reliably accomplish your goal.

如果您将它与 KeyDown 事件结合使用,我认为您可以可靠地实现您的目标。

回答by Rodolfo Neuber

I was having the exact same problem. I considered the answer @Snarfblam provided; however, if you read the documentation on MSDN, the ProcessCMDKey method is meant to override key events for menu items in an application.

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

I recently stumbled across this article from microsoft, which looks quite promising: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx. According to microsoft, the best thing to do is set e.IsInputKey=true;in the PreviewKeyDownevent after detecting the arrow keys. Doing so will fire the KeyDownevent.

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

This worked quite well for me and was less hack-ish than overriding the ProcessCMDKey.

这对我来说效果很好,而且比覆盖 ProcessCMDKey 更不那么黑客化。

回答by Marcel

I'm using PreviewKeyDown

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

回答by vaynenick

In order to capture keystrokes in a Forms control, you must derive a new class that is based on the class of the control that you want, and you override the ProcessCmdKey().

为了在 Forms 控件中捕获击键,您必须派生一个基于所需控件类的新类,并覆盖 ProcessCmdKey()。

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

Example :

例子 :

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

Full source...Arrow keys in C#

完整源代码... C# 中的箭头键

Vayne

薇恩

回答by Marcus.D

The best way to do, I think, is to handle it like the MSDN said on http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx

我认为最好的方法是像 MSDN 在http://msdn.microsoft.com/en-us/library/system.windows.forms.control.previewkeydown.aspx 上所说的那样处理它

But handle it, how you really need it. My way (in the example below) is to catch every KeyDown ;-)

但是处理它,你真的需要它。我的方法(在下面的示例中)是捕获每个 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;
    }

回答by Janez Krnc

I had a similar issue when calling the WPF window out of WinForms.

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

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

However, showing window as a dialog, it worked

但是,将窗口显示为对话框,它起作用了

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

Hope this helps.

希望这可以帮助。

回答by 4mla1fn

i had the same problem and was already using the code in the selected answer. this link was the answer for me; maybe for others also.

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

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

如何在 C# 中使用箭头禁用 WinForm 上的导航?

回答by google dev

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