首页 文章

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

提问于
浏览
62

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

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

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

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

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

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

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

9 回答

  • 2

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

  • 0
    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;                
            }
        }
    
  • 51

    我有同样的问题,并已在选定的答案中使用代码 . 这个链接是我的答案;也许对其他人也是 .

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

  • 15

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

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

    但是,将窗口显示为 dialog ,它可以工作

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

    希望这可以帮助 .

  • 55

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

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

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

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

  • 2

    请参阅Rodolfo Neuber's reply以获得最佳答案


    (我原来的答案):

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

  • 15

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

    • 正如@Snarfblam所说,你 can override the ProcessCmdKey method ,它保留了解析箭头按键的能力 .

    • 作为the accepted answer from this question状态,XNA有一个名为Keyboard.GetState()的内置方法,它允许您使用箭头键输入 . 但是,WinForms没有这个,但 it can be done through a P/Invokeby 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事件结合使用,我认为您可以可靠地实现目标 .

相关问题