Background:
I have a couple of rather complex C# gui applications with controls nested inside of controls inside of controls, which require hotkeys to be handled globally (i.e., there needs to be a top-level handler that can catch the key presses regardless of where the focus is).
My requirements are probably a bit out of the ordinary here, because some of the hotkeys are commonly pressed keys like letters, or even the space bar. When a key like the space bar is pressed, obviously there will be certain controls like text boxes which handle it already. In the case where the focused control handles the key, I want to avoid calling the global hotkey handler.
My current solution is to use PreFilterMessage to handle hotkeys globally, and then Inside of the PreFilterMessage call I have code that bypasses the global hotkey if the focused control is known to handle that key. (But, since IsInputKey is protected, I can't ask the control whether it handles the key, so I kind of just have my own messy logic about which controls the hotkeys should be bypassed inside of).
I'm not very happy with the PreFilterMessage solution, and it seems like their ought to be a more elegant way to do it. Conceptually, the behaviour I want is pretty simple. If the focused control handles the KeyDown, then I don't want anything else to handle it. Otherwise, the Parent control should try to handle it, and if that control doesn't handle the key it should try the parent of that, until it gets all the way up to the Form's KeyDown handler.
Question:
Is there a way to set up a KeyDown handler on a Control such that it only receives events if and only if:
- The Control or one of its descendents is focused, and
- Either none of the descendent controls has focus, or the focused control does not handle the KeyDown event
I have done as much research as I can on this. I'm aware of PreFilterMessage and Form.KeyPreview, but as far as I can tell, those don't have a clean way of ignoring the key when it's supposed to be handled by some more-specific control, because they get the event before the focused control gets it. What I really want is almost the opposite -- for the form not to get the KeyDown until after the focused control has decided whether or not to handle it.