处理按键事件时,我无法输入选择

问题描述:

好吧,我有一系列文本框只能接受1到49的数字值 - 每个文本框中都有一个唯一的数字。验证时,如果在其中一个框中有重复的号码,我希望将焦点设置为突出显示文本的违规文本框,以便我可以开始键入,并且选择将消失。问题(我认为)是在选择可以被删除之前,新的按键事件被添加到文本中。在一个解决方案谷歌搜索,我指着这个网站后,其最终与该代码张贴由罗伯特·巴恩斯处理按键事件时,我无法输入选择

Private Sub txtScreen_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtScreen.KeyPress 
    If txtScreen.SelectionStart < txtScreen.TextLength AndAlso Not [Char].IsControl(e.KeyChar) Then 
     Dim SaveSelectionStart As Integer = txtScreen.SelectionStart 
     Dim sb As New StringBuilder(txtScreen.Text) 
     sb(txtScreen.SelectionStart) = e.KeyChar 
     'Add the pressed key at the right position 
     txtScreen.Text = sb.ToString() 
     'SelectionStart is reset after setting the text, so restore it 
     'Advance to the next char 
     txtScreen.SelectionStart = SaveSelectionStart + 1 
     e.Handled = True 
    End If 
End Sub 

这个工作上来,但允许您改写选择一个字符时间,而不是用一个按键擦拭(替换)整个事物。我以前从未在Windows控件中看到过这种行为,也没有看到过需要这样的过程,但这是一个有趣的功能。在在意识到发生了什么的如果语句中发生的任何情况下,我想通了,我可以acheive我想要用一行代码:

If tb.SelectionStart < tb.TextLength AndAlso Not [Char].IsControl(e.KeyChar) Then 
     tb.SelectedText = "" 
End If 

这只是放弃的选择,使空间给新的输入,给人一种更传统的微软行为。在这种情况下,我不需要设置e.Handled,因为我将代码放置在KeyPress事件的开始处,允许在后续代码中处理按键,以便根据jimcilhinney进行一些更改... 我有(其中的工作,但有一点马虎)

Private Sub txtPick_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtNum1.KeyPress 
    Dim tb As TextBox = CType(sender, TextBox) 

    If tb.SelectionStart < tb.TextLength AndAlso Not Char.IsControl(e.KeyChar) Then 
     tb.SelectedText = "" 
    End If 
    'exclude all keypresses that aren't digits 
    If Not Char.IsDigit(e.KeyChar) Then e.Handled = True 

    Dim num As Integer = Val(String.Concat(tb.Text, e.KeyChar)) 
    'make sure keypress keeps number in range 
    If num > 49 Or num < 1 Then e.Handled = True 
    'allow backspace, delete 
    If e.KeyChar = vbBack Or e.KeyChar = ChrW(Keys.Delete) Then e.Handled = False 
End Sub 

,我现在有:

Private Sub txtPick_KeyPress(sender As Object, e As System.Windows.Forms.KeyPressEventArgs) Handles txtNum1.KeyPress 
    Dim tb As TextBox = CType(sender, TextBox) 

    'exclude all keypresses that aren't digits 
    If Not Char.IsDigit(e.KeyChar) Then e.Handled = True 
    'allow backspace, delete 
    If e.KeyChar = vbBack Or e.KeyChar = ChrW(Keys.Delete) Then e.Handled = False 
End Sub 

Private Sub txtNum_Validating(sender As Object, e As System.ComponentModel.CancelEventArgs) Handles txtNum1.Validating 
    Dim tb As TextBox = CType(sender, TextBox) 
    Dim num As Integer = Val(tb.Text) 

    If IsNumeric(tb.Text) Then 
     Select Case Val(tb.Text) 
      Case Is < 1, Is > 49 
       e.Cancel = True 
     End Select 
    End If 
End Sub 

整理了相当不错的工作完美,感谢jmchilinney!

KeyPress是错误的事件。您应该处理Validating事件,该事件在用户试图离开控件时发生。在这一点上,你可以检查输入是一个数字,并且它是唯一的。如果不是,请拨SelectAllTextBox并将e.Cancel设置为True以防止控制失控。

+0

是的。这也解决了能够粘贴无效输入的问题,这当然不涉及按下任何按键。 –

+0

确定有帮助,但我已经使用KeyPress将值限制为数字,Backspace和Delete以及限制输入数字的范围......你是说我应该(甚至可以)完成所有这些在验证中还是应该分离两个事件之间的逻辑? – halfacreSal

+0

当用户试图离开控件时,会引发“验证”事件。它不会阻止无效输入,但它会阻止用户在控件包含无效输入时离开控件,因此无法使用输入。如果你想首先防止无效输入,那么'KeyPress'是一个选项,但这只是为了防止非法字符。超出范围的数字仍然是您应该使用“验证”的。 – jmcilhinney