When coding a small game, I encountered a problem; my form's KeyDown
and KeyUp
events don't fire at all.
This is the form's code:
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);
}
}
There's a lot more going on, but I only pasted the relevant code.
I've already tried setting this.KeyPreview = true;
and calling this.Focus();
, neither works. The problem is not in ReactToKey()
method, I've already set a breakpoint there and the event is never fired.
Edit: After some tests I've come to a conclusion that the problem is within my ControllableBlock
. Yet, I have no idea why, but I'm working on it. If I comment out everything that's related to the player
, the events start firing.
Edit 2: Seems like the problem is me inheriting my ControllableBlock
from Control
. If I inherit it from Panel
, it works fine. Why is this? Can't I fire an event if I inherit from control? The ControllableBlock
class is empty for now, so it doesn't even do anything other than inherits from Control
.
Edit 3: Now that I've started a bounty, I'd like to clarify that I'm not looking for a solution on how to make the events fire, I'm looking for a reason on why they don't fire if I inherit from Control
.
If your events should be application-wide try to set property KeyPreview
to true
- it will allow you to fire respective events regardless of focused control.
this.KeyPreview = true;
Otherwise you should attach these events directly to control that will process them.
Edit:
I removed InitializeComponent();
from my form and got behaviour identical to yours.
After implementing solution provided in this question all events started to qork perfectly.
Copy code snippet here:
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);
}
I was able to reproduce a similar issue (which is hopefully related..)
Explanation:
CanSelect==true
are selectable for keyboard input Control()
is selectable, one of Panel()
is not Check here for a good overview of how windows keyboard input works.
Code to reproduce it:
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);
}
}
try moving the handler setup to the Form_Load event rather than the constructor. Should there not be a call to Initialize()
in the constructor? I wouldn't particularly recommend removing it
If ControllableBlock
inherits from Panel, it will have more event hookups and better UI interaction setup than a base Control object.
You need to make your control selectable before it can receive the focus.
Try adding the following to your constructor:
this.SetStyle(ControlStyles.Selectable, true);
And ensure that you give your form focus after it has been displayed. Or, override OnMouseDown() and call this.Focus() in it.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.