Discussion:
control de usuario
(demasiado antiguo para responder)
Ivan
2008-02-22 01:02:01 UTC
Permalink
hola a todos,

es mi primera entrada en este grupo como 'escribiente' y [casi] también mis primeras pruebas con vb.net (lo poco que se
es vba, y, por 'simbiosis', un pelín de vb), así que espero me disculpéis si digo muchas burradas.

la cosa es que estoy intentando crear un control de usuario para contar euros según el tipo de moneda: desde el billete
de 500 (quien los pillara) hasta la moneda de 1 céntimo.

en excel me he creado un control personalizado que en realidad es un frame con +/- los mismos controles o equivalentes
que estoy probando en net y mediante una clase consigo que funcione bastante bien (entre ""). Pero por curiosidad y
buscando la idea de tenerlo disponible realmente como si de un Activex se tratara, con sus propiedades y métodos mínimos
disponibles como un control de msForms o similar, me he liado a intentar aprender un poco de Vb.Net, y aquí me hallo,
mas perdido que ...

el control es un UserControl que contiene 15 'grupos de controles' de esta forma =>

.- 1 label para el valor de la moneda (no interviene en nada, es solo informativo)
.- 1 NumberUpDown para introducir o elegir el nº de monedas/billetes. En la prp. Tag almaceno el valor de la moneda
correspondiente( 500, 200, ..., 0.02, 0.01)
.- 1 label que muestra el total por cada moneda

forman dos columnas +/- así => Moneda//NumberUpDown //SubTotal

.-> los NumberUpDown se llaman Num1, Num2, Num3, ....., Num14, Num15
.-> los label para el subtotal se llaman SubT1, .....SubT15, y muestran el resultado de multiplicar el Tag de su
correspondiente NumN con el nº elegido o introducido en este

,- el control se completa con un TextBox para introducir cantidades diversas/aleatorias y otro label (lblTotal) que
muestra la suma total de todos los subtotales mas el textbox (txtOtros)

de momento, y tras unas cuantas peleas con la forma de uso de las funciones intrinsecas de Vb y otras muchas cosas mas,
lo que respecta a los numberupdown, subtotales y total de estos parece funcionar aceptablemente

.->> el problema es el dichoso textbox (curiosamente lo que menos problemas esperaba que me diera)

una vez +/- solucionado el tema de la mascara de entrada (gracias a SoftJaen en un mensaje de este grupo) y a duras
penas los lios con la configuración regional, ahora lo que me ocurre es un sinfín de 'sinsentidos', al menos para mi:

1.-por un lado, no se que evento utilizar para actualizar el total tras los cambios en el textbox: con el TextChanged,
que me parecía lo mas equivalente al change de vba, al intentar ejecutar el control (con F5) me dice algo parecido a
variable de objeto no establecida.

2.- he probado en otros como los de teclado o en Leave, pero lo mas que he conseguido es que en vez de actualizar el
lblTotal ponga en el primer NumberUpDown (Num1) el valor introducido en el Textbox ???, cosa que, o se me esta escapando
algo muy gordo, o no le veo el sentido por ningún lado

bueno, disculpas por el rollo, y aun mas por el código que pongo a continuación, que tampoco es corto, pero si alguno
sabéis/veis donde esta el 'truco' [o metedura de pata] del textbox os lo agradezco

este es el código, de momento, del usercontrol (se llama 'EfectivoCambio')

'****************************************
Public Class EfectivoEuros

Public Valor As Double
Private isDecimal As Boolean
'-------------------
Private Sub Num1_ValueChanged( _
ByVal sender As System.Object, _
ByVal e As System.EventArgs _
) Handles Num1.ValueChanged, _
Num2.ValueChanged, Num3.ValueChanged, _
Num4.ValueChanged, Num5.ValueChanged, _
Num6.ValueChanged, Num7.ValueChanged, _
Num8.ValueChanged, Num9.ValueChanged, _
Num10.ValueChanged, Num11.ValueChanged, _
Num12.ValueChanged, Num13.ValueChanged, _
Num14.ValueChanged, Num15.ValueChanged
Calculo(ActiveControl)
End Sub
' -----------------------------
' este proc. y el siguiente en realidad eran solo uno, pero al final lo he dividido intentando
' una solucion con palos de ciego. Tambien he intentado otras cuantas cosillas, pero nada
'
Private Function Calculo(ByRef Ct As Windows.Forms.Control) As Double
Dim Nom As String, lbl As Windows.Forms.Label, _
NumN As Windows.Forms.NumericUpDown
Nom = Microsoft.VisualBasic.Left(Ct.Name, 3)
If Nom = "Num" Then
NumN = Ct
With NumN
lbl = Me.Controls("SubT" & _
Microsoft.VisualBasic.Right(.Name, _
Microsoft.VisualBasic.Len(.Name) - 3))
lbl.Text = Format(.Value * CDbl(.Tag), "0.00")
End With
End If
Valor = Calcular()
End Function
'-----------
Private Function Calcular() As Double
Dim n As Integer, sT As Double, TT As Double
For n = 1 To 15
If Not IsNumeric(Me.Controls("SubT" & n).Text) Then _
Me.Controls("SubT" & n).Text = "0,00"
TT = TT + CDbl(Me.Controls("SubT" & n).Text)
Next
'sT = CDbl(Me.txtOtros.Text)
TT = TT + CDbl(Me.txtOtros.Text) 'sT
lblTotal.Text = Format(TT, "0.00")
End Function
'-------------
Private Sub txtOtros_KeyDown( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs _
) Handles txtOtros.KeyDown
' codigo y comentarios expuestos por SoftJaen en un foro
' junto con el procedimiento 'TeclaPresionada'
'
If e.KeyCode = Windows.Forms.Keys.Decimal Or _
e.KeyCode = Windows.Forms.Keys.Oemcomma Or _
e.KeyCode = Windows.Forms.Keys.OemPeriod Then
' Si se ha pulsado uno de los tres caracteres anteriores, dicho
' carácter actuará como separador decimal del número.
'
isDecimal = True
Else
isDecimal = False
End If
End Sub
'---------------------
Private Sub txtOtros_KeyPress( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyPressEventArgs _
) Handles txtOtros.KeyPress
TeclaPresionada(sender, e, txtOtros, isDecimal)
' este es uno de los intentos
'Calculo(txtOtros)
End Sub
'------------------------
Public Sub New()
' Llamada necesaria para el Diseñador de Windows Forms.
InitializeComponent()
' Agregue cualquier inicialización después de la llamada a InitializeComponent().
End Sub
' --------------------------
' "TeclaPresionada" => codigo y comentarios expuestos
' por SoftJaen en un foro (Gracias de mi parte)
'
Private Sub TeclaPresionada( _
ByRef sender As Object, _
ByRef e As System.Windows.Forms.KeyPressEventArgs, _
ByRef oTextBox As Windows.Forms.TextBox, _
ByVal isDecimal As Boolean)
' Caracter separador decimal existente actualmente
' en la configuración regional de windows.
'
Dim separadorDecimal As String = _
Threading.Thread.CurrentThread. _
CurrentCulture.NumberFormat.NumberDecimalSeparator
If isDecimal Then
' Si en el control hay ya escrito un separador decimal,
' deshechamos insertar otro separador más.
'
If DirectCast(sender, Windows.Forms.TextBox).Text. _
IndexOf(separadorDecimal) >= 0 Then
e.Handled = True
Return
End If
' Insertamos el separador decimal.
'
DirectCast(sender, Windows.Forms.TextBox).SelectedText = separadorDecimal
e.Handled = True
ElseIf Convert.ToInt32(e.KeyChar) = 8 Then
' Se ha pulsado la tecla retroceso
ElseIf e.KeyChar = "-"c Then
' Únicamente si no está seleccionado el texto del control
If oTextBox.SelectionLength = 0 Then
' Solo permito el signo menos si aparece en primera posición
If oTextBox.SelectionStart <> 0 Then e.Handled = True
' Si en el control hay ya escrito un signo menos,
' deshechamos todos los que posteriormente se escriban
If DirectCast(sender, Windows.Forms.TextBox).Text.IndexOf("-") >= 0 Then
e.Handled = True
End If
End If
ElseIf Not (Char.IsDigit(e.KeyChar)) Then
' No se ha pulsado un dígito.
e.Handled = True
End If
End Sub

