C# 试图捕获窗体上的 KeyDown 事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1298640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C# trying to capture the KeyDown event on a form
提问by Patrick
I am creating a small game, the game is printed onto a panel on a windows form. Now i want to capture the keydown event to see if its the arrow keys that has been pressed, the problem however is that i can't seem to capture it.
我正在创建一个小游戏,该游戏被打印到 Windows 窗体的面板上。现在我想捕获 keydown 事件以查看它是否已按下箭头键,但问题是我似乎无法捕获它。
Let me explain, on the form i have 4 buttons and various other controls and if the user for instance press one of the buttons (to trigger a game event) then the button has focus and i can't capture the movements with the arrow keys.
让我解释一下,在表单上我有 4 个按钮和各种其他控件,例如,如果用户按下其中一个按钮(以触发游戏事件),则该按钮具有焦点,我无法使用箭头键捕获移动.
I tried something like
我试过类似的东西
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());
}
}
and then when the form key down event was pressed, i used this
然后当按下表单键事件时,我使用了这个
private void MainForm_KeyDown(object sender, KeyEventArgs e)
{
KeyDown(e);
}
I also added keydown for the buttons and the various other controls on the windows form, but i am not getting any response back. I have setup a breakpoint inside the function to see if it's being called, but that breakpoint never triggers?
我还为 Windows 窗体上的按钮和各种其他控件添加了 keydown,但我没有得到任何响应。我在函数内部设置了一个断点以查看它是否被调用,但该断点永远不会触发?
Any ideas?
有任何想法吗?
The most optimal was to have a general KeyDown event that triggers (regardless of what control that currently has focus) and then calls the KeyDown method.
最理想的方法是有一个通用的 KeyDown 事件来触发(无论当前具有焦点的控件是什么),然后调用 KeyDown 方法。
采纳答案by Luis Filipe
Override IsInputKeybehaviour
覆盖IsInputKey行为
You must override the IsInputKeybehavior to inform that you want the Right Arrow key to be treated as an InputKey and not as a special behavior key. For that you must override the method for each of your controls. I would advise you to create your won Buttons, let's say MyButton
您必须覆盖IsInputKey行为以通知您希望将右箭头键视为 InputKey 而不是特殊行为键。为此,您必须覆盖每个控件的方法。我建议你创建你赢得的按钮,比如MyButton
The class below creates a custom Button that overrides the IsInputKeymethod so that the right arrow key is not treated as a special key. From there you can easily make it for the other arrow keys or anything else.
下面的类创建一个覆盖IsInputKey方法的自定义 Button,这样右箭头键就不会被视为特殊键。从那里您可以轻松地为其他箭头键或其他任何东西制作它。
public partial class MyButton : Button
{
protected override bool IsInputKey(Keys keyData)
{
if (keyData == Keys.Right)
{
return true;
}
else
{
return base.IsInputKey(keyData);
}
}
}
Afterwards, you can treat your keyDown event event in each different Button or in the form itself:
之后,您可以在每个不同的 Button 或表单本身中处理您的 keyDown 事件事件:
In the Buttons' KeyDown Method try to set these properties:
在按钮的 KeyDown 方法中尝试设置这些属性:
private void myButton1_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
//DoSomething();
}
-- OR --
- 或者 -
handle the common behaviour in the form: (do not set e.Handled = true;in the buttons)
处理表单中的常见行为:(不要在按钮中设置e.Handled = true;)
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
//DoSomething();
}
回答by Fredrik M?rk
Have you set the KeyPreview
property of the form to true
? That will cause the form to get a "first look" at key events.
您是否将KeyPreview
表单的属性设置为true
?这将导致表单对关键事件进行“第一次查看”。
Update:getting this to work properly when a Button
has focus seems to be a bit tricky. The Button control intercepts the arrow key presses and moves focus to the next or previous control in the tab order in a manner so that the KeyDown
, KeyUp
and KeyPress
events are not raised. However, the PreviewKeyDown
event is raised, so that can be used:
更新:当Button
有焦点时让它正常工作似乎有点棘手。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;
}
Still, the focus moves around in a rather ugly manner...
尽管如此,焦点以一种相当丑陋的方式移动......
回答by dnkira
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);
}
}
回答by RudolfW
I believe the easiest way of solving this problem is through overriding the ProcessCmdKey() method of the form. That way, your key handling logic gets executed no matter what control has focus at the time of keypress. Beside that, you even get to choose whether the focused control gets the key after you processed it (return false) or not (return true).
Your little game example could be rewritten like this:
我相信解决这个问题的最简单方法是通过覆盖表单的 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);
}