Curso Básico de Programación
en Visual Basic
Cuarta Entrega: 4/Jul/97.
por Guillermo "guille" Som
Estos son los links a las entregas anteriores,
si no te las has leído, peor pa ti, pero deberías leértelas.
La Primera,
la Segunda
y la Tercera.
Buenaaas, aquí estamos de nuevo (tu, yo y mi otro yo), empiezo con correcciones, ya sabes, fallos que tiene uno, y otras aclaraciones.
El primero es un fallo garrafal, que gracias a Antonio Banderas, al que le tengo que agradecer también otras cosas, que espero que vaya en beneficio de los que estáis leyendo todas estas cosas sobre el VB, (si, aparte de nosotros tres hay otros que siguen este curso). Bueno, a lo que iba, que siempre me despisto... en la segunda entrega, en el último ejemplo de Num1, Num2, la asignación: Num1 = Num1 + Num2, debería ser: Num1 = Num1 & Num2 (sé que te habrás dado cuenta del detalle, sobre todo por la explicación posterior), este "desliz" ya está corregido, así que si lo has leído después del 30 de Junio (del 97), ya está como tenía que estar.
La siguiente aclaración, es un despiste, no demasiado grande, ya que doy por hecho de que algo habrás leído sobre VB, bien los manuales, bien la Ayuda o algún libro sobre este lenguaje. Pues la cosa consiste que en la tercera entrega se crea un procedimiento: Contar, para crear procedimientos o funciones, tienes que usar el menú Insert y seleccionar Procedure (esto en VB4), en VB3 si no recuerdo mal, estaba en el menú "View" y en VB5 está en Tools (Herramientas)Bien, hechas estas aclaraciones, voy a explicar, tengo que hacerlo, ya que me comprometí y... lo prometido es deuda o eso dicen, a saber...
Antes del código hice este comentario:O sea esto es lo que se dice un programa inútil que además de consumir recursos del sistema y hacernos perder el tiempo, no vale para nada... (es que después de probarlo, me he dado cuenta de que o todos los formatos son prácticamente igual de rápidos o yo he estado "engañado" durante todo este tiempo...)
Y la cosa es que antes de hacer este ejemplo, yo creía que algunos tipos de datos eran más rápidos que otros, (y a pesar de que el ejemplo demuestra, o casi, lo contrario, sigo creyéndolo...). La cosa es que en 32 bits un Long debería ser más rápido que el resto. Y los enteros más rápidos que los de coma flotante... voy a probarlo en un 386 sin copro, a ver... ahora vuelvo...
Ya puestos a probar, he probado, aquí se demuestra lo "morrúo" (o cabezón) que soy, y en esta tabla (pulsando en el link), tienes los diferentes valores en distintos equipos y con distintas versiones de VB.
Verás que sorpresilla te llevas... ¿Lo has visto?Dejaré este tema, que ya es mucho lo que le he dedicado, vamos a ver el programa y así cambiamos de tercio...
Para introducir código en cualquiera de los eventos de los controles o del formulario, lo único que tienes que hacer es seleccionar el control y el evento que queremos codificar de las listas desplegables, en el módulo de código, pulsando en Código en la ventana en la que se muestra los módulos y formularios que forma un proyecto. En la lista de la izquierda seleccionamos el control y en el de la derecha nos mostrará todos los eventos soportados por VB para ese control. Si sabemos el nombre del control y el del evento, podemos teclearlo directamente o bien si copiamos código de otro sitio, simplemente con pegarlo, se va a su sitio.
En el caso de querer añadir al código, una función o procedimiento se puede hacer de varias formas, lo acabo de decir, pero lo repito un poco más claro:
- Directa: Escribir el código directamente, con lo cual se creará un nuevo "apartado" en la lista de las funciones/ procedimientos. En caso de que no sea un evento soportado por los controles de nuestro formulario, se mostrará en la lista de la izquierda, estando seleccionada en la derecha "General"
- Copiar/Pegar: Pues eso, si copias una función/procedimiento y lo pegas en la ventana de código...
- Por menú de VB: Según las distintas versiones de VB, será un menú u otro, deberás especificar el nombre del procedimiento o la función, marcando la casilla correspondiente. En VB4/VB5 verás que aparte de los Procedimientos (Sub) y las Funciones (Function) hay también Propiedades (Property), estas las veremos en otra ocasión. También verás que puedes declararlas Públicas o Privadas. Esto no es posible en VB3, al menos en los procedimientos y funciones de los formularios.
En otra ocasión veremos todas estas cosas y con ejemplos, que es lo que "mola".
Bueno, toda esta "retahíla" venía a cuento de cómo introducir código en los eventos de los controles o del formulario y cómo crear nuestras propias instrucciones (esto es lo que más me gustó del QuickBasic 4.0, poder crear mis propias instrucciones (subs) y funciones).Ya es hora de coger el listado de la entrega anterior y "destriparlo". Vamos a ver cada cosa por separado, que aunque parezca que es mucho código, realmente está "repetido", o casi...
Option Explicit
Esto nos obliga a declarar todas las variables que usemos en el módulo, ponerlo es una recomendación, incluso te la impondría como norma. Para que salga de forma automática en cada nuevo módulo, selecciona del menú Tools/Advanced la opción Declare variables required (o algo parecido, que viene a significar Requiere la declaración de variables)
Siguiendo nuestro recorrido por el código, no encontramos con:
Private Sub Command1_Click()
Lo de Private significa que sólo se puede acceder a este procedimiento desde dentro del módulo en el que está declarado. Es decir no se puede llamar desde otro form o módulo BAS.
Sub indica que es un procedimiento, no una función, ni una propiedad. Los Subs actúan como instrucciones propias del lenguaje. Las funciones también, pero devuelven un valor, mientras que los subs no devuelven nada, lo que cogen se los quedan ellos, aunque en su momento veremos que también nos pueden dar algo a cambio.
Command1_Click, este es el nombre que habrá que usar para acceder a él desde cualquier punto de éste módulo.
Los paréntesis sin nada dentro, indica que este procedimiento no recibe parámetros; los parámetros lo veremos dentro de un "ratillo"
Toda esta línea es la descripción del procedimiento y cuando se le llame, bien desde nuestro propio código, bien porque se pulse sobre el botón, se ejecutará todo lo que esté dentro de él. El final del procedimiento está marcado por End Sub.Las líneas con DIM indican que estamos declarando las variables y lo que se especifica después del AS es el tipo de variable, los cinco primeros son de cada uno de los tipos numéricos soportados (otro día veremos otro tipo cuasi-numérico), el sexto es Variant, el multi-uso, el que vale para todo.
Veamos ahora que es lo que se hace con esta línea:
Dim timer1#, timer2 As Double
Aquí he declarado dos variables del tipo Double. Al separarlas con comas no hay que repetir la palabra DIM, pero sí el tipo de cada variable. Ya vimos en la entrega anterior que algunos tipos de variables se podían indicar mediante unos caracteres especiales, (estos tipos son los heredados de versiones anteriores al Visual Basic 2, en esa versión, se introdujo el tipo Variant), en este caso # es lo mismo que Double, por tanto se podría haber hecho también de cualquiera de estas tres formas:
Dim timer1#, timer2#
Dim timer1 As Double, timer2#
Dim timer1 As Double, timer2 As DoubleAhora fíjate que esta otra no haría la misma tarea:
Dim timer1, timer2 As Double
Esto funcionaría con lenguajes como el C, (realmente el tipo se pone delante), pero en Basic no declara las dos variables como Double. La segunda variable si es Double, pero la primera es del tipo por defecto, en nuestro caso Variant.
Así que mucho ojito con las declaraciones de las variables. En algún sitio, no voy a decir dónde, porque lo mismo fue un "lapsus" del autor, pero decía que de esta forma declaraban tres variables de tipo Integer:
Dim i, j, k As IntegerSigamos nuestra andadura, ahora veamos esta declaración/asignación:
Const minBucle = 1, maxBucle = 10
Aquí lo que se declaran son dos constantes, éstas a diferencia de las variables, no pueden cambiar de valor, de ahí su nombre, por tanto permanecerán siempre con el mismo valor. Cuando se declara una constante, no es necesario especificar el tipo, VB se encarga de adivinarlo y usar el tipo adecuado, realmente lo que hace es sustituir estas "palabras" por el valor que hay después del signo igual. En caso de hacer esto: cNombre = "Una palabra". Visual Basic sabe que es una cadena de caracteres y cada vez que se encuentre con cNombre lo sustituirá por "Una palabra".
Ahora viene la explicación del "por qué" usar constantes. Además de "esclarecer" los listados, los hace más fáciles de comprender, también nos permite modificar un valor en un sólo sitio, con lo que ganamos en "confianza", al asegurarnos de que no omitiremos alguno de los sitios dónde tengamos o queramos cambiar el valor antiguo por uno nuevo.
En nuestro ejemplo, minBucle y maxBucle se usan en seis partes diferentes del procedimiento, si quisieras probar con otros valores, tendrías que cambiar en seis sitios esos valores, pero al declararlos como constantes, sólo cambiando el valor asignado, tenemos todo el trabajo hecho. Esto además de ser más fiable y legible, nos puede ahorrar algún que otro quebradero de cabeza y si además le añadimos que no ocupan espacio extra, salvo en la tabla de símbolos, una vez compilado el programa sólo se "compilarán" las constantes usadas. Sin embargo con las variables no ocurre esto, ya que aunque no se usen, ocupan memoria.Un inciso, esto de explicar tan detalladamente los listados, no va a ser norma, ya que al final todos nos aburriríamos, sólo lo haré cuando lo crea conveniente o bien si lo solicitas, en este caso, no tendré más remedio que cumplir tus deseos...
Command1.Caption = "Calculando..."
Cambiamos el texto mostrado en el botón, para avisarnos de que está haciendo algo...timer1 = Timer
Asignamos el valor de la función Timer a la primera de las dos variables que usaremos para calcular el tiempo empleado por cada uno de los bucles. Esta función devuelve el número de segundos transcurridos desde la media noche.For nInt = minBucle To maxBucle
Esto es un bucle, que se repetirá desde minBucle (1) hasta maxBucle (10) y la variable nInt es la que llevará la cuenta o la que se usará para saber el valor actual del bucle.Deberíamos ver primero la declaración del procedimiento Contar, para entender lo que hace la línea que viene después del For.
Private Sub Contar(valor As Integer, etiqueta As Control)
Declaramos un procedimiento privado llamado Contar (actúa como una instrucción más del VB, ya que no representa a ningún control ni evento), entre los paréntesis están declarados los dos parámetros que espera recibir en la llamada, el primero es un número entero y el segundo (separado por una coma), un Control, que puede ser cualquier control de VB.
El resto del procedimiento ahora no es demasiado significativoAhora veamos esta línea:
Contar CInt(nInt), Label1
Contar es el nombre del procedimiento y a continuación se deben indicar los parámetros que espera recibir. En este caso no sería necesario CINT ya que lo que hace esta función es convertir el número que se pone dentro de los paréntesis en un número entero y como resulta que nInt es un número entero... pues ¡no hay nada que convertir!
El segundo parámetro es el control Label1, ya sabes que tenemos 6 etiquetas en nuestro programa desde Label1 a Label6
Cuando llegue estos datos al procedimiento Contar, valor tomará lo que valga nInt y etiqueta se adueñará de Label1.Next
Continúa repitiendo el bucle hasta que se alcance el valor máximo, realmente el Next lo que hace es lo siguiente:
nInt = nInt + 1
¿Es nInt menor o igual que maxBucle? Si la respuesta es SI, sigue con lo que haya después de la línea FOR, en caso negativo continúa con la línea siguiente al Next (realmente en la siguiente instrucción después del Next, ya veremos esto en otra ocasión)timer2 = CDbl(Timer - timer1)
Asignamos a la segunda variable que usamos para el cálculo del tiempo la diferencia entre el nuevo valor de los segundos transcurridos desde la media noche (Timer) y el valor que tenía timer1, es decir cuantos segundos... antes de empezar el bucle.
El CDBL es una fución que devuelve un valor Doble. Es decir hace la resta y ese valor resultante lo convierte en doble.Label1 = "Duración con Integer: " & timer2
Esta asignación realmente es Label1.Caption, si se omite la propiedad, Visual Basic usa la que tiene por defecto, que según los manuales, suele ser la propiedad que se usa con más frecuencia. En este caso el Caption, es decir lo que se muestra en la etiqueta.DoEvents
Esta es una instrucción "controvertida" y a la que muchos programadores no les hace demasiada gracia usar, no porque no tenga su utilidad, sino porque hay que saber realmente lo que hace y tener cuidado cuando la usamos, ya que algunas veces puede crear errores o confusión... realmente no es tan drástico, pero casi...
DoEvents, detiene la ejecución del programa y devuelve el control a Windows, para que ejecute los mensajes que tiene pendientes en la cola de mensajes... ¿? no te preocupes si no te enteras, es así y punto. ¿por qué la uso? Pues para dar tiempo a que se vea el contenido del Label; prueba a quitarla y verás lo que ocurre, o debería ocurrir... que ya a estas alturas no me sorprendería nada que se mostrara...El resto del programa es idéntico a este bucle, pero usando distintas variables y las demás etiquetas. El caso es que Contar espera una variable de número entero y un control, en el caso del control es obvio que se están poniendo las distintas etiquetas y en el caso del número se convierte a entero, porque eso es lo que espera nuestra instrucción y si no lo hacemos así, se quejará.
Ya sólo queda ver una línea del procedimiento Contar:
etiqueta.Caption = valor * elMaximo + unDoble
unDoble contará desde 1 hasta elMaximo, en cada vuelta del bucle, se asignará al caption de la etiqueta pasada al procedimiento y el DoEVents que viene a continuación se encargará de que se muestre ese contenido. Bueno, también se asigna valor * elMaximo, es decir que cuando valor valga 1, se estará mostrando 1000 + unDoble, realmente para hacer un contador se tendría que haber usado lo siguiente:
etiqueta.Caption = (valor -1) * elMaximo + unDoble, para que mostrara desde el 1, en lugar de empezar desde el 1001.Una vez que Contar termina, por el End Sub, vuelve el control al bucle que lo llamó y se ejecuta la siguiente instrucción. Por tanto Contar se llamará tantas veces como dure el bucle en el que se encuentra.
Creo que queda todo más o menos claro y aunque este código no es muy útil por sí, ha servido para ver algunas cosillas del VB.
Para terminar vamos a ver una serie de cambios y a ver si adivináis que es lo que hace... así os servirá de ejercicio, cosa que algunos me habéis pedido, pero que aún no es el momento de hacerlos.
En las declaraciones generales añade esta declaración:
Dim Contando As IntegerEn Contar, añade lo siguiente después del DoEvents:
If Contando = 0 Then Exit ForAl principio del Command1_Click, añade estas líneas:
If Contando Then Command1.Caption = "Calcular" Contando = 0 DoEvents Exit Sub End If Contando = 1En cada uno de los bucles, pon esto después de llamar a Contar...
If Contando = 0 Then Exit SubY antes del End Sub añade esto otro:
Command1.Caption = "Calcular"
Contando = 0
Bueno, ahí dejo esto y como ejercicio podrías añadir dos controles TextBox para especificar los valores de maxBucle y elMaximo, de forma que según los valores introducidos, que por defecto deben ser 10 y 1000, se usen los que especifiques en cada TextBox y se tengan en cuenta cuando pulsas (haces click) en el botón.
Como pista te diré que las variables usadas y/o declaradas dentro de un procedimiento son sólo visibles dentro de ese procedimiento. No te quejarás del "pedazo" de pista que te he dado...A disfrutar y hasta la próxima entrega... ¿cuando? Eso ni se sabe...
Y ya sabes que espero tus comentarios sobre el cursillo este de marras...Nos vemos.