user4403148
user4403148

Reputation:

Why DateTimePicker won't trigger keyDown and KeyPress events with the tab key?

Fellows, I am having this problem - the DateTimePicker won't trigger KeyDown and KeyPress events with the tab key (other keys are working fine, and the keyUp event as well, although it triggers after "arriving" at the DateTimePicker after pressing tab at the previous control focused). I'm using .net 4.6.1, Visual Basic and VS 2017.

What I'm trying to do -> Go to month and year directly on DateTimePicker in C# (Go to month and year directly on DateTimePicker)

Code I'm using:

Private Sub DateTimePicker1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DateTimePicker1.KeyDown
    If e.KeyCode = Keys.Tab Then
        e.Handled = True
        MsgBox("TAB DOWN")
    End If
End Sub

Private Sub DateTimePicker1_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles DateTimePicker1.KeyPress
    e.Handled = True
    MsgBox("tab press")
End Sub

Private Sub DateTimePicker1_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles DateTimePicker1.KeyUp
    If e.KeyCode = Keys.Tab Then
        MsgBox("TAB UP")
        e.Handled = True
    End If
End Sub

Any clues?

Upvotes: 2

Views: 3203

Answers (3)

user4403148
user4403148

Reputation:

It's not the right answer to this question, although it helps as well. If you want to just make the tab behave as the right key when inside a DateTimePicker, a good (sketchy) way to do is:

Private i = 2

Protected Overrides Function ProcessTabKey(ByVal forward As Boolean) As Boolean
    Dim ctl As Control = Me.ActiveControl
    If ctl IsNot Nothing AndAlso TypeOf ctl Is DateTimePicker And i <> 0 Then
        SendKeys.Send("{Right}")
        i -= 1
        Return True
    End If
    i = 2
    Return MyBase.ProcessTabKey(forward)
End Function

Upvotes: 1

Hans Passant
Hans Passant

Reputation: 941615

The Tab key is used for navigation. Moving the focus from one control to another. So your KeyDown event handler can never see it, the keystroke is intercepted and used before that. You could subscribe the PreviewKeyDown event and set the e.IsInputKey = true as a workaround, check the MSDN sample code in the linked article for code.

But it is the wrong event to use anyway, you'd still want this to work when the user changes focus with the mouse instead of the keyboard. So use the Enter event instead.

Do beware that both approaches have the same problem, the focus might already be on the month part from previous usage of the control so now your code will incorrectly move it to the year part. And you can't find out what part has the focus, that is up a creek without a good paddle. A very ugly workaround for that is to change the Format property, and back, that forces the control to re-create the control window and that always resets the focus. Use BeginInvoke() to run that code. Perhaps more constructively, consider to just not display the day if you are only interested in month+year, CustomFormat property.

Sample code that implements the focus hack:

Private Sub DateTimePicker1_Enter(sender As Object, e As EventArgs) Handles DateTimePicker1.Enter
    Me.BeginInvoke(
        New Action(Sub()
                       '' Hack to reset focus
                       DateTimePicker1.Format = DateTimePickerFormat.Long
                       DateTimePicker1.Format = DateTimePickerFormat.Short
                       DateTimePicker1.Focus()
                       SendKeys.Send("{Right}")
                   End Sub))
End Sub

Upvotes: 2

Sunil
Sunil

Reputation: 3424

You need to override ProcessCmdKey function

Private isTab As Boolean = False

Private isShiftTab As Boolean = False

Protected Overrides Function ProcessCmdKey(ByRef msg As Message, ByVal keyData As Keys) As Boolean
    If keyData = Keys.Tab Then
        isTab = True
        'Do something with it.
    Else
        isTab = False
    End If

    Return MyBase.ProcessCmdKey(msg, keyData)
End Function

Upvotes: 0

Related Questions