Que tal a todos, tanto tiempo, ahora voy a publicarles el código fuente de un TextBox numérico bastante útil para trabajar con sistemas de administración o ventas. Este control forma parte del código fuente del Sistema de Gestión y Administración que les vengo prometiendo desde hace un tiempo, y que todavía no he tenido tiempo de terminar por uno u otro motivo, pero para no retrasar la salida más, voy a comenzar a publicar partes del código.
Este TextBox nos permite (o no) ingresar número, y es una adaptación de un código encontrado en Internet hecho originalmente en C#, yo sólo hice la transformación y algunos arreglos y adaptaciones, aunque seguramente el que lo utilice podrá seguirlo modificando o agregando funcionalidad.Recuerden que para utilizar este código deben crear un nuevo componente. Aquí tienen el código del archivo trasero del componente, es muy probable que tengan quemodificarlo para que no les tire un error.Imports System
Imports System.Globalization
Imports System.Windows
Imports System.Windows.Forms
Imports System.Text
Imports System.ComponentModel
Imports System.Drawing
Imports System.Data
Imports System.Xml
''' <summary>
''' Control TextBox que acepta sólo valores numéricos ya sean positivos o negativos
''' utilizando valores especiales, evitando que el usuario pueda cometer errores de
''' tipeo sobre el mismo. Es altamente configurable y se puede modificar para agregar
''' o quitar funcionalidad.
''' </summary>
<DefaultProperty("NumericValue"), DefaultEvent("NumericValueChanged"), _
ToolboxBitmap(GetType(System.Windows.Forms.TextBox))> _
Public Class TextBoxN
Inherits TextBox
#Region " Variables "
Private ib_AllowNegative As Boolean = True
Private ib_NoChangeEvent As Boolean = False
Private ib_ZeroNotValid As Boolean = False
Private idec_InternalValue As Decimal = 0
Private idec_NumericValue As Decimal = 0
Private ii_Precision As Integer = 1
Private ii_ScaleOnFocus As Integer = 0
Private ii_ScaleOnLostFocus As Integer = 0
Private ib_EnterColor As Color = Color.LightYellow
Private ib_LeaveColor As Color = Color.Khaki
#End Region
#Region " Eventos "
''' <summary>
''' Manejador de eventos que se dispara al cambiar un valor numérico.
''' </summary>
''' <remarks></remarks>
Public Event NumericValueChanged As EventHandler
#End Region
#Region " Constructor "
''' <summary>
''' Constructor que establece los valores por defecto del control.
''' </summary>
''' <remarks></remarks>
Public Sub New()
MyBase.New()
Me.Text = 0
Me.TextAlign = HorizontalAlignment.Right
Me.AllowNegative = False
Me.NumericPrecision = 50
Me.NumericScaleOnFocus = 2
Me.NumericScaleOnLostFocus = 2
Me.ZeroIsValid = True
End Sub
#End Region
#Region " Funciones "
''' <summary>
''' Función que formatea el texto ingresado en el TextBox de modo que tenga un
''' formato especial.
''' </summary>
''' <returns>El texto dentro del control formateado</returns>
''' <remarks></remarks>
Protected Function FormatNumber()
Dim lsb_Format As New StringBuilder
Dim li_Counter As Integer = 1
Dim ll_Remainder As Long = 0
If Not Me.Focused Then
Do While (li_Counter <= (Me.ii_Precision - Me.ii_ScaleOnLostFocus))
If (li_Counter = 1) Then
lsb_Format.Insert(0, "0")
Else
lsb_Format.Insert(0, "#")
End If
Math.DivRem(CLng(li_Counter), 3, ll_Remainder)
If ((ll_Remainder = 0) AndAlso ((li_Counter + 1) <= (Me.ii_Precision - Me.ii_ScaleOnLostFocus))) Then
lsb_Format.Insert(0, ",")
End If
li_Counter += 1
Loop
li_Counter = 1
If (Me.ii_ScaleOnLostFocus > 0) Then
lsb_Format.Append(".")
Do While (li_Counter <= Me.ii_ScaleOnLostFocus)
lsb_Format.Append("0")
li_Counter += 1
Loop
End If
Else
Do While (li_Counter <= (Me.ii_Precision - Me.ii_ScaleOnFocus))
If (li_Counter = 1) Then
lsb_Format.Insert(0, "0")
Else
lsb_Format.Insert(0, "#")
End If
Math.DivRem(CLng(li_Counter), 3, ll_Remainder)
li_Counter += 1
Loop
li_Counter = 1
If (Me.ii_ScaleOnFocus > 0) Then
lsb_Format.Append(".")
Do While (li_Counter <= Me.ii_ScaleOnFocus)
lsb_Format.Append("0")
li_Counter += 1
Loop
End If
End If
Return Convert.ToDecimal(Me.Text).ToString(lsb_Format.ToString)
End Function
#End Region
#Region " Procedimientos "
''' <summary>
''' Cambia el color cuando el usuario entra al control.
''' </summary>
Private Sub OnEnterTextBoxN(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Enter
Me.BackColor = EnterFocusColor
End Sub
''' <summary>
''' Cambia el color del control cuando el usuario sale del mismo.
''' </summary>
Private Sub OnLeaveTextBoxN(ByVal sender As System.Object, ByVal e As System.EventArgs) _
Handles MyBase.Leave
Me.BackColor = LeaveFocusColor
End Sub
''' <summary>
''' Cuando el control recibe el foco, formateamos el texto del control
''' de acuerdo al texto existente.
''' </summary>
Private Sub OnGotFocusTextBoxN(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.GotFocus
Me.ib_NoChangeEvent = True
Me.Text = Convert.ToString(Me.idec_InternalValue)
If (Me.ii_ScaleOnFocus <> 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text.IndexOf("-") < 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text = "-") Then
Me.Text = ""
Else
Me.Text = Me.FormatNumber
End If
Me.ib_NoChangeEvent = False
End Sub
''' <summary>
''' Al presionar una tecla comprobamos la posición del cursor y de acuerdo al lugar en el que
''' se encuentre realizamos las conversiones necesarias sobre la cadena de texto.
''' </summary>
Private Sub OnKeyDownTextBoxN(ByVal sender As Object, ByVal e As KeyEventArgs)
Dim lb_PositionCursorJustBeforeComma As Boolean = False
If (Me.ii_ScaleOnFocus <> 0) Then
lb_PositionCursorJustBeforeComma = (MyBase.SelectionStart = _
Me.Text.IndexOf(Me.DecimalSeperator))
End If
If (e.KeyCode = Keys.Delete) Then
If lb_PositionCursorJustBeforeComma Then
MyBase.SelectionStart = (Me.Text.IndexOf(Me.DecimalSeperator) + 1)
e.Handled = True
ElseIf (Me.Text.IndexOf("-") < 0) Then
If (Me.SelectionLength = Me.Text.Length) Then
Me.Text = "0"
MyBase.SelectionStart = 1
e.Handled = True
End If
ElseIf (Me.SelectionLength = Me.Text.Length) Then
Me.Text = "0"
MyBase.SelectionStart = 1
e.Handled = True
ElseIf (((Me.SelectionLength > 0) AndAlso (Me.SelectedText <> "-")) _
AndAlso (Convert.ToDouble(Me.SelectedText) = _
Math.Abs(Convert.ToDouble(Me.Text)))) Then
Me.Text = "0"
MyBase.SelectionStart = 1
e.Handled = True
End If
End If
End Sub
''' <summary>
''' Al presionar una tecla realiza todas las operaciones necesarias para formatear el texto
''' en el TextBox y mostrar la salida al usuario. Este es el procedimiento principal que le
''' permite al usuario er la salida del texto completa.
''' </summary>
Private Sub OnKeyPressTextBoxN(ByVal sender As Object, _
ByVal e As KeyPressEventArgs) Handles MyBase.KeyPress
Dim lb_PositionCursorBeforeComma As Boolean = False
Dim lb_InputBeforeCommaValid As Boolean = False
Dim lb_PositionCursorJustAfterComma As Boolean = False
Dim li_SelStart As Integer = 0
lb_InputBeforeCommaValid = True
If e.KeyChar = "-" AndAlso Me.AllowNegative = True Then
If (Me.Text.IndexOf("-") < 0) Then
li_SelStart = MyBase.SelectionStart
If Not (Convert.ToDecimal(Me.Text) = 0) Then
Me.Text = ("-" & Me.Text)
MyBase.SelectionStart = (li_SelStart + 1)
End If
e.Handled = True
Else
If (Me.SelectionLength = 0) Then
li_SelStart = MyBase.SelectionStart
Me.Text = Convert.ToString(CDbl((Convert.ToDouble(Me.Text) * -1)))
MyBase.SelectionStart = (li_SelStart - 1)
e.Handled = True
Else
If (Me.SelectionLength = Me.TextLength) Then
Me.Text = "-0"
End If
e.Handled = True
End If
e.Handled = True
End If
ElseIf e.KeyChar = "+" Then
If (Me.Text.IndexOf("-") >= 0) Then
If (Me.SelectionLength = 0) Then
li_SelStart = MyBase.SelectionStart
Me.Text = Convert.ToString(CDbl((Convert.ToDouble(Me.Text) * -1)))
MyBase.SelectionStart = (li_SelStart - 1)
e.Handled = True
ElseIf (Me.TextLength = Me.SelectionLength) Then
Me.Text = "0"
e.Handled = True
End If
End If
e.Handled = True
Else
If (Me.ii_ScaleOnFocus <> 0) Then
lb_PositionCursorJustAfterComma = (MyBase.SelectionStart = _
(Me.Text.IndexOf(Me.DecimalSeperator) + 1))
End If
If (e.KeyChar = ChrW(8)) Then
If lb_PositionCursorJustAfterComma Then
MyBase.SelectionStart = Me.Text.IndexOf(Me.DecimalSeperator)
e.Handled = True
End If
If (Me.SelectionLength = Me.Text.Length) Then
Me.Text = "0"
MyBase.SelectionStart = 1
e.Handled = True
End If
If e.KeyChar = Nothing Then
e.Handled = True
End If
ElseIf (("1234567890" & Me.DecimalSeperator).IndexOf(e.KeyChar) < 0) Then
e.Handled = True
Else
If (Me.ii_ScaleOnFocus <> 0) Then
lb_PositionCursorBeforeComma = (MyBase.SelectionStart < _
(Me.Text.IndexOf(Me.DecimalSeperator) + 1))
End If
If (e.KeyChar.ToString = Me.DecimalSeperator) Then
If lb_PositionCursorBeforeComma Then
MyBase.SelectionStart = (Me.Text.IndexOf(Me.DecimalSeperator) + 1)
Me.SelectionLength = 0
End If
e.Handled = True
ElseIf ((Me.ii_ScaleOnFocus <> 0) AndAlso (MyBase.SelectionStart = _
Me.Text.Length)) Then
e.Handled = True
Else
If (Me.ii_ScaleOnFocus <> 0) Then
If (Me.Text.IndexOf("-") < 0) Then
lb_InputBeforeCommaValid = (Me.Text.Substring(0, _
Me.Text.IndexOf(Me.DecimalSeperator)).Length < (Me.ii_Precision - Me.ii_ScaleOnFocus))
Else
lb_InputBeforeCommaValid = (Me.Text.Substring(0, _
Me.Text.IndexOf(Me.DecimalSeperator)).Length < ((Me.ii_Precision - Me.ii_ScaleOnFocus) + 1))
End If
ElseIf (Me.Text.IndexOf("-") < 0) Then
lb_InputBeforeCommaValid = (Me.Text.Length < Me.ii_Precision)
Else
lb_InputBeforeCommaValid = (Me.Text.Length < (Me.ii_Precision + 1))
End If
If (Me.ii_ScaleOnFocus <> 0) Then
If ((Me.Text.Substring(0, 1) = "0") AndAlso (MyBase.SelectionStart <> 0)) Then
lb_InputBeforeCommaValid = True
End If
If (Me.SelectionLength > 0) Then
lb_InputBeforeCommaValid = True
End If
Else
If ((Me.Text.Substring(0, 1) = "0") AndAlso ((MyBase.SelectionStart = _
Me.Text.Length) OrElse (Me.SelectionLength = 1))) Then
lb_InputBeforeCommaValid = True
End If
If (Me.SelectionLength > 0) Then
lb_InputBeforeCommaValid = True
End If
End If
If (Me.ii_ScaleOnFocus <> 0) Then
If Not (Not lb_PositionCursorBeforeComma OrElse lb_InputBeforeCommaValid) Then
e.Handled = True
End If
ElseIf Not lb_InputBeforeCommaValid Then
e.Handled = True
End If
End If
End If
End If
End Sub
''' <summary>
''' Al perder el foco, volvemos a formatear el texto del control de modo de evitar algún error
''' inesperado.
''' </summary>
Private Sub OnLostFocusTextBoxN(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.LostFocus
Me.ib_NoChangeEvent = True
Me.idec_InternalValue = Convert.ToDecimal(Me.Text)
If (Me.ii_ScaleOnLostFocus <> 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text.IndexOf("-") < 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text = "-") Then
Me.Text = ""
Else
Me.Text = Me.FormatNumber
End If
Me.ib_NoChangeEvent = False
End Sub
''' <summary>
''' Al cambiar el texto del control realizamos todas las comprobaciones necesarias para convertir
''' la cadena de texto en un número formateado correctamente.
''' </summary>
Private Sub OnTextChangedTextBoxN(ByVal sender As Object, _
ByVal e As EventArgs) Handles MyBase.TextChanged
Try
Dim li_SelStart As Integer = 0
Dim lb_PositionCursorBeforeComma As Boolean = False
If (Not Me.ib_NoChangeEvent AndAlso (MyBase.SelectionStart <> -1)) Then
Me.ib_NoChangeEvent = True
If String.Empty = Me.Text.Trim Then
Me.Text = "0"
End If
If (Me.ii_ScaleOnFocus <> 0) Then
If (MyBase.SelectionStart = Me.Text.IndexOf(Me.DecimalSeperator)) Then
lb_PositionCursorBeforeComma = True
Else
li_SelStart = MyBase.SelectionStart
End If
Else
li_SelStart = MyBase.SelectionStart
End If
Me.idec_InternalValue = Convert.ToDecimal(Me.Text)
Me.NumericValue = Convert.ToDecimal(Me.Text)
If Me.Focused Then
If (Me.ii_ScaleOnFocus <> 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text.IndexOf("-") < 0) Then
Me.Text = Me.FormatNumber
ElseIf Me.Text = "-" Then
Me.Text = ""
Else
Me.Text = Me.FormatNumber
End If
ElseIf (Me.ii_ScaleOnLostFocus <> 0) Then
Me.Text = Me.FormatNumber
ElseIf (Me.Text.IndexOf("-") < 0) Then
Me.Text = Me.FormatNumber
ElseIf Me.Text = "-" Then
Me.Text = ""
Else
Me.Text = Me.FormatNumber
End If
If (Me.ii_ScaleOnFocus <> 0) Then
If lb_PositionCursorBeforeComma Then
MyBase.SelectionStart = Me.Text.IndexOf(Me.DecimalSeperator)
Else
MyBase.SelectionStart = li_SelStart
End If
Else
MyBase.SelectionStart = li_SelStart
End If
Me.ib_NoChangeEvent = False
End If
Catch
End Try
End Sub
''' <summary>
''' Si el texto dentro del control no es válido, entonces obligamos al usuario a quedarse y corregir
''' los posibles errores que se encuentren. Por lo general este evento se disparará cuando esté
''' activada la opción de ZeroIsAllowed (Si está permitido el cero).
''' </summary>
Private Sub OnValidatingTextBoxN(ByVal sender As Object, _
ByVal e As CancelEventArgs) Handles MyBase.Validating
If Not ((Not Me.Text = String.Empty AndAlso Not Convert.ToDecimal(Me.NumericValue).Equals(Convert.ToDecimal(0))) OrElse Me.ZeroIsValid) Then
e.Cancel = True
End If
End Sub
''' <summary>
''' Dispara el evento OnNumericValueChanged
''' </summary>
Protected Sub OnNumericValueChanged(ByVal e As EventArgs)
RaiseEvent NumericValueChanged(Me, e)
End Sub
#End Region
#Region " Propiedades "
<Category("Especial")> _
Public Property EnterFocusColor() As Color
Get
Return ib_EnterColor
End Get
Set(ByVal value As Color)
ib_EnterColor = value
End Set
End Property
<Category("Especial")> _
Public Property LeaveFocusColor() As Color
Get
Return ib_LeaveColor
End Get
Set(ByVal value As Color)
ib_LeaveColor = value
End Set
End Property
<Category("Especial")> _
Public Property AllowNegative() As Boolean
Get
Return Me.ib_AllowNegative
End Get
Set(ByVal value As Boolean)
Me.ib_AllowNegative = value
End Set
End Property
<Category("Especial")> _
Public Property NumericPrecision() As Integer
Get
Return Me.ii_Precision
End Get
Set(ByVal value As Integer)
If (value < 0) Then
MessageBox.Show("Precision cannot be negative!", "Numeric TextBox", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Else
If (value < Me.NumericScaleOnFocus) Then
Me.NumericScaleOnFocus = value
End If
Me.ii_Precision = value
End If
End Set
End Property
<RefreshProperties(RefreshProperties.All), Category("Especial")> _
Public Property NumericScaleOnFocus() As Integer
Get
Return Me.ii_ScaleOnFocus
End Get
Set(ByVal value As Integer)
If (value < 0) Then
MessageBox.Show("Scale cannot be negative!", "Numeric TextBox", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
ElseIf (value >= Me.NumericPrecision) Then
MessageBox.Show("Scale cannot be larger than precission!", "Numeric TextBox", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Else
Me.ii_ScaleOnFocus = value
If (Me.ii_ScaleOnFocus > 0) Then
Me.Text = ("0" & Me.DecimalSeperator & New String(Convert.ToChar("0"), Me.ii_ScaleOnFocus))
Else
Me.Text = "0"
End If
End If
End Set
End Property
<Category("Especial"), RefreshProperties(RefreshProperties.All)> _
Public Property NumericScaleOnLostFocus() As Integer
Get
Return Me.ii_ScaleOnLostFocus
End Get
Set(ByVal value As Integer)
If (value < 0) Then
MessageBox.Show("Scale cannot be negative!", "Numeric TextBox", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
ElseIf (value >= Me.NumericPrecision) Then
MessageBox.Show("Scale cannot be larger than precesion!", "Numeric TextBox", MessageBoxButtons.OK, MessageBoxIcon.Asterisk)
Else
Me.ii_ScaleOnLostFocus = value
End If
End Set
End Property
<Category("Especial"), Bindable(True)> _
Public Property NumericValue() As Object
Get
Return idec_NumericValue
End Get
Set(ByVal value As Object)
If value = Nothing Then
If value = 0 Then
Me.Text = Convert.ToString(0)
idec_NumericValue = Convert.ToDecimal(0)
Me.OnNumericValueChanged(New EventArgs)
End If
ElseIf Not value = idec_NumericValue Then
Me.Text = Convert.ToString(value)
idec_NumericValue = Convert.ToDecimal(value)
Me.OnNumericValueChanged(New EventArgs)
End If
End Set
End Property
<Category("Especial")> _
Public Property ZeroIsValid() As Boolean
Get
Return Me.ib_ZeroNotValid
End Get
Set(ByVal value As Boolean)
Me.ib_ZeroNotValid = value
End Set
End Property
Private ReadOnly Property DecimalSeperator() As String
Get
Return NumberFormatInfo.CurrentInfo.NumberDecimalSeparator
End Get
End Property<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class TextBoxComprobantes
Inherits System.Windows.Forms.TextBox
'UserControl1 overrides dispose to clean up the component list.
<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub
'Required by the Windows Form Designer
Private components As System.ComponentModel.IContainer
'NOTE: The following procedure is required by the Windows Form Designer
'It can be modified using the Windows Form Designer.
'Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
End Sub
End Class
Un TextBox Numérico
Etiquetas:
Código Fuente,
Microsoft,
Programación,
TextBox,
TextBox Numérico,
Visual Basic,
Windows
|
0
comentarios
Publicado por
Adrian Paesani
en
5:23 PM
Enlaces a esta entrada
Suscribirse a:
Entradas (Atom)
