- Public Class NumericBox
- Inherits System.Windows.Forms.TextBox
-
- Dim _decimals As Integer = -1 ' -1 pour ne pas limiter le nombre de décimales
- Friend DecimalSeparator As String = Application.CurrentCulture.NumberFormat.NumberDecimalSeparator
-
- Public Shadows Event TextChanged(ByVal Sender As Object, ByVal e As System.EventArgs) 'pour l'arrondi
- Dim isRoundUp As Boolean = False 'signifie au controle qu'il est en train d'arrondir le Text
-
- Public Sub New()
- MyBase.New()
- Me.TextAlign = HorizontalAlignment.Right
- Me.Name = "NumericBox"
- 'Me.Text = "0"
- End Sub
-
- Public Property Decimals() As Integer
- Get
- Return _decimals
- End Get
- Set(ByVal Value As Integer)
- _decimals = Value
- End Set
- End Property
-
-
- #Region "Form event"
- ' on bloque tous les caractères (keypress)
- ' puis on fait une deuxième vérif au changement (TextChanged)
- ' enfin en dernier quand on quitte(LostFocus)
-
- Private Sub NumericBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
- ' Numériques + ponctuation + Ctrl sinon ne tient pas compte de l'action (évite de tout gérer sur le Handles MyBase.TextChanged)
- If Not e.KeyChar.IsDigit(e.KeyChar) And _
- Not e.KeyChar.IsPunctuation(e.KeyChar) And _
- Not e.KeyChar.IsControl(e.KeyChar) Then e.Handled = True
- ' une seule ponctuation
- If e.KeyChar.IsPunctuation(e.KeyChar) And InStr(Text, DecimalSeparator) > 0 Then e.Handled = True
- End Sub
-
- Private Sub NumericBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.TextChanged
- 'Test arrondi en cours
- If isRoundUp Then Exit Sub
- ' Test séparateur décimal
- If Not IsNumeric(Text) And SelectionStart > -1 Then
- Dim iPos As Int16 = SelectionStart 'la position du curseur
- ReplaceSeparateurDecimal()
- SelectionStart = iPos
- End If
- ' Test Numérique (notemment dans le cas d'un copié collé douteux)
- If Len(Text) > 0 And Not IsNumeric(Replace(Text, " ", "")) Then MyBase.Undo() ' Text = ""
-
- ' Arrondi fait ici si le controle n'a pas le focus quand le texte change
- If Not Focus() Then Roundup()
-
- ' Déclenche l'event
- RaiseEvent TextChanged(sender, e)
- End Sub
-
- Private Sub NumericBox_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.LostFocus
- ' Arrondi en sortant
- Roundup()
- End Sub
- #End Region
-
- #Region "private sub & functions"
- Private Sub Roundup()
- ' test numérique
- If Not IsNumeric(Replace(Text, " ", "")) Then Exit Sub
-
- ' position initiale du curseur
- Dim iPos As Int16 = SelectionStart
- isRoundUp = True
-
- ' Arrondi au nombre de décimales choisies (_decimals = -1 pour ne pas arrondir)
- If _decimals > -1 Then
- Me.Text = Math.Round(CType(Replace(Text, " ", ""), Decimal) * 10 ^ _decimals) * 10 ^ (-_decimals)
- End If
-
- ' Formatage du résultat
- Me.Text = FormatNumber(Text, _decimals)
-
- ' Retour à la position initiale du curseur si il avait le focus (iPos > -1)
- If iPos > -1 Then SelectionStart = iPos
- isRoundUp = False
- End Sub
-
- Private Sub ReplaceSeparateurDecimal() 'remplace le . en ,
- Text = Replace(Text, ".", DecimalSeparator)
- End Sub
- #End Region
-
- End Class
Public Class NumericBox
Inherits System.Windows.Forms.TextBox
Dim _decimals As Integer = -1 ' -1 pour ne pas limiter le nombre de décimales
Friend DecimalSeparator As String = Application.CurrentCulture.NumberFormat.NumberDecimalSeparator
Public Shadows Event TextChanged(ByVal Sender As Object, ByVal e As System.EventArgs) 'pour l'arrondi
Dim isRoundUp As Boolean = False 'signifie au controle qu'il est en train d'arrondir le Text
Public Sub New()
MyBase.New()
Me.TextAlign = HorizontalAlignment.Right
Me.Name = "NumericBox"
'Me.Text = "0"
End Sub
Public Property Decimals() As Integer
Get
Return _decimals
End Get
Set(ByVal Value As Integer)
_decimals = Value
End Set
End Property
#Region "Form event"
' on bloque tous les caractères (keypress)
' puis on fait une deuxième vérif au changement (TextChanged)
' enfin en dernier quand on quitte(LostFocus)
Private Sub NumericBox_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles MyBase.KeyPress
' Numériques + ponctuation + Ctrl sinon ne tient pas compte de l'action (évite de tout gérer sur le Handles MyBase.TextChanged)
If Not e.KeyChar.IsDigit(e.KeyChar) And _
Not e.KeyChar.IsPunctuation(e.KeyChar) And _
Not e.KeyChar.IsControl(e.KeyChar) Then e.Handled = True
' une seule ponctuation
If e.KeyChar.IsPunctuation(e.KeyChar) And InStr(Text, DecimalSeparator) > 0 Then e.Handled = True
End Sub
Private Sub NumericBox_TextChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.TextChanged
'Test arrondi en cours
If isRoundUp Then Exit Sub
' Test séparateur décimal
If Not IsNumeric(Text) And SelectionStart > -1 Then
Dim iPos As Int16 = SelectionStart 'la position du curseur
ReplaceSeparateurDecimal()
SelectionStart = iPos
End If
' Test Numérique (notemment dans le cas d'un copié collé douteux)
If Len(Text) > 0 And Not IsNumeric(Replace(Text, " ", "")) Then MyBase.Undo() ' Text = ""
' Arrondi fait ici si le controle n'a pas le focus quand le texte change
If Not Focus() Then Roundup()
' Déclenche l'event
RaiseEvent TextChanged(sender, e)
End Sub
Private Sub NumericBox_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.LostFocus
' Arrondi en sortant
Roundup()
End Sub
#End Region
#Region "private sub & functions"
Private Sub Roundup()
' test numérique
If Not IsNumeric(Replace(Text, " ", "")) Then Exit Sub
' position initiale du curseur
Dim iPos As Int16 = SelectionStart
isRoundUp = True
' Arrondi au nombre de décimales choisies (_decimals = -1 pour ne pas arrondir)
If _decimals > -1 Then
Me.Text = Math.Round(CType(Replace(Text, " ", ""), Decimal) * 10 ^ _decimals) * 10 ^ (-_decimals)
End If
' Formatage du résultat
Me.Text = FormatNumber(Text, _decimals)
' Retour à la position initiale du curseur si il avait le focus (iPos > -1)
If iPos > -1 Then SelectionStart = iPos
isRoundUp = False
End Sub
Private Sub ReplaceSeparateurDecimal() 'remplace le . en ,
Text = Replace(Text, ".", DecimalSeparator)
End Sub
#End Region
End Class