30

I used KeyDown event and some simple code like if (e.KeyCode == Keys.F1) to capture F1 is pressed on a form BUT if there are some text boxes on the form or if there are some spreadsheets with Dock Fill on the form then the code above gets useless and does nothing. But I want to do something when user presses F1 on this form. so how do we capture a specific keydown event like F1 on the whole form..and I do not want to go to the route that capture the KeyDown of all other controls on the form and pass them to the Form for processing. is there any cleaner way to do this?

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
Bohn
  • 26,091
  • 61
  • 167
  • 254

4 Answers4

60

Yes, indeed there is. The correct way for the form to handle key events regardless of the control that currently has the input focus is to override the ProcessCmdKey method of your form class:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData)
{
    if (keyData == Keys.F1)
    {
        MessageBox.Show("You pressed the F1 key");
        return true;    // indicate that you handled this keystroke
    }

    // Call the base class
    return base.ProcessCmdKey(ref msg, keyData);
}

You return true to indicate that you handled the keystroke and don't want it to be passed on to other controls. If you do want it to be passed on to the event handlers for other controls, simply return false.

And you're best off ignoring the KeyPreview property. That's an anachronism from the VB 6 days and not really the preferred way of doing this in the .NET world. Further reading: Disadvantage of setting Form.KeyPreview = true?

gtgaxiola
  • 9,241
  • 5
  • 42
  • 64
Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 5
    How is it not the preferred way? `KeyPreview` makes use of .NET's event-centric architecture, while you're just overriding `WndProc`, the preferred Win3.1 (yes, that's right, 1992 technology) way of doing this. – Blindy May 10 '11 at 14:26
  • 1
    @Blindy: The idiomatic way of doing things in the world of the Windows API hasn't changed much since the early days of Windows. And it's not *exactly* the same thing as overriding `WndProc` (although that works, too). The framework calls this method at the appropriate time *specifically* for handling these events. Additionally, doing things this way allows you to decide whether you want the event to be passed on to other controls, or not. – Cody Gray - on strike May 10 '11 at 14:28
  • 1
    It's actually exactly the same as overriding `WndProc` when `uMsg=WM_KEYDOWN`. And just as checking the virtual key codes in the Win32 api, you don't know if the user entered the actual key or its shifted version (among other things). To each his own, but I'd be more careful which API I call worse. – Blindy May 10 '11 at 14:37
  • 1
    @Blindy: Functionally? Or idiomatically? I'm not quibbling about function--I already said that such works as well. But I strongly disagree that `KeyPreview` is a better alternative. – Cody Gray - on strike May 10 '11 at 14:39
  • This doesn't seem to work if a WebBrowserControl has the focus. – Thomas Weller Mar 04 '23 at 19:32
5

Set the form's KeyPreview to true. This will make sure the form get the keypress messages first and if you handle it, you can set e.Handled = true so it doesn't passed down to the controls.

Bala R
  • 107,317
  • 23
  • 199
  • 210
4

Turn on KeyPreview and every key press in the form will get routed through it's key event handlers first.

Blindy
  • 65,249
  • 10
  • 91
  • 131
3

Another way is to Override the ProcessCmdKey function http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey(v=VS.100).aspx

JTorrecilla
  • 208
  • 1
  • 4