Roy Osherove

View Original

Winforms menu shortcuts not working sometimes? Use ProcessDialogKey()

One of the one of the usability standards I always try to live up to in my win forms apps is letting the user choose how to perform any specific action, Mouse or keyboard. What I mean is that for every action that the user will be able to click on something to perform it, I always try to make sure there’s a keyboard shortcut or at least some way to do it using the keyboard.

 

In Regulator, I came into somewhat of a problem, something which I’m used to encountering in VB6 apps. I have multiple forms hosted within a single form (not MDI). I also have various toolbar controls from ComponentOne and the Magic Library controls (the free version). I discovered that, in some situations, even though I have setup the correct shortcut keys to the main toolbar in the hosting form, pressing these keys when some control in the hosted form is focused might not always trigger the shortcut action I wanted. So how do I still grab it? How do I “snatch” the pressed key combination without having to catch the KeyDown event for each of my sub-form’s constituent controls?

 

The answer lies within the Control class. The Control Class has an overridable method called ProcessDialogKey. My form will  process the dialog key that was pressed no matter what control inside it was focused during that time. It will actually process this key before any child controls process it.

Here’s how I override the method and check for specific key combinations:

 

protected override bool ProcessDialogKey(Keys keyData)

 

try

{

switch (keyData)

{

      case Keys.F5:

            StartMatchThread();

            break;

 

      case Keys.F6:

            StartReplaceThread();

 

            break;

 

      case Keys.Control | Keys.S:

            Save();

            break;

      ...

}

return base.ProcessDialogKey (keyData);

}

catch(Exception )

{

      return false;        

}

 

What’s important here is to, in the end, return the result from the base class, so that regular processing can continue as usual.