views:

97

answers:

2

Test project which exhibits the problem: http://mike-caron.com/Testbed.zip

Basically, I have a form with a custom control on it (and nothing else). The custom control is completely empty, and the form has KeyPreview set to true.

With this setup, I am not receiving any KeyDown events for any arrow keys or Tab. Every other key that I have on my keyboard works. I have KeyDown event handlers hooked up to everything that has such events, so I'm sure I'm not missing anything.

Also of note is that if I remove the (completely empty) custom control, I DO get the arrow key events.

What on earth is going on here?

EDIT:

I added this to both the form and the control, but I'm STILL not getting arrow keys:

protected override void WndProc(ref Message m) {
    switch (m.Msg) {
        case 0x100: //WM_KEYDOWN
            //this is the control's version. In the form, it's this.Text
            ParentForm.Text = ((Keys)m.WParam).ToString();
            break;
    }
    base.WndProc(ref m);
}

I also checked with Spy++, and determined that the form itself is not getting any WM_KEYDOWN messages, they're all going to the control. However, that said, the control IS getting the arrow key WM_KEYDOWN messages. Sigh.

Edit 2: I've also updated the ZIP file with this version. Please look at it, if you want to help...

Edit 3:

I've figured this out, sort of. The form is eating the arrow keys, probably in an attempt to maintain focus amongst its children. This is proven by the fact that I DO get the events if the form is empty.

Anyway, if I add this code to the form, I start getting the events again:

public override bool PreProcessMessage(ref Message msg) {
    switch (msg.Msg) {
        case 0x100: //WM_KEYDOWN
            return false;
    }
    return base.PreProcessMessage(ref msg);
}

When I override this, the form doesn't get a chance to do its dirty work, and so I get my KeyDown events as I expect. I assume that a side effect of this is that I can no longer use my keyboard to navigate the form (not a big deal in this case, as it's a game, and the entire purpose of this exercise is to implement keyboard navigation!)

The question still remains about how to disable this "properly", if there is a way...

A: 

If focus is your issue, and you can't get your user control to take a focus and keep it, a simple work-around solution would be to echo the event to your user control on the key event you are concerned about. Subscribe your forms keydown or keypress events and then have that event raise an event to your user control.

So essentially, Form1_KeyPress would Call UserControl1_KeyPress with the sender and event args from Form1_KeyPress e.g.

protected void Form1_KeyPress(object sender, KeyEventArgs e)
{
    UserControl1_KeyPress(sender, e);
}

Otherwise, you may have to take the long route and override your WndProc events to get the functionality you desire.

George
The UserControl is empty, and can't receive focus (AFAIK). So, the Form itself should be receiving the KeyDown events. However, it isn't. As I stated in the question, I have event handlers hooked up to everything that has the event, but nothing is getting the event.I may try overriding WndProc, but I really shouldn't have to...
Mike Caron
I've updated the OP with the results of my overriding WndProc
Mike Caron
A: 

I've done some extensive testing, and I've figured everything out. I wrote a blog post detailing the solution.

In short, you want to override the ProcessDialogKey method in the form:

protected override bool ProcessDialogKey(Keys keyData) {
    return false;
}

This will cause the arrow keys (and tab) to be delivered as normal KeyDown events. HOWEVER! This will also cause the normal dialogue key functionality (using Tab to navigate controls, etc) to fail. If you want to retain that, but still get the KeyDown event, use this instead:

protected override bool ProcessDialogKey(Keys keyData) {
    OnKeyDown(new KeyEventArgs(keyData));
    return base.ProcessDialogKey(keyData);
}

This will deliver a KeyDown message, while still doing normal dialogue navigation.

Mike Caron