编写小游戏时遇到了问题;我的表单的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:似乎问题是我从ControllableBlock
继承了Control
。
如果我从Panel
继承它,它可以正常工作。
这是为什么?
如果我从控件继承,我不能激活一个事件吗?
ControllableBlock
类暂时为空,因此除了从Control
继承之外,它甚至都不做任何事情。
编辑3:既然我已经开始了赏金,我想澄清一下,我不是在寻找一个如何解决事件的解决方案,我正在寻找如果我继承Control
,他们为什么不解雇的原因。
答案 0 :(得分:4)
如果您的活动应该是应用程序范围的,请尝试将属性KeyPreview
设置为true
- 它将允许您触发相应的事件,无论集中控制如何。
this.KeyPreview = true;
否则,您应该将这些事件直接附加到将要处理它们的控件上。
修改强>
我从表单中删除了InitializeComponent();
并获得了与您相同的行为。
在实施this问题中提供的解决方案之后,所有事件都开始完全正常 复制代码段:
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);
}
答案 1 :(得分:3)
我能够重现一个类似的问题(希望是相关的......)
说明:
CanSelect==true
可用于键盘输入Control()
的空白后代是可选的,Panel()
中的一个不是检查here,了解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);
}
}
答案 2 :(得分:0)
尝试将处理程序设置移动到Form_Load事件而不是构造函数。是否应该在构造函数中调用Initialize()
?我不特别建议删除它
如果ControllableBlock
继承自Panel,它将具有比基本Control对象更多的事件连接和更好的UI交互设置。
答案 3 :(得分:0)
您需要先控制您的控件才能获得焦点。
尝试将以下内容添加到构造函数中:
this.SetStyle(ControlStyles.Selectable, true);
确保在显示后重点关注表单。或者,重写OnMouseDown()并在其中调用this.Focus()。