geopraxis

IDockableWindow addin tab key and AcceptButton problems, workaround

Discussion created by geopraxis on Nov 30, 2012
I implemented a combination of an IEditor and IDockableWindow addin using VB.Net under VS 2010.

Encountered two problems:
1. Tab key does not work as expected. Controls are jumped to without regard to TabIndex value.
This has been logged with Redlands as NIM086656 but is not resolved as of this writing.
2. There is no equivalent to the System.Windows.Forms.Form.AcceptButton property, which would allow you specify a default button control that would be pressed by hitting Enter on the keyboard.

My first approach was to handle the keyboard event myself by using an AddHandler on PreviewKeyDown or KeyDown or KeyPress at the level of the IDockableWindow. I also tried overriding ProcessTabKey, ProcessCmdKey, and a number of other approaches of this nature. None work--the code never is entered. The problem seems to arise because the keyboard event is being intercepted outside the DockableWindow and handled in such a way that it never arrives at the DockableWindow object itself. Apparently something outside the DockableWindow grabs the event and either handles it or hands it directly to the active control inside the DockableWindow.

A partial workaround to the tab key problem is to implement the Leave event for each control where the cursor jumps, and set focus to the right control there. This is explicitly against a Microsoft caution not to set focus within any of the Enter, GotFocus, Leave, LostFocus, Validating, or Validated event handlers (see http://msdn.microsoft.com/en-us/library/system.windows.forms.control.leave.aspx). However, in this case apparently correcting the problem focus imposed outside doesn't cause any message deadlocking. This workaround is partial because all you can know is that the control was left, i.e. you can't know if what caused it to be left was a mouse click, tab, shift-tab, etc. Thus, you're forcing the tab key to do what is expected at the cost that using any other means to exit the control might cause something unexpected. For instance, if you click on another control with the mouse the Leave code will override its focus. However, if your requirements are likely to have the user working with the keyboard and tabbing through a form this buys you expected behaviour.

The problem behind the tab key issue above means that the solution you'll find if you search for AcceptButton and UserControl on the web (override ProcessCmdKey and process the keystroke) won't work--your override will never receive the event. A workaround is to implement KeyPress for each control where you expect the user might want to use Enter to press the button and add code similar to:

    If e.KeyChar = Microsoft.VisualBasic.ChrW(System.Windows.Forms.Keys.Return) Then
      'Presuming your button is called btnApply
      If btnApply.Enabled Then
        ' (execute the code run by your button here)
        e.Handled = True
      End If
    Else
      e.Handled = False
    End If

I hope this is helpful for someone. It has been an exercise in frustration for me, and I still hope the underlying problem is fixed sometime soon.

Outcomes