End Class
'**********************************
si alguno veis donde estoy metiendo la pata os lo agradezco

un saludo
Ivan
Ivan
2008-02-22 13:26:56 UTC
Permalink
hola de nuevo,

la verdad es que revisando hoy los codigos mandados ayer me acabo de
dar cuenta de unas cuantas burradas, fruto en gran parte de la
exasperacion/improvisacion, sobre todo en los proc. Calculo y
Calcular.

estos en realidad deberian quedar mas o menos asi =>

'**************************************************************************
Private Sub Calculo(ByRef Ct As Windows.Forms.Control)
Dim Nom As String, lbl As Windows.Forms.Label, _
NumN As Windows.Forms.NumericUpDown
Nom = Microsoft.VisualBasic.Left(Ct.Name, 3)
If Nom = "Num" Then
NumN = Ct
With NumN
lbl = Me.Controls("SubT" & _
Microsoft.VisualBasic.Right(.Name, _
Microsoft.VisualBasic.Len(.Name) - 3))
lbl.Text = Format(.Value * CDbl(.Tag), "0.00")
End With
End If
Valor = Calcular()
lblTotal.Text = Format(Valor, "0.00")
End Sub
'---------------------------
Private Function Calcular() As Double
Dim n As Integer, TT As Double
For n = 1 To 15
If Not IsNumeric(Me.Controls("SubT" & n).Text) Then _
Me.Controls("SubT" & n).Text = "0,00"
TT = TT + CDbl(Me.Controls("SubT" & n).Text)
Next
Calcular = TT + CDbl(Me.txtOtros.Text)
End Function
'*************************************
de todas formas, me sigue ocurriendo lo mismo: al modificar el
textbox(txtOtros) en lugar de cargar el total en lblTotal me lo carga
en el 1er NumberUpDown, y, aunque seguro que en algun lado la estoy
pifiando, no logro ver donde. Sin embargo con los cambios en los
botones de numero si parece funcionar correctamentre.

un saludo Ivan
SoftJaén
2008-02-23 14:23:14 UTC
Permalink
Post by Ivan
1.-por un lado, no se que evento utilizar para actualizar el total tras
los cambios en el textbox: con el TextChanged, que me parecía lo mas
equivalente al change de vba, al intentar ejecutar el control (con F5) me
dice algo parecido a variable de objeto no establecida.
Hola, Iván:

Los eventos que tienes que utilizar son TextChanged (para el control de
texto) y ValueChanged (para el control NumberUpDown), porque ambos se
desencadenarán cuando se modifiquen sus respectivos valores, para que de
ésta manera puedas actualizar el control Label con el total.

Por ejemplo, desde estos eventos podrías llamar a un procedimiento para
actualizar el control Label, donde más o menos ejecutarías lo siguiente:

Private Sub ValorTotal( _
ByVal cantidad As String, _
ByVal numero As Decimal)

Dim total As Single
Try
total = Convert.ToSingle(cantidad) * numero

Catch ex As Exception
total = 0

End Try

lblTotal.Text = String.Format("{0:f}", total)

End Sub

Y al procedimiento lo llamarías desde los eventos comentados, de ésta
manera:

ValorTotal(TextBox1.Text, Num1.Value)

Por supuesto, ésto es solo un ejemplo que deberás de adaptarlo a tus
necesidades.

Un saludo
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-24 02:47:33 UTC
Permalink
hola Enrique,

antes que nada muchas gracias, tanto por tu respuesta como por el
codigo para validar el textbox (y por tus articulos sobre ADO/DAO/
excel, entre otras cosas)
Post by SoftJaén
Los eventos que tienes que utilizar son TextChanged (para el control de
texto) y ValueChanged (para el control NumberUpDown), porque ambos se
desencadenarán cuando se modifiquen sus respectivos valores, para que de
ésta manera puedas actualizar el control Label con el total.
en realidad aqui esta lo curioso.=>

Con el ValueChanged del Numericupdown no parece haber ningun
problema, y de hecho ya funcionaba bastante bien, [aunque para
asignarle la propiedad Value mediante la propiedad Controls de
Windows.Forms no me lo permite (me dice que Value no es una propiedad
de Controls) y tengo que instanciarlo como NumericUpDown directamente]

sin embargo, con el TextChanged del textbox, en cuanto meto algo en el
me da 'error al crear "UserControl ClassLibrary1.EfectivoEuros" ' y
con el mensaje "Referencia a objeto no establecida como instancia de
un objeto"

por mas vueltas que le doy no consigo ver donde esta el problema. Aun
mas si tenemos en cuenta que realmente el textbox si me lo reconoce
como tal en [creo] todas las demas partes del proyecto. En la unica
que de momento parece darme el problema es en TextChanged (gracias por
confirmarme que se corresponde al Change, como me daba la impresion)

¿puede tener que ver con la version Express? estoy usando la 2005
Express y al crear el control, como no he encontrado el tipo de
proyecto 'Biblioteca de controles' (o algo asi), que creo haber leido
en algun lado es el tipo de proyecto que se utiliza parra crear
controles de usuario, estoy haciendolo en uno tipo 'biblioteca de
clases' agregando un control de usuario desde el menu proyecto


por otro lado, por si antes no se me ha entendido bien la idea, lo que
intento hacer es un control con diversas propiedades, o al menos una
(Value/Valor).

Este control contiene,

a) por un lado 15 grupos de controles con esta estructura =>

un Label informativo con el valor la moneda/billete <=> un
NumericUpDown para el nº de monedas/billetes contadas/os <=> un label
que recoge el subtotal calculado de multiplicar el valor de esa moneda
por lo introducido en el numericupdown

esto por cada tipo de moneda, es decir un grupo para las monedas de 1
centimo, otro para las de 2, y asi hasta el billete de 500

b) ademas tiene un textbox unico para introducir cantidades mixtas de
moneda (imaginate una bolsa llena de monedas de diferentes tipos pero
que sabes el total y es lo que introduces en este textbox, sin tener
que contar cada tipo)

c) un label que recoge el total y que se actualiza con los cambios en
cualquiera de los controles citados

ahora mismo este es el codigo que estoy usando/practicando para
intentar evitar los bucles cada vez que cambie algo. Seguramente es
muy mejorable, aparte de que seguro que existen formas en net que
podrian sustituir a las funciones de VB, pero al menos van haciendo el
apaño de momento

(he deshabilitado el control de errores para ver donde saltaba)

' NOTA: en la propiedad Tag del NumericUpDown almaceno el valor de la
moneda correspondiente concatenada al ultimo valor del control y
separada por un espacio para usar con split (al textbox le asigno 1
como 1er elemento para split y el valor ultimo como 2º)

