VB.NET-Tipp 0141: Textbox für numerische Eingaben
von pks
Beschreibung
Dieser Tipp präsentiert eine TextBox für numerische Eingaben. Diese erlaubt es das Format der eingebbaren Zahl (Anzahl der Stellen vor und nach dem Komma) festzulegen und bietet eine Vielzahl an Darstellungmöglichkeiten (unterschiedliche Hintergrundfarbe bei Fokus, unterschiedliche Textfarben für positive und negative Zahlen)
Schwierigkeitsgrad: | Framework-Version(en): .NET Framework 1.0, .NET Framework 1.1, .NET Framework 2.0, .NET Framework 3.0, .NET Framework 3.5, .NET Framework 4 | .NET-Version(en): Visual Basic 2002, Visual Basic 2003, Visual Basic 2005, Visual Basic 2008, Visual Basic 2010 | Download: |
' Dieser Quellcode stammt von http://www.activevb.de ' und kann frei verwendet werden. Für eventuelle Schäden ' wird nicht gehaftet. ' Um Fehler oder Fragen zu klären, nutzen Sie bitte unser Forum. ' Ansonsten viel Spaß und Erfolg mit diesem Source! ' Projektversion: Visual Studio 2005 ' Option Strict: An ' ' Referenzen: ' - System ' - System.Data ' - System.Deployment ' - System.Drawing ' - System.Windows.Forms ' - System.Xml ' ' Imports: ' - System ' - System.Collections ' - System.Collections.Generic ' - System.Data ' - System.Drawing ' - System.Diagnostics ' - System.Windows.Forms ' ' ############################################################################## ' ################################# Form1.vb ################################### ' ############################################################################## Public Class Form1 Private Sub TboxEnter(ByVal sender As Object, ByVal e As System.EventArgs) DirectCast(sender, TextBox).BackColor = Color.PaleTurquoise End Sub Private Sub TboxNInsertError(ByVal sender As Object, _ ByVal e As TextboxNum.EventArgs) 'Eingabefehler behandeln End Sub Private Sub TboxKeyPress(ByVal sender As Object, _ ByVal e As System.Windows.Forms.KeyPressEventArgs) If e.KeyChar = Convert.ToChar(13) Then e.Handled = True SendKeys.Send("{Tab}") End If End Sub Private Sub TboxLeave(ByVal sender As Object, ByVal e As System.EventArgs) DirectCast(sender, TextBox).BackColor = SystemColors.Window End Sub Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load TextBoxHandlesAdd(Me) End Sub Private Sub TextBoxHandlesAdd(ByVal Container As Control, _ Optional ByVal SubContainerAlso As Boolean = True) For Each Ctl As Control In Container.Controls If TypeOf Ctl Is TextBox Then AddHandler Ctl.Enter, AddressOf TboxEnter AddHandler Ctl.KeyPress, AddressOf TboxKeyPress AddHandler Ctl.Leave, AddressOf TboxLeave ElseIf TypeOf Ctl Is TextboxNum Then Dim Tbox As TextboxNum = DirectCast(Ctl, TextboxNum) AddHandler Tbox.InsertError, AddressOf TboxNInsertError ElseIf (Ctl.Controls.Count > 0) AndAlso SubContainerAlso Then TextBoxHandlesAdd(Ctl, SubContainerAlso) End If Next End Sub Private Sub TextboxNum1_TextChanged(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles TextboxNum1.TextChanged End Sub End Class ' ############################################################################## ' ############################### TextboxNum.vb ################################ ' ############################################################################## Imports System.ComponentModel Public Class TextboxNum Inherits TextBox Private m_DecSeparator As Char = Convert.ToChar( _ System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyDecimalSeparator) Private m_GroupSeparator As Char = Convert.ToChar( _ System.Globalization.CultureInfo.CurrentCulture.NumberFormat.CurrencyGroupSeparator) Private m_DigitsTotal As Integer = 9 Private m_DigitsAfterPoint As Integer = 0 Private m_DigitsBeforePoint As Integer = 9 Private m_MinusAllowed As Boolean = False Private m_ShowNullOnEmpty As Boolean = False Private m_TextAlignFocus As Windows.Forms.HorizontalAlignment _ = HorizontalAlignment.Left Private m_TextAlignNotFocus As Windows.Forms.HorizontalAlignment _ = HorizontalAlignment.Right Private m_BackColorFocus As Color = Color.PaleTurquoise Private m_BackColorNotFocus As Color Private m_ForeColorMinus As Color Private m_ForeColorPlus As Color Private m_InsertFromClipBoard As Boolean = True Private m_FormatErrorShow As Boolean = False Private m_InsertErrorShow As Boolean = True Private m_Leaving As Boolean = False Private m_LeaveOnEnter As Boolean = True Private m_MouseDownRight As Boolean = False Private m_LastText As String Private m_FormatNumeric As String = "########0" #Region " Events " Public Event FormatError As EventHandler(Of EventArgs) Public Event InsertError As EventHandler(Of EventArgs) Public Class EventArgs Inherits System.EventArgs Private m_ErrorMessage As String Public Sub New(ByVal mErrorMessage As String) m_ErrorMessage = mErrorMessage End Sub ''' <summary> ''' liefert eine Fehlermeldung ''' </summary> Public ReadOnly Property ErrorMessage() As String Get Return m_ErrorMessage End Get End Property End Class #End Region Public Sub New() Me.TextAlignNotFocus = HorizontalAlignment.Right Me.TextAlign = HorizontalAlignment.Right m_ForeColorPlus = Me.ForeColor m_ForeColorMinus = Color.Red End Sub <Description("Regelt ob über Enter auf das nächste Steuerelementfeld " & _ "gewechselt wird"), Category("Verhalten")> _ Public Property LeaveOnEnter() As Boolean Get Return m_LeaveOnEnter End Get Set(ByVal value As Boolean) m_LeaveOnEnter = value End Set End Property <Description("Regelt ob über das Clipboard Daten eingefügt " & _ "werden können"), Category("Verhalten")> _ Public Property InsertFromClipBoard() As Boolean Get Return m_InsertFromClipBoard End Get Set(ByVal value As Boolean) m_InsertFromClipBoard = value End Set End Property <Description("Fehlermeldung anzeigen bei Formatfehlern (Anzahl Vor- " & _ "oder Nachkommastellen, Minus"), Category("Verhalten")> _ Public Property FormatErrorShow() As Boolean Get Return m_FormatErrorShow End Get Set(ByVal value As Boolean) m_FormatErrorShow = value End Set End Property <Description("Fehlermeldung anzeigen bei Insertfehlern " & _ "(einfügen über Clipboard)"), Category("Verhalten")> _ Public Property InsertErrorShow() As Boolean Get Return m_InsertErrorShow End Get Set(ByVal value As Boolean) m_InsertErrorShow = value End Set End Property <Description("Dezimalzeichen wie Komma (,)"), Category("Darstellung")> _ Public Property DecSeparator() As Char Get Return m_DecSeparator End Get Set(ByVal value As Char) m_DecSeparator = value End Set End Property <Description("Tausendertrennzeichen wie Punkt (.)"), _ Category("Darstellung")> _ Public Property Groupseparator() As Char Get Return m_GroupSeparator End Get Set(ByVal value As Char) m_GroupSeparator = value End Set End Property <Description("Gültige Formatierung wie (-#,###,##0.00), legt auch die " & _ "Maximaleingabe fest ausser Minus "), Category("Darstellung")> _ Public Property FormatNumeric() As String Get Return m_FormatNumeric End Get Set(ByVal value As String) If String.IsNullOrEmpty(value) Then MessageBox.Show("ungültiges Format") Else m_FormatNumeric = value m_MinusAllowed = False If value.IndexOf("-") >= 0 Then m_MinusAllowed = True End If Dim s() As String = value.Replace(",", "").Split("."c) If s.GetUpperBound(0) = 1 Then m_DigitsAfterPoint = s(1).Length Else m_DigitsAfterPoint = 0 End If m_DigitsBeforePoint = s(0).Replace("-", "").Length m_DigitsTotal = m_DigitsBeforePoint If m_DigitsAfterPoint > 0 Then m_DigitsTotal += m_DigitsAfterPoint + 1 End If End If End Set End Property <Description("Forecolor bei Positivwerten"), _ Category("Darstellung")> _ Public Property ForeColorPlus() As System.Drawing.Color Get Return m_ForeColorPlus End Get Set(ByVal value As System.Drawing.Color) m_ForeColorPlus = value End Set End Property <Description("Forecolor bei Minuswerten"), _ Category("Darstellung")> _ Public Property ForeColorMinus() As Color Get Return m_ForeColorMinus End Get Set(ByVal value As Color) m_ForeColorMinus = value End Set End Property <Description("Backcolor bei Focuserhalt"), _ Category("Darstellung")> _ Public Property BackColorFocus() As Color Get Return m_BackColorFocus End Get Set(ByVal value As Color) m_BackColorFocus = value End Set End Property <Description("Backcolor ohne Focus"), _ Category("Darstellung")> _ Public Property BackColorNotFocus() As Color Get Return m_BackColorNotFocus End Get Set(ByVal value As Color) m_BackColorNotFocus = value End Set End Property <Description("bei Leereingabe gemäss Formatierung Nullen anzeigen"), _ Category("Darstellung")> _ Public Property ShowNullOnEmpty() As Boolean Get Return m_ShowNullOnEmpty End Get Set(ByVal value As Boolean) m_ShowNullOnEmpty = value End Set End Property <Description("Minuseingabe erlaubt, wird gesteuert durch ein " & _ "führendes Minuszeichen (-) in FormatNumeric"), Category("Verhalten")> _ Public ReadOnly Property MinusAllowed() As Boolean Get Return m_MinusAllowed End Get End Property <Description("Ausrichtung bei Focuserhalt"), _ Category("Darstellung")> _ Public Property TextAlignFocus() As Windows.Forms.HorizontalAlignment Get Return m_TextAlignFocus End Get Set(ByVal value As Windows.Forms.HorizontalAlignment) m_TextAlignFocus = value End Set End Property <Description("Ausrichtung ohne Focus"), _ Category("Darstellung")> _ Public Property TextAlignNotFocus() As Windows.Forms.HorizontalAlignment Get Return m_TextAlignNotFocus End Get Set(ByVal value As Windows.Forms.HorizontalAlignment) m_TextAlignNotFocus = value End Set End Property <Description("Gesamtkapazität = Vorkomma+Komma+Nachkomma (ohne Minus)"), _ Category("Verhalten")> _ Public ReadOnly Property DigitsTotal() As Integer Get Return m_DigitsTotal End Get End Property Protected Overrides Sub OnEnter(ByVal e As System.EventArgs) ' Einrichten Align und Farben Me.TextAlign = TextAlignFocus Me.BackColor = BackColorFocus MyBase.OnEnter(e) End Sub Protected Overrides Sub OnKeyDown( _ ByVal e As System.Windows.Forms.KeyEventArgs) ' Einfügen über Clipboard abhandeln If e.Shift And (e.KeyCode = Keys.Insert) Then ' Erlaubt? If Not InsertFromClipBoard Then e.Handled = True Exit Sub Else Dim s As String = Me.Text.Insert(Me.SelectionStart, _ Clipboard.GetText) ' Einfügen möglich? If Not CanInsert(s) Then Dim ErrMsg As String = "Werte können nicht eingefügt werden" Dim Titel As String = "Einfügen über Clipboard" e.Handled = True If InsertErrorShow Then MessageBox.Show(ErrMsg, Titel, MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent InsertError(Me, New EventArgs(ErrMsg)) End If Exit Sub End If End If End If MyBase.OnKeyDown(e) End Sub Protected Overrides Sub OnValidated(ByVal e As System.EventArgs) ' Beim Verlassen formatieren If Not String.IsNullOrEmpty(Me.Text) Then Dim s As String = Me.Text.Replace(Groupseparator.ToString, "") Dim c As Decimal = Decimal.Parse(s) Me.Text = c.ToString(FormatNumeric.Replace("-", "")) Else If ShowNullOnEmpty Then Dim d As Double = 0 Me.Text = d.ToString(m_FormatNumeric) End If End If Me.BackColor = BackColorNotFocus MyBase.OnValidated(e) End Sub Protected Overrides Sub OnLeave(ByVal e As System.EventArgs) Dim Frm As Form = DirectCast(Me.Parent, Form) Dim Ctl As Control = Frm.ActiveControl Me.TextAlign = TextAlignNotFocus Ctl.Focus() MyBase.OnLeave(e) End Sub Protected Overrides Sub OnMouseDown( _ ByVal e As System.Windows.Forms.MouseEventArgs) 'Check für Einfügen über Clipboard vorbereiten m_MouseDownRight = (e.Button = Windows.Forms.MouseButtons.Right) m_LastText = Me.Text MyBase.OnMouseDown(e) End Sub Protected Overrides Sub OnMouseUp( _ ByVal mevent As System.Windows.Forms.MouseEventArgs) m_MouseDownRight = False MyBase.OnMouseUp(mevent) End Sub Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs) If m_MouseDownRight Then 'Einfügen über Clipboard erfolgt m_MouseDownRight = False If Not CanInsert(Me.Text) Or (Not InsertFromClipBoard) Then Me.Text = m_LastText Me.Refresh() Dim ErrMsg As String = "Werte können nicht eingefügt werden" Dim Titel As String = "einfügen über Clipboard" If InsertErrorShow Then MessageBox.Show(ErrMsg, Titel, MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent InsertError(Me, New EventArgs(ErrMsg)) End If Exit Sub End If End If 'Farbe für Plus/Minus regulieren If Not String.IsNullOrEmpty(Me.Text) Then If Me.Text.IndexOf("-") >= 0 Then Me.ForeColor = m_ForeColorMinus Else Me.ForeColor = m_ForeColorPlus End If End If MyBase.OnTextChanged(e) End Sub Protected Overrides Sub OnKeyPress(_ ByVal e As System.Windows.Forms.KeyPressEventArgs) MyBase.OnEnter(e) Dim ErrMsg As String = Nothing Dim Titel As String = "Eingabe numerisch" ' Zulässiges Kopieren über Ctrl+C, Einfügen über Ctrl+V Dim i As Integer = Convert.ToInt32(e.KeyChar) If i = 3 Then Exit Sub ElseIf i = 22 Then Dim s As String = Me.Text.Insert(Me.SelectionStart, _ Clipboard.GetText) ' Einfügen möglich? If Not CanInsert(s) Then e.Handled = True ErrMsg = "Werte können nicht eingefügt werden" Titel = "einfügen über Clipboard" e.Handled = True If InsertErrorShow Then MessageBox.Show(ErrMsg, Titel, MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent InsertError(Me, New EventArgs(ErrMsg)) End If End If Exit Sub End If Select Case e.KeyChar Case Convert.ToChar(13) e.Handled = True If LeaveOnEnter Then SendKeys.Send("{Tab}") End If Case Groupseparator If FormatNumeric.IndexOf(Groupseparator) < 0 Then e.Handled = True Else If Me.SelectionLength = Me.Text.Length Then Me.Text = "" End If End If Case "0"c To "9"c If Me.SelectionLength = Me.Text.Length Then Me.Text = "" End If If Not String.IsNullOrEmpty(Me.Text) Then Dim s() As String = Me.Text.Replace( _ Groupseparator.ToString, "").Split(DecSeparator) s(0) = s(0).Replace("-", "") If s.GetUpperBound(0) = 1 Then If Me.SelectionStart <= _ Me.Text.IndexOf(DecSeparator) Then If s(0).Length = m_DigitsBeforePoint Then ErrMsg = "maximal " & _ m_DigitsBeforePoint.ToString & _ " (Vorkomma)Stellen" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, _ New EventArgs(ErrMsg)) End If End If Else If s(1).Length = m_DigitsAfterPoint Then ErrMsg = "maximal " & _ m_DigitsAfterPoint.ToString & _ " Nachkommastellen" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, _ New EventArgs(ErrMsg)) End If End If End If Else If s(0).Length = m_DigitsBeforePoint Then ErrMsg = "maximal " & _ m_DigitsBeforePoint.ToString & _ " (Vorkomma)Stellen" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, _ New EventArgs(ErrMsg)) End If End If End If End If Case "-"c If Not MinusAllowed Then ErrMsg = "keine Minuswerte erlaubt" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, New EventArgs(ErrMsg)) End If ElseIf Me.SelectionLength = Me.Text.Length Then Me.Text = "" Else If (Me.Text.IndexOf("-"c) >= 0) Or _ (Me.SelectionStart > 0) Then ErrMsg = "Minuszeichen immer an 1. Stelle" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, New EventArgs(ErrMsg)) End If End If End If Case Convert.ToChar(8) Case DecSeparator If m_DigitsAfterPoint = 0 Then ErrMsg = "keine Nachkommastellen erlaubt" e.Handled = True If FormatErrorShow Then MessageBox.Show(ErrMsg, Titel, _ MessageBoxButtons.OK, _ MessageBoxIcon.Error) Else RaiseEvent FormatError(Me, New EventArgs(ErrMsg)) End If ElseIf Me.SelectionLength = Me.Text.Length Then Me.Text = "" Else If Me.Text.IndexOf(DecSeparator) >= 0 Then e.Handled = True End If End If Case Else e.Handled = True End Select End Sub ''' <summary> ''' Aufruf bei Einfügen über Clipboard ''' </summary> Private Function CanInsert(ByVal s As String) As Boolean Try Dim d As Decimal = Decimal.Parse(s) s = d.ToString If (d < 0) AndAlso (Not MinusAllowed) Then Return False End If s = s.Replace("-", "") Dim k() As String = s.Split(","c) If k.GetUpperBound(0) > 1 Then Return False End If If k(0).Length > m_DigitsBeforePoint Then Return False End If If k.GetUpperBound(0) = 1 Then If k(1).Length > m_DigitsAfterPoint Then Return False End If End If Return True Catch ex As Exception Return False End Try End Function End Class
Ihre Meinung
Falls Sie Fragen zu diesem Artikel haben oder Ihre Erfahrung mit anderen Nutzern austauschen möchten, dann teilen Sie uns diese bitte in einem der unten vorhandenen Themen oder über einen neuen Beitrag mit. Hierzu können sie einfach einen Beitrag in einem zum Thema passenden Forum anlegen, welcher automatisch mit dieser Seite verknüpft wird.