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

发布于 2025-01-16 12:28:36 字数 315 浏览 11 评论 0原文

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

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

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

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

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

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

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

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

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

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

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

零崎曲识 2025-01-23 12:28:36

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

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

这对我来说非常有效,并且比覆盖 ProcessCMDKey 更不那么黑客化。

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.

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 PreviewKeyDown event after detecting the arrow keys. Doing so will fire the KeyDown event.

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

楠木可依 2025-01-23 12:28:36
    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;                
        }
    }
    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;                
        }
    }
浅笑轻吟梦一曲 2025-01-23 12:28:36

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

I'm using 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;
        }
    }
压抑⊿情绪 2025-01-23 12:28:36

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


(我的原始答案):

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

See Rodolfo Neuber's reply for the best answer


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

温柔女人霸气范 2025-01-23 12:28:36

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

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:

  • As @Snarfblam stated, you can override the ProcessCmdKey method, which retains the ability to parse arrow key presses.
  • As the accepted answer from this question states, 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.

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.

葬﹪忆之殇 2025-01-23 12:28:36

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

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

但是,将窗口显示为对话框,它有效

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

希望这会有所帮助。

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

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.

地狱即天堂 2025-01-23 12:28:36

为了捕获 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# 中的箭头键

Vayne

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

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#

Vayne

謌踐踏愛綪 2025-01-23 12:28:36
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);
}
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);
}
葵雨 2025-01-23 12:28:36

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

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

But handle it, how you really need it. My way (in the example below) is to catch every 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;
    }
心病无药医 2025-01-23 12:28:36

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

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

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#?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文