Private Sub NuevoTT(ByVal NombreCt As String)
Dim mas As Single, ctN As Windows.Forms.NumericUpDown, _
ctT As Windows.Forms.TextBox
SinEventos = True
With Me.Controls(NombreCt)
'Try
Select Case Microsoft.VisualBasic.Left(NombreCt, 3)
Case "Num"
ctN = Me.Controls(NombreCt)
mas = CSng(Split(.Tag)(0)) * ctN.Value
Me.Controls("SubT" & _
Microsoft.VisualBasic.Right(NombreCt, _
Microsoft.VisualBasic.Len(NombreCt) - 3)) _
.Text = Format(mas, "0.00")
ctN = Nothing
Case Else

' aqui he probado a instanciar directamente como
w.f.textbox,
' a ver si resolvia algo, pero me tem o que sigue
igual

ctT = Me.Controls(NombreCt)
mas = CSng(ctT.Text)
ctT = Nothing
End Select
'Catch ex As Exception
'mas = 0
'End Try
lblTotal.Text = Format(CSng(lblTotal.Text) + mas _
- CSng(Split(.Tag)(1)), "0.00")
.Tag = Split(.Tag)(0) & " " & mas
End With
SinEventos = False
End Sub

y lo llamo desde el ChangeValue del numericupdown o el TextChange del
textbox +/- asi =>

en e 1º => If not SinEventos then NuevoTT(ActiveControl.Name) pues
puede ser culaquier de los 15 botones y solo uso el evnto de un unico
control para controlar todos los demas [en este caso funcioona sin
problemas (al menos aparentes)]

y sin embargo, para el txtbox, que en teoria deberia ser mas facil
pues solo hay uno y le paso el nombre directamente (tambien he probado
otros tipos de argumento) => If not SinEventos then
NuevoTT("txtOtros")

bueno, disculpas por el nuevo rollo, y si puedes/podeis echarme un
cable, sobre todo para que deje de volverme majara buscando la causa,
os lo agradezco

un sludo
Ivan
SoftJaén
2008-02-24 10:15:54 UTC
Permalink
Post by Ivan
Con el ValueChanged del Numericupdown no parece haber ningun
problema, y de hecho ya funcionaba bastante bien, [aunque para
asignarle la propiedad Value mediante la propiedad Controls de
Windows.Forms no me lo permite (me dice que Value no es una propiedad
de Controls) y tengo que instanciarlo como NumericUpDown directamente]
¡Eso es así! El objeto «Control» no tiene ninguna propiedad llamada «Value»,
por tanto, no puedes utilizar el nombre de una propiedad inexistente.

Tienes que tener en cuenta que, aunque todos los controles heredan de la
clase «Control», posteriormente éstos pueden implementar sus propias
propiedades, métodos y eventos, como es el caso del control NumericUpDown,
que define una propiedad «Value» para obtener y establecer el valor del
cuadro de número.

Imagina que tienes un procedimiento para obtener el nombre y el valor de una
propiedad concreta del control. La firma del procedimiento sería la
siguiente:

Private Sub ObtenerValorControl(ByVal ct As Control)

If TypeOf ct Is NumericUpDown Then
' Referenciamos el control
Dim num As NumericUpDown = CType(ct, NumericUpDown)

' Leemos su propiedad Value
MessageBox.Show(num.Value.ToString, num.Name)

ElseIf TypeOf ct Is TextBox Then
' Referenciamos el control
Dim tb As TextBox = CType(ct, TextBox)

' Leemos su propiedad Text
MessageBox.Show(tb.Text, tb.Name)

ElseIf TypeOf ct Is Label Then
' Referenciamos el control
Dim lbl As Label = CType(ct, Label)

' Leemos su propiedad Text
MessageBox.Show(lbl.Text, lbl.Name)

End If

End Sub

Ahora, si deseas conocer el valor de la propiedad «Value» del control
NumericUpDown, llamarías al procedimiento de la siguiente manera:

ObtenerValorControl(Num1)

Y si deseas conocer el valor de un cuadro de texto, la llamarías así:

ObtenerValorControl(TextBox1)

Pero si el parámetro del procedimiento se pasa por referencia (ByRef ct As
Control), entonces deberás de hacer una conversión explícita al tipo de
objeto «Control», siempre y cuando tengas activada la instrucción «Option
Strict», que es lo que se recomienda que se haga. Si es así, llamarías al
procedimiento como sigue:

ObtenerValorControl(CType(Num1, Control))

ObtenerValorControl(CType(TextBox1, Control))

ObtenerValorControl(CType(lblTotal, Control))
Post by Ivan
sin embargo, con el TextChanged del textbox, en cuanto meto algo en el
me da 'error al crear "UserControl ClassLibrary1.EfectivoEuros" ' y
con el mensaje "Referencia a objeto no establecida como instancia de
un objeto"
Sin ver el código fuente completo del proyecto, ignoro el motivo que hace
que obtengas la excepción que me comentas. Lo que sí está claro, es que
antes de utilizar una propiedad o método de cualquier objeto, deberá estar
previamente instanciado el mismo, salvo que se trate de llamadas a métodos
compartidos (declarados como «Shared»).
Post by Ivan
¿puede tener que ver con la version Express? estoy usando la 2005
Express y al crear el control, como no he encontrado el tipo de
proyecto 'Biblioteca de controles' (o algo asi), que creo haber leido
en algun lado es el tipo de proyecto que se utiliza parra crear
controles de usuario, estoy haciendolo en uno tipo 'biblioteca de
clases' agregando un control de usuario desde el menu proyecto
Si en la biblioteca de controles has añadido un control de usuario, que es
el que utilizas para añadirlo al formulario de otro proyecto «Aplicación
para Windows», no creo que tenga nada que ver, pero te repito que sin ver lo
que estás haciendo, y cómo lo estás haciendo, es un poco complicado
averiguar lo que te está sucediendo.
Post by Ivan
ahora mismo este es el codigo que estoy usando/practicando para
intentar evitar los bucles cada vez que cambie algo. Seguramente es
muy mejorable, aparte de que seguro que existen formas en net que
podrian sustituir a las funciones de VB, pero al menos van haciendo el
apaño de momento
Private Sub NuevoTT(ByVal NombreCt As String)
Observando el código escrito en el procedimiento, lo único que te puedo
decir es que apliques la técnica que te he comentado más arriba. En lugar de
pasar el nombre del control, pasa una referencia propiamente dicha del
control:

Private Sub NuevoTT(Byval ct As Control)

End Sub

El nombre del control lo podrás averiguar mediante la propiedad «Name», y
como dices que tienes varios, puedes incluir un bloque «Select Case ct.Name»
en lugar de averiguar el nombre del control mediante las funciones de cadena
típicas de Visual Basic clásico.

Asimismo, también te recomendaría que al principio del código fuente
activaras la instrucción «Option Strict»:

Option Strict On

Lo mismo tu código fuente se llena automáticamente de líneas onduladas de
color azul, impidiéndote ejecutar el proyecto, pero eso significa que
existen errores de conversión entre tipos de datos que deberás depurarlos.
:-)
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-24 21:28:02 UTC
Permalink
hola Enrique

muchas gracias por tus indicaciones

al final, siguiendo estas y con alguna cosilla mas he conseguido que
funcione.

