Private Sub cellTextBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles cellTextBox.KeyPress
' Referenciamos el control TextBox subyacente.
'
Dim tb As TextBox = TryCast(sender, TextBox)
' Si la conversión ha fallado, abandonamos el procedimiento.
'
If (tb Is Nothing) Then
e.Handled = True
Return
End If
Dim isDecimal, isSign, isValidChar As Boolean
Dim decimalSeparator As String = Nothing
Select Case e.KeyChar
Case "."c, ","c
' Obtenemos el carácter separador decimal existente
' actualmente en la configuración regional de Windows.
'
decimalSeparator = Threading.Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator
' Hacemos que el carácter tecleado coincida con el
' carácter separador existentente en la configuración
' regional.
'
e.KeyChar = decimalSeparator.Chars(0)
' Si el primer carácter que se teclea es el separador decimal,
' o si bien, existe un signo en el primer carácter, envío la
' combinación '0,'.
'
If (((tb.TextLength = 0) OrElse (tb.SelectionLength = tb.TextLength)) OrElse _
((tb.TextLength = 1) AndAlso ((tb.Text.Contains("-")) OrElse (Text.Contains("+"))))) Then
' NOTA: Envío la combinación "0," mediante el método Send,
' para que en el código cliente se desencadenen los
' eventos de teclado.
'
SendKeys.Send("{0}")
SendKeys.Send("{" & decimalSeparator & "}")
e.Handled = True
Return
End If
' Es un carácter válido.
'
isDecimal = True
isValidChar = True
Case Else
' Sólo se admitirán números y la tecla de retroceso.
'
Dim isDigit As Boolean = Char.IsDigit(e.KeyChar)
Dim isControl As Boolean = Char.IsControl(e.KeyChar)
If ((isDigit) OrElse (isControl)) Then
isValidChar = True
Else
e.Handled = True
Return
End If
End Select
' Si es un carácter válido, y el texto del control
' se encuentra totalmente seleccionado, elimino
' el valor actual del control.
'
If ((isValidChar) And (tb.SelectionLength = tb.TextLength)) Then
tb.Text = String.Empty
End If
If (isSign) Then
' Admitimos los caracteres positivo y negativo, siempre y cuando
' sea el primer carácter del texto, y no exista ya ningún otro
' signo escrito en el control.
'
If ((tb.SelectionStart <> 0) OrElse _
(tb.Text.IndexOf("-") >= 0) OrElse _
(tb.Text.IndexOf("+") >= 0)) Then
e.Handled = True
Return
End If
End If
If (isDecimal) Then
' Si en el control hay ya escrito un separador decimal,
' deshechamos insertar otro separador más.
'
If (tb.Text.IndexOf(decimalSeparator) >= 0) Then
e.Handled = True
Return
End If
End If
End Sub