[英]KeyDown event not firing?
在编写小型游戏时,我遇到了问题。 我的窗体的KeyDown
和KeyUp
事件根本不会触发。
这是表单的代码:
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:似乎问题出在我从Control
继承了ControllableBlock
。 如果我从Panel
继承它,它将正常工作。 为什么是这样? 如果我从控件继承,就不能触发事件? ControllableBlock
类目前为空,因此除了继承Control
之外,它甚至不做任何其他事情。
编辑3:既然我已经开始了赏金计划,我想澄清一下,我不是在寻找使事件触发的解决方案,而是在寻找为什么事件不会触发的原因我继承自Control
。
如果您的事件应在整个应用程序范围内,请尝试将属性KeyPreview
设置为true
,这将使您可以触发各个事件,而无需进行集中控制。
this.KeyPreview = true;
否则,您应该将这些事件直接附加到将处理这些事件的控件上。
编辑:
我删除了InitializeComponent();
从我的表单中获得的行为与您的行为相同。
实施此问题提供的解决方案后,所有事件开始完美地响起来。
在此处复制代码段:
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);
}
我能够重现类似的问题(希望是相关的。)
说明:
CanSelect==true
控件对于键盘输入是可选的 Control()
空白后代,而Panel()
则不能 在此处查看有关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);
}
}
尝试将处理程序设置移至Form_Load事件而不是构造函数。 构造函数中应该没有对Initialize()
的调用吗? 我不建议您删除它
如果ControllableBlock
从Panel继承,则与基本Control对象相比,它将具有更多的事件连接和更好的UI交互设置。
您需要使控件处于可选状态,然后才能获得焦点。
尝试将以下内容添加到构造函数中:
this.SetStyle(ControlStyles.Selectable, true);
并确保在显示表单焦点后为其赋予焦点。 或者,重写OnMouseDown()并在其中调用this.Focus()。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.