lo 1º que he hecho ha sido iniciar un nuevo proyecto, en este caso de
'aplicacion para windows' en vez de 'biblioteca de clases', agregar un
nuevo control de usuario y pegar en este los controles que ya tenia
configurados en el otro.

no se si esto habra influido, pero al menos si hace mucho mas comodo
el manejo de los tipos de controles, pues no hay que referenciarlos a
windows.forms como me ocurria en el otro proyecto

lo demas es simplemente la aplicacion de tus comentarios y ejemplos
unido a algo de la logica de VBa (o al menos de la mia), aunque la
mayor parte de esta me la ha 'descabalgado', ... y de mucho F1
(ufff .., y eso que es totalmente basico)

esta claro que hay que quitarse una buena parte del chip VBa para
meterse en VB.Net, pero al menos este tanteo me hace ver por donde
pueden ir al menos parte de las diferencias

te pongo el codigo resultante, por si ves/veis cosas muy chirriantes y
quereis comentarlas (he omitido la parte de la mascara de entrada al
textbox para reducir el mensaje)

pero antes solo un par de preguntas (aunque si crees que debe ir en
otro hilo no hay problema):


1º)¿hay posibilidad de poder usar este control desde una aplicacion de
VBa? y de ser asi ¿por donde deberia empezar? . Como comentaba es
practicamente mi primer tanteo en VB.Net y no tengo ni idea.

Tambien esta el tema de que se trata de la version express y no se si
desde esta se pueden crear controles de este tipo

2º) aunque esto voy a ponerme a estudiarlo/probarlo ahora y no se lo
que me voy a encontrar ¿como podria crear/atrapar agun evento del
control?

bueno, aqui va el codigo, que parece ir bien

el codigo va en la ventana de idem de un UserControl de una
aplicacion para windows y como decia consta de

a)15 grupos de controles' uno por tipo de moneda +/- asi=>

(Label_Moneda//NumericUpDown_NroMonedas//Label_SubTotal<Moneda*nro>)

donde los numericupdown se llaman Num1 a Num15 y los label para el sub
total SubT1 a SubT15

b) un textbox para cantidades diversas (txtOtros)

c) un label para el total (lblTotal) que ademas proporciona el valor
para la propiedad Valor del control

Public Class ContarEfectivo

Private ctT As TextBox = New TextBox
Private SinEventos As Boolean
Private sn_mValor As Single
Private Const Monedas As String = _
"500 200 100 50 20 10 5 2 1 " & _
"0,5 0,2 0,1 0,05 0,02 0,01"
Public ReadOnly Property Valor() As Single
Get
Try
sn_mValor = Convert.ToSingle(lblTotal.Text)
Catch ex As Exception
sn_mValor = 0
End Try
Return sn_mValor
End Get
End Property
Private Sub CalcularTT(ByRef ct As Control)
Dim St As Single = 0, preTt As Single = 0, nroCt As String =
""
If TypeOf ct Is NumericUpDown Then
Dim num As NumericUpDown = CType(ct, NumericUpDown)
St = num.Value * Convert.ToSingle(Split(num.Tag)(0))
nroCt = Microsoft.VisualBasic.Right(num.Name,
Len(num.Name) - 3)
Me.Controls("SubT" & nroCt).Text = Format(St, "0.00")
ElseIf TypeOf ct Is TextBox Then
St = Convert.ToSingle(ctT.Text)
End If
preTt = Convert.ToSingle(Split(ct.Tag)(1))
lblTotal.Text = Format(lblTotal.Text + St - preTt, "0.00")
ct.Tag = Split(ct.Tag)(0) & " " & CStr(St)
End Sub

Private Sub ctT_TextChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles txtOtros.TextChanged
If Not SinEventos Then CalcularTT(ctT)
End Sub

Public Sub New()
SinEventos = True
InitializeComponent()
ctT = txtOtros
ctT.Text = "0,00"
ctT.Tag = "1 0"
Dim n As Byte
Dim ctN As NumericUpDown = New NumericUpDown
For n = 1 To 15
ctN = Me.Controls("Num" & n)
ctN.Tag = Split(Monedas)(n - 1) & " 0"
Me.Controls("SubT" & n).Text = "0,00"
Next
ctN = Nothing
lblTotal.Text = "0,00"
SinEventos = False
End Sub

Private Sub Num1_ValueChanged( _
ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles Num1.ValueChanged, _
Num2.ValueChanged, Num3.ValueChanged, _
Num4.ValueChanged, Num5.ValueChanged, _
Num6.ValueChanged, Num7.ValueChanged, _
Num8.ValueChanged, Num9.ValueChanged, _
Num10.ValueChanged, Num11.ValueChanged, _
Num12.ValueChanged, Num13.ValueChanged, _
Num14.ValueChanged, Num15.ValueChanged
If Not SinEventos Then CalcularTT(ActiveControl)
End Sub

Protected Overrides Sub Finalize()
ctT = Nothing
MyBase.Finalize()
End Sub
End Class

muchas gracias de nuevo y cualquier comentario sera bien recibido

un saludo
Ivan
SoftJaén
2008-02-24 23:44:05 UTC
Permalink
Post by Ivan
1º)¿hay posibilidad de poder usar este control desde una aplicacion de
VBa? y de ser asi ¿por donde deberia empezar? . Como comentaba es
practicamente mi primer tanteo en VB.Net y no tengo ni idea.
En teoría, sí es posible, exponiendo a COM el ensamblado que constituye el
control de usuario. Échale un vistazo al siguiente enlace:

Exponer componentes de .NET Framework en COM
http://msdn2.microsoft.com/es-es/library/zsfww439(VS.80).aspx
Post by Ivan
Tambien esta el tema de que se trata de la version express y no se si
desde esta se pueden crear controles de este tipo
Nunca he instalado la versión Express de Visual Basic 2005, y no puedo
confirmar si existe una plantilla para la creación de controles de usuarios.

De todas formas, para crear un control de usuario, tu clase simplemente
tiene que heredar de «System.Windows.Forms.UserControl». Para ello, añade al
proyecto una nueva clase, y escribe lo siguiente:

Public Class NombreControl

Inherits System.Windows.Forms.UserControl

End Class

Con eso es suficiente para comenzar a diseñar un control de usuario en
Visual Studio, y salvo que esté equivocado, me imagino que así será también
con la versión Express.

Por supuesto, deberás de referenciar los ensamblados «System.Windows.Forms»
y «System.Drawing», e importar dichos espacios de nombre para que no tengas
que escribirlos cada vez que desees referenciar una clase existente en
aquellos.

Ten en cuenta que Visual Studio nos facilita, y mucho, la creación de
aplicaciones .net, pero digamos que tampoco es sumamente necesario, porque
mientras que se disponga del SDK, con el mismísimo Bloc de Notas podemos
escribir el código de nuestras clases, aunque ésta sea una tarea ardua y
bastante complicada. Pero poder, se puede. Otra cosa es que merezca la pena.
:-)
Post by Ivan
2º) aunque esto voy a ponerme a estudiarlo/probarlo ahora y no se lo
que me voy a encontrar ¿como podria crear/atrapar agun evento del
control?
Para declarar eventos de usuario, se utiliza la instrucción «Event», y para
desencadenarlos la instrucción «RaiseEvent»:

Public Event NombreEvento(ByVal nombreParametro As TipoDato)

Abre la ayuda de Visual Studio, y busca dichas instrucciones, así como el
tema «Cómo: Agregar eventos a una clase» y restantes temas relacionados
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-25 01:37:47 UTC
Permalink
hola de nuevo, Enrique
    Exponer componentes de .NET Framework en COM
 http://msdn2.microsoft.com/es-es/library/zsfww439(VS.80).aspx
