Keyboard input in Form

I'd like a Form to handle keyboard input.  However, I do not want it to clash with other controls that use keyboard input, such as ComboBox, PropertyGrid, etc.

Is there a way I can find the Control that has the keyboard focus and query it to see if it (is one of the known ) text entry Controls.  This way I could prevent multiple controls from handling the same input.  This particular application needs global level input due to its UI requirements.

If there is a better way to handle input at the form level, please comment also.


Answer this question

Keyboard input in Form

  • tmorton

    Thanks for your comments so far.  I took a closer look at my current implementation and found that I am trying to use OnKeyDown() from the Form itself.  I notice that OnKeyDown is never called unless 1) I set the form style to be 'Selectable' during construction, then manually call Focus() to the form, then press a key or 2) I enable KeyPreview on the Form.

    What I expected to happen was that various controls on the form handle input for themselves (in their OnKeyDown() etc.), if they do not handle the key (eg. because they are a TextBox etc.) the key event would then be processed by the parent control until it reaches the highest level parent (the Form).  This does not appear to happen.  Instead, if I create two controls as parent and child, then implement OnKeyDown(), only the child will receive this event.  This is contradictory to the information in http://blogs.msdn.com/jfoscoding/archive/2005/01/24/359334.aspx

    I believe I simply want to let the forms Controls process input, and if they do not, then let the Form itself process the key as a potential global command.

    What am I missing here

  • cs101

    Keystrokes generally are not handled recursively in the manner you expected.  Parents are called to handle shortcuts and navigation keys, which is what the blog entry you mention discusses. If the key pressed is not a shortcut, nor a navigation character, the parents (including the form) do not handle it.  Typically, if you type whilst on a control, and that control does not understand the strokes, it ignores them.  For example, a Button that has focus handles (but tosses) keystrokes except Return, Space, which it interprets as a click. 

    I think to change this, you would need to override the keystroke handling for a control (in WndProc) so that it doesn't toss keystrokes it doesn't understand, and send them to the Form instead.

  • Software Engineer

    I'm not sure if this is an easy or hard question...

    Form.ActiveControl will return the control that has focus.  You can call GetType() on it to and compare it to, for example, typeof(TextBox) to see if it is a textbox.  You can have the parent form process keystrokes before it's consituent controls by setting the Form.KeyPreview property to true.  If the form chooses to intercept and handle the keystroke, set the KeyPressEventArgs.Handled property to true and the keystroke will not be sent to the active control.

  • Brian Cross

  • marmok

    Thank you once again for your input (pun not intended).  I have read all your comments and the keyboarding article a few times and I may have the solution.  The ProcessDialogKey function does in fact behave the way I would like.  It does not preview the key before child controls, it does allow handling the key by any parent as long as they key has not been already handled by child controls or higher level short cuts. 

    In my test case, the TextBox consumed the input, but other controls allowed the input to pass up to the parent form.  This is looking promising, though I notice ProcessDialogKey combines multiple keys into one code, does not appear to signal the release state, and is effected by repeat rate.

    Edit: This appears to be working quite well...
    bool MyControl::ProcessDialogKey( Keys keyData )
    {
      KeyEventArgs keyArgs(keyData);

      this->OnKeyDown( %keyArgs );

      if(keyArgs.Handled)
      {
        return true;
      }
      return __super::ProcessDialogKey(keyData);
    }


  • Keyboard input in Form