我正在创建一个小游戏,游戏被打印到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());
}
}
然后当按下表单按键事件时,我使用了这个
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
KeyDown(e);
}
我还为Windows窗体上的按钮和各种其他控件添加了keydown,但我没有收到任何回复。我在函数内部设置了一个断点,看它是否被调用,但该断点永远不会触发?
有什么想法吗?
最优化的是触发一般的KeyDown事件(无论当前有什么焦点控制),然后调用KeyDown方法。
答案 0 :(得分:29)
您是否已将表单的KeyPreview
属性设置为true
?这将使表格在关键事件中得到“第一眼”。
更新:当Button
具有焦点时,使其正常工作似乎有点棘手。按钮控件截取箭头键,并以一种方式将焦点移动到Tab键顺序中的下一个或上一个控件,以便不会引发KeyDown
,KeyUp
和KeyPress
事件。但是,会引发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;
}
然而,焦点仍然以一种相当丑陋的方式移动......
答案 1 :(得分: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);
}
}
}
之后,您可以在每个不同的Button或表单中处理您的keyDown事件事件:
在按钮的KeyDown方法中尝试设置这些属性:
private void myButton1_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
//DoSomething();
}
- 或 -
处理表单中的常见行为:(不要在按钮中设置 e.Handled = true; )
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//DoSomething();
}
答案 2 :(得分: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);
}
答案 3 :(得分: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);
}
}