<<<

muchas gracias. Ya lo he echado un ojo (a el y a unos cuantos de sus
enlaces) y, aunque me temo que me va a costar 'un poquito', voy a ver
si consigo aplicar alguna de las formulas propuestas en el/los enlace/
s
Post by SoftJaén
Nunca he instalado la versión Express de Visual Basic 2005, y no puedo
confirmar si existe una plantilla para la creación de controles de usuarios.<<<
es posible que yo tenga desde el principio un error de concepto. Me
explico:

antes de liarme con este proyecto estuve echando un ojo por la ayuda
en lo referido a la creacion de controles de usuario, y en general
casi todo lo que encontre coincidia en que para empezar el proyecto el
primer paso era crear un nuevo proyecto del tipo 'Biblioteca de
controles', para lo cual en el cuadro 'nuevo proyecto' habia que
elegir dicho icono y a currar.

el problema es que, al menos en mi caso, no aparece este tipo de
proyecto, sino tan solo 'Aplicacion para Windows', 'Biblioteca de
clases', 'Aplicacion de consola'., 'Starter Kit de mis peliculas' y
'Starter kit del protector de pantalla', y, en un segundo grupo
llamado 'Mis plantillas' aparecen 'Buscar plantillas en linea' y una
plantilla de pruba creada por mi

despues de unas cuantas busquedas por la ayuda y por las opciones
intentando encontrar la formula de cargar dicho tipo de proyectos,
desisti y probe a crear una 'Biblioteca de clases' (y actualmente una
'Aplicacion para windows') e insertar un control de usuario desde el
menu 'Agregar' => agregar control de usuario. En este caso si se abre
un cuadro de 'plantillas' en el que aparece 'Control de usuario', pero
claro, te lo integra en el proyecto desde el que lo agregas.

la cuestion es que me imagino que no es lo mismo una cosa que la otra.
Supongo que el primer caso es el adecuado a la hora de crear
componentes COM de tipo control y que en el segundo caso tan solo es
una parte mas de un proyecto mas amplio con otros componentes.

aun asi, y como te digo, no se las implicaciones que pueda tener esto
a la hora de exportar el componente y a la hora de llamarlo desde otra
aplicacion, pues de momento no he encontrado nada que aclare la
diferencia entre uno y otro.
Post by SoftJaén
, para crear un control de usuario, tu clase simplemente
tiene que heredar de «System.Windows.Forms.UserControl». Para ello, añade al
proyecto una nueva clase, y escribe lo siguiente:<<<
muchas gracias una vez mas (creo que esto del VB.Net puede acabar
añadiendose a mis [no pocas] adicciones). Voy a ir probandolo.
Post by SoftJaén
Para declarar eventos de usuario, se utiliza la instrucción «Event», y para
    Public Event NombreEvento(ByVal nombreParametro As TipoDato) <<<<
al final, al empezar a plantear un evento personalizado para el
control he caido en la cuenta de que el propio control expone ya de
por si suficientes eventos para realizar lo que pensaba (en este caso
actualizar un control ajeno al usercontrol con el valor del mismo al
salir de este, para lo que he probado en leave y parece funcionar
bien) sin liarme mas.

pero de todas formas, y como es algo que me gustaria empezar a
aprender, tomo nota y espero poco a poco irlo viendo

lo dicho, muchas gracias por todo, y si consigo ir avanzando en la
'exportacion a COM' y me surjen dudas, seguramente tendre que abrir
algun que otro nuevo hilo

un saludo
Ivan
SoftJaén
2008-02-25 13:38:44 UTC
Permalink
Post by Ivan
el problema es que, al menos en mi caso, no aparece este tipo de
proyecto, sino tan solo 'Aplicacion para Windows', 'Biblioteca de
clases', 'Aplicacion de consola'., 'Starter Kit de mis peliculas' y
'Starter kit del protector de pantalla', y, en un segundo grupo
llamado 'Mis plantillas' aparecen 'Buscar plantillas en linea' y una
plantilla de pruba creada por mi
Pues parece ser que es así, porque esos son los proyectos que también se
pueden hacer con la versión Express de Visual Basic 2008.

Pero repito que eso no es un problema. Si te permite crear un proyecto de
«Biblioteca de clases», y añadirle a la misma un control de usuario, digamos
que ya tienes un proyecto de «Biblioteca de controles de Windows», porque
ésta es lo mismo que una biblioteca de clases, pero con la diferencia que
sus clases heredan de «System.Windows.Forms.UserControl».

Los pasos a seguir serían los siguientes:

1º) Abre Visual Basic Express y creas un nuevo proyecto de Bibliotecas de
clases. Si lo deseas, puedes eliminar la clase que se ha creado por defecto
(Class1).

2º) Abre las propiedades del proyecto y referencias los siguientes
ensamblados .net:

System.Drawing
System.Windows.Forms

3º) Añade un control de usuario (Proyecto --> Agregar nuevo elemento -->
Control de usuario).

4º) Generas el ensamblado seleccionando el menú Generar --> Generar
ClassLibrary1.

Ya estás en condiciones para hacer doble clic sobre el nombre del archivo
«UserControl1» existente en el Explorador de soluciones, para que se abra
éste en el diseñador de Visual Basic Express y puedas añadir sobre él los
controles necesarios.

Por último, solo queda que guardes el proyecto y le indiques el nombre que
creas conveniente.

Como habrás podido observar, no es necesario tener una versión superior de
Visual Studio para crear una biblioteca de controles de usuario.

Si deseas trabajar de una manera más cómoda, añade las siguientes
instrucciones «Imports» al comienzo de la clase «UserControl1»:

Imports System.Windows.Forms
Imports System.Drawing
Post by Ivan
la cuestion es que me imagino que no es lo mismo una cosa que la otra.
Supongo que el primer caso es el adecuado a la hora de crear
componentes COM de tipo control y que en el segundo caso tan solo es
una parte mas de un proyecto mas amplio con otros componentes.
aun asi, y como te digo, no se las implicaciones que pueda tener esto
a la hora de exportar el componente y a la hora de llamarlo desde otra
aplicacion, pues de momento no he encontrado nada que aclare la
diferencia entre uno y otro.
Si hablamos de utilizar el control creado desde otra aplicación .net para
Windows, simplemente tendrías que añadir una referencia a la biblioteca .net
creada.

Lo que no tengo ya tan claro es si vas a poder utilizar la parte visual del
control de usuario en un formulario «UserForm» de Visual Basic para
Aplicaciones. Para eso, mejor será que construyas un control ActiveX con
Visual Basic 6.0, o simplemente, construye un formulario en un proyecto VBA.
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-25 21:03:27 UTC
Permalink
hola Enrique,
Post by SoftJaén
Post by SoftJaén
esos son los proyectos que también se
pueden hacer con la versión Express de Visual Basic 2008.
Pero repito que eso no es un problema. Si te permite crear un proyecto de
«Biblioteca de clases», y añadirle a la misma un control de usuario, digamos
que ya tienes un proyecto de «Biblioteca de controles de Windows»,....
.....
1º) Abre ...
...
Como habrás podido observar, no es necesario tener una versión superior de
Visual Studio para crear una biblioteca de controles de usuario.<<<<
en cuanto tenga un rato probare a seguir todos los pasos para intentar
familiarizarme un poco con los usos del lenguaje

