Home > Blockchain >  VB.NET - How to make textbox input only numbers, space, backspace/delete, decimals, and shortcuts
VB.NET - How to make textbox input only numbers, space, backspace/delete, decimals, and shortcuts

Time:04-16

My biggest problem here is to get the CTRL-V (Paste) to work. I've tested many ctrl-v ascii code but I got none of them to work. CtrlX and CtrlC works perfetly so I don't know what the problem is. This is my half working code:

Private Sub alltb_KeyPress(sender As Object, e As KeyPressEventArgs) Handles txtF.KeyPress, txtCLL.KeyPress, txtCLU.KeyPress
    e.Handled = Not (Char.IsDigit(e.KeyChar) Or e.KeyChar = "." Or e.KeyChar = " " Or Asc(e.KeyChar) = 8 Or Asc(e.KeyChar) = 235 Or Asc(e.KeyChar) = 1 Or Asc(e.KeyChar) = 3 Or Asc(e.KeyChar) = 26 Or Asc(e.KeyChar) = 22 Or Asc(e.KeyChar) = 24)
End Sub

If you could suggest new code that will only allow numbers, decimals, space, backspace/delete, and shortcuts Or help me be able to use ctrlV, that would be really amazing and a big help!

CodePudding user response:

Things are actually a bit more complex even than the first answer suggests because the user might select paste a valid number within another valid number to create an invalid input, so you need to validate the result of the paste, not just the text being pasted.

You also need to consider that the user might enter one or more characters that are valid but then leave a result that is not. Here's a basic implementation I wrote some years ago:

Imports System.Globalization

Public Class SimpleNumberBox
    Inherits System.Windows.Forms.TextBox

    Private Const WM_PASTE As Integer = &H302

    Protected Overrides Sub OnKeyPress(ByVal e As System.Windows.Forms.KeyPressEventArgs)
        Dim keyChar = e.KeyChar
        Dim formatInfo = NumberFormatInfo.CurrentInfo

        If Char.IsControl(keyChar) OrElse _
           Char.IsDigit(keyChar) OrElse _
           ((keyChar = formatInfo.NegativeSign OrElse _
             keyChar = formatInfo.NumberDecimalSeparator) AndAlso _
            Me.ValidateText(keyChar)) Then
            MyBase.OnKeyPress(e)
        Else
            e.Handled = True
        End If
    End Sub

    Protected Overrides Sub OnValidated(ByVal e As System.EventArgs)
        If Not Decimal.TryParse(Me.Text, New Decimal) Then
            Me.Clear()
        End If

        MyBase.OnValidated(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As System.Windows.Forms.Message)
        If m.Msg <> WM_PASTE OrElse _
           Not Clipboard.ContainsText() OrElse _
           Me.ValidateText(Clipboard.GetText()) Then
            MyBase.WndProc(m)
        End If
    End Sub

    Private Function ValidateText(ByVal newText As String) As Boolean
        Dim isValid = True
        Dim currentText = Me.Text
        Dim selectionStart = Me.SelectionStart
        Dim proposedText = currentText.Substring(0, selectionStart) & _
                           newText & _
                           currentText.Substring(selectionStart   Me.SelectionLength)

        If Not Decimal.TryParse(proposedText, _
                                NumberStyles.AllowLeadingSign Or NumberStyles.AllowDecimalPoint, _
                                Nothing, _
                                New Decimal) Then
            Dim formatInfo = NumberFormatInfo.CurrentInfo
            Dim negativeSign = formatInfo.NegativeSign
            Dim decimalSeparator = formatInfo.NumberDecimalSeparator

            isValid = (proposedText = negativeSign) OrElse _
                      (proposedText = decimalSeparator) OrElse _
                      (proposedText = negativeSign & decimalSeparator)
        End If

        Return isValid
    End Function

End Class

In case you're interested, here is a more rigorous implementation, although I'm not 100% sure that there aren't still some bugs in this one as I haven't looked at it for a long time.

CodePudding user response:

When you press Ctrl V keys in an edit-box like the TextBox control, you actually request a string containing the text data on the system Clipboard if any. So, the TextBox.KeyPress event is not the right place to validate the pastes. You need a way to trap the WM_PASTE messages and validate the string that returns from the Clipboard.GetText() method.

For that and the keyboard inputs, create a new class and inherit from the TextBox control, override the OnKeyPress and WndProc methods to apply your input condition(s).

Public Class TextBoxEx
    Inherits TextBox

    Const WM_PASTE As Integer = &H302

    Protected Overrides Sub OnKeyPress(e As KeyPressEventArgs)
        If Not Char.IsControl(e.KeyChar) AndAlso Not Char.IsWhiteSpace(e.KeyChar) Then
            Dim s = Text.Insert(SelectionStart, e.KeyChar)

            If Not Decimal.TryParse(s.Replace(" ", ""), Nothing) Then
                e.Handled = True
            End If
        End If

        MyBase.OnKeyPress(e)
    End Sub

    Protected Overrides Sub WndProc(ByRef m As Message)
        If m.Msg = WM_PASTE AndAlso Clipboard.ContainsText() Then
            Dim s = Text.Remove(SelectionStart, SelectionLength).
                Insert(SelectionStart, Clipboard.GetText().Replace(" ", ""))
            If Not Decimal.TryParse(s, Nothing) Then Return
        End If

        MyBase.WndProc(m)
    End Sub

End Class
  • Related