Vb.net 为什么DateTimePicker赢了';是否使用tab键触发keyDown和KeyPress事件?

Vb.net 为什么DateTimePicker赢了';是否使用tab键触发keyDown和KeyPress事件?,vb.net,winforms,Vb.net,Winforms,伙计们,我遇到了这个问题-DateTimePicker不会用tab键触发KeyDown和KeyPress事件(其他键工作正常,keyUp事件也正常,尽管在上一个控件上按tab键“到达”DateTimePicker后会触发)。我正在使用.net 4.6.1、Visual Basic和VS 2017 我想做的事->(直接在DateTimePicker上转到月份和年份) 我正在使用的代码: Private Sub DateTimePicker1_KeyDown(ByVal sender As Obje

伙计们,我遇到了这个问题-DateTimePicker不会用tab键触发KeyDown和KeyPress事件(其他键工作正常,keyUp事件也正常,尽管在上一个控件上按tab键“到达”DateTimePicker后会触发)。我正在使用.net 4.6.1、Visual Basic和VS 2017

我想做的事->(直接在DateTimePicker上转到月份和年份)

我正在使用的代码:

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

有什么线索吗?

您需要重写
ProcessCmdKey
函数

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

Tab键用于导航。将焦点从一个控件移动到另一个控件。因此,您的KeyDown事件处理程序永远看不到它,击键在此之前被截获并使用。您可以订阅并将e.IsInputKey=true设置为解决方法,检查链接文章中的MSDN示例代码以获取代码

但无论如何,这是一个错误的事件,当用户用鼠标而不是键盘改变焦点时,您仍然希望它能够工作。因此,请改用
Enter
事件

请注意,这两种方法都有相同的问题,重点可能已经放在控件以前使用的月份部分,因此现在代码将错误地将其移动到年份部分。你不知道哪一部分有重点,那就是没有好的桨的小溪上游。一个非常难看的解决方法是更改Format属性,然后返回,这将强制控件重新创建控件窗口,并且始终重置焦点。使用BeginInvoke()运行该代码。也许更具建设性,如果你只对月份+年感兴趣,定制格式属性。 实现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

这不是这个问题的正确答案,尽管它也有帮助。如果您只想在DateTimePicker中使选项卡充当正确的键,一个好的(粗略的)方法是:

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
Private i=2
受保护的重写函数ProcessTabKey(ByVal forward作为布尔值)作为布尔值
Dim ctl As Control=Me.ActiveControl
如果ctl不是Nothing,ctl的类型也是DateTimePicker和i 0,那么
SendKeys.Send(“{Right}”)
i-=1
返回真值
如果结束
i=2
返回MyBase.ProcessTabKey(前进)
端函数

您是否需要当天的节目?如果您将其设置为“mmmyyy”的自定义格式,那么它将立即转到月份。现在这是一个完整的答案。谢谢