muchas gracias de nuevo
Post by SoftJaén
Post by SoftJaén
Post by SoftJaén
Si deseas trabajar de una manera más cómoda, añade las siguientes
    Imports System.Windows.Forms
    Imports System.Drawing
si no me equivoco, y a falta de probarlo, esto evitara el tener que
referenciar cada objeto de windows.forms, como si directamente
estubieramos en una aplicacion para windows

otra vez gracias, y ahora por partida doble, pues aparte del dato en
si, admeas lo intuyo muy util en la practica
Post by SoftJaén
Post by SoftJaén
Post by SoftJaén
...utilizar el control creado desde otra aplicación .net para
Windows, simplemente tendrías que añadir una referencia a la biblioteca .net
creada.
Lo que no tengo ya tan claro es si vas a poder utilizar la parte visual del
control de usuario en un formulario «UserForm» de Visual Basic para
Aplicaciones. Para eso, mejor será que construyas un control ActiveX con
Visual Basic 6.0, o simplemente, construye un formulario en un proyecto VBA.
en realidad se trata sobre todo de un ejercicio nacido de la
curiosidad mas que de la necesidad. De hecho en VBa Excel ya lo tenia
resuelto de una forma bastante satisfactoria (al menos para mi) con un
frame conenedor agregado al cuadro de herramientas y recurriendo a una
clase-

pero me pico el gusanillo de probar en Net y asi aprender un poco
sobre este

la verdad es que me voy muy contento con al menos haber empezado a
conseguir que algo funcione en VB.Net. Y ello la verdad es que en gran
medida gracias a ti.

lo dicho muchas gracias y seguramente nos seguiremos viendo por aqui,
pues creo que me ha empezado a enganchar un poco

un saludo
Ivan
Ivan
2008-02-28 00:10:35 UTC
Permalink
hola de nuevo,

solo por si a algun 'incauto' le diera por probar algo de lo comentado
por mi, comentar algunas peculiaridades que me he ido encontrando y
que hacian que la cosa no acabara de funcionar como debiera:

en concreto y sobre todo en el caso del evento ValuedChange del
NumericUpDown parece ser que los cambios introducidos directamente via
teclado en la caja de texto del control no provocan el evento salvo si
se pulsa intro (ni siquiera al salir con Tab), con lo que realmente en
muchas ocasiones el valor del control no se actualizaba correctamente

esto parecia resolverse ejcutando el procedimiento de calculo tambien
e KeyUp, pero mira por donde al pulsar determinadas teclas, la
propiedad Value del control parece que tampoco cambia, aunque
realmente el contenido si haya cambiado. es el caso pej. de si dejamos
la caja en blanco ("") mediante las teclas Supr o Back. La propiedad
Value parece seguir 'conteniendo' el ultimo valor antes de borrar el
contenido de la caja de texto, con lo que realmente el procedimiento
de calculo tampoco ejecutaba bien su trabajo

esto si parece resolverse ya recurriendo a la propiedad Text del
ActiveControl (pues los NumericUpDown parece que no contienen como
tales dicha propiedad) y comprobando si el contenido es una cadena
vacia para volver a asignarle un valor 0 y actualizar asi
adecuadamente los label del subtotal y por ende el total del control

bueno disculpas por el galimatias, pero me daba 'cosa' dejarlo tal y
como esta por si a alguien tan novato como yo le da por intentar
utilizar algo de lo expuesto y se vuelve majareta con el tema.

aunque me han surjido unas cuantas dudas mas las dejo para otros hilos
concretos

aqui pongo el resultado (casi) final con las ultimas correcciones (de
nuevo gracias a Enrique SoftJaen por todas sus ayudas, y como autor de
los procedimientos de mascara de entrada al textbox)

el ejemplo es para un usercontrol con los componentes expuestos en los
anteriores mensajes y va en su modulo de codigo:

Imports System.Windows.Forms
Imports System.Drawing

Public Class UserControl1
Private NumCt As NumericUpDown = New NumericUpDown
Private ctT As TextBox = New TextBox
Private NroMonedas As String = ""
Private sn_mValor As Single
Private Const Monedas As String = _
"500 200 100 50 20 10 5 2 1 " & _
"0,5 0,2 0,1 0,05 0,02 0,01"
Private SinEventos As Boolean
Private IsDecimal As Boolean

Public ReadOnly Property Valor() As Single
Get
Try
sn_mValor = Convert.ToSingle(lblTotal.Text)
Catch ex As Exception
sn_mValor = 0
End Try
Return sn_mValor
End Get
End Property

Private Sub CtBold(ByRef ct As Control, _
ByVal Negrita As Boolean)
If Negrita Then
ct.Font = New System.Drawing.Font( _
ct.Font, FontStyle.Bold)
Else
ct.Font = New System.Drawing.Font( _
ct.Font, FontStyle.Regular)
End If
End Sub

Private Sub CalcularTT(ByRef ct As Control)
Dim St As Single, preTt As Single, nroCt As String
If TypeOf ct Is NumericUpDown Then
Dim num As NumericUpDown = CType(ct, NumericUpDown)
St = num.Value * Convert.ToSingle(Split(num.Tag)(0))
nroCt = Microsoft.VisualBasic.Right(num.Name, _
Len(num.Name) - 3)
Me.Controls("SubT" & nroCt).Text = Format(St, "0.00")
CtBold(Me.Controls("SubT" & nroCt), St > 0)
ElseIf TypeOf ct Is TextBox Then
St = Convert.ToSingle(ctT.Text)
End If
preTt = Convert.ToSingle(Split(ct.Tag)(1))
lblTotal.Text = Format(lblTotal.Text + St - preTt, "0.00")
ct.Tag = Split(ct.Tag)(0) & " " & CStr(St)
CtBold(ct, St > 0)
End Sub

