The standard Windows event model is that the window with the keyboard focus gets all keyboard events. Remember that in Windows, everything is a window - a 'control' is just a window that is a child of another window. It's up to that window to fire messages to its parent if it chooses to do so, when certain keys are pressed.
To standardise navigation between controls on a dialog box, Windows also provides the 'dialog manager'. In native code, for modal dialogs this is handled by the modal message loop inside the DialogBox
function. For modeless dialogs you have to call IsDialogMessage
within your own message loop. This is how it steals the Tab and cursor keys to navigate between controls, and Enter to press the default button. This has the opposite effect of not allowing the controls to handle Enter by default, which multi-line edit controls would normally handle. To discover whether a control wants to handle a key, the dialog manager code sends the focused control a WM_GETDLGCODE
message; if the control responds appropriately the dialog manager returns FALSE
allowing DispatchMessage
to actually deliver it to the window procedure, otherwise the dialog manager does its own thing.
Windows Forms largely just wraps up the old native controls, so it has to conform to Win32's event model. It implements the same dialog manager approach - hence why it doesn't, by default, allow you to see Tab, Return and the cursor keys.
The recommended approach, if you want to handle one of those keys, is to override PreviewKeyDown
and set the PreviewKeyDownEventArgs
IsInputKey
property to true
.