Reputation: 41
I am trying to call a Sub from within the keyPress event in a textBox, the problem is that the Sub will not get called until the second keyPress, at that time the keyPress processes the first key entered, if a third keyPress is done the sub will process the second keyPress and so on... Here is an image;
And here is my code;
Private nonNumberEntered As Boolean = False
Private Sub txtAmount_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles txtAmount.KeyPress
'Only allowed characters
Dim allowedChars As String = "0123456789."
nonNumberEntered = False
If Char.IsDigit(e.KeyChar) = False And Char.IsControl(e.KeyChar) = False Then
If e.KeyChar <> ControlChars.Back Then
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character, notify clear and return
MsgBox("Numbers only", MsgBoxStyle.Exclamation)
txtAmount.Text = ""
txtAmount.Focus()
nonNumberEntered = True
End If
End If
End If
'If shift key was pressed, it's not a number.
If Control.ModifierKeys = Keys.Shift Then
nonNumberEntered = True
End If
'Call the function to create a text line out of the numbers
'Regex to ensure the string contains numbers
Dim re As New Text.RegularExpressions.Regex("\d")
If re.IsMatch(txtAmount.Text) Then
If nonNumberEntered = False Then
Dim newNum = txtAmount.Text.Trim
'If there are any leading weird . in the string
newNum = newNum.TrimStart(".")
Dim newStr As String
'Build the array
Dim newDec As String() = newNum.Split(New Char() {"."c})
If newNum.Contains(".") Then
newStr = NumberToText(newDec(0))
lblResult.Text = newStr & " Dollars and " & newDec(1) & "/100 "
Else
newStr = NumberToText(newDec(0))
lblResult.Text = newStr & " Dollars and 00/100 "
End If
End If
End If
End Sub
Any ideas?
Upvotes: 0
Views: 514
Reputation: 41
Ok Chris, you were close. What I needed to do was set e.KeyChar = "" and then trap the and in KeyPress. So here is my final solution that is working as intended.
Private Sub cbCheckAmount_KeyPress(sender As Object, e As KeyPressEventArgs) Handles cbCheckAmount.KeyPress
'Only allowed characters
Dim allowedChars As String = "0123456789."
If Char.IsDigit(e.KeyChar) = False And Char.IsControl(e.KeyChar) = False Then
If e.KeyChar <> ChrW(Keys.Return) Or e.KeyChar <> ChrW(Keys.Tab) Then
If e.KeyChar <> ControlChars.Back Or e.KeyChar <> ControlChars.Tab Then
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character, notify clear and return
nonNumberEntered = True 'Set to True to 'swallow' the keypress and prevent the TextChanged event from firing.
MsgBox("Numbers only", MsgBoxStyle.Exclamation)
cbCheckAmount.Text = ""
cbCheckAmount.Focus()
lblTotalText.Text = ""
e.KeyChar = ""
nonNumberEntered = False
End If
End If
End If
End If
'If shift key was pressed, it's not a number.
If Control.ModifierKeys = Keys.Shift Then
nonNumberEntered = True
cbCheckAmount.Text = ""
cbCheckAmount.Focus()
End If
End Sub
Private Sub cbCheckAmount_TextChanged(sender As Object, e As EventArgs) Handles cbCheckAmount.TextChanged
'Call the function to create a text line out of the numbers
'Regex to ensure the string contains numbers
Dim t As ComboBox = sender
Dim foo As Decimal
If nonNumberEntered = False Then
If Decimal.TryParse(cbCheckAmount.Text, foo) Then
'data is good
Dim re As New Text.RegularExpressions.Regex("\d")
If re.IsMatch(cbCheckAmount.Text) Then
If nonNumberEntered = False Then
Dim newNum = cbCheckAmount.Text.Trim
'If there are any leading weird . in the string
newNum = newNum.TrimStart(".")
Dim newStr As String
'Build the array
Dim newDec As String() = newNum.Split(New Char() {"."c})
If newNum.Contains(".") Then
newStr = NumberToText(newDec(0))
lblTotalText.Text = newStr & " Dollars and " & newDec(1) & "/100 "
Else
newStr = NumberToText(newDec(0))
lblTotalText.Text = newStr & " Dollars and 00/100 "
End If
End If
End If
End If
Else
'data is bad
nonNumberEntered = True
cbCheckAmount.Text = ""
'cbCheckAmount.Focus()
'lblTotalText.Text = ""
End If
End Sub
Upvotes: 0
Reputation: 41
Here is what I am using as my solution, might be a bit of a kluge but it works;
Private nonNumberEntered As Boolean = False
Private Sub txtAmount_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtAmount.KeyPress
'Only allowed characters
Dim allowedChars As String = "0123456789."
If Char.IsDigit(e.KeyChar) = False And Char.IsControl(e.KeyChar) = False Then
If e.KeyChar <> ControlChars.Back Then
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character, notify clear and return
nonNumberEntered = True 'Set to True to 'swallow' the keypress and prevent the TextChanged event from firing.
MsgBox("Numbers only", MsgBoxStyle.Exclamation)
txtAmount.Text = ""
txtAmount.Focus()
lblResult.Text = ""
End If
End If
End If
'If shift key was pressed, it's not a number.
If Control.ModifierKeys = Keys.Shift Then
nonNumberEntered = True
txtAmount.Text = ""
txtAmount.Focus()
End If
End Sub
Private Sub txtAmount_TextChanged(sender As Object, e As EventArgs) Handles txtAmount.TextChanged
'Call the function to create a text line out of the numbers
'Regex to ensure the string contains numbers
Dim t As TextBox = sender
Dim foo As Decimal
If Decimal.TryParse(txtAmount.Text, foo) Then
'data is good
Dim re As New Text.RegularExpressions.Regex("\d")
If re.IsMatch(txtAmount.Text) Then
If nonNumberEntered = False Then
Dim newNum = txtAmount.Text.Trim
'If there are any leading weird . in the string
newNum = newNum.TrimStart(".")
Dim newStr As String
'Build the array
Dim newDec As String() = newNum.Split(New Char() {"."c})
If newNum.Contains(".") Then
newStr = NumberToText(newDec(0))
lblResult.Text = newStr & " Dollars and " & newDec(1) & "/100 "
Else
newStr = NumberToText(newDec(0))
lblResult.Text = newStr & " Dollars and 00/100 "
End If
End If
End If
Else
'data is bad
nonNumberEntered = False
txtAmount.Text = ""
txtAmount.Focus()
lblResult.Text = ""
End If
End Sub
Note that in the textChanged I am checking to see if the value is actually a number, if ot, clear contents and keep going. In textChanged I also allow a decimal point, but nothing else, and then I clear everything making the user start over. Simple, yet effective......
Upvotes: 0
Reputation: 11216
As @jmcilhinney alluded in the comments, you are trying to do too much in the KeyPress
event handler. That handler should only be used to allow valid key presses and suppress invalid key presses. Whenever a valid key press is made, it is allowed to go through and then the TextChanged
event handler will be called. Setting e.Handled = True
will suppress the key press and the TextChanged
event will not be called.
Private Sub txtAmount_KeyPress(sender As Object, e As KeyPressEventArgs) Handles TextBox2.KeyPress
'Only allowed characters
Dim allowedChars As String = "0123456789."
If Char.IsDigit(e.KeyChar) = False And Char.IsControl(e.KeyChar) = False Then
If e.KeyChar <> ControlChars.Back Then
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character, notify clear and return
e.Handled = True 'Set to True to 'swallow' the keypress and prevent the TextChanged event from firing.
MsgBox("Numbers only", MsgBoxStyle.Exclamation)
txtAmount.Text = ""
txtAmount.Focus()
End If
End If
End If
End Sub
Private Sub txtAmount_TextChanged(sender As Object, e As EventArgs) Handles TextBox2.TextChanged
lblResult.Text = NumberToText(txtAmount.Text)
End Sub
Public Function NumberToText(input As String) As String
'Convert value of amount to words here
End Function
You may also wish to look into using a MaskedTextBox
which will handle the validation automatically.
Upvotes: 1