Private Sub ctT_TextChanged(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles txtOtros.TextChanged
If Not SinEventos Then CalcularTT(ctT)
End Sub

Public Sub New()
SinEventos = True
InitializeComponent()
ctT = txtOtros
ctT.Text = "0,00"
ctT.Tag = "1 0"
Dim n As Byte
For n = 1 To 15
Me.Controls("Num" & n).Tag = _
Split(Monedas)(n - 1) & " 0"
Me.Controls("SubT" & n).Text = "0,00"
Next
lblTotal.Text = "0,00"
SinEventos = False
End Sub

Private Sub Num1_Enter( _
ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles Num1.Enter, _
Num2.Enter, Num3.Enter, _
Num4.Enter, Num5.Enter, _
Num6.Enter, Num7.Enter, _
Num8.Enter, Num9.Enter, _
Num10.Enter, Num11.Enter, _
Num12.Enter, Num13.Enter, _
Num14.Enter, Num15.Enter
NumCt = ActiveControl
NumCt.Select(0, Len(ActiveControl.Text))
End Sub

Private Sub Num1_KeyUp( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs _
) Handles Num1.KeyUp, _
Num2.KeyUp, Num3.KeyUp, _
Num4.KeyUp, Num5.KeyUp, _
Num6.KeyUp, Num7.KeyUp, _
Num8.KeyUp, Num9.KeyUp, _
Num10.KeyUp, Num11.KeyUp, _
Num12.KeyUp, Num13.KeyUp, _
Num14.KeyUp, Num15.KeyUp
If ActiveControl.Text = "" Then
ActiveControl.Text = "0"
NumCt.Select(0, 1)
End If
If Not SinEventos Then CalcularTT(NumCt)
End Sub

Private Sub Num1_ValueChanged( _
ByVal sender As Object, _
ByVal e As System.EventArgs _
) Handles Num1.ValueChanged, _
Num2.ValueChanged, Num3.ValueChanged, _
Num4.ValueChanged, Num5.ValueChanged, _
Num6.ValueChanged, Num7.ValueChanged, _
Num8.ValueChanged, Num9.ValueChanged, _
Num10.ValueChanged, Num11.ValueChanged, _
Num12.ValueChanged, Num13.ValueChanged, _
Num14.ValueChanged, Num15.ValueChanged
If Not SinEventos Then CalcularTT(NumCt)
End Sub

Protected Overrides Sub Finalize()
NumCt = Nothing
ctT = Nothing
MyBase.Finalize()
End Sub

Private Sub TeclaPresionada( _
ByRef sender As Object, _
ByRef e As System.Windows.Forms.KeyPressEventArgs, _
ByRef oTextBox As Windows.Forms.TextBox, _
ByVal isDecimal As Boolean)
' Autor Soft Jaen
' Caracter separador decimal existente actualmente
' en la configuración regional de windows.
'
Dim separadorDecimal As String = _
Threading.Thread.CurrentThread. _
CurrentCulture.NumberFormat.NumberDecimalSeparator
If isDecimal Then
' Si en el control hay ya escrito un separador decimal,
' deshechamos insertar otro separador más.
'
If DirectCast(sender, Windows.Forms.TextBox).Text. _
IndexOf(separadorDecimal) >= 0 Then
e.Handled = True
Return
End If
' Insertamos el separador decimal.
'
DirectCast(sender, Windows.Forms.TextBox).SelectedText = _
separadorDecimal
e.Handled = True
ElseIf Convert.ToInt32(e.KeyChar) = 8 Then
' Se ha pulsado la tecla retroceso
ElseIf e.KeyChar = "-"c Then
' Únicamente si no está seleccionado el texto del control
If oTextBox.SelectionLength = 0 Then
' Solo permito el signo menos si aparece en primera _
' posición()
If oTextBox.SelectionStart <> 0 Then e.Handled = True
' Si en el control hay ya escrito un signo menos,
' deshechamos todos los que posteriormente se
escriban
If DirectCast(sender, Windows.Forms.TextBox).Text. _
IndexOf("-") >= 0 Then
e.Handled = True
End If
End If
ElseIf Not (Char.IsDigit(e.KeyChar)) Then
' No se ha pulsado un dígito.
e.Handled = True
End If
End Sub

Private Sub txtOtros_KeyDown( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs _
) Handles txtOtros.KeyDown
' codigo y comentarios expuestos por SoftJaen en un foro
' junto con el procedimiento 'TeclaPresionada'
'
If e.KeyCode = Windows.Forms.Keys.Decimal Or _
e.KeyCode = Windows.Forms.Keys.Oemcomma Or _
e.KeyCode = Windows.Forms.Keys.OemPeriod Then
' Si se ha pulsado uno de los tres caracteres anteriores,
' dicho() carácter actuará como separador decimal del
' número.
'
isDecimal = True
Else
isDecimal = False
End If
End Sub

Private Sub txtOtros_KeyPress( _
ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyPressEventArgs _
) Handles txtOtros.KeyPress
TeclaPresionada(sender, e, txtOtros, isDecimal)
End Sub

End Class

un saludo y lo dicho, solo por no liar a nadie
Ivan
SoftJaén
2008-02-28 10:37:11 UTC
Permalink
Post by Ivan
en concreto y sobre todo en el caso del evento ValuedChange del
NumericUpDown parece ser que los cambios introducidos directamente via
teclado en la caja de texto del control no provocan el evento salvo si
se pulsa intro (ni siquiera al salir con Tab), con lo que realmente en
muchas ocasiones el valor del control no se actualizaba correctamente
El evento «ValueChanged» sólo se desencadena cuando se modifica el valor de
la propiedad «Value» del control NumericUpDown, pero si deseas controlar lo
que escribe directamente el usuario dentro del cuadro de texto de dicho
control, entonces deberás de controlar el evento «TextChanged», el cual se
desencadenará cuando se modifique el valor de la propiedad «Text» del
control NumericUpDows.

Tanto la propiedad «Text» como el evento «TextChanged» del control
NumericUpDown, se encuentran ocultos en el diseñador, y por tanto no lo
muestra IntelliSense, porque admiten la infraestructura de .NET Framework, y
no se deben usar directamente a partir del código, al menos, eso es lo que
se indica en la ayuda de Visual Studio. No obstante, eso no es un obstáculo
para averiguar el contenido escrito por el usuario dentro del control.

Aunque parezca un único control, el control NumericUpDown se compone en
realidad de dos controles, o mejor dicho, su clase base (UpDownBase) se
compone de dos controles, heredando el segundo de ellos de la clase TextBox,
que es el cuadro de texto que se muestra en el control NumericUpDown. Por
tanto, si el control tiene un TextBox, es fácil averiguar su contenido.

En primer lugar vamos a declarar un procedimiento que tenga la misma firma
que el evento TextChanged de un control TextBox cualquiera:

Private Sub NumericUpDownTextChanged( _
ByVal sender As Object, ByVal e As EventArgs)

' Referenciamos el control
'
Dim tb As TextBox = CType(sender, TextBox)

' Mostramos el texto del control
'
Me.Text = tb.Text

End Sub

Ahora, vamos a instalar el controlador para el evento TextChanged. Para
ello, en el evento «Load» del formulario ejecutaríamos lo siguiente:

Private Sub Form1_Load( ...)

' Referenciamos el cuadro de texto del control NumericUpDown
'
Dim tb As TextBox = CType(Me.NumericUpDown1.Controls(1), TextBox)

' Añadimos el controlador de evento TextChanged
'
AddHandler tb.TextChanged, AddressOf NumericUpDownTextChanged

End Sub

Ya estas en condiciones de averiguar lo que el usuario ha escrito en el
cuadro de texto, valor éste que se lo podrás pasar al procedimiento que
creas conveniente. :-)
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-28 13:21:55 UTC
Permalink
hola Enrique,

en plan 'adivinatorio' parece que has intuido algunas de esas otras
dudas que comentaba, y ademas me las has aclarado bastante: =>
Post by SoftJaén
Post by SoftJaén
Aunque parezca un único control, el control NumericUpDown se compone en
realidad de dos controles, o mejor dicho, su clase base (UpDownBase) se
compone de dos controles, ..... <<<<
la verdad es que dando vueltas por la ayuda esto es lo que me habia
dado la impresion, y de hecho estuve un buen rato intentando averiguar
como derivar de la clase base 'UpDownBase' hacia cada uno de los dos
controles para intentar utilizar las propiedades del textbox asociado
individualmente (estuve a punto de enviar una consulta al respecto),
pero mi impericia y mi desconocimiento del manejo de las clases en
general y en Net en particular, me hizo desistir y tender a una
solucion mas de VBa que de Net

muchas gracias por tu ayuda. Me voy a poner a practicarla/estudiarla
dentro de un rato
Post by SoftJaén
Post by SoftJaén
... si deseas controlar lo
que escribe directamente el usuario dentro del cuadro de texto de dicho
control, entonces deberás de controlar el evento «TextChanged», el cual se
desencadenará cuando se modifique el valor de la propiedad «Text» del
control NumericUpDows.
Tanto la propiedad «Text» como el evento «TextChanged» del control
NumericUpDown, se encuentran ocultos en el diseñador, y por tanto no lo
muestra IntelliSense, porque admiten la infraestructura de .NET Framework, y
no se deben usar directamente a partir del código,...<<<<
efectivamente en mis vueltas por la ayuda me he encontrado (en este y
en otros cuantos casos) con la expresion => " admiten la
infraestructura de .NET Framework, y no se deben usar directamente a
partir del código "

pero confieso que mi comprension del lenguaje/terminologia informatica
(o mejor dicho, del uso que en muchas ocasiones se suele hacer en los
archivos de ayuda, plagado de sobreentendidos) deja mucho que desear y
a veces me hace dudar de lo evidente

en este caso, y teniendo en cuenta de inicio que no se muy bien a que
se refiere con que "admiten la infraestuctura de Net.Framwork" ni lo
que esto supone, he llegado a dudar de que quiere decir algo tan obvio
como que "no se deben usar directamente en el codigo"

supongo que simplemente quiere decir lo que pone, es decir que dichas
propiedad y evento no se pueden usar en el codigo referenciandolas
directamente al numericupdown, pero tras ver varios ejemplos de la
ayuda me entro la duda

ahora tras tus comentarios parece un poco mas claro

como duda añadida y aunque quizas diga algun 'desproposito' =>

¿quiere esto decir que en general, cuando nos encontramos con alguna
propiedad/metodo/evento que 'admite la infraestructura??' de
Net.Framwork, estos no se pueden usar directamente con el objeto/clase
al que pertenecen pero si con sus derivados y/o con sus 'ancestros' y/
o con clases mas genericas que a su vez pueden contener a dicho
control/clase (como en el caso de ActiveControl y NumericUpDown)?

bueno, no se si queda muy clara la pregunta [ni siquiera yo lo tengo
claro], pero supongo que mas o menos sabes a que me refiero (burradas
a parte)

y por ultimo otra duda consecuencia de tu explicacion (y posiblemente
tambien tonta y que ademas seguramente pueda aclarar con unas pruebas)
=>

al usar ActiveControl con algun control 'compuesto', como es el caso
de mi codigo en el evento Enter, supongo que hacemos referencia al
control 'completo' y no al 'subcontrol' que tenga realmente el foco
(como la caja de texto en este caso) ¿o quizas no es asi?

como te digo, supongo que es facilmente comprobable con unas pruebas,
pero hasta esta tarde no podre liarme a ello

bueno, de nuevo muchas gracias por tu ayuda y espero no estar dando
demasiadas patadas al 'buen gusto del programador'

un saludo
Ivan
SoftJaén
2008-02-28 15:25:18 UTC
Permalink
Post by Ivan
¿quiere esto decir que en general, cuando nos encontramos con alguna
propiedad/metodo/evento que 'admite la infraestructura??' de
Net.Framwork, estos no se pueden usar directamente con el objeto/clase
al que pertenecen pero si con sus derivados y/o con sus 'ancestros' y/
o con clases mas genericas que a su vez pueden contener a dicho
control/clase (como en el caso de ActiveControl y NumericUpDown)?
Si te digo la verdad, es un tema que no tengo nada claro, y no sé
exactamente lo que se quiere decir con que «no está diseñada para utilizarse
directamente desde el código».

Lo único que te puedo decir, es que todos los miembros que soportan la
infraestructura .net, o al menos aquellos que acabo de comprobar, están
marcados con el atributo «Browsable» establecido a «False», lo que significa
que la propiedad aparecerá en la ventana de propiedades y se puede modificar
en tiempo de diseño.

Pero, ¡vamos! Que no he observado nada raro por utilizar en el código el
valor de la propiedad «Text» del control NumericUpDown, así como declarar el
evento «TextChanged» del citado control, por lo que en lugar de instalar un
controlador para dicho evento, puedes utilizar el que nos dispensa el propio
control.

Esto es lo que se limita a comentar la ayuda de Visual Studio respecto de la
propiedad «Text» del control NumericUpDow:

[...]
Text no tiene ningún efecto sobre la apariencia del control NumericUpDown;
por tanto, está oculta en el diseñador y no la muestra IntelliSense.
[...]

Pero digo yo que una cosa es que no afecte a la apariencia del control, y
otra cosa muy distinta es que afecte al valor del control, por lo que ignoro
el motivo que dicha propiedad se encuentre oculta, salvo que sea para
indicarnos que no hereda directamente de «Control.Text», ya que la propiedad
«Text» del control NumericUpDown se encuentra sobrescrita en la clase
«UpDownBase» de la cual deriva el control NumericUpDown.

No sé. Lo mismo los diseñadores del control han optado porque prevalezca el
valor de la propiedad «Value» al de la propiedad «Text», que dicho sea de
paso, el valor de ésta última propiedad hay que controlarlo para que se
encuentre dentro de los límites de los valores de las propiedades «Minimun»
y «Maximun» establecidas en el control NumericUpDown.
Post by Ivan
al usar ActiveControl con algun control 'compuesto', como es el caso
de mi codigo en el evento Enter, supongo que hacemos referencia al
control 'completo' y no al 'subcontrol' que tenga realmente el foco
(como la caja de texto en este caso) ¿o quizas no es asi?
En el caso del control NumericUpDown, y me imagino que sucederá igual con
otros controles compuestos, con la propiedad «ActiveControl» se hace
referencia al control en sí, es decir, al control completo, en este caso, al
control NumericUpDown.
--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
SoftJaén
2008-02-28 16:03:10 UTC
Permalink
Post by SoftJaén
Lo único que te puedo decir, es que todos los miembros que soportan la
infraestructura .net, o al menos aquellos que acabo de comprobar, están
marcados con el atributo «Browsable» establecido a «False», lo que
significa que la propiedad aparecerá en la ventana de propiedades y se
puede modificar en tiempo de diseño.
Espera que lo he dicho al revés. Si el valor del atributo «Browsable» es
False, la propiedad NO aparecerá en la ventana de propiedades, pero sí se
puede referenciar en el código fuente.

--
Enrique Martínez
[MS MVP - VB]

Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Ivan
2008-02-28 16:12:26 UTC
Permalink
Post by SoftJaén
Espera que lo he dicho al revés. Si el valor del atributo «Browsable» es
False, la propiedad NO aparecerá en la ventana de propiedades, pero sí se
puede referenciar en el código fuente.
no te procupes, lo habia supuesto

muchas gracias y un saludo
Ivan

Ivan
2008-02-28 16:08:23 UTC
Permalink
hola Enrique,

me temo que 'el camino' va a ser largo y aspero, pero, sin animo de
resultar 'pelotero' ni adulador (ni empalagoso), con personas como tu
estoy seguro que va a ser mucho mas facil aguantar y no tirar la
toalla en plena 'ruta'

muchas gracias de nuevo por todo. Tomo nota y espero ir estudiandolo
poco a poco.

un saludo y hasta pronto
Ivan

PD: todavia me ha aparecido algun problemilla mas, sobre todo [creo]
por el uso de activecontrol, que parece hacer algunos 'extraños' al
pasar de un control a otro mediante el raton. Parece solucionarse
usando select con el control que recibe el enter, pero no estoy
seguro. De todas formas esto es en la forma expuesta en mi anterior
mensaje. Supongo que aplicando tus nuevas indicaciones sera
controlable de otra forma. Si me 'atoro' mucho ya comentare
Continúe leyendo en narkive:
Loading...