KeyDown事件没有触发?

时间:2013-02-26 14:14:08

标签: c# winforms events keydown onkeydown

编写小游戏时遇到了问题;我的表单的KeyDownKeyUp事件根本不会触发。

这是表格的代码:

public class GameForm : Form
{
    private ControllableBlock player;

    public GameForm()
    {
        KeyDown += Game_KeyDown;
        KeyUp += Game_KeyUp;

        player = new ControllableBlock();
        Controls.Add(player);
    }

    private void Game_KeyDown(object sender, KeyEventArgs e)
    {
        player.ReactToKey(e.KeyCode);
    }

    private void Game_KeyUp(object sender, KeyEventArgs e)
    {
        player.ReactToKey(e.KeyCode);
    }
}

还有很多事情要发生,但我只粘贴相关代码。

我已尝试设置this.KeyPreview = true;并致电this.Focus();,但都无效。 问题不在ReactToKey()方法中,我已经在那里设置了断点,事件永远不会被触发。


编辑:经过一些测试后,我得出结论,问题出在我的ControllableBlock范围内。 然而,我不知道为什么,但我正在研究它。 如果我注释掉与player相关的所有内容,则事件会开始触发。


编辑2:似乎问题是我从ControllableBlock继承了Control。 如果我从Panel继承它,它可以正常工作。 这是为什么? 如果我从控件继承,我不能激活一个事件吗? ControllableBlock类暂时为空,因此除了从Control继承之外,它甚至都不做任何事情。


编辑3:既然我已经开始了赏金,我想澄清一下,我不是在寻找一个如何解决事件的解决方案,我正在寻找如果我继承Control,他们为什么不解雇的原因。

4 个答案:

答案 0 :(得分:4)

如果您的活动应该是应用程序范围的,请尝试将属性KeyPreview设置为true - 它将允许您触发相应的事件,无论集中控制如何。

this.KeyPreview = true;

否则,您应该将这些事件直接附加到将要处理它们的控件上。

修改

我从表单中删除了InitializeComponent();并获得了与您相同的行为。

在实施this问题中提供的解决方案之后,所有事件都开始完全正常 复制代码段:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
        if (keyData == Keys.Left) {
            // Do your staff for Left Key here

            return true;
        }
        // you need to add if condition to every direction you want to handle
        return base.ProcessCmdKey(ref msg, keyData);
    }

答案 1 :(得分:3)

我能够重现一个类似的问题(希望是相关的......)

说明:

  • 控制哪些返回CanSelect==true可用于键盘输入
  • Control()的空白后代是可选的,Panel()中的一个不是
  • 添加到表单的第一个可选控件将被选中
  • 默认情况下,所选控件将从其父级中窃取键盘事件
  • 窗口内用于导航的某些键需要额外的步骤才能处理

检查here,了解Windows键盘输入的工作原理。

重现它的代码:

public class GameForm : Form
{
    public GameForm()
    {
        this.KeyDown += Game_KeyDown;
        var tests = new List<Control[]>() { 
            new[] { new Panel() },
            new[] { new Panel(), new Panel() },
            new[] { new Control() },
            new[] { new Control(), new Panel() },
            new[] { new Panel(), new Control() }
        };
        // When test index 2 to 4 used, keyboard input does not reach form level
        Controls.AddRange(tests[0]);            
        // When uncommented, ensures all keyboard input reaches form level
        /*this.KeyPreview = true;              
        // Additional plumbing required along with KeyPreview to allow arrow and other reserved keys
        foreach (Control control in this.Controls)
        {
            control.PreviewKeyDown += control_PreviewKeyDown;
        }*/
    }
    void control_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
    {
        e.IsInputKey = true;
    }
    private void Game_KeyDown(object sender, KeyEventArgs e)
    {
        // breakpoint here
        Debug.WriteLine(e.KeyCode);
    }
}

答案 2 :(得分:0)

尝试将处理程序设置移动到Form_Load事件而不是构造函数。是否应该在构造函数中调用Initialize()?我不特别建议删除它

如果ControllableBlock继承自Panel,它将具有比基本Control对象更多的事件连接和更好的UI交互设置。

答案 3 :(得分:0)

您需要先控制您的控件才能获得焦点。

尝试将以下内容添加到构造函数中:

this.SetStyle(ControlStyles.Selectable, true);

确保在显示后重点关注表单。或者,重写OnMouseDown()并在其中调用this.Focus()。