C#试图捕获表单上的KeyDown事件

Pat*_*ick 25 c# capture keydown winforms

我正在创建一个小游戏,游戏被打印到Windows窗体上的面板上.现在我想捕获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());
        }
    }
Run Code Online (Sandbox Code Playgroud)

然后当按下表单按键事件时,我使用了这个

private void MainForm_KeyDown(object sender, KeyEventArgs e)
    {
        KeyDown(e);
    }
Run Code Online (Sandbox Code Playgroud)

我还为Windows窗体上的按钮和各种其他控件添加了keydown,但我没有收到任何回复.我在函数内部设置了一个断点,看它是否被调用,但该断点永远不会触发?

有任何想法吗?

最优化的是具有触发的通用KeyDown事件(无论当前具有什么焦点的控件),然后调用KeyDown方法.

Fre*_*örk 29

您是否将KeyPreview表单的属性设置为true?这将使表单在关键事件中获得"第一眼".

更新:Button有焦点时让它正常工作似乎有点棘手.按钮控件截取的箭头按键和焦点移动到在标签顺序的下一个或前一控制的方式使得KeyDown,KeyUpKeyPress事件不升高.但是,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;
}
Run Code Online (Sandbox Code Playgroud)

尽管如此,焦点却以一种相当丑陋的方式移动......


Lui*_*ipe 17


覆盖IsInputKey行为


您必须覆盖IsInputKey行为,以通知您希望将右箭头键视为InputKey而不是特殊行为键.为此,您必须覆盖每个控件的方法.我建议你创建你赢得的按钮,让我们说MyButton

下面的类创建一个自定义Button,它覆盖IsInputKey方法,因此右箭头键不会被视为特殊键.从那里你可以轻松地为其他箭头键或其他任何东西.

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

之后,您可以在每个不同的Button或表单本身中处理您的keyDown事件事件:

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

private void myButton1_KeyDown(object sender, KeyEventArgs e)
{
  e.Handled = true;
  //DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

- 要么 -

处理表单中的常见行为:(不要设置e.Handled = true;在按钮中)

private void Form1_KeyDown(object sender, KeyEventArgs e)
{
    //DoSomething();
}
Run Code Online (Sandbox Code Playgroud)


Rud*_*lfW 17

我认为解决此问题的最简单方法是重写表单的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);
}
Run Code Online (Sandbox Code Playgroud)

  • 好的解决方案 捕获所有按键.甚至空间. (2认同)

dnk*_*ira 7

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);
    }
}
Run Code Online (Sandbox Code Playgroud)