C#试图捕获KeyDown事件在窗体上(C# trying to capture the KeyDo

2019-07-01 11:32发布

我创建一个小游戏,游戏被印刷到一个视窗形式的面板。 现在我想捕捉的keydown事件,看看它已按下方向键,问题不过是,我似乎无法捕捉到它。

让我来解释一下,在表单上我有4个按钮和其他各种控制和举例来说如果按用户的一个按钮(触发游戏事件),则该按钮具有焦点,我不能捕获使用箭头键动作。

我想是这样

private void KeyDown(KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Left)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.E);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Right)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.W);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Up)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.N);
            game.DrawObjects(panel1.CreateGraphics());
        }
        else if (e.KeyCode == Keys.Down)
        {
            game.MovePlayer(DonutWarsLibrary.GameObjects.Direction.S);
            game.DrawObjects(panel1.CreateGraphics());
        }
    }

然后按下形式键按下事件的时候,我用这个

private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
        KeyDown(e);
    }

我还添加了的keydown的按钮和Windows窗体上的其他各种控制,但我没有得到任何回应了。 我已经安装的功能中的断点,看它是否被呼叫,但从来没有断点触发?

有任何想法吗?

最理想的是有一个一般的KeyDown事件触发(无论当前聚焦什么控制的),然后调用的KeyDown方法。

Answer 1:


覆盖IsInputKey行为


您必须重写IsInputKey行为告知对方您想要的右箭头键被视为InputKey,而不是作为一种特殊的行为的关键。 对于您必须重写为每个控件的方法。 我会建议你创建你赢了按钮,让我们说myButton的

下面的类创建了覆盖IsInputKey方法使右箭头键没有作为一个特殊的键处理自定义按钮。 从那里,你可以很容易地使它成为其他箭头键或其他任何东西。

    public partial class MyButton : Button
    {
        protected override bool IsInputKey(Keys keyData)
        {
            if (keyData == Keys.Right)
            {
                return true;
            }
            else
            {
                return base.IsInputKey(keyData);
            }
        }
    }

之后,你可以在每个不同的按钮或在窗体本身对待你的keyDown事件的事件:

在按钮的KeyDown方法尝试设置这些属性:

private void myButton1_KeyDown(object sender, KeyEventArgs e)
{
  e.Handled = true;
  //DoSomething();
}

- 要么 -

处理共同行为的形式:(不设置e.Handled =真;在按钮)

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    //DoSomething();
}


Answer 2:

您在设定KeyPreview形式的属性为true ? 这将导致形式获得“先看看”在关键事件。

更新:得到这个当正常工作Button具有焦点似乎是有点棘手。 按钮控件截取的箭头按键和焦点移动到在标签顺序的下一个或前一控制的方式,以使KeyDownKeyUpKeyPress事件不被引发。 然而, PreviewKeyDown事件引发的,所以可以使用:

private void Form_KeyDown(object sender, KeyEventArgs e)
{
    e.Handled = ProcessKeyDown(e.KeyCode);
}

// event handler for the PreViewKeyDown event for the buttons
private void ArrowButton_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
    ProcessKeyDown(e.KeyCode);

}

private bool ProcessKeyDown(Keys keyCode)
{
    switch (keyCode)
    {
        case Keys.Up:
            {
                // act on up arrow
                return true;
            }
        case Keys.Down:
            {
                // act on down arrow
                return true;
            }
        case Keys.Left:
            {
                // act on left arrow
                return true;
            }
        case Keys.Right:
            {
                // act on right arrow
                return true;
            }
    }
    return false;
}

不过,重点围绕移动在相当丑陋的方式...



Answer 3:

我认为,解决这个问题的最简单的方法就是通过覆盖表单的给ProcessCmdKey()方法。 这样一来,你的关键处理逻辑被无论怎样控制已集中在按键时执行。 旁边的是,你甚至可以选择聚焦控制是否得到钥匙你处理之后(返回false)否(返回true)。
你的小游戏例子可以改写如下:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.Left)
    {
        MoveLeft(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Right)
    {
        MoveRight(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Up)
    {
        MoveUp(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else if (keyData == Keys.Down)
    {
        MoveDown(); DrawGame(); DoWhatever();
        return true; //for the active control to see the keypress, return false
    }
    else
        return base.ProcessCmdKey(ref msg, keyData);
}


Answer 4:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
        KeyPreview = true;
        KeyDown += new KeyEventHandler(Form1_KeyDown);
    }

    void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        System.Diagnostics.Debug.Write(e.KeyCode);
    }
}


文章来源: C# trying to capture the KeyDown event on a form