Está en la página 1de 168

Introducción a la Programación Visual Página 1 de 168

INTRODUCCIÓN A LA PROGRAMACIÓN VISUAL


Ms. C. Alfonso J. Rivero Errico
Nota a los lectores:
Este libro representa un intento de poner en contacto a profesores y estudiantes de Computación
con el interesante mundo de la programación visual para el ambiente Windows, y en particular con
el lenguaje de programación Visual Basic.
Por la extensión del libro no ha sido posible hablar en él de todo lo que consideramos importante
para el trabajo con este lenguaje, y hemos debido limitarnos a los aspectos esenciales que
permitan a nuestros lectores dar los primeros pasos en este terreno. Nos disculpamos de
antemano por ello.
Por supuesto, el lector interesado podrá profundizar sobre los aspectos en los que nos resultó
imposible extendernos en la explicación, consultando la bibliografía que referenciamos, y
consultando, sobre todo, la excelente ayuda que acompaña al lenguaje.
Hace pocos años, para aprender un lenguaje de programación bastaba con dominar un puñado de
conceptos y dejar lo demás a la empírica. Hoy en día no es así. El lenguaje Visual Basic se ha
desarrollado sobre la base de un sólido sistema conceptual que incluye elementos de
programación orientada a objetos y de programación conducida por eventos. Hemos dedicado
varias páginas a la discusión teórica de estos aspectos porque somos del criterio de que sin un
adecuado dominio de estos elementos, resulta muy difícil avanzar con seguridad y comprender
realmente la operación de este lenguaje de nuevo tipo.
El tamaño del libro nos impide desarrollar aquí un curso completo de programación, además de la
iniciación al trabajo con Visual Basic. Por ello hemos elaborado este libro pensando en un lector
familiarizado con el ambiente Windows a nivel de usuario, y que domine los elementos
fundamentos de la programación, preferiblemente en Quick Basic u otra versión de Basic.
En algunos ejemplos hemos sacrificado la eficiencia del código en pos de la claridad de los
programas, con el propósito de evitar que el lector se aparte del trabajo con los elementos
novedosos de Visual Basic por no lograr descifrar un subprograma.
El Autor
Introducción a la Programación Visual Página 2 de 168

INDICE
Capítulo Contenidos Página
1 Introducción
2 El ambiente de desarrollo de Visual Basic.
3 Características del lenguaje
4 Primeras aplicaciones en Visual Basic
5 Arreglos de controles.
6 Incorporando menús.
7 Explotando el ratón.
8 Jugando con el tiempo.
9 Accediendo a bases de datos.
Bibliografía
Introducción a la Programación Visual Página 3 de 168

Capítulo 1. Introducción Windows y la programación para Windows.


La aparición y la posterior estandarización de los sistemas operativos de interfaz gráfica como
Windows y Macintosh y la consecuente pérdida de terreno por parte del MS -DOS, colocó de
repente a los programadores en una situación muy complicada. A continuación veremos porque.
El MS-DOS, como sistema operativo, no estableció, ni pretendió en ningún momento establecer,
características o estándar para el interfaz hombre máquina en la pantalla en modo de textos que
manejaba. Lo único que estableció fue el empleo de modificadores a los comandos, del tipo /P, /W.
En tal situación fueron los programadores de aplicaciones los que de forma empírica fueron
proponiendo modelos de organización para el interfaz, y los que resultaron más prácticos y
eficientes, como las ventanas de modo texto, y los menús desplegables, se generalizaron, a tal
extremo que el propio sistema operativo, en sus actualizaciones, hizo uso de estos elementos de
interfaz, que el uso y la vox populi habían consagrado. Windows, en cambio sí se planteo desde
un primer momento el propósito de establecer un conjunto de características estándar para el
interfaz, y con este propósito las aplicaciones del propio sistema operativo fueron dotadas de
poderosos controles, como los Botones de Órdenes, las Barras de Desplazamiento, las Casillas
de Selección, entre otros muchos, que permiten a los usuarios realizar la navegación por el
sistema con extrema facilidad.
Este situación provocó que los programadores se vieran obligados a desarrollar aplicaciones que
permitieran al usuario realizar la navegación tal y como la hacía en las programas propios del
sistema. Pero, para poder lograr esto, resultaba necesario disponer de recursos similares a los que
dispone el interfaz gráfico de Windows, es decir, botones, barras, casillas etc. Y la tarea de
programar esos recursos en los lenguajes habituales en el ambiente MS-DOS, (Quick Basic, Quick
C, Turbo Pascal, etc.) resultaba suficientemente compleja como para que la mayor parte de los
programadores pudiera llevarla a feliz término.
2 Introducción a la Programación Visual
La alternativa que quedaba a ese grupo de programadores no era otra que esperar, por la
aparición de un lenguaje de programación especialmente diseñado para facilitar la elaboración de
aplicaciones para ser ejecutadas sobre Windows; un lenguaje que les permitiera emplear sin
grandes complicaciones los recursos estándar del interfaz gráfico del sistema operativo. Y esa
espera fue recompensada con la aparición de Visual Basic.
El Visual Basic dentro de las tendencias actuales de la programación.
En la actualidad el universo de la programación se desarrolla bajo el signo (o el paradigma) de la
Programación Orientada a Objetos, pero también, al estudiar la programación para Windows,
resulta frecuente encontrar referencias a otro modelo, el de la Programación Conducida por
Introducción a la Programación Visual Página 4 de 168

Eventos. A continuación intentaremos hacer una sucinta descripción de los mismos y discutir su
presencia o su influencia en el lenguaje Visual Basic.
Programación Orientada a Objetos.
La programación orientada a objetos es la expresión de uno de los más avanzados paradigmas en
el campo de la programación, y es, al mismo tiempo, el resultado de la evolución experimentada
por los paradigmas anteriores. Evolución motivada por la insuficiencia de los mismos para resolver
de forma segura y eficiente las cada vez más complejas tareas de la programación.
La Programación Orientada a Objetos surgió en tiempos de la “crisis del software” de finales de
los años 60, casi al mismo tiempo que la Programación Estructurada, aunque con menos fortuna
que esta última, que fue aceptada en aquel momento como la metodología de programación
llamada a resolver la severa crisis. En ese ámbito, la programación orientada a objetos pasó
inadvertida en el concierto de los lenguajes y las técnicas de programación. Sin embargo, la
persistencia a través de los años 70 y 80 de problemas similares a los que desataron la ya
mencionada “crisis del software”, obligó a que se retomaran las ideas originales de la programación
orientada a objetos, siendo hoy de amplio consenso que se trata del mejor paradigma disponible,
en estos momentos, para enrumbar los más complejos proyectos de programación. A diferencia de
otros paradigmas de programación, que intentan, al abordar un problema, representarlo o
modelarlo empleando entidades cercanas a la computadora (arreglos, subrrutinas, módulos) la
programación orientada a objetos se propone emplear entidades lo más cercanas posibles a la
realidad. O sea, en vez de intentar acercar el problema a la computadora, se trata de acercar la
computadora al problema. Para lograr esto se modela la realidad a través de entidades
independientes, capaces de interactuar entre si, que representan los diferentes elementos que
intervienen, en la vida real, en el problema planteado. A estas entidades se les denomina Objetos
Para resolver un problema bajo el paradigma de la programación orientada a objetos basta con
determinar y caracterizar los diferentes objetos que intervienen en el problema, definir sus
propiedades y sus acciones y ponerlos a interactuar entre si. Así de sencillo.
Los conceptos fundamentales en programación orientada a objetos son los conceptos de Objeto y
Clase, intentaremos a continuación definirlos de la forma más asequible.
El Objeto, tal y como ocurre en la vida real, es un ente que posee un conjunto de propiedades
que permiten definirlo individualmente, diferenciándolo de cualquier otro, y un conjunto de
acciones que es capaz de realizar. Por ejemplo, un camión se define por la marca del fabricante,
el modelo, el número de serie del motor, el tonelaje de la carga que puede transportar, el número
de la matrícula, el color etc. y es capaz de realizar un conjunto de acciones como moverse,
estacionarse, descargar, encender las luces, apagar el motor etc.
Introducción a la Programación Visual Página 5 de 168

La Clase, por su parte, debe verse como un ente abstracto que permite declarar el conjunto de
propiedades que definirán al objeto y el conjunto de acciones que estará en capacidad de realizar.
Las propiedades del camión que enumeramos en el párrafo anterior, son propiedades generales,
propiedades que tienen todos los camiones. Lo que hicimos allí fue, en realidad, definir la Clase
‘camión’. O sea, para nuestro programa, un camión será, de forma genérica, un ente que posea
esas propiedades y sea capaz de realizar ese conjunto de acciones.
Pero para poder hablar de un camión en particular, tenemos que asignar valores a esas
propiedades. Podremos hablar, por ejemplo, de un camión Kamaz, modelo 6824, de color verde,
cuya matrícula es HB 51248, el número de serie de su motor es 456-12-782 y es capaz de
transportar 18 toneladas de carga. Podemos hablar de otro camión, marca Ford, modelo de 1994,
de color rojo, con matrícula HB 11674, con número de serie del motor 718-F315 y con una
capacidad de carga de 10 toneladas. Esos dos entes concretos, que se definen como instancias
individuales de la clase ‘camión’ serán Objetos.
La implementación computacional de los objetos hace que estos sean módulos, donde se
encapsulan los datos que sirven para representar los valores de sus propiedades, y las
instrucciones de los procedimientos, que representan y ejecutan las acciones que es capaz de
realizar el objeto. Esta capacidad de agrupar los datos y los procedimientos que operan con ellos
hace que los objetos sean entidades sumamente fáciles de transportar y de mantener. En esto se
diferencia radicalmente de los esquemas de programación tradicional, donde los datos se definen
en un área y los procedimientos en otra, haciendo muy difícil conservar la integridad y privacidad
de los datos.
Un lenguaje de programación orientada a objetos debe permitir al programador realizar
definiciones de clases, y construir objetos a partir de esas clases. Visual Basic nos permite hacer
esto, pero también facilita nuestro trabajo al proporcionar un conjunto de objetos ya elaborados,
con los que podemos construir el interfaz gráfico que el programa mostrará a sus usuarios. El
programador tiene la posibilidad de operar libremente con estos objetos, asignando valores a sus
propiedades y ejecutando sus métodos de acuerdo a las necesidades del programa que esta
elaborando.
La programación conducida por eventos.
El planteamiento de la programación conducida por eventos resulta diametralmente opuesto al de
la programación tradicional, donde normalmente encontramos bloques monolíticos de instrucciones
y donde la secuencia de ejecución de los distintos procedimientos resulta por lo general bien clara.
La programación conducida por eventos propone la fragmentación del código del programa, en
Introducción a la Programación Visual Página 6 de 168

pequeños módulos, que se ejecutan únicamente cuando tiene lugar el evento (normalmente
producido por el usuario del programa) que desencadena su ejecución.
Un evento es un hecho concreto que afecta la ejecución del programa, pero que el instante de su
ocurrencia no puede ser previsto con exactitud por el diseñador del programa. Nadie puede, por
ejemplo, prever en que momento el usuario del programa va a oprimir un botón, o va a accionar
sobre una barra de desplazamiento. Puede pasar, inclusive, que el usuario
nunca oprima el botón. Y no se debe tratar de controlar por la fuerza estas situaciones. Un
programa para Windows debe ofrecer un interfaz abierto, donde el usuario pueda actuar
libremente. El programa debe esperar a que tenga lugar el evento y, cuando esto suceda,
reaccionar en consecuencia.
La programación conducida por eventos puede implementarse en algunos lenguajes de
programación tradicionales. Por ejemplo en Quick Basic (y en general en casi todas las versiones
de Basic) se dispone de instrucciones del tipo ON KEY GOSUB y ON INTERVAL GOSUB, que
permiten la detección de eventos del tipo opresión de tecla o transcurso de un lapso de tiempo.
Con esas herramientas se puede diseñar un programa que funcione bajo el principio de la
conducción por eventos. Pero evidentemente la programación orientada a objetos es el sustrato
ideal para desarrollar la programación conducida por eventos. La idea de la fragmentación del
código resulta natural en este medio, ya que cada objeto contiene las instrucciones necesarias
para realizar sus propias tareas. Ahora bien, para poder desarrollar programación conducida por
eventos, los objetos deben tener un tercer ingrediente, que se adiciona a las propiedades (o
atributos)
y a los métodos (o procedimientos). El objeto debe ser capaz de detectar o reconocer eventos, y
cuando eso suceda debe desencadenar la ejecución de un procedimiento o método de atención al
evento. De esta forma, para caracterizar genéricamente al Objeto, en la definición de su Clase será
necesario indicar:
· Los atributos o propiedades que individualizarán al objeto.
· Los eventos que el objeto será capaz de detectar.
· Los métodos o procedimientos que el objeto será capaz de ejecutar.
Estos métodos se dividirán en:
1. Métodos generales, o independientes de eventos.
2. Métodos de atención a eventos.
Visual Basic resulta un excelente lenguaje para desarrollar programación conducida por eventos.
Todos los objetos con que opera son sensibles a eventos. Programar en Visual Basic no es más
que construir un interfaz con los objetos de pantalla que el lenguaje nos suministra, determinar
Introducción a la Programación Visual Página 7 de 168

ante que eventos deben reaccionar esos objetos y escribir los correspondientes procedimientos de
atención al evento. Así de sencillo.
Introducción a la Programación Visual Página 8 de 168

Capítulo 2. El ambiente de desarrollo de Visual Basic. Instalación de Visual Basic.


La instalación de Visual Basic no entraña especiales dificultades. Basta con ejecutar el programa
Setup que se encuentra en el primer disco del paquete de instalación, (o en el directorio principal,
si se instala desde un CD ROM) y a continuación sólo será necesario ir cumpliendo con las
indicaciones que nos realiza el programa instalador. Al término de la instalación se ha incorporado
una nueva carpeta denominada Visual Basic 4.0 (o 5.0, según la versión que instalemos) dentro
de la carpeta Programas, en el menú Inicio, si estamos trabajando con Windows 95, o un grupo
con el mismo nombre, en el Administrador de Programas si estamos trabajando con Windows
3.x
Para ejecutar Visual Basic basta con acceder a la carpeta (o grupo para Windows 3.1) en que se
encuentra, y allí ordenar la ejecución de la aplicación Microsoft Visual Basic. Al recibir esa orden,
Windows coloca en la pantalla lo siguiente:

Figura 2-1. El ambiente de Programación de Visual Basic


Cuando un experimentado programador de Quick Basic (o de cualquier otro lenguaje para MS
DOS) carga Visual Basic por primera vez, lo asalta una sensación de estupor o desconcierto. En
efecto, la pantalla se llena en un instante de diferentes ventanas, pero por ninguna parte se
encuentra un editor, y el programador se pregunta: ¿Y dónde puedo yo escribir INPUT aquí? La
respuesta a la pregunta del programador podría ser aún más desconcertante: “Nunca más
escribirá INPUT”.
Introducción a la Programación Visual Página 9 de 168

Por supuesto, esa respuesta no encierra toda la verdad. En realidad el ambiente no nos ofrece
directamente ningún lugar donde escribir instrucciones, porque en Visual Basic antes de escribir la
primera línea del programa debemos realizar el diseño del interfaz que ese programa mostrará a
sus usuarios. Para cumplimentar esa tarea Visual Basic nos suministra de forma inmediata todas
las herramientas necesarias.
Como se aprecia en la figura 2-1, el ambiente (o entorno) de desarrollo de Visual Basic está
integrado por cinc o ventanas. De acuerdo al número con que las hemos marcado, estas ventanas
serán:
1. Ventana principal de Visual Basic.
2. Ventana del primer formulario.
3. Ventana de la Caja de Herramientas.
4. Ventana de Propiedades.
5. Ventana del Proyecto.
Ventana principal: A partir de esta ventana se controla todo el ambiente de desarrollo de Visual
Basic. Posee además de la barra de título, una barra de menú y una barra de herramientas, con
botones que permiten acceder con rapidez a las principales opciones del entorno. La barra de
herramientas se detalla en la siguiente figura:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
Figura 2-2. El panel de botones de la ventana principal
La función de los botones será, de acuerdo a la numeración que les hemos dado:
1. Crear un nuevo formulario.
2. Crear un nuevo módulo.
3. Abrir un proyecto o programa.
4. Salvar un proyecto o programa.
5. Fijar la posición de los controles sobre el formulario.
6. Mostrar la ventana de diseño de menú.
7. Mostrar la ventana de propiedades.
8. Mostrar la ventana del examinador de objetos.
9. Mostrar la ventana del proyecto.
10. Ejecutar el programa. (Run)
11. Detener la ejecución del programa. (Pause).
12. Finalizar la ejecución del programa. (Stop).
Introducción a la Programación Visual Página 10 de 168

13. Colocar un punto de parada. (Breakpoint).


14. Examinar el valor de un elemento.
15. Visualizar la estructura de llamadas activa.
16. Ejecución paso a paso a nivel de instrucción.
17. Ejecución paso a paso a nivel de procedimiento.
Ventana del primer formulario: Esta ventana no forma parte del ambiente de Visual Basic, por el
contrario: ¡Es parte de nuestro programa! Toda aplicación desarrollada para Windows debe
ejecutarse dentro de una ventana, de modo que Visual Basic nos proporciona automáticamente
este formulario o ventana, para que realicemos sobre el, el diseño del interfaz de nuestro
programa. Si más adelante necesitáramos nuevos formularios, podremos obtenerlos pulsando el
botón ‘Crear nuevo formulario’ en la ventana principal.
Ventana de la caja de Herramientas: Esta ventana suministra los elementos (controles), que
podemos emplear en el diseño del interfaz de nuestro programa. Estos controles al igual que los
formularios son clases de objetos, y por tanto disponen de propiedades, métodos, y como nos
encontramos en un ambiente visual, de eventos. Cada botón de la caja identifica una clase de
controles. Para colocar un control sobre el formulario hay que oprimir el botón correspondiente a su
clase y luego indicar, arrastrando con el ratón sobre el formulario el área rectangular que ocupará
el control. Como se puede ver Visual Basic dispone de un número considerable de clases de
controles, pero en este libro no disponemos de espacio suficiente para describirlos todos. Al final
de este capítulo haremos una descripción detallada de los más importantes.
Ventana de propiedades: Muestra una lista con las propiedades del objeto que halla sido
seleccionado. Se selecciona un objeto pinchándolo con el ratón (es decir, situando el puntero del
ratón sobre el objeto y pulsando el botón principal, que por lo general es el botón izquierdo).
También permite modificar los valores de las propiedades. Algunas de las propiedades de los
formularios y los controles pueden recibir sus valores mientras se realiza el diseño. Otras sólo
pueden recibirlos en tiempo de ejecución. Esta ventana muestra las propiedades del objeto
seleccionado, que pueden ser modificadas en tiempo de diseño.
Ventana del proyecto: Los programas (también llamados proyectos), escritos en Visual Basic,
pueden estar formados por más de un formulario, y contar también con módulos de código. Cada
formulario y cada módulo se almacena en un fichero independiente. La ventana del proyecto nos
permite visualizar y acceder a cada uno de los módulos y formularios que integran nuestro
proyecto.
¿Y dónde se escribe el código?
Introducción a la Programación Visual Página 11 de 168

Una vez terminado el diseño se puede comenzar a escribir el código del programa. Para ello Visual
Basic dispone de las Ventanas de edición de código. Cada formulario y cada módulo tiene su
propia ventana de código. Para acceder a ella basta realizar un doble clic sobre el formulario o el
control para el que se desea escribir código. También se puede acceder con la opción de mostrar
código de la Ventana del proyecto.
Cómo resolver un problema empleando un Lenguaje de Programación Visual.
En la programación tradicional resulta frecuente ver, como los programadores se concentran, a la
hora de resolver un problema, en las complicaciones algorítmicas del mismo, dejando para más
adelante, cuando ya hubiesen salido a flote de esas complicaciones, la implementación de la salida
en pantalla del programa. En muchas ocasiones se prepara una salida en pantalla elemental para
poder ir probando el comportamiento del programa, y sólo al final, esa salida elemental era
sustituida por el interfaz definitivo, el que debe ser mostrado a los usuarios.
Esta forma de organizar el trabajo del programador funcionaba aceptablemente en los viejos
buenos tiempos de la programación estructurada, cuando al terminar el diseño del programa
resultaba bastante clara la secuencia de ejecución de las instrucciones, los puntos claves de
bifurcación, etc., y sólo se permitía al usuario interactuar con el programa en determinados
procedimientos del mismo, y bajo un control sumamente riguroso. En un diseño realizado bajo
esos principios sólo se atendía al interfaz de pantalla cuando ello resultaba estrictamente
necesario.
Sin embargo, para escribir un programa con el propósito de ejecutarlo en un ambiente gráfico
como Windows, ese estilo de trabajo resulta inaplicable.
La razón es sencilla: el programador que pretenda escribir aplicaciones en estos momentos, y
tenga la natural pretensión de lograr que esas aplicaciones se ejecuten sobre el interfaz gráfico de
Windows, debe proponerse diseñarlas de forma tal que resulten consecuentes con los principios de
trabajo del ambiente gráfico. Para lograr eso es imprescindible que la ejecución de esas
aplicaciones sea conducida por eventos. Y la casi totalidad de los eventos se producen,
precisamente en la interfaz de la aplicación. Por esta razón si la interfaz no esta correcta y
completamente diseñada no resultará posible determinar con exactitud, desde un primer momento,
la totalidad de los eventos que pueden intervenir y resultar significativos para el buen
funcionamiento de nuestros programas, y esto redundará en un diseño deficiente, que obligará al
programador a realizar continuas retroalimentaciones, cada vez que se haga evidente la falta de un
elemento (objeto), en el diseño original del interfaz, y que para colocarlo y atender a su posible
interacción con los restantes objetos del interfaz, sea necesario generar nuevo código, modificar el
que ya se había escrito, o hacer ambas cosas.
Introducción a la Programación Visual Página 12 de 168

En principio a nadie se le ocurriría cerrar contrato con un arquitecto para la construcción de una
casa, y dejarlo que comience a mover la tierra y levantar las estructuras, sin antes haber revisado
los planos y quedar convencido de que el aspecto de la futura casa realmente le agrada.
Cuando se ejecuta una aplicación desarrollada para Windows, la misma se presenta y queda a la
espera de las acciones del usuario. Cada una de las posibles acciones del usuario (oprimir un
botón, desplegar un menú, etc.) produce un evento; entonces la aplicación realiza determinadas
acciones, (esto es, se ejecuta el subprograma de atención al evento) y cuando termina de
realizarlas vuelve a quedar a la espera de la próxima acción del usuario.
Esto responde al esquema de la programación conducida por eventos y así deben estar
concebidas todas las aplicaciones que desarrollemos con Visual Basic para ser ejecutadas sobre
Windows. Por esto es tan importante la etapa del diseño, porque es necesario tener el interfaz
completamente diseñado para poder realizar la segundo etapa en la solución del problema:
Determinar cuales serán las acciones que el usuario podrá realizar sobre ese interfaz, y como debe
reaccionar nuestro programa ante cada una de esas acciones. Es evidente que el usuario puede
realizar un sinnúmero de acciones sobre el interfaz, algunas de ellas tendrán importancia en la
solución del problema que estemos analizando y otras no. Al hacer este análisis debemos
identificar las acciones que resulten significativas para nuestro programa, y determinar los
Eventos que se producirán como consecuencia de estas acciones.
La determinación de los eventos significativos nos permitirá establecer, en un primer paso de
refinamiento, las tareas que tendrán los diferentes Procedimientos de atención a eventos. Los
posteriores pasos de refinamiento nos permitirán comprender si es necesario dividir alguna de
estas tareas y escribir para ello los procedimientos que resulte necesario.
Estos procedimientos serán denominados Procedimientos generales, o independientes de
eventos, y su ejecución se invoca desde otro procedimiento, tal y como sucede en la programación
procedural convencional.
Los anteriores argumentos nos permiten comprender la importancia que reviste disponer de un
interfaz completamente diseñado desde las etapas tempranas del diseño del programa, un interfaz
que permita determinar, con facilidad, el conjunto de eventos que resultarán significativos para la
conducción del programa que se pretende diseñar y poner a punto. Nos encontramos ya en
condiciones de conformar el esquema de las etapas para la solución de un problema con
computadoras empleando un lenguaje de programación visual.
Etapas para la solución de un problema empleando un Lenguaje de Programación Visual
1. Realizar el análisis y la interpretación del problema.
2. Realizar el diseño del interfaz visual del problema.
Introducción a la Programación Visual Página 13 de 168

 · Ajustar la posición y las dimensiones de los formularios.


 · Colocar los controles sobre los formularios.
 · Establecer las propiedades del formulario y los controles.
3. Determinar para que controles es necesario escribir código.
 · Determinar las tareas particulares de cada control.
 · Determinar los eventos asociados a esas tareas.
 · Determinar por refinamiento las tareas derivadas.
4. Escribir los procedimientos.
 · Declarar los datos de alcance general.
 · Escribir los procedimientos generales (o independientes de eventos).
 · Escribir los procedimientos de atención a eventos.
5. Verificar el programa.
 · Salvar la aplicación.
 · Ejecutar y poner a punto.
 · Retroalimentar, regresando al punto que sea necesario.
Diseño del Interfaz visual del problema.
Colocación de formularios y controles.
El primer paso en el diseño del interfaz de una aplicación es la preparación del formulario. Es decir,
ubicarlo en pantalla en la posición que deberá ocupar durante la ejecución del programa y ajustar
sus dimensiones. Normalmente, cuando se carga Visual Basic, se nos proporciona un primer
formulario con el que podemos trabajar. Si necesitáramos nuevos formularios podemos obtenerlos
por medio de la opción Formulario del menú Insertar en la versión 4.0 (opción New Form del
menú File, en la 3.0), o por medio del botón correspondiente en la ventana principal . Para ubicar
un formulario en la posición apropiada y ajustar sus dimensiones basta con arrastrarlo y modificarlo
con el ratón, tal y como se hace en Windows con una ventana normal.
A continuación debemos colocar los controles necesarios para nuestra aplicación sobre el
formulario. Para realizar esto se selecciona el control deseado en la ventana o caja de
Herramientas, y a continuación se arrastra con el ratón sobre el formulario, seleccionando un área
rectangular, donde será colocado el control. Una vez colocado el control, es perfectamente posible
reajustar sus dimensiones o su ubicación, para ello basta con seleccionarlo con el ratón y realizar
la modificación necesaria, arrastrando o redimensionando el control.
Introducción a la Programación Visual Página 14 de 168

Modificación de las propiedades de formularios y controles durante el diseño


Para modificar las propiedades de nuestros formularios y controles durante la etapa de diseño,
disponemos de la ventana de propiedades. Si no se encuentra visible esta ventana, podemos
activarla pulsando el botón correspondiente en la barra de herramientas, o a través del menú Ver.
La ventana Propiedades nos presenta en su parte superior una lista desplegable con los diferentes
objetos presentes en nuestro formulario, que incluye al propio formulario (Lista de Objetos), y en
su parte inferior una lista con las propiedades (Lista de Propiedades) del objeto seleccionado y
sus valores implícitos. Entre ambas listas se encuentra una caja de texto que contiene el valor de
la propiedad seleccionada. Podemos alterar con facilidad los valores por defecto, seleccionando la
ropiedades deseada, la cual se resalta de las demás, y escribiendo en la caja de texto el valor que
deseamos asignarle. En muchos casos no hay tan siquiera que escribir, la caja de texto presenta a
menudo un botón similar a los de las listas desplegables en su extremo derecho. Ese botón
despliega una lista con los posibles valores de la propiedad, y sólo tenemos que seleccionar el
apropiado. En el caso particular de las propiedades referentes a colores (ForeColor, BackColor,
etc.) se despliega una paleta de 64 colores, donde podemos seleccionar el que nos parezca más
conveniente. También es posible modificar el valor de una propiedad haciendo doble clic sobre ella
en la Lista de Propiedades.
La mayor parte de las propiedades de los objetos que nos permite emplear Visual Basic pueden
ser modificadas tanto en el momen-to inicial del diseño como más tarde, durante la ejecución del
programa. Sin embargo en determinados momentos tendremos que trabajar con objetos que tienen
la particularidad de que algunas de sus propiedades no pueden ser modificadas en tiempo de
ejecución, conservando los valores que recibieron durante el diseño. También nos tropezaremos
Introducción a la Programación Visual Página 15 de 168

con el caso contrario, propiedades cuyos valores no pueden ser definidos durante el diseño,
debiendo esperarse a que comience la ejecución del programa para actuar sobre ellas.

Manejo de aplicaciones que contienen múltiples formularios.


Tal y como hemos dicho un proyecto en Visual Basic puede estar integrado por un conjunto de
formularios y módulos de código. Los formularios contienen la interfaz visual, o sea la ventana que
se muestra en pantalla, y la ventana de código, donde se encuentran las declaraciones y
definiciones de los datos y procedimientos propios del formulario. Los módulos de código no
poseen interfaz visual, tan sólo contienen declaraciones y definiciones de datos y procedimientos.
Para administrar un proyecto integrado por varios componentes debemos emplear la ventana del
proyecto, que se muestra a continuación:
Introducción a la Programación Visual Página 16 de 168

Esta ventana contiene un listado con los nombres de los archivos donde se guardan los distintos
elementos que componen el proyecto. Entre ellos encontramos a los ya mencionados formularios y
módulos de código.
También pueden aparecer formando parte de nuestro proyecto los archivos de que se emplean
para incorporar nuevos controles a Visual Basic. Estos archivos se identifican por la extensión
.VBX en Visual Basic 3.0 y con .OCX en Visual Basic 4.0. y 5.0
Para acceder a un componente en particular basta con seleccionarlo y oprimir alguno de los
botones que contiene la ventana del proyecto en su parte superior. El primero de ellos nos permite
ver el interfaz visual del componente (sólo esta disponible si se selecciona un formulario), y el
segundo permite abrir la ventana de código del componente seleccionado (formularios o módulos
de código).
Esta ventana también nos ayuda a eliminar componentes que estén de más en un proyecto. Para
hacerlo, debe seleccionarse en ella el componenteque sobra, y entonces solicitar la opción
Eliminar Archivo del menú Archivo de la ventana principal, en la versión 4.0 (Remove File en el
menú File en la versión 3.0).
Clases y objetos del interfaz de Windows disponibles en Visual Basic.
Como hemos venido insistiendo, el primer paso en la elaboración de un programa para la solución
de un problema empleando Visual Basic, es el diseño del interfaz que el programa mostrará a sus
usuarios. Pero, para poder diseñar correctamente dicho interfaz, resulta imprescindible conocer
con profundidad las funciones y características de los diferentes elementos que Visual Basic pone
a nuestra disposición para conformar el interfaz.
Visual Basic nos permite emplear en el diseño de nuestros programas los objetos que
habitualmente encontramos en el interfaz visual de Windows (botones, casillas de selección, etc.).
Por las limitaciones de espacio, en este libro no podremos describir todas las características de
todos los objetos que nos proporciona Visual Basic. Nos limitaremos a los que nos han parecido
ser los más importantes para comenzar a trabajar. Y aún en el estudio de estos objetos no
resultará posible detallar la totalidad de sus propiedades ni de sus eventos, por lo que nos
restringiremos a los que resultan de uso más frecuente. El lector podrá encontrar la
informaciónrestante consultando la ayuda del propio Visual Basic o la bibliografía que
referenciamos en este libro. Una vez más nos disculpamos.
El interfaz gráfico de Visual Basic nos proporciona dos grandes clases de objetos: los formularios
y los controles. Los formularios no son otra cosa que las ventanas donde se ejecutan nuestros
programas, mientras los controles son todos aquellos elementos que aparecen dentro de esas
ventanas o formularios.
Introducción a la Programación Visual Página 17 de 168

Formularios.
La clase de los formularios, como todas las clases es una definición abstracta, y por tanto general.
Cuando creamos un formulario nuevo, estamos creando un objeto, que es una instancia particular
de esa clase.
Estos objetos expresan su individualidad por los valores específicos que asignamos a las
propiedades que los caracterizan. Para crear un formulario debemos emplear la opción Formulario
en el menú Insertar de Visual Basic, o pulsar el botón correspondiente a esta opción en la barra de
tareas de la ventana principal.
Principales propiedades de los Formularios.
NAME Nombre con que se identifica al formulario dentro del proyecto.
Visual Basic genera automáticamente nombres para los formularios y los controles, en el momento
en que estos son creados. Los nombres están compuestos por el identificador genérico de la clase
y por un número entero que se genera consecutivamente para cada clase. Por ejemplo, el primer
formulario generado recibe el nombre Form1, el segundo Form2 etc. Estos nombres pueden ser
cambiados a conveniencia del programador para que resulten más mnemotécnicos. Los nombres
que seleccionemos para los formularios y/o controles deben cumplir con las características
habituales de los identificadores en BASIC: comenzar en un carácter alfabético y no tener más de
40 caracteres. La propiedad Name sólo puede ser modificada durante la etapa de diseño,
accediendo a la caja de las propiedades. Nunca durante la ejecución del programa. Para acceder a
las propiedades de un formulario (o de un control) debe emplearse un identificador compuesto por
el nombre del formulario, un punto, y el nombre de la propiedad.
TOP Define a que distancia se encuentra nuestro formulario del borde superior de la pantalla. La
distancia se expresa en TWIPS (1 Twip=1/567 cm) a no ser que se especifique otra unidad de
medida mediante la propiedad Scalemode.
LEFT Complemento de la anterior. Define a que distancia se encuentra nuestro formulario del
borde izquierdo de la pantalla.
WIDTH Define el ancho que tendrá el formulario. El ancho se expresa en TWIPS a no ser que se
especifique otra unidad de medida mediante la propiedad Scalemode.
HEIGHT Complemento del anterior. Define la altura que tendrá el formulario.
SCALEMODE Permite definir las unidades de medida que se emplearán en el formulario (1-Twips,
3-Pixels, 5-Pulgadas, 7-Centimetros etc.).
Introducción a la Programación Visual Página 18 de 168

CAPTION Permite modificar el título del formulario que se muestra en la barra de título de la
ventana.
FORECOLOR Permite establecer el color de los elementos (textos o gráficos) que se dibujen sobre
el fondo del formulario por métodos como Print, Line etc.
BACKCOLOR Permite establecer el color del fondo del formulario.
FONTNAME Permite establecer la fuente de la tipografía con que escribirá en el fondo del
formulario el método Print.
FONTSIZE Permite establecer el tamaño de las letras para la salida del método Print.
CURRENTX y CURRENTY Definen la posición dentro del formulario a partir de la cual se realizará
la escritura de textos (vienen a sustituir al antiguo Locate) y el trazado de gráficos (punto de
referencia).
PICTURE Permite colocar un dibujo previamente elaborado en el fondo de un formulario. Esto
puede hacerse directamente en tiempo de diseño o durante la ejecución.
VISIBLE Permite mostrar u ocultar un formulario, en dependencia del valor (True o False) que
reciba esta propiedad.
ENABLED Habilita o inhabilita al formulario para percibir los eventos. Toma los valores True o
False. Capacitado
Principales Métodos de los Formularios:
SHOW Permite mostrar un formulario que ha sido previamente ocultado, ya sea por la
manipulación de su propiedad Visible, o por el empleo del método Hide.
HIDE Permite ocultar un formulario sin descargarlo de la memoria.
SETFOCUS Sitúa el foco sobre el formulario. La ventana que tiene el foco es la única sensible a
los eventos generados por el teclado o por el ratón.
PRINTFORM Imprime el contenido de un formulario.
LINE, CIRCLE, PSET, POINT, CLS, PRINT Permiten colocar sobre el fondo del formulario dibujos
o textos con una sintaxis similar a la empleada en otras versiones de Basic.
Principales Eventos de los Formularios:
Clasificaremos los eventos de acuerdo a los elementos que los provocan en tres grupos: los
eventos provocados por el ratón, los eventos provocados por el teclado y los eventos generales.
· Eventos del Ratón
CLICK Tiene lugar cuando se realiza un clic simple (oprimir y liberar el botón principal del ratón)
sobre el formulario.
DBLCLICK Tiene lugar cuando se realizan dos clics con rapidez.
MOUSEDOWN Tiene lugar cuando se oprime cualquiera de los botones del Ratón.
Introducción a la Programación Visual Página 19 de 168

MOUSEUP Tiene lugar cuando se libera cualquiera de los botones del Ratón que se encuentre
oprimido.
MOUSEMOVE Tiene lugar cuando el ratón se muevo sobre áreas libres del formulario. O sea,
áreas donde no se encuentren ubicados controles.
DRAGOVER Tiene lugar cuando un control es arrastrado con el ratón sobre el formulario.
DRAGDROP Tiene lugar cuando el objeto que esta siendo arrastrado sobre el formulario es
liberado.
· Eventos del Teclado
KEYDOWN Tiene lugar cuando se oprime una tecla. Permite identificar todas las teclas del
teclado. Si hemos colocado controles sobre el formulario, serán éstos, y no el formulario, quienes
detecten la opresión de las teclas. r
KEYUP Tiene lugar cuando se libera una tecla. Opera en forma similar al anterior.
KEYPRESS Tiene lugar cuando se oprime una tecla que devuelve un carácter ANSI. (El código
ANSI es un conjunto de 256 caracteres, empleado por Windows, cuya primera mitad coincide con
el código ASCII.
· Eventos generales de la Ventana
LOAD Tiene lugar cuando el formulario es cargado en memoria. Aunque no necesariamente sea
exhibido en la pantalla. Es muy útil para inicializar las variables privadas del formulario.
UNLOAD Tiene lugar cuando el formulario es descargado de la memoria. En ese momento se
destruyen las variables privadas del formulario, por lo tanto, si le interesa conservar la información
de alguna, esta es la última oportunidad.
GOTFOCUS Tiene lugar cuando el formulario recibe el foco.
LOSTFOCUS Tiene lugar cuando el formulario esta perdiendo el foco.
RESIZE Tiene lugar cuando la forma del formulario es alterada por el usuario.
Controles.
Los controles son los objetos que se colocan sobre los formularios. Tienen las funciones de facilitar
las entradas y salidas del programa, así como servir para que el usuario produzca eventos que
serán empleados para la conducción de la ejecución del programa. Existe un conjunto de controles
standard que forma parte de Visual Basic, y otro conjunto, los controles personalizados, que se
suministran en archivos independientes y para poder utilizarlos deben ser adicionados a la lista de
la ventana del proyecto.
Control LABEL (Etiqueta) Este control se emplea para colocar sobre el formularios textos
que el usuario no puede modificar accediendo a ellos con el ratón. Resulta más cómodo
emplear Etiquetas que escribir directamente en el formulario con el método Print, ya que las
Introducción a la Programación Visual Página 20 de 168

Etiquetas las podemos ubicar con gran facilidad durante el diseño del interfaz, mientras que ubicar
correctamente las salidas del método Print mediante las propiedades CurrentX y CurrentY resulta
mucho más complicado.
Propiedades de las Etiquetas.
Muchas de las propiedades, métodos y eventos que encontraremos en los controles, también se
encuentran en los formularios y ya han sido descritas.
En esos casos nos limitaremos a mencionarlos, y sólo profundizaremos en sus características
cuando presenten diferencias apreciables con lo ya descrito.
TOP, LEFT Describen la distancia a que se encuentra el control etiqueta (y en general el control)
del borde superior y del borde izquierdo del formulario que lo contiene.
WIDTH, HEIGHT Describen el ancho y la altura de la etiqueta (y en general del control).
CAPTION En esta propiedad se coloca el texto que la etiqueta mostrará sobre el formulario.
FORECOLOR, BACKCOLOR Color de los textos y del fondo de la etiqueta.
BORDERSTYLE Determina si la etiqueta tendrá o no un borde negro a su alrededor.
BACKSTILE Determina si el fondo de la etiqueta resulta transparente, o si se muestra del color
establecido por la propiedad BackColor.
ALIGNMENT Permite establecer la alineación del texto de la etiqueta (a la derecha, a la izquierda
o centrado).
PARENT Permite conocer el identificador (propiedad NAME ) del objeto sobre el que se encuentra
colocado el control.
También están presentes las propiedades NAME, FONTSIZE, FONTNAME, ENABLED, VISIBLE y
otras.
Eventos de las Etiquetas.
Las etiquetas son capaces de reconocer los eventos generados por el ratón que describimos para
los formularios.

Control TEXTBOX (Caja de Texto) Este control permite colocar sobre el formulario un
cuadro que muestra en su interior un texto. Este texto puede ser cambiado por el usuario,
accediendo a él con el ratón. Es especialmente útil para permitir que el usuario proporcione
información al programa, (viene a sustituir de cierta forma a la vieja y bastante problemática
instrucción INPUT). En esa función es posible colocar en la Caja de Texto un valor
predeterminado para la entrada, que el usuario puede sustituir a voluntad, o se puede emplear la
caja de texto en blanco, para que el usuario escriba en ella. Se puede emplear también para
exhibir información, pero no es recomendable ya que no se garantiza la integridad de la misma.
Introducción a la Programación Visual Página 21 de 168

Propiedades de las Cajas de Texto.


TEXT En esta propiedad se coloca el texto que mostrará la Caja de Texto. (Valga la redundancia).
MULTILINE Contiene un valor lógico (True o False) que determina si la Caja de Texto se
comportará como un editor lineal o multilineal. ¡Este control puede emplearse fácilmente como un
editor de textos!
SCROLLBARS Esta propiedad permite añadir barras de desplazamiento horizontales, verticales,
o ambas a nuestra Caja de Texto, en caso que el texto que contenga pueda exceder el tamaño de
la caja.
SELTEXT Es posible seleccionar una parte del texto contenido en la caja, arrastrando con el
cursor. Esta propiedad nos proporciona el texto seleccionado.
SELSTART Indica la posición en que comienza la selección, dentro del texto de la caja.
SELLENGHT Indica la longitud del texto seleccionado.
La Caja de Texto también presenta las propiedades siguientes:
TOP, LEFT, WIDTH, HEIGHT, NAME, FORECOLOR, BACKCOLOR, FONTNAME,
FONTSIZE, ENABLED, VISIBLE, ALIGNMENT, PARENT, cuyas características ya señalamos.
Eventos de las Cajas de Texto.
CHANGE Tiene lugar cuando se realiza algún cambio o alteración en el contenido de la Caja de
Texto (es decir en su propiedad Text). El cambio puede ser realizado de forma externa, por el
usuario del programa, accediendo a la Caja de Texto mediante el ratón, o puede también ser
realizado de forma interna, por instrucciones del programa, que modifiquen la propiedad Text.
También es sensible a los eventos del ratón y del teclado descritos para los formularios, así como
a los eventos GOTFOCUS y LOSTFOCUS.

Control COMMAND BUTTON (Botón de Órdenes) Es uno de los controles de uso más
frecuente. Nos proporciona los botones que se emplean para impartir la mayor parte de las
órdenes en el interfaz gráfico de W indows.
Propiedades de los Botones de Órdenes.
CAPTION En esta propiedad se coloca el texto que se mostrará en el Botón de Órdenes.
DEFAULT El Botón que tenga esta en esta propiedad el valor True, será el Botón por defecto (o
botón implícito). Esto significa que para oprimirlo se puede emplear indistintamente el ratón o la
tecla Enter. Sólo un Botón dentro de un formulario puede tener asignado el valor True en esta
propiedad. Normalmente se realiza esta asociación en los botones que se emplean para aceptar o
terminar positivamente una tarea.
Introducción a la Programación Visual Página 22 de 168

CANCEL Similar a la anterior. Permite asociar un Botón con la tecla Escape.


Esto normalmente se emplea en los botones que se van a emplear para cancelar una operación
También están presentes las propiedades siguientes:
TOP, LEFT, WIDTH, HEIGHT, NAME, BACKCOLOR, FONTNAME, FONTSIZE, ENABLED,
VISIBLE, PAEENT, cuyas características ya señalamos.
Eventos de los Botones de Órdenes.
El evento más importante para esta clase de controles es el evento Click, que se produce cuando
el botón de órdenes es pulsado. Además de este, los Botones de Órdenes son sensibles a los
restantes eventos del ratón, con excepción del Doble Click. También reconocen los eventos del
teclado que antes hemos descrito, y los eventos GOTFOCUS y LOSTFOCUS.

Control PICTURE BOX (Caja de Imágenes) Este control tiene dos importantes tareas en el
interfaz de Windows. En primer lugar permite incorporar elementos gráficos en el diseño de
nuestras aplicaciones, y en segundo lugar sirve como contenedor para otros controles. En efecto,
los controles que se colocan sobre una Caja de Imágenes, radican en su interior y no sobre el
fondo del formulario. Esto resulta muy conveniente, ya que nos permitirá agrupar controles que
tengan una determinada interrelación funcional, e incluso moverlos de conjunto, si esto fuera
necesario.
Propiedades de las Cajas de Imágenes.
PICTURE Similar a la propiedad de igual nombre estudiada para los formularios. Permite colocar
una imagen previamente elaborada en el fondo de la Caja de Imágenes. Esto se puede hacer en
tiempo de diseño, operando con la caja de propiedades, o en tiempo de ejecución, con la
instrucción LoadPicture
AUTOREDRAW Permite seleccionar, mediante un valor True o False si la Caja de Imágenes,
además de mostrarse en la pantalla, es copiada en memoria en una imagen persistente. Esa
copia permite que los elementos que se escriban o dibujen sobre la Caja de Imágenes, sean
restaurados y no se pierdan cuando la propia Caja es ocultada total o parcialmente por cualquier
causa, bien sea por un formulario que se superpone al que la contiene, bien porque el usuario
modifique (en tiempo de ejecución) las dimensiones del formulario, o por el efecto de un
resguardador de pantalla.
Esta propiedad también esta presente en los formularios.
AUTOSIZE También almacena un valor lógico (True o False) Si el valor es True, las dimensiones
del control se ajustarán a las de la imagen asociada con su propiedad Picture. En caso contrario
(valor False) se mostrará aquella parte de la imagen que quepa dentro del área ocupada por el
control.
Introducción a la Programación Visual Página 23 de 168

SCALELEFT, SCALETOP, SCALEWIDTH, SCALEHEIGHT Estas propiedades permiten redefinir


el sistema de coordenadas en el interior de la Caja de Imágenes. Esto se debe hacer cuando no
nos resultan convenientes ninguno de los sistemas preestablecidos que se pueden establecer
mediante la propiedad ScaleMode.
Estas propiedades también están disponibles para los formularios.
También están presentes las propiedades siguientes:
TOP, LEFT, WIDTH, HEIGHT, NAME, FORECOLOR, BACKCOLOR, BORDERSTYLE,
FONTNAME, FONTSIZE, ENABLED, VISIBLE, SCALEMODE, CURRENTX, CURRENTY,
PARENT, entre otras.
Métodos de las Cajas de Imágenes.
Las Cajas de Imágenes, al igual que los formularios, están dotadas de un grupo de métodos que
permiten el trazado de gráficos y la escritura, como son LINE, CIRCLE, PSET, POINT, CLS y
PRINT.
Eventos de las Cajas de Imágenes.
PAINT Este evento tiene lugar cuando algún área de la Caja de Imágenes que previamente había
sido ocultada por cualquier vía (ver propiedad AutoRedraw) es descubierta y aparece nuevamente
en la pantalla
Las Cajas de Imágenes reciben además, tanto los eventos generados por el ratón, como los
producidos por el teclado. También reciben eventos generales como GOTFOCUS, LOSEFOCUS y
RESIZE.

Control TIMER (Temporizador) Este control recibe también el apodo de ‘El control invisible’
y con mucha razón. Nadie, que sepamos, ha logrado ver el tiempo, y el tiempo es
precisamente la ocupación de este importantísimo control, que nos permite aprovechar a esa
implacable magnitud física para beneficio de nuestros programas. Bromas aparte, el control
Temporizador recibe esa denominación porque aunque lo colocamos y lo vemos sobre el
formulario durante el diseño, en tiempo de ejecución no resulta visible (ni es necesario que lo sea).
El control Temporizador se ocupa de generar un pulso de reloj de forma periódica, cada vez que
transcurre un determinado intervalo de tiempo que se fija en sus propiedades. Este pulso es
causante de un evento, que puede ser detectado y aprovechado para producir efectos en nuestros
programas.
Propiedades de los Temporizadores.
INTERVAL Determina el intervalo de tiempo que será usado como período para la generación de
los pulsos del Temporizador. Se expresa en milisegundos.
Introducción a la Programación Visual Página 24 de 168

ENABLED Habilita o inhabilita la actividad del Temporizador, y por tanto la detección del evento
asociado.
Eventos de los Temporizadores.
TIMER Es el único evento de los temporizadores. Cuando la propiedad Enabled toma el valor
True, el Temporizador genera este evento en forma periódica, cada vez que transcurre el intervalo
de tiempo fijado por la propiedad Interval. Si Enabled toma el valor False se suspende la
generación del evento TIMER, hasta tanto se restablezca el valor True en Enabled.

Control OPTION BUTTON (Botón de Opciones) Estos controles se emplean generalmente


en grupos, con el propósito de permitir al usuario seleccionar una entre un conjunto de
opciones. Esos grupos deben colocarse sobre un objeto contenedor, que puede ser el formulario,
o una caja de imágenes. Tienen la particularidad de que sólo un botón de opciones del conjunto
colocado en un contenedor, puede encontrase activado. Si fuera necesario colocar sobre un mismo
formulario dos grupos de botones de opciones, deben emplearse dos contenedores diferentes.
Propiedades de los Botones de Opciones.
VALUE Es la propiedad más importante de los botones de opciones. Recibe un valor booleano
(True o False) que permite saber si el botón de opciones se encuentra activado o no. El usuario
puede cambiar su valor realizando un clic sobre el botón. Dentro de un conjunto de botones de
opciones sólo uno puede estar activo.
Los botones de opciones también presentan las propiedades siguientes:
TOP, LEFT, WIDTH, HEIGHT, NAME, FORECOLOR, BACKCOLOR, FONTNAME, FONTSIZE,
ENABLED, VISIBLE, ALIGNMENT, PARENT.

Eventos de los Botones de Opciones.


Los botones de opciones son sensibles a los eventos del ratón y del teclado descritos para los
formularios, así como a los eventos GOTFOCUS y LOSTFOCUS.
Control CHECK BOX (Casilla de Selección) Las casillas de selección resultan muy similares a
los botones de opciones. También se emplean para permitir al usuario seleccionar entre un
conjunto de posibles opciones. La única diferencia entre estos dos controles radica en que
en un mismo conjunto de casillas de selección el usuario puede tener activadas más de una
simultáneamente. Las propiedades y eventos son los mismos que para los botones de opciones.

Control LIST (Lista) Este control permite colocar y administrar una lista de datos (en forma
de cadenas de caracteres), en nuestro interfaz.
Introducción a la Programación Visual Página 25 de 168

Propiedades de las Listas


LISTCOUNT Permite conocer la cantidad de elementos que contiene la lista.
LISTINDEX Indica el índice del elemento seleccionado de la lista.
Implícitamente es el primer elemento, ListIndex = 0.
LIST En esta propiedad se coloca el texto que se mostrara como parte de la lista.
MULTISELECT Indica si en la lista se podrá seleccionar solamente un elemento, o si admitirá la
multiselección.
SELECTED Contiene un valor booleano que indica si un elemento particular de la lista se
encuentra seleccionado.
SORTED Contiene un valor booleano que indica si la lista aparecerá ordenada alfabéticamente o
no.
Las listas también presentan las propiedades siguientes:
TOP, LEFT, WIDTH, HEIGHT, NAME, FORECOLOR, BACKCOLOR, FONTNAME, FONTSIZE,
ENABLED, VISIBLE, PARENT, que ya hemos estudiado.
Métodos de las Listas
ADDITEM Incorpora un nuevo elemento a la lista.
REMOVEITEM Elimina un elemento de la lista.
CLEAR Elimina todos los elementos de la lista dejándola vacía.
Eventos de las Listas
Las listas reconocen los eventos del ratón y del teclado, así como a los eventos GOTFOCUS y
LOSTFOCUS.

Control VERTICAL SCROLL BAR (Barra de Desplazamiento Vertical) Este control nos
permite desplazar un indicador a lo largo de una barra vertical.
Este movimiento produce la modificación proporcional de un valor numérico en un rango
predefinido. El valor puede modificarse arrastrando el indicador, pulsando los botones con flechas
que ocupan los extremos de la barra, o pinchando con el ratón en la superficie de la barra.
Propiedades de las Barras de Desplazamiento.
MIN Representa el extremo inferior del rango en que se moverá el valor numérico asociado al
desplazamiento del indicador.
MAX Representa el extremo superior del rango.
SMALLCHANGE Es el cambio que sufrirá el valor numérico cuando se pulsen los botones de los
extremos de la barra.
LARGECHANGE Es el cambio que sufrirá el valor numérico cuando se golpee con el ratón sobre
la superficie de la barra.
Introducción a la Programación Visual Página 26 de 168

VALUE Esta propiedad contiene el valor que es modificado por el usuario al actuar sobre la barra
de desplazamiento.
También están presentan las propiedades:
TOP, LEFT, WIDTH, HEIGHT, NAME, ENABLED, VISIBLE, PARENT, que ya hemos estudiado.
Eventos de las Barras de Desplazamiento.
CHANGE Tiene lugar cuando el valor asociado a la barra de desplazamiento es modificado de
cualquier forma.
SCROLL Tiene lugar cuando el usuario arrastra el indicador a lo largo de la barra de
desplazamiento.

Control SPIN (Botón de Conteo) Este control permite incrementar o decrementar el valor de
una variable con características de contador. Este control se emplea normalmente en asociación
con otros (cajas de textos o etiquetas, en los que se muestra el valor de la variable que se
modifica.
Para Visual Basic 5.0 este control se oresenta con el nombre UPDOWN
Propiedades de los Botones de Conteo.
SPINORIENTATION Permite orientar el Botón de Conteo es sentido vertical (valor 0, implícito) o en
sentido horizontal (valor 1).
También presenta las propiedades TOP, LEFT, WIDTH, HEIGHT, NAME, ENABLED, VISIBLE,
PARENT, que ya hemos estudiado.
Eventos de los Botones de Conteo.
SPINUP Tiene lugar cuando el usuario oprime el botón superior (si la orientación es vertical) o el
botón derecho (si la orientación es horizontal)
Este evento se aprovecha para incrementar la variable contadora que se esté utilizando.
SPINDOWN Tiene lugar cuando el usuario oprime el botón inferior (si la orientación es vertical) o el
botón izquierdo (si la orientación es horizontal)
Este evento se aprovecha para decrementar la variable contadora que se esté utilizando.
Control DIÁLOGOS COMUNES (Common Dialog) Este control permite utilizar desde
nuestros programas las cinco cajas de diálogos estandar deWindows, o sea Abrir Archivo,
Guardar Archivo Seleccionar Fuente de Letras,
Seleccionar Color e Imprimir. También permite ejecutar el programa Ayuda de Windows, que es
el manejador de hipertexto empleado por Windows para mostrar sus archivos de ayuda. Si
nosotros elaboramos archivos con el mismo formato que los archivos de ayuda de Windows
podremos mostrarlos desde nuestros programas empleando este control. Durante la ejecución el
Introducción a la Programación Visual Página 27 de 168

control resulta invisible, al igual que el temporizador. Se actúa sobre él modificando sus
propiedades desde el código de nuestros programas.
Introducción a la Programación Visual Página 28 de 168

Capítulo 3. Características del lenguaje.


Como lenguaje de programación Visual Basic es prácticamente semejante a su predecesor, el
Quick Basic, por lo que en este capítulo trataremos de hacer énfasis en los aspectos donde
puedan existir diferencias y sobre todo en los elementos nuevos que introduce Visual Basic. Por
las características del equipamiento instalado en nuestras escuelas desarrollaremos nuestros
ejemplos pensando en las versiones 3.0 , 4.0 y 5.0 de Visual Basic.
Tipos de Datos y Variables.
Visual Basic soporta todos los tipos de datos del BASIC estándar, y también los nuevos tipos de
datos introducidos por Quick Basic.
Cantidad de
Tipo de Dato Símbolo Rango de valores
Bytes
Integer (Entero) % 2 de -32767 a 32768
Long (Entero largo) & 4 de -2147483648 a 2147483647.
Single (Real de ¡ 4 de -3.402823E38 a 3.402823E38
simple precisión)

Double (Real de # 8 de -1.79769313486232E3 08 a


doble precisión) 1.79769313486232E308
Currency (Real @ 8 de -922,337,203,685,477.5808
ajustado) 922,337,203,685,477.5807
String (Cadena de $ Según el
tamaño
caracteres)
Variant ¡Nuevo en 16
Visual Basic!
Object ¡Nuevo en
Visual Basic!

Visual Basic introduce el tipo de datos Variant, que tiene la propiedad de adaptarse aceptar
valores de cualquier tipo, adaptándose a las características del dato que contiene. Una variable de
tipo variant, tiene la capacidad de cambiar de tipo en la medida en que recibe datos de tipos
diferentes. Por ejemplo:
A= 25 ‘Aquí la variable A se comporta como entera.
A= “Casa” ‘Aquí se comporta como cadena de caracteres.
A= 19.758 ‘Aquí se comporta como real de simple presición.
A diferencia de Quick Basic, el tipo de datos implícito en Visual Basic va a ser precisamente el
Variant, lo que tiene el inconveniente de ser el que mayor cantidad de memoria ocupa.
Introducción a la Programación Visual Página 29 de 168

También se introducen los datos de tipo object, que sirven para declarar variables como
referencias a objetos. Como ya se explicó más arriba, Visual Basic pone a disposición del
programador, un conjunto de objetos del interfaz gráfico de Windows, para permitirle desarrollar el
interfaz particular de su programa. Estos objetos se dividen en dos grandes clases: los formularios
o ventanas y los controles.
Dim A as Form ‘La variable A se comportará como una referencia a un objeto de la clase
formulario.
Dim B as Control ‘La variable B se comportará como una referencia a un objeto de la clase
control.
Dim C as Label ‘La variable C se comportará como una referencia a un objeto de la clase etiqueta
Para asociar estas referencias a un objeto se emplea la instrucción SET.
Set A As Form1 ‘La variable A hace referencia al objeto Form1, de la clase formulario.
Set B As Label1 ‘La variable B hace referencia al objeto Label1, de la clase control etiqueta
Set C As Label2 ‘La variable C hace referencia al objeto Label2, de la clase control etiqueta
La clase Control es una clase general, las clases de todos los controles particulares se derivan de
ella. Por eso a la variable B se le puede asignar la referencia de un objeto de cualquier clase de
control, mientras C sólo puede recibir referencias a controles de la clase etiqueta.
Una vez asignada la referencia las propiedades de los objetos pueden ser accedidas
indistintamente por su identificador o por la variable asociada.
Por ejemplo:
Form1.BackColor = QbColor(15) es equivalente a: A.BackColor = QbColor (15)
Label1.Caption = “Buenos Días” es equivalente a: B.Caption = “Buenos Días”
Ámbito de las variables
Un programa en Visual Basic esta integrado por un conjunto de entidades, entre los cuales se
encuentra distribuido el código. Algunos de estas entidades son formularios, que tienen
representación directa sobre la pantalla, en forma de una ventana. Otras son módulos, que
contienen exclusivamente código, en forma de declaraciones de tipos de datos, de variables y
procedimientos (subprogramas o funciones).
El ámbito de las variables dependerá del lugar dentro del proyecto, donde han sido declaradas.
Estos lugares pueden ser:
· Dentro de un módulo, en su área de declaraciones generales. En este caso la variable será
accesible para todos los procedimientos del módulo, pero inaccesible desde los restantes módulos
y formularios que componen el proyecto. Las variables se declaran normalmente, empleando la
palabra clave Dim. Por ejemplo:
Introducción a la Programación Visual Página 30 de 168

Dim A As Integer
Dim B (50) As Double
Sin embargo las variables que se declaran en el área general de los módulos pueden tener alcance
global para todo el proyecto si en vez de la palabra clave Dim, empleamos la palabra clave Global.
Por ejemplo:
Global C As Single,
Global N (120) As Long
· Dentro de un formulario, en su área de declaraciones generales. En este caso la variable será
accesible para todos los procedimientos del formulario, pero inaccesible desde los restantes
módulos y formularios que componen el proyecto. Para realizar esta declaración se emplea la
palabra clave Dim.
Dentro de un procedimiento. En ese caso la variable será privada de ese procedimiento, y ningún
otro procedimiento podrá tener acceso a ella.
Esta declaración puede realizarse por medio de las palabras claves Dim, ReDim o Static.
Operadores.
Visual Basic emplea los mismos operadores con que tradicionalmente hemos trabajado en Basic y
en Quick Basic, pero también introduce algunos operadores nuevos. En la siguiente tabla los
mostramos ordenados de acuerdo a su prioridad. (Los operadores relacionales tienen todos la
misma prioridad).

Tipo Operador Operación Nuevo en Visual


Basic
Aritmético ^ Exponenciación
- Cambio de signo (menos
unario)
*,/ Multiplicación y División
reales
\ División entera
Mod Resto entero de la división
+,- Suma y resta
Concatenación & Si
Relacional > Mayor que
< Menor que
= Igual
<> Desigual
<= Menor o igual
>= Mayor igual
Otros Like Comparación de cadenas Si
Is Comparación de referencias a Si
objetos
Introducción a la Programación Visual Página 31 de 168

Lógico Not Negación


And Conjunción
Or Disyunción inclusiva
Xor Disyunción exclusiva
Eqv Equivalencia
Imp Implicación
Tabla 1 Los operadores de Visual Basic.
El operador ‘&’ se emplea para concatenar expresiones, al estilo de la concatenación de cadenas
que normalmente realiza el operador ‘+‘. La ventaja del nuevo operador radica en que es capaz de
concatenar también, cadenas de caracteres con expresiones numéricas. Para realizar esto primero
convierte el resultado de la expresión numérica a una cadena y luego realiza la concatenación. Por
ejemplo:
A%= 25 ‘A% es una variable numérica entera
B$= “CDR “ ‘B$ es una variable alfanumérica
C$ = B$ & A% ‘C$ recibe la cadena “CDR 25”
El operador Like es extremadamente poderoso en la comparación de cadenas, ya que permite
realizar la comparación con patrones generales o con conjuntos de elementos. Su sintaxis es:
Resultado = <Expresión de cadenas> Like <Patrón de comparación>
El patrón de comparación también es una cadena de caracteres, pero esta cadena puede contener
uno o más de los siguientes elementos especiales:
El elemento: Puede ser sustituido en la cadena por:
? Un carácter cualquiera.
* Una cadena de caracteres.
# Un dígito cualquiera.
[ lista ] Uno de los caracteres que aparecen en la lista.
[ !lista ] Un carácter que no aparezca en la lista.
Veremos a continuación algunos ejemplos que ilustran la identificación de patrones por el operador
Like:
Con este patrón Se reconocen cadenas como: Pero no:
“a?a” “ana” , “ada” , “aTa” , “a3a” , “abcdea” , “alicia”
“a+a”
“a*a” “ana” , “alicia” , “aBcDea” , ” “abced” , “a120”
“a54321a
“a#a” “a5a” , “a7a” , “a0a” “ana” , “ada”
“a[ d, n, m]a” “ama” , “ana” , “ada” “ala” , “ara”
“a[ t, r, j ]a” “asa” , “ana” “ata” , “ara”

El operador IS se emplea para comparar las referencias contenidas por variables de tipo objeto.
Por ejemplo, después de las declaraciones:
Dim B As Control
Introducción a la Programación Visual Página 32 de 168

Dim C As Label y las asignaciones:


Set B = Label1
Set C= Label1
Se puede preguntar:
IF B Is Label1 THEN o IF B Is C THEN En ambos casos la respuesta es verdadera.
Estructuras de Control.
En Visual Basic encontramos todas las estructuras de control que acostumbramos trabajar en
Quick Basic, ellas son:
· IF ... THEN ... ELSE
Esta estructura de control que nos sirve para programar algoritmos alternativos permite bifurcar la
secuencia de ejecución de nuestros programas a partir de evaluar una expresión lógica. Puede
presentarse con dos sintaxis diferentes:
1. Como estructura lineal. En ese caso su sintaxis será:
IF <Condición> THEN <Instrucción1 >. ELSE <Instrucción2>
En este caso, si la condición evaluada resulta verdadera se ejecutará la Instrucción1, de lo
contrario se ejecutará la Instrucción2
2. Como estructura de bloques. En ese caso su sintaxis será
IF <Condición> THEN
<Bloque de instrucciones1 >.
ELSE
<Bloque de instrucciones2 >.
End if
Esta segunda sintaxis es muy poderosa, porque permite ejecutar bloques formados por varias
instrucciones y además la escritura del programa resulta más clara y comprensible. En este si la
condición evaluada resulta verdadera se ejecutarán las instrucciones del Bloque de instrucciones
1, y de lo contrario se ejecutarán las instrucciones del Bloque de instrucciones 2.
En ambos casos la segunda alternativa indicada por la palabra reservada ELSE resulta opcional y
sólo la tendremos que escribir cuando nos interese ejecutar alguna instrucción de resultar falsa la
condición que estamos evaluando.
SELECT CASE
La estructura de control SELECT CASE nos permite también evaluar alternativas, pero de una
forma diferente a la estructura IF THEN; mientras esta última estructura nos permite analizar una
condición y tomar dos alternativas, (una para cuando la condición evaluada resulta ser cierta y otra
para cuando resulta falsa) la estructura SELECT CASE nos permite evaluar múltiples alternativas
Introducción a la Programación Visual Página 33 de 168

en dependencia del valor de una variable o de una expresión. Esto lo ilustraremos a partir de un
ejemplo:
SELECT CASE a+b
CASE 4
Bloque de instrucciones 1
CASE 8
Bloque de instrucciones 2
CASE 12
Bloque de instrucciones 3
CASE IS > 15
Bloque de instrucciones 4
CASE ELSE
Bloque de instrucciones 5
END SELECT
En este caso se analiza el valor de la expresión a+b. Si el resultado es 4 seejecuta el Bloque de
instrucciones 1; si el resultado es 8 se ejecuta el Bloque de instrucciones 2; si el resultado es
12 se ejecuta el Bloque de instrucciones 3; si el resultado (y vean que interesante) es mayor
que 15 se ejecuta el Bloque de instrucciones 4; Por último si el resultado no cae dentro de
ninguna de esas alternativas se ejecuta el Bloque de instrucciones 5.
Esta estructura de control es especialmente útil cuando nos proponemos resolver problemas donde
debemos seleccionar entre varias alternativas (más de dos). Un ejemplo de esto es el problema de
clasificar un ángulo de acuerdo a su amplitud, aquí las alternativas serán nulo, agudo, recto,
obtuso, llano, sobreobtuso y completo. Este problema se puede resolver usando la estructura IF
THEN pero es mucho más fácil si empleamos la estructura SELECT CASE.
· FOR ... NEXT
Esta clásica estructura de control (la primera con que contó el lenguaje BASIC), permite programar
algoritmos cíclicos (o repetitivos) cuando el problema nos permite conocer de antemano la cantidad
de repeticiones que se deben efectuar.
FOR <Variable> = <Valor Inicial> TO <Valor Final>
Bloque de Instrucciones
NEXT
Esta estructura emplea una variable, llamada variable de control, cuyo valor se incrementa (de
uno en uno), desde el valor inicial hasta que sobrepasa el valor final. Cada vez que la variable de
control toma un nuevo valor, se ejecutan las instrucciones incluidas dentro del Bloque de
Introducción a la Programación Visual Página 34 de 168

Instrucciones. De esta forma si queremos ejecutar diez veces un conjunto de instrucciones,


debemos escribir:
FOR I = 1 TO 10
Instrucciones
NEXT
Si para nuestro problema fuera necesario incrementar la variable de control en una cantidad
diferente de 1 se incorpora a la estructura FOR la palabra reservada STEP para indicar el valor del
incremento.
Supongamos que en nuestro ejemplo necesitamos incrementar la variable de control desde 1 hasta
diez, pero variando de 0.5 en 0.5. Para lograr eso debemos escribir:
FOR I = 1 TO 10 STEP 0.5
Muchos estudiantes de programación se preguntan por qué razón en casi todos los libros, las
variables de control que se emplean llevan por nombres I, J y K. No es otra que la fuerza de la
costumbre. Casi todos los autores de libros de programación tenemos ya algunos años en el oficio,
y aprendimos a programar en el viejo lenguaje FORTRAN. En ese lenguaje el tipo de las variables
estaba indicado por la letra con que comenzaba su nombre, y solo las variables enteras podían ser
empleadas como variables de control en un ciclo. En FORTRAN las variables enteras eran
aquellas cuyos nombres comenzaban con letras desde la I hasta la N. De ahí que los primeros
ciclos que programamos se controlaran con variables I, J, etc... y de ahí nació la costumbre. Valga
esta referencia al FORTRAN para incluir en la bibliografía el viejo libro con que muchos
aprendimos a programar.
· DO ... LOOP
Esta estructura de control también permite programar algoritmos cíclicos (o repetitivos) y es
especialmente útil cuando el problema no nos permite conocer de antemano la cantidad de
repeticiones que se deben efectuar, y debemos repetir el ciclo hasta que ocurra algo (es decir se
cumpla una condición) que nos indique que debemos finalizar las repeticiones. Esta estructura
tiene dos sintaxis fundamentales:
1. Realizando el control a la salida. En ese caso su sintaxis será:
DO
Bloque de Instrucciones
LOOP WHILE <Condicion>
En este caso el bloque de instrucciones se repite mientras la condición indicada se evalúe como
verdadera. Como la comprobación se realiza después de la última instrucción del bloque estas
Introducción a la Programación Visual Página 35 de 168

instrucciones se ejecutan por lo menos una vez, aún cuando la condición resulte falsa desde el
primer momento.
2. Realizando el control a la entrada. En ese caso su sintaxis será:
DO WHILE <Condicion>
Bloque de Instrucciones
LOOP
Aquí también el bloque de instrucciones se repite mientras la condición indicada se evalúe como
verdadera. Pero como la comprobación se realiza antes de la primera instrucción del bloque, si la
condición resulta falsa desde el primer momento estas instrucciones no se ejecutan ni siquiera una
vez.
La condición se expresa en términos de Mientras que... por medio de la palabra reservada
WHILE, pero también puede expresarse en términos de Hasta que... si en lugar de WHILE
empleamos la palabra reservada UNTIL En ese caso se escribiría:
DO
Bloque de Instrucciones
LOOP UNTIL <Condicion>
o DO UNTIL <Condicion>
Bloque de Instrucciones
LOOP
En ese caso las instrucciones del ciclo se ejecutarán hasta que lacondición se evalúe como
verdadera.
Algo que no podemos pasar por alto al di scutir esta estructura decontrol es el peligro de caer en
un ciclo infinito, es decir que la estructura no se detenga nunca. Esto puede ocurrir si no
seleccionamos bien la condición de parada, o si no programamos correctamente. Para ayudarnos
en esta tarea disponemos de la instrucción EXIT DO que nos permite detener un ciclo DO LOOP
desde cualquier lugar de su bloque de instrucciones
DO
Instrucciones.........
IF <Condición1> THEN EXIT DO
......... Instrucciones
LOOP WHILE <Condicion2>
La condición a partir de la cual ejecutamos la instrucción EXIT DO
Introducción a la Programación Visual Página 36 de 168

(Condicion1) puede ser la misma que se utiliza para controlar la estructura (Condicion2) pero
también puede ser diferente esto dependerá de lascaracterísticas de los problemas que tengamos
que resolver y de losalgoritmos que elaboremos para ello.
No hemos querido extendernos demasiado en este estudio teórico de las estructuras de control, su
aplicación práctica en los próximos capítulos nospermitirá comprender mucho mejor su
funcionamiento.
Instrucciones
Tal y como dijimos un poco en broma, nunca más escribiremos INPUT. Las instrucciones
habituales de entrada como INPUT, LINEINPUT e INKEY$ no aparecen en Visual Basic, ya que la
entrada de información se realiza a través de controles. La instrucción de salida PRINT sobrevive
como método en los formularios, pero tampoco se recomienda su uso, prefiriéndose los controles
etiqueta para exhibir información.
Introducción a la Programación Visual Página 37 de 168

Capítulo 4. Primeras aplicaciones en Visual Basic. Un programa elemental.


Una vez que hemos entrado en contacto con las características fundamentales del lenguaje y de
los principales objetos que podemos emplear en Visual Basic, nos encontramos en condiciones de
desarrollar nuestro primer programa, o proyecto en este lenguaje.
Comenzaremos por un problema muy sencillo que nos permitirá ilustrar tanto la elaboración de un
interfaz simple como la aplicación en Visual Basic del modelo de la programación conducida por
eventos. Prepararemos una ventana con tres botones, el primer botón dará la orden: “Saludar”, el
segundo botón dará la orden: “Despedirse” y el tercer botón dará la orden:
“Terminar”. Cuando el usuario que emplee este programa oprima el primer botón en la ventana
debe aparecer el letrero “Hola, que tal.” en letras grandes y de color rojo. Cuando oprima el
segundo botón en la ventana debe aparecer el letrero “Hasta luego.” también en letras grandes,
pero de color azul y cuando oprima el tercer botón el programa terminará.
En este caso las tareas a realizar por el programa resultan muy claras, por lo que podemos
dedicarnos a diseñar el interfaz. Prepararemos un formulario que contendrá tres controles botones
de órdenes y un control etiqueta, que emplearemos para escribir los mensajes. Como el
formulario contendrá pocos elementos no es necesario que sea demasiado grande, por lo que
podemos ajustar sus dimensiones arrastrando sus bordes con el puntero del ratón, tal y como se
hace con cualquier otra ventana en Windows. Para componer el interfaz debemos colocar sobre el
formulario vacío que nos ofrece Visual Basic, el control Etiqueta y los tres controles Botones de
órdenes. Para hacer esto debemos seleccionar el botón correspondiente a las etiquetas en la caja
de herramientas de Visual Basic y luego seleccionar sobre el formulario el área donde deseamos
colocar la etiqueta. Después seleccionaremos el botón correspondiente a los botones de órdenes y
colocaremos sobre el formulario el primer botón. De igual forma colocaremos los otros dos
botones. El resultado de nuestro diseño se muestra en la figura 2-1.

Figura 4-1. Nuestro primer interfaz.


Como ya se dijo, Visual Basic asigna a cada formulario un identificador (propiedad Name) formado
por el nombre de la clase del control y por un número consecutivo. Para facilitar la identificación
visual de los controles, Visual Basic coloca ese mismo identificador en aquella propiedad del
control que resulta visible en el interfaz. Por lo general la propiedad que el control muestra es la
propiedad Caption. Así podemos identificar con facilidad a la etiqueta Label1, a los botones de
órdenes Command1, Command2 y Command3 y por supuesto al formulario Form1.
Introducción a la Programación Visual Página 38 de 168

Es evidente que esos no son los títulos que nos interesa ver en los controles cuando nuestro
programa se ejecute. La etiqueta no debe mostrar nada mientras no se oprima ningún botón, y los
títulos de los botones ya se mencionaron. Al formulario le pondremos por título “Mi primera
aplicación”.
Para colocar estos títulos en los controles debemos seleccionar cada control pinchándolo con el
puntero del ratón (es fácil reconocer cuándo un control esta seleccionado, en ese caso el control
aparece rodeado por unos cuadrados negros, esos cuadrados son a su vez puntos elásticos que
sirven para modificar las dimensiones del control) una vez seleccionado el control accedemos a la
ventana de propiedades (que muestra las propiedades del control que se encuentra seleccionado),
en la lista de propiedades seleccionamos la que deseamos modificar (en nuestro caso la propiedad
Caption) y escribimos su nuevo valor.
Pero no son estas las únicas propiedades que tendremos que modificar. El problema nos pide que
los letreros se escriban con letras grandes. Para asegurar eso tendremos que cambiar el valor
implícito de la propiedad FontSize (que controla el tamaño de las letras) en la etiqueta Label1.
También por razones de estética procuraremos que el letrero aparezca centrado, para eso
tendremos que actuar sobre la propiedad Alignment de la etiqueta. Por último, para garantizar que
la etiqueta no se destaque del fondo del formulario asignaremos un valor 0 en su propiedad
BorderStyle.
A continuación presentamos una tabla con las propiedades a las que es necesario asignar valores
como parte del diseño de nuestro formulario:
Objeto Propiedad Valor asignado Comentario
Form1 Caption “Mi primera aplicación”
Título de la aplicación.
Label1 Caption “” (cadena vacía) Al principio no esta escrito nada.
FontSize 24 Se agranda la letra para que los letreros se aprecien mejor.
Alignment 2 (Centrado) Asegura que los letreros queden centrados dentro de la etiqueta.
BorderStyl e
0 (Ninguno) Impide que aparezca un borde negro alrededor de la etiqueta.
Command 1
Caption “Saludar”
Command 2
Caption “Despedirse”
Command 3
Caption “Terminar”
Introducción a la Programación Visual Página 39 de 168

También es sencillo determinar las acciones a desarrollar por los distintos controles del formulario,
los dos primeros botones deben escribir letreros en la etiqueta y el tercer botón debe finalizar el
programa.
Estas acciones se deben ejecutar cuando se opriman los botones. El evento que se produce
cuando el usuario oprime un botón es el evento Click. Por tanto tendremos que escribir código
para los procedimientos de atención a los eventos Click de cada uno de los botones. El nombre
del procedimiento de atención a evento de un control (o de un formulario) está compuesto por el
identificador del control y el nombre del evento, separados por un carácter “_”. Por ejemplo, el
procedimiento de atención al evento Click del botón de órdenes Command1 de denomina
Command1_Click.
Para escribir las instrucciones de nuestros procedimientos, o las declaraciones de las variables que
emplearán nuestros programas debemos abrir la Ventana de Código de nuestro formulario. Cada
formulario posee su propia ventana de código y los procedimientos y las declaraciones (de
variables o de tipos) que en ella se escriban serán locales a ese formulario. Para abrir la ventana
de código de un formulario debemos seleccionar el mismo en la lista de objetos de la Ventana del
Proyecto y a continuación oprimir el botón View Code, de esa misma ventana. Otra forma de
hacerlo es realizando un doble click sobre el propio formulario.
La ventana de código, como la que se muestra en la figura 4-2, se encuentra dividida en dos
partes. En su parte superior encontramos dos listas desplegables, a la izquierda la lista de los
objetos y a la derecha la lista de los procedimientos asociados a los objetos. La parte inferior de la
ventana contiene un editor, que nos permite escribir nuestras instrucciones.
En la lista de los objetos encontraremos todos los objetos que forman parte del formulario, es decir,
el propio formulario y todos los controles que hayamos colocado sobre él. Cuando seleccionamos
un objeto, la lista de los procedimientos nos mostrará todos los posibles eventos que ese objeto
puede reconocer. Cuando seleccionamos un evento el editor nos proporciona el encabezamiento
del procedimiento de atención a ese evento, de forma tal que sólo tenemos que escribir las
instrucciones del procedimiento. También encontraremos en la lista de los objetos un elemento
denominado (general). Este no es propiamente un objeto del formulario, sino que identifica la zona
de declaraciones del formulario. Allí podemos declarar tipos, variables y procedimientos, que serán
de acceso local (o privado) para todos los objetos del formulario. Para el elemento (general) la lista
de procedimientos nos mostrará tan sólo un elemento nombrado (declarations), este identifica el
área de declaraciones de tipos y variables. En la medida en que vayamos escribiendo
procedimientos generales, o independientes de eventos, los mismos se irán incorporando a la lista
de procedimientos del elemento (general).
Introducción a la Programación Visual Página 40 de 168

En nuestro programa necesitamos escribir código para el evento Click del objeto Command1.
Para hacerlo abriremos la ventana de código, seleccionaremos en la lista Object: el objeto
Command1 y en la lista Proc: seleccionaremos el evento Click.
Cuando se oprima el botón de órdenes Command1 debemos escribir en pantalla el letrero "Hola,
que tal." en color rojo. Veamos como hacerlo:
Figura 4-2. La ventana de código
Para escribir un texto en la etiqueta hay que asignar una cadena de caracteres que contenga el
texto en la propiedad Caption de la etiqueta. El identificador de una propiedad esta formado por el
nombre del objeto y el nombre de la propiedad, separados por un punto. En este caso la etiqueta
recibe el nombre de Label1. Así, escribiendo Label1.Caption = “Hola, que tal.”estaremos
colocando el letrero en la propiedad Caption de la etiqueta, y por tanto el letrero se hará visible
sobre el formulario.
Para cambiar el color del texto de una etiqueta tenemos que modificar el valor de la propiedad
ForeColor de esa etiqueta, asignándole el valor correspondiente al color que deseamos. Para
proporcionarle a la propiedad ForeColor el valor que necesitamos podemos emplear dos recursos:
las funciones QBColor y RGB. La función RGB tiene tres parámetros, cada uno de los cuales
contiene un valor entre 0 y 255 que definen la intensidad de los tres colores básicos, Rojo, Verde y
Azul. Combinando convenientemente los tres parámetros de RGB se puede generar toda la rica
gama de colores que admiten las tarjetas de video Super VGA. En nuestro caso, para obtener el
color rojo tendríamos que escribir Label1.ForeColor=RGB(255,0,0). La función QBColor es mas
modesta, nos permite emplear el mismo conjunto de colores , del 0 al 15 que se empleaba en
Quick Basic. Nos decidimos por esta última función, empleando el parámetro 12 (rojo brillante), de
esta forma escribiremos Label1.ForeColor= QBColor (12).
De esta forma el procedimiento de atención al evento Click del botón Command1 quedará así:
Sub Command1_Click ()
Label1.ForeColor = QBColor(12)
Label1.Caption = "Hola, que tal."
End Sub
Nota. Est a es la sintaxis de Visual Basic 3.0. En las versiónes 4.0 y 5.0 se coloca la palabra
reservada Private, delante de Sub. El encabezamiento de este procedimiento sería en Visual
Basic 4.0: Private Sub Command1_Click ().
Cuando el usuario oprima el botón de órdenes Command2 debemos escribir en pantalla el letrero
"Hasta luego." en color azul. Pare ello seleccionaremos en la lista de objetos de la ventana de
código el control Command2 y en la lista de Procedimientos el elemento Click. El procedimiento
Introducción a la Programación Visual Página 41 de 168

de atención a este evento es muy similar al anterior, sólo cambia el texto del letrero y el color.
Veamos como queda:
Sub Command2_Click ()
Label1.ForeColor = QBColor(9)
Label1.Caption = "Hasta luego."
End Sub
Por último, cuando se oprima el botón de órdenes Command3 debe concluir el programa. Al igual
que en Quick Basic esto se hace con la instrucción End.
El procedimiento de atención al evento Click del botón de órdenes Command3 será simplemente
así:
Sub Command3_Click ()
End
End Sub
De esta forma hemos concluido nuestra primera aplicación en Visual Basic, y estamos en
condiciones de ejecutarla para comprobar su funcionamiento.
Para ejecutarla podemos emplear el botón ejecutar en la barra de herramientas de la ventana
principal de Visual Basic, o seleccionar la opción Iniciar en el menú Ejecutar.
Un programa un poco más complejo.
Nuestro primer problema no presentaba ninguna complicación algorítmica. Ahora les propongo
enfrentar una tarea algo más complicada: elaboraremos un programa que nos permita entrar dos
números enteros y sea capaz de mostrarnos el resultado de la suma de ambos cuando lo
solicitemos.
La solución de este problema en un lenguaje de programación tradicional resulta sumamente
sencilla, bastaría con entrar los dos números y esperar por la opresión de una determinada tecla (o
del ratón) para realizar e imprimir la suma. Programando en Quick Basic la solución podría ser algo
así:
INPUT A
INPUT B
DO
A$=INPUT$(1)
IF A$=“F” T HEN END
IF A$=“+” THEN EXIT DO
LOOP
PRINT A+B
Introducción a la Programación Visual Página 42 de 168

En este caso la tecla con del símbolo ‘+’ esta prevista pare realizar la suma y la tecla ‘F’ para
finalizar el programa. Las cosas se complicarían un poco si quisiésemos permitir al usuario operar
con varios juegos de datos, o si quisiéramos hacer más agradable la presentación de la
información en la pantalla, lo que nos obligaría a recurrir a instrucciones como LOCATE, PRINT
USING, etc. Más complicado aún, sería tratar de controlar la entrada de datos para evitar que el
usuario incluya caracteres ilegales (como signos o letras) dentro de los números.
Trabajar con Visual Basic hace que muchos de estos problemas, especialmente el lograr una
presentación agradable, resulten extremadamente sencillos. De acuerdo a lo que planteábamos
sobre la programación visual, el diseño general de nuestro programa debe comenzar por un diseño
claro de la interfaz, que permita determinar con facilidad a que controles y eventos es necesario
asociar código. Por ejemplo para nuestro problema resultaría agradable y conveniente una
presentación como la siguiente:
Evidentemente las dos primeras casillas blancas están destinadas a contener los dos números
suministrados por el usuario y por tanto este debe tener oportunidad de escribir en ellas. La tercera
casilla se destina a colocar el resultado y por tanto el usuario no debe poder alterar su contenido
libremente. Los dos botones muestran explícitamente su función y los símbolos ‘+’ e ‘=‘ sirven para
esclar ecer el sentido de la operación que se pretende realizar.
Ahora bien ¿qué recursos emplear para construir este interfaz? Para las dos primeras casillas,
donde el usuario puede escribir, el recurso apropiado es el control Caja de Texto (TextBox),
mientras para la casilla de la respuesta debemos emplear un control Etiqueta (Label) cuyo
contenido no puede ser modificado libremente. Para escribir los símbolos ‘+’ e ‘=‘también
emplearemos controles Etiqueta, a los que asignaremos un fondo transparente, para que no
resalten sobre el fondo del formulario.
Figura 4-3.
Para los botones empleamos el control Botón de Órdenes (CommandButton) .
Una vez determinados los controles necesarios podemos ir seleccionándolos uno por uno,
arrastrándolos desde la caja de controles hasta el formulario y acomodándolos allí, ajustando
convenientemente su tamaño, hasta conformar el interfaz deseado, tal y como se ve a
continuación:
Una vez colocados los controles necesarios sobre el formulario, y ajustados sus tamaños, tanto del
formulario como de los controles, debemos pasar a modificar sus restantes propiedades. En
nuestro caso las propiedades a modificar son las siguientes:
Objeto Propiedad Valor asignado
Comentario
Introducción a la Programación Visual Página 43 de 168

Form1 Caption “Sumador a


Elemental”
Título de la aplicación.
BackColor &H0080FF8
0 (Verde claro)
Color del fondo del formulario.
Text1 Text “” Al comienzo del programa esta casilla debe estar vacía.
Text2 Text “” Esta también.
Label1 Caption “+”
FontSize 13.5 Se agranda la letra para que el símbolo ‘+’ se aprecie mejor.
BackStyle 0
(Transparente)
El fondo de la etiqueta se vuelve transparente, el texto parece estar escrito directamente sobre el
formulario.
BorderStyl 0 Elimina el borde negro que rodea e (Ninguno) las etiquetas. La combinación de estas
dos propiedades hace que la etiqueta parezca parte del fondo del formulario.
Label2 Caption “=“ Lo mismo que para Label1
FontSize 13.5 Lo mismo que para Label1
BackStyle 0 Lo mismo que para Label1
BorderStyl e
0
(Ninguno)
Lo mismo que para Label1
Label3 Caption “” Lo mismo que para Text1 y Text2
Command1 Caption “+”
FontSize 13.5 Lo mismo que en Label1 y Label2
Command2 Caption “Terminar”
Cuando terminemos de establecer los valores de estas propiedades ya el formulario tendrá el
aspecto mostrado en la Figura 1. Corresponde ahora el momento de determinar a que controles se
debe asociar código.
En principio no es necesario realizar ninguna acción al inicio del programa, ya que el ajuste de las
propiedades garantiza los valores iniciales de Text1, Text2 y Label3. Por tanto no es necesario
escribir código para el evento Load del formulario. Siguiendo nuestro análisis -en un primer nivel
de refinamiento- vemos que la entrada de datos puede ser realizada directamente por el usuario,
Introducción a la Programación Visual Página 44 de 168

operando con los controles Text (más adelante nos ocuparemos de validar los datos que el usuario
entra) por tanto la única acción a realizar es la suma, que debe efectuarse cuando el usuario
oprima el Botón de Ordenes 1, que muestra el símbolo ‘+’.
Para asociar código a ese control debemos acceder a la ventana de código del formulario, como
hicimos en el problema anterior. Una vez abierta la ventana de código seleccionemos en la lista
Object: el objeto
Command1 y en la lista Proc: el evento Click, y escribamos lo siguiente:
Sub Command1_Click( )
Label3.Caption=Format$( Val( Text1.Text )+Val( Text2.Text ) )
End Sub
De esta forma queda conformado el procedimiento que se ejecutará cuando el control Command1
identifique la ocurrencia del evento Click.
Simplemente se sumarán los contenidos de los dos controles Text (previamente convertidos a
valor numérico) y el resultado, convertido a cadena se coloca en el control Label3. Para realizar
esta última conversión empleamos la función Format$. Esta función es una novedad de Visual
Basic, que integra la posibilidad de realizar transformaciones de tipo, con facilidades para
establecer formatos de salida muy superiores a las de la antigua instrucción PRINT USING.
El otro código que debemos escribir es el del control Command2, que deseamos emplear para
terminar el programa. Basta con seleccionar en la lista Object: el objeto Command2 y en la lista
Proc: el evento Click, y escribir:
Sub Command2_Click( )
End
End Sub
Con esto hemos terminado una primera solución (un tanto burda) de nuestro problema. Para que la
solución sea completamente aceptable debe ser capaz de verificar los datos suministrados por el
usuario, y también permitirle operar con varios juegos de datos. Comenzaremos por implementar la
verificación de la entrada. Para esto es necesario poder advertir cuando el usuario oprime una
tecla dentro de alguno de los controles TextBox. La opresión de una tecla debe representar, de
acuerdo con la filosofía del interfaz de Windows, la ocurrencia de un evento. Si revisamos el
conjunto de eventos notables de los controles Caja de Texto, encontraremos los eventos
KeyDown y KeyPress, que tienen lugar cuando una tecla es oprimida. La diferencia entre ambos
es que el primero se produce cuando se oprime cualquier tecla, mientras el segundo sólo ocurre
cuando la tecla oprimida genera un carácter ANSI. Por esta razón preferiremos el evento
KeyPress, escribiendo para él el siguiente código:
Introducción a la Programación Visual Página 45 de 168

Sub Text1_KeyPress (KeyAscii As Integer)


If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 0
End Sub
El parámetro KeyAscii contiene el código ANSI (muy similar al ASCII) del carácter
correspondiente a la tecla oprimida. Como los dígitos aparecen en la tabla ASCII ocupando
consecutivamente las posiciones desde el código 48 (correspondiente al carácter “0”) hasta el 57
(carácter “9”) es fácil determinar si la tecla oprimida corresponde a un dígito. Si el carácter ANSI
de la tecla oprimida no corresponda a un dígito, lo sustituimos por el código 0, cadena vacía, y por
lo tanto no será incorporado a la propiedad Text de la Caja de Texto. Para el control Text2 se
escribe un código similar.
En principio el problema está resuelto satisfactoriamente. Sin embargo, en la práctica nuestra
solución puede confrontar algunos problemas. En efecto, la libertad que tiene el usuario para
acceder y modificar el contenido de las cajas de texto permitiría que, una vez efectuada la suma, el
usuario modificara alguno de los sumandos, quedando en nuestro formulario una expresión
matemáticamente incorrecta, como esta que muestra la figura 4-5.
Aquí, después de haber introducido los datos 8 y 4 y operado con ellos, el usuario ha accedido a la
segunda Caja de Texto, y ha introducido un dígito “1”, transformando la expresión matemática en
un error garrafal. Para resolver esta situación tenemos dos caminos: o bien prohibimos al usuario
modificar los sumandos una vez realizada la suma, o preparamos nuestro programa para que borre
la solución y deje en blanco la casilla, en caso que cualquiera de los sumandos sean alterados. En
este último caso el usuario podría tener, incluso, la posibilidad de volver a sumar nuevos juegos de
datos, aspecto que, aunque no formaba parte del enunciado inicial de nuestro problema,
representa un enriquecimiento importante del mismo.
Como nos interesa familiarizarnos con Visual Basic probaremos dos posibles soluciones.
Solución 1: Se impide al usuario alterar las Cajas de Texto una vez realizada la suma.
Para lograr esto basta con manipular la propiedad Enabled en ambas Cajas de Texto una vez que
se realiza la suma. Esto se debe realizar de conjunto con la suma como parte de la atención al
evento generado al oprimir el Botón de Ordenes 1. El procedimiento correspondiente quedaría:
Sub Command1_Click ( )
Label3.Caption = Format$(Val(Text1.Text) + Val(Text2.Text))
Text1.Enabled = False ‘ Se inactiva el control Text1
Text2.Enabled = False ‘ Se inactiva el control Text2
End Sub
Introducción a la Programación Visual Página 46 de 168

Solución 2: Borrar el resultado cuando se alteren los valores de los sumandos. Para poder hacer
esto debemos averiguar si es posible reconocer la ocurrencia de un cambio o modificación en el
contenido de una Caja de Texto. Esta situación ocurre de manera imprevista, cuando el usuario
decide acceder a la Caja de Texto. Por tanto nuestra única posibilidad radica en determinar si la
modificación del contenido de una Caja de Texto (o alguna de las acciones necesarias para
realizar esa modificación) genera un evento que podamos aprovechar para colocar en su rutina de
tratamiento nuestro código. Si revisamos la lista de los principales eventos identificables sobre una
Caja de Texto, encontraremos el evento Change, que precisamente tiene lugar cuando se
producen modificaciones en el contenido de la Caja de Textos. No queda sino escribir código para
anular el contenido del control Label3 cuando tenga lugar este evento en cualquiera de las dos
cajas de textos:
Sub Text1_Change ( )
Label3.Caption = "" ‘ Borra el contenido de la propiedad ‘ Caption del control Label3
End Sub
Lo mismo se escribiría en el subprograma Sub Text2_Change ( )
Sub Text2_Change ( )
Label3.Caption = "" ‘ Borra el contenido de la propiedad ‘ Caption del control Label3
End Sub
Figura 4-5.

De esta forma queda resuelto totalmente nuestro problema, disponemos de una sumadora
elemental que funciona de manera eficiente. Sin embargo cualquiera puede ver que no es difícil
extenderla a las tres restantes operaciones aritméticas. ¿Por qué no hacerlo? Para ello debemos
preguntarnos ¿Qué haría falta para que nuestra sumadora realizara las tres operaciones
aritméticas restantes? Pues adicionarle tres nuevos controles botones de órdenes para representar
los operadores “-”, “*” y “/” y escribir código para cada uno de ellos. Por la enumeración automática
de Visual Basic a estos controles les corresponderían los identificadores Command3, Command4
y Command5. El interfaz modificado se muestra en la figura 4 -6.
En la siguiente tabla representamos las propiedades que necesitan ser modificadas en los nuevos
controles que se incorporan a nuestro formulario.
Objeto Propiedad
Valor
Asignado Comentario
Form1 Caption “Calculadora Debemos cambiar el título de la Elemental” aplicación.
Introducción a la Programación Visual Página 47 de 168

Command3 Caption “-”


FontSize
13.5 Lo mismo que en Label1 y Label2
Command4 Caption “*”
FontSize
13.5 Lo mismo que en Label1 y Label2
Command5 Caption “/”
FontSize
13.5 Lo mismo que en Label1 y Label2
El mayor inconveniente que presenta el interfaz es el signo “+” que muestra de forma permanente
la etiqueta Label1. Este signo que tenía sentido en la sumadora elemental ya que junto con el
signo “=“ conformaba la expresión aritmética, haría absurda cualquier expresión en que el cálculo
realizado sea una resta una multiplicación o una división. Si este signo no puede permanecer fijo
debemos entonces modificarlo de acuerdo a la operación aritmética que se realice. De esta forma
el procedimiento que escribimos para realizar la suma debe ahora además de realizar el cálculo,
colocar en la etiqueta Label1 el signo “+”. El procedimiento modificado quedaría así:
Sub Command1_Click ()
Label3.Caption = Format$(Val(Text1.Text) + Val(text2.Text))
Label1.Caption = "+"
End Sub
Los procedimientos para realizar las operaciones de sustracción y multiplicación resultan similares
al que ya elaboramos para la suma
Sub Command3_Click ()
Label3.Caption = Format$(Val(Text1.Text) - Val(text2.Text))
Label1.Caption = "-"
End Sub
Figura 4-6.
Sub Command4_Click ()
Label3.Caption = Format$(Val(Text1.Text) * Val(text2.Text))
Label1.Caption = "*"
End Sub
El procedimiento para realizar la división sí resulta diferente, ya que debemos controlar la
posibilidad de una división entre cero. En ese caso escribiremos la palabra error en la casilla de las
soluciones.
Introducción a la Programación Visual Página 48 de 168

Sub Command5_Click ()
If Val(Text2.Text) = 0 Then
Label3.Caption = "Error"
Else
Label3.Caption = Format$(Val(Text1.Text) / Val(Text2.Text))
End If
Label1.Caption = "/"
End Sub
Con esta modificación que convierte nuestra sumadora elemental en una calculadora elemental
damos por terminado este capítulo, en que hemos pretendido mostrar los principios de la
programación para Windows con Visual Basic mediante la solución de dos problemas simples. En
el próximo capítulo estudiaremos nuevos recursos de este lenguaje que nos permitirán enfrentar
tareas de programación de mayor grado de complejidad.
Introducción a la Programación Visual Página 49 de 168

Capítulo 5. Arreglos de Controles


Para resolver los problemas que hasta ahora han sido planteados, hemos necesitado diseñar
interfaces con relativamente pocos controles Sin embargo problemas más complejos, como puede
ser, por ejemplo, la elaboración de una calculadora, nos pueden obligar a trabajar con todo un
conjunto de controles (en este caso los que se empleen para representar los dígitos del teclado de
la calculadora) que realizan prácticamente la misma función (en el ejemplo, ayudar a componer el
número que muestra la pantalla de la calculadora), y que por tanto responden a los mismos
eventos de forma similar, lo que nos obligaría a escribir repetidamente el mismo procedimiento de
atención al evento, una vez para cada control.
Cuando aprendimos la programación tradicional, entramos en contacto con una problemática
bastante similar: la incomodidad de tener que representar en variables simples un conjunto de
datos, del mismo tipo, y que debían ser procesados por los mismos procedimientos. Los lenguajes
de programación tradicionales resolvieron esta situación poniendo a disposición de los
programadores el tipo de datos estructurado Arreglo, que permitía agrupar bajo un mismo
identificador un conjunto de datos del mismo tipo, simplificando de manera apreciable el trabajo de
programación.
El lenguaje de programación Visual Basic nos ofrece una solución muy similar a la anteriormente
descrita: cuando necesitemos operar con todo un conjunto de controles que realizan tareas
similares respondiendo de la misma forma a los mismos eventos podemos agruparlos
cómodamente en un Arreglo de Controles.
¿En qué situación emplear un arreglo de controles?
Los arreglos de controles nos van a resultar especialmente útiles para solucionar dos tipos de
situaciones; la primera de ellas ya fue mencionada:
La segunda, aunque aparenta ser más sencilla que la primera (y posiblemente lo sea para la mayor
parte de los programadores) no deja de resultar incómoda de enfrentar sin disponer de arreglos de
controles: es la representación en pantalla de listas de datos, cuando por alguna necesidad del
programa, no resulta posible emplear, para realizar esa representación, ninguno de los controles
que suministra Visual Basic para el trabajo con listas.
¿Cómo crear un arreglo de controles?
Para crear un arreglo de controles debemos colocar primeramente sobre el formulario todos
aquellos controles que formarán parte del mismo. Una vez colocados, procederemos a modificar la
propiedad NAME de cada uno de ellos, asignándole el nombre que hallamos seleccionado para el
arreglo de controles. Visual Basic no reaccionará cuando cambiemos el nombre del primer control,
pero, cuando cambiemos el nombre del segundo, reconocerá la duplicación del identificador y nos
Introducción a la Programación Visual Página 50 de 168

mostrará una ventana de confirmación, advirtiéndonos de la existencia de otro control con ese
nombre, y preguntándonos si deseamos formar un arreglo de controles.
Al recibir nuestra respuesta afirmativa, Visual Basic conforma el arreglo de controles, activando la
propiedad INDEX de los controles. Esta propiedad, a la que aún no habíamos hecho referencia,
esta disponible en todos los controles que nos ofrece Visual Basic, y sólo se utiliza para establecer
el orden de los elementos que integran el arreglo de controles. Normalmente Visual Basic indexa
los controles en el mismo orden en que vamos incorporándolos al arreglo, pero podemos
perfectamente modificar los valores de los La propiedad INDEX es de sólo lectura, o sea, los
índices de los controles de un arreglo no pueden ser alterados por software, durante la ejecución
del programa.
Un arreglo de controles tiene una serie de características que lo diferencia de los arreglos
ordinarios y que resulta conveniente puntualizar.
 · A pesar de ser arreglos, no se declaran en el código del programa con la instrucción DIM.
 · El límite inferior de los índices es el cero.
 · El límite superior no esta definido.
 · Son exclusivamente unidimensionales.
Cuando trabajamos con arreglos de controles, los subprogramas de tratamiento de eventos
incorporan como primer parámetro el índice del arreglo. Por ejemplo, el procedimiento:
Figura 5-1. Ventana de confirmación para la creación de un arreglo de controles
Sub Text1_Change ()
Text1.ForeColor = QBColor(12) ‘ QBColor(12) Rojo brillante
End Sub
Preparado para operar con el control simple Text1, y que es capaz de cambiar el color del texto de
la caja cuando ese texto es modificado, se convierte en:
Sub Text1_Change (Index As Integer)
Text1(Index).ForeColor = QBColor(12)
End Sub
Este procedimiento cambia el color del texto de cualquiera de los controles Caja de Texto que
integran el arreglo, Text1 cuando la información que contiene ese control integrante del arreglo es
alterada.
Para ilustrar las posibilidades que nos brinda el empleo de arreglos de controles resolveremos a
continuación dos problemas donde el empleo de arreglos de controles simplifica
extraordinariamente la tarea del programador, y que ejemplifican las dos situaciones en que, como
señalábamos son especialmente necesarios los arreglos de controles. El primero de ellos se refiere
Introducción a la Programación Visual Página 51 de 168

al uso de arreglos de controles para representar los valores de listas de datos, mientras el
segundo ejemplifica el empleo de arreglos de controles para explotar el tratamiento de eventos
comunes a grupos de controles.
El primer problema nos propone elaborar un programa que muestre en pantalla una lista de
5 números seleccionados al azar entre el 1 y el 50 y sea capaz de ordenarla a petición del
usuario. El programa debe ser capaz de renovar a petición del usuario los números de la
lista, y también debe permitir establecer el sentido en que se efectuará el ordenamiento
(ascendente o descendente).
Los algoritmos para ordenar una lista son suficientemente conocidos para que debamos
detenernos a explicarlos. En la solución de esta problema emplearemos el algoritmo de máximos
o mínimos sucesivos. Trabajando en Quick Basic la lista se representa sobre un arreglo y la
solución sería algo así:
DIM A(5)
GENERADATOS A()
ORDENA A()
SUB GENERADATOS( A() )
FOR I= 1 TO 5
A(I)= INT(RND()*50)+1
NEXT
END SUB
SUB ORDENA (A() )
FOR I=1 TO 4
M=I
FOR J=I+1 TO 5
IF A(I)> A(M) THEN M=I
NEXT
SWAP A(I),A(M)
NEXT
END SUB
quedando de parte del usuario la colocación de la lista original en pantalla, y su actualización al
producirse el ordenamiento. Para resolver este problema en Visual Basic, comenzaremos, de
acuerdo al método de solución que proponemos, por realizar el diseño del interfaz. Allí debemos
colocar los cinco datos, ubicándolos de forma tal que permita comprender el carácter de lista de los
mismos, y que permita además, apreciar el ordenamiento de la lista cuando tenga lugar. Debemos
Introducción a la Programación Visual Página 52 de 168

colocar también botones que permitan impartir las órdenes para que el programa genere los
valores de la lista, para que los ordene y por supuesto, para que finalice la ejecución. También
debemos colocar un indicador para seleccionar el sentido del ordenamiento. El aspecto de nuestro
interfaz podría ser así:
Para los números de la lista proponemos emplear cinco controles Etiquetas, para la selección del
sentido de ordenamiento dos controles Botón de Opciones y para las tareas del programa tres
controles Botón de Órdenes. Las etiquetas las colocamos en columna y empleamos colores de
fondo en progresión de tonos azules, para apoyar la idea de lista, y de lista ordenada.
Nuestro arreglo de controles estará integrado por los cinco controles etiqueta, que inicialmente
tienen por nombre en sus propiedades Name los identificadores Label1, Label2, Label3, Label4 y
Label5. Para convertirlos en un arreglo de controles modificaremos esa propiedad. Para hacerlo
seleccionemos el primer control, identificado como Label1, pasemos a su ventana de Propiedades
y alteremos la propiedad Name escribiendo el identificador ‘Datos’. Ese será el nombre de nuestro
arreglo de controles. Una vez modificada esta etiqueta, seleccionamos la siguiente identificada
como Label2 y repetimos la operación. Al asignar a la propiedad Name el valor ‘Datos’ Visual
Basic mostrará una ventana de confirmación como la que se muestra en la figura 1. Al contestar
afirmativamente, la primera etiqueta pasa a identificarse como Datos(0) y la segunda como
Datos(1), quedando conformado el arreglo de controles. Luego se repite la operación para las
etiquetas Label3, Label4 y Label5 transformándolas en Datos(2), Datos(3) y Datos(4). Para que
los objetos del interfaz el interfaz adquieran la apariencia que se muestra en la figura 2, debemos
modificar los valores implícitos de sus propiedades, asignándoles los que se muestran en la tabla
1.
Objeto Propiedad
Valor asignado
Comentario
Form1 Caption “Ordenamient o de Datos”
Título de la aplicación.
Datos( 0 ) Caption “” No hay valores preestablecidos.
FontSize 12 Se agranda la letra para que el dato de la lista se aprecie mejor.
Alignment
2 (Centrado) Se colocan los números en el
centro de la etiqueta.
Figura 5-2. Interfaz para ordenar una lista.
60 Introducción a la Programación Visual
Introducción a la Programación Visual Página 53 de 168

ForeColo
r
&H00FF0000 Azul.
BackColo
r
&H00FFFFC0 Azul muy claro.
Datos( 1 ) Caption ““
FontSize 12 Lo mismo que para Datos(0).
Alignmen
t
2
ForeColo
r
&H00FF0000 Azul.
BackColo
r
&H00FFFF00 Azul claro.
Datos( 2 ) ForeColo
r
&H00FFFF00 Azul claro.
BackColo
r
&H00FF0000 Azul.
Datos( 3 ) ForeColo
r
&H00FF0000 Azul claro.
BackColo
r
&H00C00000 Azul oscuro
Datos( 4 ) ForeColo
r
&H00FF0000 Azul claro.
BackColo
r
Introducción a la Programación Visual Página 54 de 168

&H00800000 Azul muy oscuro


Las restantes propiedades de Datos(2), Datos(3) y Datos(4) son similares
a las de Datos( 0 ) y Datos ( 1 )
OptionButto
n1
Caption “Ascendente”
Value True Para que el sentido implícito
del ordenamiento sea
ascendente.
OptionButto
n2
Caption “Descendent
e”
Value False
Command1 Caption “Generar
Datos”
Command2 Caption “ Ordenar”
Command3 Caption “Terminar”
Tabla 1. Principales propiedades de los objetos en el interfaz para Problema
1
Introducción a la Programación Visual 61
A continuación corresponde determinar a que controles será necesario
asociar código. En este caso y a diferencia del primer problema que
resolvimos, si resulta necesario realizar acciones al iniciarse la ejecución del
programa, es necesario generar el primer juego de cinco datos para
colocar en el arreglo de controles. Esta tarea debe realizarse antes de que
el usuario pueda realizar ninguna acción, por tanto resulta conveniente
efectuarla en el momento en que el formulario es cargado en memoria.
Cuando un formulario es cargado en memoria por Windows, produce un
evento Load. Nosotros aprovecharemos precisamente ese evento para
realizar la inicialización de nuestros datos. Los otros controles que necesitan
código son los tres botones de ordenes, que realizarán las tareas de generar
un nuevo juego de datos (lo mismo que se realiza cuando se carga el
formulario al inicio del programa), ordenar los datos de la lista y terminar el
Introducción a la Programación Visual Página 55 de 168

programa, respectivamente. Los controles etiqueta del arreglo sólo se


emplean para exhibir los datos de la lista, y los dos botones de opción se
limitan a almacenar información en su propiedad Value, pero esa
información no debe ser empleada por ellos sino por el procedimiento de
ordenar, por lo que no necesitan código para atender eventos.
También a diferencia del primer problema que resolvimos, en esta problema
necesitaremos emplear una entidad de datos a nivel de formulario, en este
caso el arreglo que almacenará los valores de la lista. Para declarar datos a
nivel de formulario debemos abrir la ventana de código del formulario y
seleccionar dentro de la lista desplegable de los Objetos el campo
(general) y en la lista de procedimientos asociados, seleccionar el ítem
(declarations). En esa sección podemos escribir las declaraciones de todas
aquellas entidades de datos ( ya sean datos simples o estructurados) que
deban tener alcance a nivel de formulario.
En un segundo paso de
refinamiento debemos
determinar, si también resulta
necesario escribir
procedimientos generales, o
independientes de evento. En
esta caso podemos ver con
facilidad que la tarea de
generar los juegos de datos
aparece tanto en el evento
Load del formulario, como en el evento Click del primer botón de órdenes.
Podemos escribir entonces un procedimiento único que sea llamado por el
código asociado a cada uno de los eventos. Este subprograma sería así:
Figura 5-3. Declaración de un arreglo
con alcance a nivel de formulario.
62 Introducción a la Programación Visual
Sub Generar_Datos (a( ) As Integer)
For I = 0 To 4
A( I ) = Int(Rnd * 50) + 1
Datos( I ).Caption = Format$(A( I ))
Introducción a la Programación Visual Página 56 de 168

Next
End Sub
Los procedimientos generales se ubican dentro de la ventana de código de
un formulario en el mismo lugar que las declaraciones generales de datos,
es decir en el área identificada como (general) en la lista desplegable de
objetos. Para incorporar un nuevo subprograma tenemos dos caminos:
· Activar la ventana de código y escribir en cualquier lugar dentro de ella
el encabezamiento del subprograma (las palabras Sub o Function y el
nombre). Al pulsar Enter se creará un área de edición para el nuevo
subprograma general como se muestra en la figura 4.
· Seleccionar la opción Procedimiento dentro del menú Insertar e indicar
el nombre y tipo del procedimiento en la ventana que aparecerá a
continuación.
Como los subprogramas generales se encuentran en el área identificada
como (general) en la ventana de código, para acceder a alguno de ellos
basta con seleccionar esa área y desplegar la lista de procedimientos
(identificada como Proc :) en esa lista a continuación del ítem (declarations)
se encuentra el listado de los procedimientos generales del formulario.
Continuando con la solución de nuestro problema, habíamos dicho que
cuando el formulario se carga debe generarse un juego de datos para el
arreglo de controles, esto se consigue invocando al procedimiento general
Generar_Datos desde el procedimiento de atención al evento Load.
Sub Form_Load ( )
Figura 5-4 Escribiendo un subprograma
general en la ventana
Introducción a la Programación Visual 63
Generar_Datos A( )
End Sub
Realmente no es estrictamente necesario transferir al procedimiento el
arreglo A(), ya que el mismo tiene alcance dentro del formulario y por tanto
cualquier entidad de código del formulario puede utilizarlo. Preferimos sin
embargo colocarlo como parámetro para poder mostrar la declaración
de un subprograma en su forma completa:
SUB Nombre_del_Procedimiento (Parámetros).
Introducción a la Programación Visual Página 57 de 168

El procedimiento asociado con el primer botón de órdenes también tiene la


tarea de proveernos de un nuevo juego de datos por tanto su código será
muy similar.
Sub Command1_Click ()
Generar_Datos A()
End Sub
Para ordenar la lista escribiremos para el segundo botón de órdenes lo
siguiente:
Sub Command2_Click ()
Dim I As Integer, J As Integer, K As Integer
For I = 0 To 3
K=I
For J = I + 1 To 4
Prop1 = A(K) > A(J) And Option1.Value
Prop2 = A(K) < A(J) And Option2.Value
If Prop1 Or Prop2 Then K = J
Next
Temp = A(I)
A(I) = A(K)
A(K) = Temp
Datos(I).Caption = A(I)
Datos(K).Caption = A(K)
Next
End Sub
Los buenos programadores de Basic se sorprenderán seguramente de no ver
en este subprograma la emblemática instrucción SWAP. La razón es simple:
Visual Basic no incorpora esta instrucción, y no hemos encontrado ninguna
buena razón para justificar esta decisión. Por eso para realizar el
64 Introducción a la Programación Visual
intercambio debemos emplear una variable temporal en función de pivote.
Tal vez lo más interesante de esta solución sea el empleo de una condición
compuesta por dos proposiciones para analizar con una sola alternativa
tanto el ordenamiento ascendente como el descendente.
Noten como una vez realizado el intercambio basta con actualizar los
Introducción a la Programación Visual Página 58 de 168

valores de las propiedades Caption para que se actualice la lista en la


pantalla.
Una vez terminado el programa corresponde someterlo a pruebas. Al hacer
esto es fácil detectar un pequeño problema que nos obligará a realizar
retroalimentación hacia la fase de escritura del código. El problema es
simple: La serie de números aleatorios empleada para generar los juegos de
datos siempre comienza por el mismo número y en consecuencia la serie se
repite una corrida tras otra del programa. Para resolver este problema se
debe agregar una instrucción Randomize en el procedimiento de atención
al evento Load.
La segunda situación no es propiamente un problema. Varias de las
personas que participaron en la revisión y prueba de los programas de este
libro, opinaron que podría resultar cómodo que al cambiar el sentido del
ordenamiento en los botones de opción, entre ascendente y descendente,
la lista se reordenará automáticamente sin necesidad de volver a
solicitarlo oprimiendo el botón de órdenes correspondiente. El atender a
esta sugerencia nos obligará a retroalimentar hacia la etapa de determinar
a que controles se debe asociar código, ya que será necesario escribir
instrucciones para los eventos Click de los dos botones de opción, de forma
que al producirse estos eventos tenga lugar también el proceso de
ordenamiento.
No es difícil ver que el código necesario para ordenar la lista es el mismo
que ya hemos escrito para el evento Click del control Command2 por tanto
podemos intentar aprovechar ese código en vez de tener que reescribirlo
para cada uno de los botones de opción. Para aprovechar desde un nuevo
control las instrucciones escritas para otro control tenemos dos caminos:
· Trasladar el grupo de instrucciones que deben usar los dos controles
hacia un subprograma o procedimiento general, el cual será invocado
desde los procedimientos de atención a evento de los dos controles.
Esto fue lo que hicimos con el subprograma de generar datos, que debía
aparecer tanto en el evento load del formulario como en el evento
Click del primer botón de órdenes.
Introducción a la Programación Visual 65
· Dejar las instrucciones tal y como están, en el procedimiento de
Introducción a la Programación Visual Página 59 de 168

atención a evento del primer control, y cuando tenga lugar el evento


correspondiente en el segundo control, invocar la ejecución del
procedimiento de atención a evento del primero. Para utilizar este
camino se requiere que las rutinas de atención a evento de los dos
controles sean absolutamente idénticas.
Como ese es precisamente nuestro caso, y además, ya hemos empleado en
este problema el primero de los dos caminos, aprovecharemos la
oportunidad para ejemplificar el uso del segundo. Para ello basta con
escribir para el evento Click del primer botón de opciones lo siguiente:
Sub Option1_Click ( )
Command2_Click
End Sub
Noten que la única instrucción del procedimiento de atención al evento
Click del control Option1 es una llamada al procedimiento de atención al
evento Click del control Command2, donde previamente habíamos escrito
el código para ordenar la lista.
De forma similar, para el segundo botón de opciones quedaría:
Sub Option2_Click ( )
Command2_Click
End Sub
Estos procedimientos permiten que cada vez que se active uno de los
botones de opción, pulsando sobre él con el ratón, se actualice la
propiedad Value de ese control y se ejecute el procedimiento para ordenar
la lista. Recuerde que para que un botón de opciones se active, debe estar
desactivado, o sea, el botón activo no reconoce el evento Click aunque
pulsemos con el ratón sobre él.
Con estas enmiendas podemos considerar satisfactoriamente resuelto
nuestro primer problema con empleo de arreglos de controles, y podemos
pasar entonces a intentar la solución de un segundo problema ligeramente
más complejo.
66 Introducción a la Programación Visual
Nuestro segundo problema resulta un poco más complejo. Nos
propondremos elaborar un programa que permita jugar al Juego del
15.
Introducción a la Programación Visual Página 60 de 168

El Juego del 15 es bien conocido; data del siglo pasado, cuando fue tan
popular como el cubo de Rubik o los Tamagoshis. Se trata de un tablero de 4
filas y 4 columnas, que contiene 15 fichas numeradas consecutivamente y
un espacio vacío. Las únicas fichas que el jugador puede mover son las que
ocupan posiciones contiguas al espacio vacío, para que ocupen
precisamente ese espacio. Para comenzar a jugar, se mueven las fichas
hasta dejarlas en desorden y luego el jugador debe regresarlas a su posición
original. Para preparar una interfaz en Visual Basic para este juego, lo más
conveniente será contar con un formulario de forma lo más cuadrada
posible, que represente el tablero, y sobre él, colocar 15 controles que
representen las fichas. Estos controles deben mostrar los números del 1 al 15,
para realizar esta función podemos emplear etiquetas o botones de
órdenes. Nos decidimos por estos últimos.
Las tareas de los controles
resultan bastante claras: si el
jugador marca con el ratón
sobre una ficha, esa ficha debe
comprobar si el espacio vacío
colinda con ella, y de ser así,
moverse al espacio vacío. De lo
contrario la ficha permanece en
su lugar.
Es evidente que las fichas reúnen todas las condiciones para constituir un
arreglo de controles: son representadas por controles de la misma clase, en
nuestro caso botones de órdenes, todas reconocen el mismo evento y
realizan la misma acción. Agruparemos entonces, a los quince botones de
órdenes en un arreglo, al que llamaremos ‘Ficha‘. A continuación se
muestra la tabla de las propiedades de los objetos que intervienen en el
interfaz.
Objeto Propiedad Valor
asignado
Comentario
Form1 Caption “Juego
del 15”
Introducción a la Programación Visual Página 61 de 168

Título de la aplicación.
Height 3330 Se ajusta el tamaño del formulario
Figura 5-5. Juego del 15.
Fichas
Espacio
Vacío
Introducción a la Programación Visual 67
al
Width 2550 que tendrán las fichas. La diferencia
entre el alto y el ancho representa
el alto de la barra de títulos.
BorderStyl
e
1 (Borde
simple
Fijo)
Se coloca el borde fijo porque no es
conveniente que el jugador
modifique la forma cuadrada del
tablero
Ficha( 0 ) Caption “1” Número de la ficha.
FontSize 18 Se agranda la letra para que el
número de la ficha se aprecie
mejor.
Top 0 Primera fila
Left 0 Primera columna
Height 600
(pixels)
Se garantiza que la ficha sea un
Width 600 cuadrado
Ficha( 1 ) Caption “2” Número de la ficha.
Top 0 Primera fila
Left 600 Segunda columna
Ficha( 2 ) Caption “3”
Introducción a la Programación Visual Página 62 de 168

Top 0 Primera fila


Left 1200 Tercera columna
Ficha( 3 ) Caption “4”
Top 0 Primera fila
Left 1800 Cuarta columna
Ficha( 4 ) Caption “5”
Top 600 Segunda fila
Left 0 Primera columna
Ficha( 5 ) Caption “6”
Top 600 Segunda fila
Left 600 Segunda columna
Ficha( 6 ) Caption “7”
Top 600 Segunda fila
Left 1200 Tercera columna
Ficha( 7 ) Caption “8”
Top 600 Segunda fila
Left 1800 Cuarta columna
Ficha( 8 ) Caption “9”
Top 1200 Tercera fila
68 Introducción a la Programación Visual
Left 0 Primera columna
Ficha( 9 ) Caption “10”
Top 1200 Tercera fila
Left 600 Segunda columna
Ficha( 10
)
Caption “11”
Top 1200 Tercera fila
Left 1200 Cuarta columna
Ficha( 11
)
Caption “12”
Top 1200 Tercera fila
Left 1800 Cuarta columna
Introducción a la Programación Visual Página 63 de 168

Ficha( 12
)
Caption “13”
Top 1800 Cuarta fila
Left 0 Primera columna
Ficha( 13
)
Caption “14”
Top 1800 Cuarta fila
Left 600 Segunda columna
Ficha( 14
)
Caption “15”
Top 1800 Cuarta fila
Left 1200 Tercera columna
Las propiedades FontSize, Height y Width tienen el mismo valor para
todas las Fichas
Normalmente para resolver un problema como este se emplea un arreglo
bidimensional, de 4 por 4, con el que se representa la posición de las fichas
sobre el tablero. Nosotros trataremos de resolver el problema empleando
solamente recursos de carácter visual. En el tablero tenemos 15 elementos
bastante regulares: las fichas, y uno muy singular: el espacio vacío. No es
difícil comprender que es precisamente éste último el gran protagonista del
juego, y por tanto es imprescindible conocer dónde se encuentra en cada
momento. Mientras las fichas son objetos que poseen propiedades Top y
Left, que permiten conocer su posición, el espacio vacío no se representa
por ningún objeto. Por tanto nuestras entidades de datos fundamentales
serán dos variables enteras que representarán la fila y la columna del
tablero en que se encuentra ubicado el espacio vacío. La singularidad de
este ejemplo esta en la correspondencia que es necesario establecer entre
Introducción a la Programación Visual 69
la distribución bidimensional de las fichas el arreglo de controles que
necesariamente tiene que ser unidimensional.
Cuando una ficha recibe el evento Click debe comprobar si puede
Introducción a la Programación Visual Página 64 de 168

moverse, esto quiere decir: determinar si el espacio vacío es uno de sus


vecinos. Para poder comprobar esa situación es necesario conocer la
posición, dentro del tablero, tanto de la ficha como del espacio vacío.
Aunque no estemos empleando un arreglo bidimensional, las fichas sobre el
tablero se colocan en forma de tabla, diferenciándose con claridad cuatro
filas y cuatro columnas. Identificaremos Las filas con una numeración del 0 al
3 y lo mismo haremos con las columnas. Ahora debemos buscar una forma
de determinar en que fila y columna se encuentra una ficha a partir de los
valores de las propiedades Top y Left de las fichas.
Si analizamos en la tabla los valores de las propiedades Top y Left,
encontraremos fácilmente la siguiente regularidad: todas las fichas que
están en una misma fila tienen el mismo valor de Top, y todas las fichas que
se encuentran en una misma columna tienen el mismo valor de Left. Y
además esos valores progresan linealmente: para la primera fila Top=0, para
la segunda Top=600, para la tercera Top=1200 y para la cuarta Top=1800. El
incremento es precisamente de 600 twips, por que esa es la altura de una
ficha. Podemos establecer una relación que nos transforme los valores 0,
600, 1200 y 1800 de la propiedad Top en los números 0, 1, 2, 3 que hemos
asignado a las columnas de la tabla. Esta relación es:
Y = Ficha( I ).Top \ Ficha( I ).Height
La misma relación puede ser establecida para las columnas, resultando:
X = Ficha(Index).Left \ Ficha(Index).Width
Ya somos capaces de determinar la posición de una ficha cualquiera que el
jugador marque con el ratón. Ahora pensemos en cómo determinar lo
posición del espacio vacío. La ubicación inicial del espacio vacío es
conocida: ocupa la última posición del tablero, o sea fila 3, columna 3. Sin
embargo esa posición cambiará cada vez que se mueva una ficha. Para
conservar información sobre la posición actual del espacio vacío
necesitaremos definir dos variables enteras, en el área de declaraciones
(general) de la ventana de código.
Dim X_Vacio As Integer, Y_Vacio As Integer
70 Introducción a la Programación Visual
Ambas variables deben ser inicializadas con el valor 3. Para eso nos
valdremos del evento Load del formulario.
Introducción a la Programación Visual Página 65 de 168

Sub Form_Load ()
X_Vacio = 3 ‘ Columna que ocupa el espacio vacío
Y_Vacio = 3 ‘ Fila que ocupa el espacio vacío
End Sub
Los procedimientos que se ocupen de mover las fichas tendrán también la
responsabilidad de actualizar estas dos variables.
La tarea de determinar si la ficha tocada por el usuario puede ser movida se
puede descomponer en cuatro tareas secundarias: comprobar si la ficha
tiene el espacio vacío a su derecha, a su izquierda, arriba o abajo. De igual
forma, la tarea de mover una ficha desde su posición actual hasta el
espacio vacío se puede descomponer en cuatro tareas secundarias: mover
la ficha hacia la derecha, moverla hacia la izquierda, moverla hacia abajo y
moverla hacia arriba.
El procedimiento de atención al evento Click de un control Ficha quedaría
entonces así:
Sub Ficha_Click ( Index As Integer )
Dim X As Integer, Y As Integer
X = Ficha(Index).Left \ Ficha(Index).Width ‘ Columna que ocupa la
ficha
Y = Ficha(Index).Top \ Ficha(Index).Height ‘ Fila que ocupa la ficha
I f Vacio_Izquierda( X, Y ) Then
Mover_Izquierda Index
ElseIf Vacio_Derecha( X, Y ) Then
Mover_Derecha Index
ElseIf Vacio_Arriba( X, Y ) Then
Mover_Arriba Index
ElseIf Vacio_Abajo( X, Y ) Then
Mover_Abajo Index
End If
End Sub
Donde Vacio_Izquierda, Vacio_Derecha, Vacio_Arriba y Vacio_Abajo son
funciones generales que resuelven las cuatro subtereas en que
descompusimos la determinación de la vecindad con el espacio vacío.
Introducción a la Programación Visual 71
Introducción a la Programación Visual Página 66 de 168

Para determinar, por ejemplo, si el espacio vacío se encuentra a la derecha,


basta con comprobar que las coordenadas y de la ficha y del espacio vacío
coincidan y que la coordenada x del espacio vacío sea mayor que la de la
ficha en una unidad. La función quedaría así:
Function Vacio_Derecha (X As Integer, Y As Integer)
If (X + 1 = X_Vacio And Y = Y_Vacio) Then
Vacio_Derecha = True
Else
Vacio_Derecha = False
End If
End Function
Las restantes funciones serán:
Function Vacio_Izquierda (X As Integer, Y As Integer)
If (X - 1 = X_Vacio And Y = Y_Vacio) Then
Vacio_Izquierda = True
Else
Vacio_Izquierda = False
End If
End Function
Function Vacio_Arriba (X As Integer, Y As Integer)
If (X = X_Vacio And Y - 1 = Y_Vacio) Then
Vacio_Arriba = True
Else
Vacio_Arriba = False
End If
End Function
Function Vacio_Abajo (X As Integer, Y As Integer)
If (X = X_Vacio And Y + 1 = Y_Vacio) Then
Vacio_Abajo = True
Else
Vacio_Abajo = False
End If
End Function
Para mover, por ejemplo una ficha hacia abajo, basta con adicionar a la
Introducción a la Programación Visual Página 67 de 168

propiedad Top de la ficha, la altura de la propia ficha (almacenada en su


72 Introducción a la Programación Visual
propiedad Height) que representa, como ya habíamos señalado, el
separación entre dos filas consecutivas. También se debe actualizar la
variable que contiene la fila en que se encuentra el espacio vacío, el cual
se mueve en sentido contrario al de la ficha, y por tanto debe ser
decrementado en uno. El procedimiento quedaría así:
Sub Mover_Abajo ( Index as Integer )
Ficha(Index).Top = Ficha(Index).Top + Ficha(Index).Height
Y_Vacio = Y_Vacio - 1
End Sub
Los restantes procedimientos quedarán:
Sub Mover_Arriba (Index As Integer)
Ficha(Index).Top = Ficha(Index).Top - Ficha(Index).Height
Y_Vacio = Y_Vacio + 1
End Sub
Sub Mover_Derecha (Index As Integer)
Ficha(Index).Left = Ficha(Index).Left + Ficha(Index).Width
X_Vacio = X_Vacio - 1
End Sub
Sub Mover_Izquierda (Index As Integer)
Ficha(Index).Left = Ficha(Index).Left - Ficha(Index).Width
X_Vacio = X_Vacio + 1
End Sub
Con esto podemos considerar que nuestro programa esta terminado. El
jugador lo puede emplear con las mismas posibilidades y limitaciones con
que jugaron los primeros aficionados hace más de un siglo. Sin embargo una
primera revisión del programa nos señala que una implementación para
computadoras del ‘Juego del 15’ debe ofrecer a sus jugadores algunos
servicios adicionales.
Primera sugerencia: El programa debe ser capaz de informar al jugador que
ha logrado colocar las fichas en la posición correcta. ¡Es lo menos que se
puede hacer por el jugador!
Segunda sugerencia : El programa debe ofrecer al usuario el servicio de
Introducción a la Programación Visual Página 68 de 168

preparar el tablero para comenzar el juego. En efecto desordenar las fichas


es demorado y tedioso, el programa debe asumir esa tarea.
Introducción a la Programación Visual 73
Tercera sugerencia: Las fichas saltan de una posición a otra. El programa
podría incorporar algún efecto de animación a ese movimiento.
Atención a las sugerencias.
La primera sugerencia es absolutamente oportuna, es lo menos que un
juego para computadoras puede hacer por sus jugadores. Para lograr esto
lo más práctico es escribir una función que devuelva un resultado
booleano, indicando si las fichas están o no correctamente colocadas.
Para atender esta sugerencia debemos escribir un procedimiento que
detecte si las fichas ocupan su posición inicial.
Necesitamos una relación que permita obtener, a partir de la numeración
consecutiva desde el 0 al 14 de las fichas en el arreglo de controles, los
pares ordenados (x,y) (0,0) (1,0) (2,0) (3,0) (0,1) (1,1) (2,1) (3,1) hasta el (3,2).
Para eso no hay mas que recurrir a las propiedades de la división entera y el
resto entero de la división:
Y = I \ 4 y X = I Mod 4
Convierten los valores del 0 al 14 el los pares ordenados que necesitamos.
Estos pares representan la posición correcta de las fichas, sólo queda
comparar esos números con los que corresponden a las posiciones reales de
las fichas. esas posiciones las obtuvimos en el procedimiento Ficha_Click
dividiendo los valores de las propiedades Top y Left de las fichas entre los
valores de sus propiedades Height y Width, respectivamente. Luego
comparamos para cada ficha las coordenadas de la posición correcta con
las coordenadas reales, y si coinciden para las 15 fichas podemos decir que
hemos terminado el juego con éxito.
Esta función debe ser chequeada cada vez que se realiza el movimiento de
una ficha, de modo que el chequeo se realizará infructuosamente muchas
veces. Para evitarle al programa el trabajo inútil, emplearemos algunos
ardides.
En primer lugar controlaremos una condición necesaria muy fuerte: si las
fichas están ordenadas el espacio vacío tiene que estar de nuevo en su
posición original (fila 3 columna 3). Por tanto si no esta allí, la función
Introducción a la Programación Visual Página 69 de 168

devolverá False sin realizar ningún otro chequeo. En segundo lugar


74 Introducción a la Programación Visual
compararemos los quince juegos de datos dentro de un ciclo y en cuanto se
detecte una desigualdad la función también terminará devolviendo False.
El código de la función será:
Function En_Orden ( )
Dim C as Integer
C=0
If X_Vacio <> 3 Or Y_Vacio <> 3 Then Exit Function
For I = 0 To 14
Y=I\4
X = I Mod 4
If Ficha(I).Left \ Ficha(I).Width = X And Ficha(I).Top \ Ficha(I).Height = Y
Then
C=C+1
Else
Exit For
End If
Next
If C = 15 Then En_Orden = True Else En_Orden = False
End Function
Ya somos capaces de reconocer si el jugador ha logrado colocar las fichas
en las posiciones adecuadas. Ahora debemos pensar en cómo emitir el
mensaje correspondiente. Con los elementos que manejamos del interfaz de
Windows podríamos pensar en colocar sobre nuestro formulario una
etiqueta oculta con el mensaje y mostrarla en el momento oportuno,
manipulando para ello su propiedad Visible. Otra variante podría ser
preparar un segundo formulario colocando en el la etiqueta del mensaje y
mostrarlo en pantalla en el momento preciso por medio de su método Show.
Sería un buen ejercicio el programar estas dos variantes.
Nosotros en cambio vamos a aprovechar la oportunidad para introducir
otro recurso del interfaz de Windows, la caja de diálogos (o de mensajes)
que sin dudas Si en este momento intentara terminar la sesión de trabajo
con mi procesador de textos sin salvar estos últimos párrafos, en la pantalla
Introducción a la Programación Visual Página 70 de 168

aparecería lo siguiente:
Introducción a la Programación Visual 75
Precisamente esto es una caja
de diálogos, o de mensajes: un
formulario con un mensaje
adecuado, un elemento
gráfico que sirve para resaltar
el contenido del mensaje y un
conjunto de botones que
permitan al usuario expresar su conformidad con el mensaje o seleccionar
alguna de las opciones que se le ofrecen.
Visual Basic nos permite emplear con gran facilidad cajas de mensajes en
nuestros programas. Por ejemplo, para mostrar una caja de mensajes
idéntica a la que aparece en la figura 5-6 tan solo es necesario escribir la
siguiente línea de programa:
A = MsgBox ("¿Desea guardar los cambios he chos a LIBROVB.DOC? ", 35,
"Microsoft Word")
La función MsgBox es en efecto la encargada de exhibir en pantalla la caja
de mensajes. El primer parámetro de la función MsgBox es una cadena de
caracteres que contiene el mensaje que será exhibido dentro de la caja de
diálogos. El tercer parámetro también es una cadena de caracteres, y su
contenido se colocará en la barra de título del formulario que contiene la
caja de diálogos. El segundo parámetro es el más complejo de todos: es un
número que se forma sumando varios componentes.
El primer sumando es un número del 0 al 5 que representa las seis
combinaciones de botones que se pueden colocar en la caja de diálogos.
El valor 0 indica que en la caja de mensajes aparecerá el botón “Aceptar”
(“OK” en la versión inglesa de Visual Basic). El valor 1 indica que aparecerán
los botones “Aceptar” y “Cancelar” (“OK” y “Cancel”). El 2, los botones
“Anular”, “Reintentar” e “Ignorar” (“Abort”, “Retry” “Ignore”). El 3, los botones
“Si”, “No” y “Cancelar”. El 4, los botones “Si” y “No”, y el valor 5, los botones
“Reintentar” y “Cancelar”.
El segundo sumando es un número del conjunto 16, 32, 48, 64, y sirve para
indicar el icono que se colocará para reforzar el mensaje. El 16 representa el
Introducción a la Programación Visual Página 71 de 168

icono con el símbolo de Problemas; el 32 coloca un signo de interrogación,


el 48 coloca un signo de exclamación, y el 64 el símbolo de Información.
Figura 5-6. Caja de mensajes estándar de
Windows.
76 Introducción a la Programación Visual
El tercer sumando es un número del conjunto 128, 256, 512 y sirve para
indicar cual de los botones colocados en la caja de diálogos recibirá el
foco. Puede haber como máximo tres botones en una caja de diálogos.
Las cajas de diálogos requieren de la atención inmediata del usuario. Por tal
motivo bloquean el trabajo con la aplicación, hasta que no se oprima
alguno de sus botones. El cuarto sumando indica cual es el alcance de este
bloqueo. Si vale 0 sólo se bloquea el trabajo con la aplicación que exhibe la
caja de diálogos. Pero si vale 4096 se bloquea todo el sistema.
En nuestro ejemplo, como segundo parámetro aparece escrito el número
35. Ese valor 35 es el resultado de la suma de 3 + 32, donde el 3 indica que
en la caja de mensajes aparecerá la combinación de botones “Si”, “No” y
”Cancelar” y el 32 indica que en la caja de mensajes aparecerá el icono
con el signo de interrogación.
El valor que devuelva la función MsgBox estará en dependencia del botón
que seleccione el usuario. Los valores de retorno de la función serán:
Botón seleccionado por el
usuario
Valor que retorna la función
MsgBox
“Aceptar” (“OK”) 1
“Cancelar”
(“Cancel”)
2
“Abortar” (“Abort”) 3
“Reintentar” (“Retry”) 4
“Ignorar” (“Ignore”) 5
“Si” (“Yes”) 6
“No” (“No”) 7
Cuando no es necesario que el usuario responda al mensaje realizando una
Introducción a la Programación Visual Página 72 de 168

selección, y sólo interesa proporcionarle


determinada información, se coloca en la
caja de mensajes tan solo el botón
“Aceptar”. En esos casos MsgBox puede
emplearse como procedimiento, en lugar
de como función. En nuestro programa del
Juego del 15 nos encontramos en esa
situación. Simplemente nos interesa
Figura 5-7.
Introducción a la Programación Visual 77
informar al usuario que ha logrado colocar todas las fichas en su lugar. La
caja de diálogos que necesitaremos mostrar al jugador puede ser como la
siguiente.
Para mostrar esta caja de diálogos basta con añadir en nuestro programa la
siguiente línea:
MsgBox "¡ Las fichas están en orden !", 48, "Juego del 15"
Veamos dónde, dentro de nuestro programa, debe estar colocada esta
instrucción. Como ya se dijo, la función En_Orden debe ser chequeada cada
vez que se realiza el movimiento de una ficha, por tanto debemos
colocarla a continuación de cada una de las cuatro llamadas a los
subprogramas Mover... que aparecen en el procedimiento de atención a
eventos Ficha_Click. La instrucción completa quedaría así:
If En_Orden( ) Then MsgBox "¡Las fichas están en orden!", 48, "Juego del 15"
De esta forma si la función En_Orden devuelve un valor de verdad True , se
exhibirá la caja de diálogos que hemos preparado.
De esta manera podemos considerar satisfactoriamente atendida la
primera observación sobre nuestro programa.
La segunda sugerencia también resulta justa y oportuna. En el tablero de
madera con que se jugaba durante el siglo pasado, el jugador debía
desordenar las fichas por si mismo, lo que resulta como ya dijimos, tardo y
tedioso. Nuestro tablero informático puede perfectamente asumir esa
tarea, y así el programa resultará más atractivo para el jugador.
La primera idea que se nos ocurre para resolver esta situación es clara e
inmediata: generemos aleatoriamente las posiciones de las 15 fichas y listo!
Introducción a la Programación Visual Página 73 de 168

Cuidado, el Juego del 15 no es tan simple, y en su tiempo los matemáticos


se ocuparon de revelar sus secretos. Sólo la mitad de las posibles
distribuciones de las fichas sobre el tablero permite regresar las fichas a su
formación original. La otra mitad de las distribuciones no lo permite (se llega
a una formación casi igual, pero con las fichas 14 y 15 permutadas). Y lo
peor: no es posible saber de antemano a cual de las dos mitades pertenece
una distribución aleatoria determinada. Por esta causa, la forma segura de
desordenar las fichas es realizando un determinado número de
movimientos, seleccionando de manera aleatoria las direcciones de los
mismos.
78 Introducción a la Programación Visual
Para realizar estos movimientos arbitrarios, debemos escoger cual de las
fichas colindantes con el espacio vacío va a ser movida. Claro, la cantidad
de fichas que pueden ocupar el espacio vacío también es variable. Si este
se encuentra en el centro del tablero, podrán ser cuatro fichas, pero si
ocupa una de las esquinas sólo podrán ser dos. Para evitarnos el tener que
controlar tantas condiciones, buscaremos una vía mas sencilla.
Generaremos al azar un número entre 0 y 3 que represente las cuatro
posibles fichas vecinas del espacio vacío, a partir de ese número
ubicaremos las coordenadas de la ficha y probaremos si esas coordenadas
pertenecen al rango del tablero (0...3, 0...3) de ser así intercambiaremos esa
ficha con el espacio vacío. Repetiremos este procedimiento hasta efectuar
una determinada cantidad de movimientos. Vean que esta operación
podría haberse enfocado al revés, como si el espacio vacío fuera una ficha
que se moviera por el tablero vacío ¿o no?
El subprograma que desordena nuestro tablero quedará así:
Sub Desordenar ( )
Dim C As Integer, X As Integer, Y As Integer
C=0
Do Until C = 200 ‘ Repetiremos hasta efectuar 200 movimientos
X = X_Vacio ‘ La posición de la ficha que será movida se
Y = Y_Vacio ‘ genera a partir de la posición del espacio vacío
Direccion = Int(Rnd * 4)
Select Case Direccion
Introducción a la Programación Visual Página 74 de 168

Case 0 ‘ Trataremos de mover la ficha que esta a la derecha del


espacio vacío
X=X+1
Case 1 ‘ Trataremos de mover la ficha que esta a la izquierda
X=X-1
Case 2 ‘ Trataremos de mover la ficha que esta debajo
Y=Y+1
Case 3 ‘ Trataremos de mover la ficha que esta arriba
Y=Y-1
End Select
If X >= 0 And X <= 3 And Y >= 0 And Y <= 3 Then ‘ Si la
‘ posición calculada
Indice = Ficha_a_Mover(X, Y) ‘ pertenece al tablero
Introducción a la Programación Visual 79
Mover_a_Vacio Indice, X_Vacio, Y_Vacio ‘ se mueve la ficha
X_Vacio = X ‘ El espacio vacío pasa a ocupar la
posición
Y_Vacio = Y ‘ donde estaba la ficha que movimos
C = C + 1 ‘ Se cuenta el movimiento efectuado
End If
Loop
End Sub
La función Ficha_a_Mover se ocupa de determinar el índice, dentro del
arreglo de controles de la ficha que ocupa la posición (X,Y) sobre el tablero.
Su código es:
Function Ficha_a_Mover (X, Y) ‘ X y Y contienen la posición
‘ que ocupa en el tablero
Dim Xt As Integer, Yt As Integer ‘ la ficha que se desea mover
For I = 0 To 14 ‘ Se analiza para las 15 fichas
Xt = Ficha( I ).Left \ Ficha( I ).Width ‘ Se calcula la posición en
Yt = Ficha( I ).Top \ Ficha( I ).Height ‘ el tablero de la ficha de índice I
If Xt = X And Yt = Y Then Exit For ‘ Si las posiciones
Next ‘ coinciden se abandona el ciclo
Ficha_a_Mover = I ‘La ficha que se desea mover ocupa la
Introducción a la Programación Visual Página 75 de 168

End Function ‘posición I dentro del arreglo de controles


El procedimiento Mover_a_Vacio se encarga de mover la ficha
seleccionada a la posición del espacio vacío. Su código es muy corto.
Sub Mover_a_Vacio (F, X, Y)
Ficha(F).Top = Y * Ficha(F).Height
Ficha(F).Left = X * Ficha(F).Width
End Sub
Como empleamos la función generadora de números aleatorios resultará
conveniente, al igual que en el problema del ordenamiento de la lista,
emplear la instrucción Randomize en el procedimiento Form_Load.
La tercera sugerencia parece abandonar el plano práctico, para dirigirse al
estético. Pero en los ambientes gráficos los elementos estéticos son de vital
importancia para la aceptación de un producto. Pero, cómo animar el
movimiento de las fichas? Pues muy sencillo. Para mover una ficha de una
80 Introducción a la Programación Visual
posición a otra modificamos el valor de sus propiedades Left (para los
movimientos horizontales) o Top (para los verticales) adicionándole o
decrementándole de un golpe una cantidad que representa el ancho de
una columna o la altura de una fila, respectivamente. De esta forma la ficha
pasa con una sola operación de una posición a otra. Para animar ese
movimiento debemos incrementar paulatinamente los valores de las
propiedades Left o Top, desde el valor inicial, que corresponde a las
coordenadas de la posición que ocupa la ficha en el tablero, hasta el valor
que corresponde a la coordenada de la posición a donde debe ser movida
la ficha.
Con esta idea podemos incorporar animación por ejemplo al
procedimiento Mover_Derecha sustituyendo la línea:
Ficha(Index).Left = Ficha(Index).Left + Ficha(Index).Width
por la estructura:
For I = 1 To 10
Ficha(Index).Left = Ficha(Index).Left + Ficha(Index).Width / 10
Next
De esta forma, la ficha a mover realizará diez desplazamientos de un
décimo del ancho de la columna cada uno, en lugar de un único
Introducción a la Programación Visual Página 76 de 168

desplazamiento. Visualmente el jugador podrá apreciar como la ficha se


‘mueve a lo largo de la fila, hasta ocupar totalmente la posición que estaba
vacía. Para evitar complicaciones resulta conveniente que el numero de
divisiones del intervalo sea divisor de la distancia a recorrer. En nuestro
caso el ancho de la ficha es de 600 twips, por tanto 10 resulta un número
apropiado.
Mientras mayor sea la cantidad de divisiones que realicemos al intervalo,
mayor será el número de movimientos que deberá realizar la ficha y por
tanto más lento será su movimiento. En sentido contrario mientras menor
sea el número de divisiones del intervalo, menor será la cantidad de
movimientos a realizar por la ficha y por tanto más rápido será su
movimiento. En el caso límite, si el número de divisiones es 1, nos
encontraremos de regreso en la situación original, con la ficha saltando de
una posición a otra sobre el tablero.
Introducción a la Programación Visual 81
Este análisis nos sugiere la idea de establecer diferentes niveles de
animación. Para ello debemos emplear una variable para representar la
cantidad de divisiones del intervalo a recorrer por la ficha. El procedimiento
Mover_Derecha quedaría definitivamente así:
Sub Mover_Derecha (Index As Integer)
For I = 1 To Delta
Ficha(Index).Left = Ficha(Index).Left + Ficha(Index).Width / Delta
Next
X_Vacio = X_Vacio - 1
End Sub
Los restantes procedimientos Mover_Izquierda, Mover_Arriba, Mover_Abajo
reciben la misma modificación que Mover_Derecha .
En la variable Delta colocaremos los valores 1 (movimiento a saltos, sin
animación), 10 (movimiento animado rápido) y 100 (movimiento animado
lento). Esta variable debe recibir sus valores fuera de los procedimientos
Mover... por tanto debe tener alcance a nivel de todo el formulario y para
ello debe aparecer declarada en el área (general) de la ventana de
código.
El valor inicial de la variable Delta podría ser 1. Esa asignación inicial
Introducción a la Programación Visual Página 77 de 168

debemos realizarla junto a las de las variables X_Vacio y Y_Vacio, en el


procedimiento de atención a evento Form_Load. Ahora debemos meditar
en como modificar convenientemente los valores de Delta. De los recursos
con que hemos trabajado el que parece más apropiado es el de emplear un
grupo de botones de opción. Pero trabajar con ellos tendría el
inconveniente de añadir elementos al formulario, haciendo que pierda la
forma cuadrada que debe tener un tablero del Juego del 15. Una posible
interfaz con esas características se muestra en la figura 5-8
En efecto este interfaz no resulta a
nuestro juicio el más adecuado, ya que
en él se pierde la asociación visual con
el tablero cuadrado del juego, y para
recuperarla en forma aceptable, nos
veremos precisados a no colocar las
fichas directamente sobre el
formulario, sino sobre algún objeto de
forma cuadrada que si esté colocado
directamente sobre el formulario, pero
Figura 5-8
82 Introducción a la Programación Visual
que se distinga del mismo, ya sea por un borde o por su color de fondo.
Podría emplearse con ese fin una caja de imágenes.
Muy distinto sería si pudiésemos incorporar un menú a nuestra aplicación, tal
y como lo tienen casi todos los programas diseñados para Windows. En este
menú podríamos colocar como opciones principales ‘Desordenar fichas’,
‘Animación’ y ‘Terminar’ y en un submenú dentro del acápite ‘Animación’,
las opciones ‘Sin Animación’, ‘Animación Rápida’ y ‘Animación Lenta’, que
servirían para asignar los valores 1, 10 o 100 a la variable Delta. Operando
con este menú el jugador podría realizar con facilidad sus selecciones, y no
nos veríamos obligados a modificar el diseño del tablero.
Por supuesto, Visual Basic dispone de recursos que nos permitirán incorporar
menús a nuestras aplicaciones de una forma muy cómoda y sencilla. En el
próximo capítulo nos ocuparemos de estudiar cómo Visual Basic nos
permite desarrollar ese trabajo.
Introducción a la Programación Visual Página 78 de 168

Introducción a la Programación Visual 83


Capítulo 6. INCORPORANDO MENÚS A NUESTRAS
APLICACIONES.
Características de los menús en Windows.
El trabajo con Windows nos ha permitido familiarizarnos con las
características de los menús que aparecen formando parte de las
aplicaciones del sistema operativo. El modelo de menú de Windows
también se ha convertido en un estándar que es respetado por casi todas
las aplicaciones escritas para ejecutar sobre Windows. Los menús que Visual
Basic nos suministra para incorporar a nuestras aplicaciones, se ajustan, por
supuesto, a este estándar.
Cada uno de los formularios que formen parte de un programa pueden tener
definido su propio menú. La barra del menú (menú horizontal) aparece en los
formularios exactamente debajo de la barra de título. En esa barra se
encuentran los elementos del menú principal. Cuando estos elementos son
seleccionados por el usuario, pueden ocurrir dos situaciones: o se ejecuta
directamente alguna acción, o se produce el despliegue de un menú
vertical primario (menú desplegable). Los elementos que aparecen en un
menú vertical se pueden agrupar en cuatro grandes grupos:
· Los elemento del menú que a continuación de su nombre presentan el
símbolo “4“ tienen asociado el despliegue de un submenú. El submenú
también es un menú vertical, pero se despliega a partir de un elemento
de otro menú vertical, a diferencia del menú vertical primario que se
despliega a partir de un elemento del menú horizontal.
· Los elemento del menú que a continuación de su nombre presentan tres
puntos suspensivos “...” tienen asociado la realización de una
determinada acción; pero, para la realización de esa acción es preciso
que el usuario suministre información adicional y por tanto, al seleccionar
esos elementos se muestra una caja de diálogos o un nuevo formulario,
para que el usuario suministre la información necesaria.
· Los restantes elementos tienen asociado la realización directa de una
acción.
· Los separadores. No pueden ser seleccionados por el usuario, sólo sirven
para agrupar visualmente los elementos de un menú vertical.
Introducción a la Programación Visual Página 79 de 168

84 Introducción a la Programación Visual


Otra característica de los elementos de menú es la posibilidad de acceder
a ellos oprimiendo una tecla una vez que el menú esta desplegado (en
lugar de pincharlos con el ratón). Esta tecla ‘caliente’ aparece subrayada
dentro del nombre del elemento de menú.
También es posible ejecutar la acción asociada con un elemento de menú
sin necesidad de desplegar el menú. Para esto se utilizan las ‘teclas de
método abreviado’ (Shortcut) , que son combinaciones de teclas, que
incluyen por lo general a ‘Control’ o ‘Alt’ y alguna otra tecla, casi siempre
letras o números.
En determinados momentos uno o mas elementos de menú pueden no estar
accesibles para el usuario. En esos momento sus nombres aparecen escritos
en un color gris pálido, a diferencia del negro con que están escritos los
elementos de menú que resultan accesibles.
El menú como un control en Visual Basic.
El menú de una aplicación también debe verse como un objeto (de la clase
de los controles) del interfaz gráfico de Windows, que Visual Basic pone a
nuestra disposición. Todo menú esta conformado por un conjunto de
elementos, que representan las opciones entre las que el usuario puede
realizar su selección. Cada uno de estos elementos que integran el menú
puede, a su vez, ser visto como un objeto (también de la clase de los
controles). Esa condición de ser objetos implica que cada elementos de
menú posea determinadas propiedades y reaccione ante determinados
eventos.
Las principales propiedades de un control Elemento de Menú son:
NAME. Contiene el identificador del control Elemento de Menú.
CAPTION.. Contiene el título (texto) que muestra el elemento
dentro del menú
VISIBLE Indica si el elemento de menú se mostrará o no dentro
del menú. Contiene un valor booleano (True o False)
CHECKED Indica si delante del nombre del elemento aparecerá un
marca. Contiene un valor booleano.
ENABLED Indica si el elemento puede ser accedido o no. Contiene
un valor booleano.
Introducción a la Programación Visual Página 80 de 168

SHORTCUT Indica las teclas de método abreviado asociadas con el


elemento de menú.
Introducción a la Programación Visual 85
INDEX Los elementos de un menú o de un submenú pueden
manejarse como un arreglo de controles. En tal caso
poseerán la propiedad INDEX, como cualquier otro
arreglo de controles.
El único evento que es reconocido por los controles Elemento de Menú, es
el evento CLICK, que tiene lugar cuando el usuario pincha con el ratón
sobre el elemento de menú, o cuando accede al mismo por las restantes
vías de acceso (teclas calientes y teclas de método abreviado). En el
procedimiento de atención a esos eventos debemos escribir las
instrucciones que deseamos ejecutar cuando el usuario seleccione cada
una de las opciones del menú.
En los últimos párrafos del capítulo anterior describimos los elementos que
podrían aparecer en el menú del juego del 15. La figura 6-1 muestra la
apariencia visual de ese menú.
En la figura se aprecia el menú horizontal que contiene un sólo elemento
(‘Opciones’) el menú vertical primario y el submenú asociado al elemento
‘Animación’. En el menú vertical primario hemos agrupado los elementos en
dos bloques delimitados por un separador. En el submenú se emplea una
marca de chequeo para indicar cuál de los posibles efectos de animación
ha sido seleccionado por el jugador.
Para diseñar el menú que incorporaremos a un formulario debemos acceder
a la Ventana de Diseño de Menú. Para hacerlo debemos, en primer lugar,
enfocar el formulario. Entonces podemos pinchar el botón Diseño de Menú
en la barra de herramientas de la ventana principal de Visual Basic, o
seleccionar la opción Editor de Menús del menú Herramientas en esa propia
ventana, o simplemente oprimir la combinación de teclas Ctrl E en la versión
86 Introducción a la Programación Visual
4.0 (Menu Design del menú Window o la combinación Ctrl M, en la versión
3.0).
La mitad superior de la Ventana de Diseño de Menú, tal como se muestra en
la figura 6-2, nos permite establecer las distintas propiedades de los
Introducción a la Programación Visual Página 81 de 168

elementos de menú. La propiedad Caption, al igual que en otros objetos,


contiene el texto que se muestra, en este caso dentro del menú. La
propiedad Name, por su parte, contiene el identificador del control
elemento de menú, y con ese identificador se formará el nombre del
procedimiento de atención a evento que se ejecutará cuando el jugador
realice se selección en el menú.
La mitad inferior de la ventana muestra una lista con todos los elementos de
menú. Estos elementos aparecen alineados en profundidad de forma tal que
aquellos que se encuentran junto al borde izquierdo de la ventana (en este
caso el elemento ‘Opciones’) serán los elementos del menú horizontal y los
que se encuentren alineados en los diferentes niveles de profundidad serán
submenús. En este caso ‘Desordenar’, ‘Animación’, ‘-’ y ‘Terminar’ son
elementos del menú vertical asociado al elemento ‘Opciones’ del menú
horizontal, y ‘Sin Animación’ ‘Animación Rápida’ y ‘Animación Lenta’
pertenecen al submenú asociado al elemento ‘Animación’. Los botones con
las flechas sirven para desplazar
los elementos de menú. Bien sea
cambiando su posición dentro de
la lista (Flecha Arriba y Flecha
Abajo), bien sea modificando su
profundidad (Flecha Izquierda y
Flecha Derecha). El botón Insert
sirve para insertar un nuevo
elemento de menú en cualquier
posición dentro de la lista,
mientras el botón Delete elimina
el elemento de menú que este
seleccionado. El botón Next desplaza la selección por todos la lista de
elementos de menú. El símbolo ‘&’ que aparece en las propiedades Caption
sirve para indicar la letra que permitirá realizar el acceso directo al
elemento de menú. Esta letra aparecerá subrayada dentro del texto.
Figura 6-3. Elementos de menú
ordenados en profundidad.
Introducción a la Programación Visual 87
Introducción a la Programación Visual Página 82 de 168

Cuando escribimos los distintos


elementos de menú, podemos
hacerlo de forma consecutiva,
sin ubicarlos en profundidad. De
esta forma aparecen escritos en
la figura 6-2. Una vez terminada
la escri-tura de los mismos
procedemos a aco-modarlos en
pro-fundidad empleando el
botón flecha izquierda. La figura
6-3. nos muestra un fragmento
de la ventana de diseño de
menú con la lista de elementos
de menú ordenada en
profundidad.
Se aprecia con facilidad como los el elemento “Opciones” que pertenece
al menú horizontal, permanece alineado junto al borde izquierdo de la
ventana. Por su parte los cuatro elementos del menú vertical primario
“Desordenar Fichas”, Animación” “-” y “Terminar” aparecen alineados en un
primer nivel de profundidad y por último, los tres elementos del submenú
“Sin Animación” “Animación Rápida” y “Animación Lenta” se encuentran
alineados en un segundo nivel de profundidad.
Las propiedades más significativas de los elementos del menú del ‘Juego
del 15’ aparecen listadas en la siguiente tabla:
Caption Name Index Checked
“Opciones” Opciones
“Desordenar
Fichas”
Desorden
“Animación” Animacion
“Sin Animación” Anima 0 True
“Animación
Rápida”
Anima 1 False
Introducción a la Programación Visual Página 83 de 168

“Animación Lenta” Anima 2 False


“-” Separador
“Terminar” Fin
Figura 6-2. Ventana de diseño de menú
88 Introducción a la Programación Visual
Las opciones de animación las hemos agrupado en un submenú. Es evidente
que sólo una de las tres puede estar activa en un instante dado. Si el
jugador seleccionara otra, ello implicaría desactivar la que antes estuviese
seleccionada. Para que el jugador pueda saber cuál es la opción de
animación activa, nos valdremos de la marca de chequeo asociada a la
propiedad Checked. Hemos decidido que la opción ‘Sin Animación’ sea la
que se encuentre seleccionada al inicio del programa. A tal efecto su
propiedad Checked recibe el valor True , mientras las demás reciben False.
Para hacer más cómoda la actualización de la marca de chequeo hemos
formado un arreglo de controles con los elementos del submenú Animación.
El signo ‘-’ en la propiedad Caption de un elemento de menú, sirve para
colocar una línea de separación dentro del menú. Aún cuando se emplee
como separador y el usuario no puede seleccionarlo, se trata de un
elemento de menú, y por tanto es necesario suministrarle un identificador
mediante su propiedad Name.
Veamos a continuación los procedimientos de atención a los eventos
generados por el menú:
Cuando el jugador seleccione la opción ‘Desordenar Fichas’ se ejecutará el
procedimiento Desorden_Click, (según la tabla, el identificador de este
control Elemento de Menú es ‘Desorden’) este procedimiento debe invocar
la ejecución del procedimiento Desordenar que ya habíamos elaborado.
Sub Desorden_Click ()
Desordenar
End Sub
El procedimiento que atiende la opción ‘Terminar’ es muy sencillo:
Sub Fin_Click ()
End
End Sub
El más complejo es el procedimiento que atiende a los eventos Click
Introducción a la Programación Visual Página 84 de 168

detectados por los controles del arreglo Anima. Se aprovecha el arreglo de


controles para facilitar la búsqueda de la marca con el empleo de un ciclo.
Sub Anima_Click (Index As Integer)
If Anima(Index).Checked=True then Exit Sub ‘ Si se selecciona
Introducción a la Programación Visual 89
‘ el elemento que está marcado
For I = 0 To 2 ‘ se abandona el procedimiento.
If Anima(I).Checked = True Then Anima(I).Checked = False
‘ Se elimina la marca del elemento que la tenía
Next
Anima(Index).Checked = True ‘ Se coloca la marca en el
‘ elemento de menú que seleccionó el jugador.
Select Case Index
Case 0
Delta = 1 ‘ Sin animación
Case 1
Delta = 10 ‘ Animación rápida
Case 2
Delta = 100 ‘ Animación lenta
End Select
End Sub
De esta forma queda incorporado el menú a nuestro ‘Juego del 15’. Sin
embargo podríamos pensar en incorporar nuevos elementos a ese menú. En
efecto, se ha convertido en norma (y es una buena norma), que los
programas proporcionen una Ayuda a sus usuarios donde se les explique el
funcionamiento del programa y se les proporcione toda la información que
pueda resultar útil para el usuario. También se acostumbra colocar los
créditos acerca de los autores del programa. Para proporcionar estas dos
informaciones proponemos incorporar un nuevo elemento en el menú
horizontal con el título ‘Ayuda’, que despliegue un menú vertical compuesto
por dos elementos con los títulos ‘Cómo Jugar’ y ‘Créditos’
Para incorporar estos elementos es preciso enfocar el formulario del ‘Juego
del 15’ y abrir nuevamente la Ventana de diseño de Menú, y colocándose
después del último elemento de la lista incorporar los tres siguientes
Introducción a la Programación Visual Página 85 de 168

elementos cuyas principales propiedades detallamos en la tabla:


Caption Name Index Checked
“Ayuda” Ayuda
“Cómo Jugar” Como_Jugar
“Créditos” Creditos
Luego de escribirlos en la ventana de diseño, con el botón Flecha Derecha
se desplazan los elementos “Cómo Jugar” y “Créditos” para que ocupen su
posición como submenú del elemento “Ayuda”. La lista de la Ventana de
Diseño de Menú tendrá ahora la siguiente estructura:
90 Introducción a la Programación Visual
Noten como los elementos
“Opciones” y “Ayuda” que
pertenecen al menú principal se
encuentran alineados junto al
borde izquierdo de la ventana. Por
su parte “Desordenar Fichas”,
“Animación” “-” y “Terminar” se
encuentran alineadas a la misma
profundidad que “Cómo Jugar” y
“Créditos”. Esto es así porque
ambos grupos de elementos
pertenecen a menús verticales
primarios, o sea menús que se
despliegan a partir de un elemento
del menú horizontal. Los tres
elementos del submenú asociado
al elemento “Animación” se
observan claramente alineados en
un tercer nivel de profundidad.
Para mostrar los créditos podemos emplear perfectamente una caja de
mensajes. El código para el procedimiento de atención a evento
Creditos_Click será:
Sub Creditos_Click ()
a$ = "'Juego del 15' Versión 1.00 1998" + Chr$(13) + Chr$(13)
Introducción a la Programación Visual Página 86 de 168

a$ = a$ + "Ha sido desarrollado como ejemplo" + Chr$(13)


a$ = a$ + "para el Libro de Texto:" + Chr$(13) + Chr$(13)
a$ = a$ + "'Introducción a la Programación" + Chr$(13)
a$ = a$ + "para Windows con Visual Basic'" + Chr$(13)
MsgBox a$, 64, "Juego del 15"
End Sub
Los símbolos de cambio de línea Chr$(13) sirven precisamente para dividir
en varias líneas el texto que mostrará la caja de mensajes. Si no aparecen
esos símbolos y el mensaje es demasiado extenso, Visual Basic lo separará
en líneas de manera arbitraria.
Incorporar ayuda a nuestro programa con una estructura de hipertexto
similar a la empleada por la Ayuda de Windows puede resultar algo
complejo. Primero es necesario preparar el archivo de ayuda con todas los
Figura 6-4. Lista definitiva de los
elementos de menú del ‘Juego del
15’
Introducción a la Programación Visual 91
requerimientos para ser procesado como hipertexto, y más tarde es preciso
compilarlo con el compilador de ayudas. El utilitario Help Magician también
puede emplearse (y resulta más cómodo) para preparar archivos de ayuda.
Una vez preparado el archivo de ayuda, para que nuestro programa pueda
mostrarlo debemos colocar sobre el formulario un control Diálogos Comunes
que como recordarán permite emplear desde nuestros programas
determinadas cajas de diálogos estándar de Windows. Uno de sus servicios
es ejecutar el programa WINHELP.EXE, o sea el manejador de ayudas de
Windows, permitiéndonos indicar el archivo de ayuda que deseamos
mostrar.
Realmente la elaboración completa de un archivo de ayuda escapa tanto
a los propósitos de este libro como a su extensión. Por estas causas
buscaremos otras alternativas para colocar ayuda en nuestro programa. Las
más promisorias resultan: primero, conformar una caja de mensajes con la
información, o tal vez en preparar un nuevo formulario donde se encuentre
la información de ayuda.
La caja de mensajes no resulta totalmente conveniente porque esta
Introducción a la Programación Visual Página 87 de 168

concebida para mostrar mensajes relativamente cortos y un texto de ayuda


debe sobrepasar sus límites. Por esta razón el recurso que más apropiado
debe ser la preparación de un nuevo formulario.
Incorporando otros formularios a una aplicación.
Para incorporar el nuevo formulario a nuestro programa o aplicación
debemos emplear la opción Formulario del menú Insertar en la versión 4.0
(New Form del menú File en la versión 3.0)
El diseño de este segundo formulario
resulta muy simple: necesitamos que
contenga una Caja de Texto donde
colocaremos la información de ayuda
y un Botón de Órdenes para terminar el
trabajo con la ayuda, cerrar la
ventana y continuar con el juego. El
aspecto del formulario podría ser así:
A primera vista el lector podría pensar
que ha faltado por describir un objeto
Figura 6-5. Formulario para la
ayuda del ‘Juego del 15’
92 Introducción a la Programación Visual
del interfaz, en efecto, hay una barra de desplazamiento vertical a la
derecha de la caja de textos! En realidad esa barra no es un objeto
independiente, sino es parte de la Caja de Texto. Precisamente, la
posibilidad de colocar barras de desplazamiento fue lo que nos decidió a la
hora de seleccionar el control a emplear para colocar la información de
ayuda. De acuerdo con el estilo de trabajo que hemos venido empleando,
el control adecuado debía haber sido le Etiqueta, ya que el texto que
pretendemos mostrar no debe ser modificado por el usuario. Pero con la
Etiqueta tropezaríamos con el mismo inconveniente que presentan las cajas
de mensajes: el texto de la ayuda debe sobrepasar el tamaño físico de la
Etiqueta y tendremos que colocar un control Barra de Desplazamiento
Vertical para controlar la exhibición del texto. En cambio las Cajas de Texto
disponen de las propiedades MultiLine que permite mostrar el texto de la
caja en formato multilineal y ScrollBars que incorpora como parte de la Caja
Introducción a la Programación Visual Página 88 de 168

de Texto barras de desplazamiento y administra. El único inconveniente de


emplear una Caja de Texto radica como ya dijimos en que el jugador puede
acceder a ella y modificar su contenido. Será responsabilidad de nuestro
programa evitar que eso suceda. Es conveniente recordar que cualquier
cambio en el contenida de una Caja de Texto desencadena un evento
Change, el cual podremos emplear para reparar los daños sufridos por el
texto.
Nota: El lector podría pensar que para resolver este problema basta con
evitar que el jugador escriba en la Caja de Texto colocando el
valor False en su propiedad Enabled. Le invitamos a experimentar
para que descubra el inconveniente de esa vía de solución.
El Botón de Órdenes se encuentra ostensiblemente centrado en la zona
inferior del formulario. En un primer diseño lo habíamos colocado alineado
con el borde derecho de la Caja de Texto, como se muestra en la figura 6-
6.
Sin embargo no creímos que fuese conveniente colocar
el botón que cierra la ventana en las cercanías de otro
botón que puede ser pinchado con frecuencia, como es
el botón inferior de la barra de desplazamiento. Puede
perfectamente pasar que el usuario oprima
accidentalmente el botón “Terminar” mientras opera
con la barra de desplazamiento. Por esta razón preferimos colocar el botón
de órdenes lo más separado posible, siempre que el hacer esto no estropee
irreparablemente la estética del formulario. Este es un buen principio a
seguir en el diseño de los formularios. Evitar que un botón que realiza una
Figura 6-6.
Introducción a la Programación Visual 93
tarea potencialmente peligrosa (como puede ser cerrar una ventana,
eliminar un archivo, etc.) se ubique en una zona del formulario donde el
usuario deba pinchar continuamente trabajando sobre otros controles.
A continuación mostraremos la tabla con las principales propiedades de
este formulario:
Objeto Propiedad Valor asignado Comentario
Form2 Caption “Ayuda del Juego del 15” Título de la
Introducción a la Programación Visual Página 89 de 168

aplicación.
Height 3645
Width 5055
Text1 Text “”
MultiLine True Para que la caja de
texto muestre el
mensaje en formato
multilineal.
ScrollBars 2 (Vertical) Para que la Caja de
Texto presente una
barra de
desplazamiento
Vertical.
0 - Ninguna Barra de
desplazamiento.
1 - Barra Horizontal.
2 - Barra Vertical.
3 - Ambas Barras de
desplazamiento.
Command
1
Caption “Terminar”
Debe llamar nuestra atención el hecho de que la propiedad Text de la Caja
de Texto aparezca vacía en el diseño, cuando era de esperar que en ella se
colocara el texto de la ayuda. La razón es sencilla: la longitud del texto que
se puede colocar en esa propiedad en tiempo de diseño no puede exceder
los 256 caracteres. Por esa razón preferimos dejarla vacía y colocar en ella
el texto durante la ejecución, en el momento en que se cargue la ventana
de ayuda.
Las acciones a realizar dentro de este formulario son también pocas y
sencillas. Primero la que acabamos de describir: colocar el texto de ayuda
94 Introducción a la Programación Visual
en la Caja de Texto que debe realizarse cuando se cargue el formulario y
por tanto puede asociarse al evento Load del mismo. La segunda cerrar el
Introducción a la Programación Visual Página 90 de 168

formulario cuando el usuario pinche el Botón de Órdenes lo que causa el


evento Click del botón y por último restaurar el texto de la caja si en algún
momento el usuario lo modifica. Esta modificación provocaría un evento
Change en la Caja de Texto.
El texto de la ayuda debe emplearse por dos procedimientos de atención a
eventos, el Load del Formulario y el Change de la Caja de Texto, por tanto
resulta conveniente almacenar dicho texto en una variable que este
disponible para todos los procedimientos del formulario. Para eso
escribiremos en la sección (general) la siguiente declaración:
Dim A$ ‘ También habría servido la declaración Dim A AS String
El evento Load del formulario contendrá el siguiente código:
Sub Form_Load ( )
A$ = "El 'Juego del 15' está formado por un tablero con capacidad para 16 "
A$ = A$ + "fichas, distribuidas en cuatro filas y cuatro columnas. En el
tablero "
A$ = A$ + "se han colocado 15 fichas numeradas precisamente del 1 al 15,
estas "
A$ = A$ + "fichas se encuentran ordenadas al comienzo del juego y falta la
última "
A$ = A$ + "ficha, quedando en su lugar un sitio vacío. Este espacio vacío
sirve "
A$ = A$ + "para mover las fichas, ya que cuando pinchamos con el ratón
una de las "
A$ = A$ + "fichas colindantes con el espacio vacío, esta se mueve
ocupándolo. "
A$ = A$ + "Para jugar debemos desordenar las fichas, podemos hacerlo con
la opción "
A$ = A$ + "'Desordenar Fichas del menú 'Opciones'. Luego moviendo
convenientemente "
A$ = A$ + "las fichas debemos devolverlas a sus posiciones iniciales. " +
Chr$(13) + Chr$(10)
A$ = A$ + "Las tres opciones del menú 'Animación' nos permiten incorporar
efectos "
A$ = A$ + "al movimiento de las fichas."
Introducción a la Programación Visual Página 91 de 168

Text1.Text = A$
End Sub
Introducción a la Programación Visual 95
Cuando el formulario de ayuda es cargado en memoria se prepara el texto y
se coloca en la Caja de Texto Text1. La combinación Chr$(13) + Chr$(10)
sirve, como en la caja de mensajes para insertar un cambio de línea dentro
del texto que se muestra. Por cierto, hemos escrito la ayuda lo más breve
posible. El lector puede completarla convenientemente.
Para atender a las posibles alteraciones que realice el jugador al texto de la
ayudo proponemos una solución muy sencilla. Como conservamos en la
variable A$ el texto original de la ayuda, cada vez que el jugador lo
modifique nuestro programa la restaurará. Para esto debemos escribir:
Sub Text1_Change ( )
Text1.Text = A$
End Sub
El control de la barra de desplazamiento no es nuestra responsabilidad.
Forma parte del control Caja de Texto y se ocupa de desplazar el texto
dentro de la caja sin necesidad de nuestra intervención.
Por último debemos atender al problema de como cerrar la ventana de la
ayuda. Para esto Visual Basic proporciona la instrucción Unload que recibe
como argumento el identificador (propiedad Name) del formulario que
deseamos cerrar. El procedimiento a ejecutar cuando se oprime el botón
‘Terminar’ será así:
Sub Command1_Click ( )
Unload Form2
End Sub
Ya hemos preparado completamente el formulario de ayuda para el juego
del 15. Sólo falta escribir las instrucciones necesarias para colocarlo en la
pantalla desde el elemento ‘Cómo Jugar’ del menú de ayuda del juego.
Para ello escribiremos
Sub Como_Jugar_Click ( )
Load Form2
Form2.Show
End Sub
Introducción a la Programación Visual Página 92 de 168

A diferencia del procedimiento anterior, donde descargamos el formulario


con una sola instrucción, para mostrarlo en la pantalla empleamos dos
96 Introducción a la Programación Visual
líneas de código. Primero la instrucción Load que tiene como argumento al
identificador del formulario que deseamos cargar y a continuación se
ejecuta el método Show de ese mismo formulario. Veamos porqué. La
instrucción Load realiza la función contraria de Unload, es decir es capaz de
cargar el formulario en la memoria, pero no lo muestra , el método Show es
quien se ocupa de hacer visible el formulario. En realidad podemos resolver
esta situación sin necesidad de la instrucción Load, ya que el método Show
tiene la doble capacidad de hacer visible un formulario previamente
cargado y de cargar un y visualizar un formulario.
Cuando ya pensamos que todo esta listo y que tenemos la versión definitiva
del Juego del 15 nos hacen una última sugerencia: todas las ayudas se
ejecutan cuando el usuario oprime la tecla de función F1 ¿porqué la de
nuestro programa no lo hace? y no tenemos más remedio que otorgar la
razón buscar la vía de atender la sugerencia.
Cómo identificar la opresión de una tecla y en particular de la tecla F1?
Para ello debemos valernos de los eventos generados por el teclado que
enumeramos en el capítulo 2. De esos eventos debemos desechar al
evento KeyPress ya que sólo tiene lugar cuando se oprime una tecla que
devuelva un carácter ANSI, lo cual sucede con las letras, los dígitos y otros
símbolos, pero no con las teclas especiales como los cursores y las teclas de
función. En cambio los eventos KeyDown y KeyUp se producen cuando se
oprime o libera cualquier tecla. Los procedimientos de atención a ambos
eventos reciben como primer parámetro un número que identifica la tecla
oprimida y como segundo parámetro otro número que indica el estado de
las teclas de estado del teclado, o sea Shift, Alt y Ctrl.
El listado con los números que identifican las teclas se encuentra en el
archivo CONSTANT.TXT que se distribuye como parte de Visual Basic.
Revisando ese archivo encontramos que el código identificador de la tecla
de función F1 es el número &H70 en notación hexadecimal, es decir 112 en
notación decimal.
Escribiremos entonces código para el evento KeyDown de las fichas. Como
Introducción a la Programación Visual Página 93 de 168

se trata de un arreglo de controles el procedimiento de atención al evento


tendrá como primer parámetro el índice de la ficha que recibe el evento
(será aquella que tenga el foco en el momento de oprimirse la tecla) los
restantes parámetros se colocarán a continuación. De esta forma el
parámetro que nos interesa pasará a ocupar la segunda posición. El
procedimiento quedará así:
Introducción a la Programación Visual 97
Sub Ficha_KeyDown (Index As Integer, KeyCode As Integer, Shift As Integer)
If KeyCode = 112 Then Como_Jugar_Click
End Sub
Resulta muy sencillo, si el código que identifica la tecla oprimida es
precisamente el 112 se ejecuta el procedimiento de atención al evento
Click del elemento de menú Como_Jugar, que carga el formulario de la
ayuda.
A pesar de que una zona del formulario siempre esta visible (el espacio
vacío) no es posible que el formulario reciba la acción del teclado y
detecte por tanto el evento KeyDown. Los eventos del teclado tienen lugar
para el control que tiene el foco y un formulario que contiene al menos un
control visible y activo (es decir que su propiedad Enabled tenga el valor
True) nunca tendrá el foco. El foco estará colocado en alguno de los
controles.
Finalmente podemos dar por terminado nuestro programa del ‘Juego del
15’ al que hemos incorporado un menú y una ayuda elemental. En el próximo
epígrafe lo modificaremos un poco más, pero no será porque el programa lo
necesite sino e mpleándolo como ejemplo para ilustrar el trabajo con los...
Menús Emergentes
Hasta aquí hemos estudiado como incorporar menús a nuestros programas.
Estos menús se ubican en pantalla en una posición preestablecida: a partir
de la barra de menú del formulario. Por esto podemos llamarlos Menús de
Formulario. Pero no es este el único tipo de menú que podemos emplear en
nuestros programas. Existe otro tipo de menú, un menú que no se encuentra
colocado en ninguna posición específica dentro del formulario, y que
normalmente ni siquiera se encuentra visible. Estos menús solamente
aparecen cuando el usuario del programa realiza una determinada acción.
Introducción a la Programación Visual Página 94 de 168

Una acción que genera un evento previsto por el programador, y el


procedimiento de atención a ese evento ejecuta la instrucción que
despliega el menú. Este tipo de menú es conocido con el nombre de Menú
Emergente (Pop Up Menu) y en estos años han cobrado especial
popularidad por su empleo en Windows 95 y en el paquete MS Office para
presentar los menús contextuales que se despliegan al oprimir el botón
derecho del ratón.
98 Introducción a la Programación Visual
Un menú emergente es un menú vertical y puede contener todos los tipos
de elementos que se describieron al comienzo de esta capítulo. Los
elementos de un menú emergente también deben estar colocados en la
Ventana de Diseño de Menú, subordinados directamente a un elemento del
menú horizontal (es lo más usual) o como submenú de algún elemento de los
menús verticales. Si se desea que los elementos del menú emergente no se
muestren como parte del menú del formulario debemos desactivar la
propiedad Visible (eliminando la marca de chequeo) del elemento de menú
al que se subordinan los elementos del menú emergente.
Para desplegar un menú emergente Visual Basic dispone del método
PopUpMenu. Este método emplea cuatro parámetros, el primero que es de
obligatorio suministro contiene el identificador del menú, o sea la
propiedad Name del elemento de menú que provoca el despliegue del
menú, esto puede ser o bien un elemento del menú principal o bien un
elemento de un menú vertical que tenga asociado un submenú.
El segundo parámetro contiene un valor que resulta de la suma de dos
componentes. El primero sirve para indicar si el botón izquierdo podrá
emplearse para seleccionar dentro del menú emergente (valor 2), o si sólo
se podrá seleccionar con el botón izquierdo (valor 0). El segundo
componente indica la ubicación del menú a la derecha, centrado o a la
izquierda respecto a la coordenada X de ubicación del menú que se indica
en el tercer parámetro.
Los parámetros tercero y cuarto representan las coordenadas X y Y del
punto a partir del cual se desplegará el menú emergente estos valores se
toman a partir de la esquina superior izquierda del formulario. Si no se
especifican estos valores Visual Basic emplea las coordenadas X y Y del
Introducción a la Programación Visual Página 95 de 168

puntero del ratón.


Para ejemplificar el empleo de menús emergentes, vamos a añadir uno a
nuestro programa del ‘Juego del 15’. Como en el juego no hace falta
realmente ningún nuevo menú, haremos que el menú Ayuda se presente
también como menú emergente. Para seguir el estándar de Windows
haremos que el menú se despliegue cuando el jugador oprima el botón
derecho del ratón.
Esto nos sitúa ante una interrogante. ¿Cómo identificar la opresión del
botón derecho en particular? Para dilucidar la interrogante revisaremos los
eventos asociados al ratón. El evento Click, el de uso más frecuente, no nos
Introducción a la Programación Visual 99
sirve para esto, ya que su procedimiento de atención no recibe ninguna
información que permita determinar qué botón lo generó. La única
información que puede recibir el procedimiento de atención al evento
Click es el índice, en caso de ser generado por un control que forme parte
de un arreglo. El otro evento que se relaciona con la opresión de botones
del ratón es el evento MouseDown. Si revisamos la ayuda para ese evento
veremos que a los procedimientos de atención al evento MouseDown se les
transfiere normalmente cuatro parámetros. El primero de ellos es un número
que indica que botón produjo el evento. Un valor 0 en este parámetro
identifica al botón izquierdo, un 2 al botón derecho y un 4 al botón central.
El segundo parámetro permite saber si se encuentran oprimidas las teclas
Shift, Control o Alt, y los dos restantes indican las coordenadas del punto
donde pincho el ratón dentro del formulario o control que causó el evento.
Este es precisamente el evento que necesitamos! Escribiendo código para
este evento podemos identificar la opresión del botón izquierdo y desatar
el despliegue del menú emergente. Ahora se nos presenta una segunda
interrogante. ¿Para qué objetos atender el evento MouseDown? Es
evidente que debe atenderse para el arreglo de las fichas, que cubre casi
todo el tablero, pero también debe analizarse para el propio tablero (es
decir el formulario) ya que una parte del mismo, el espacio vacío, siempre se
encuentra visible, y a diferencia de lo que vimos para los eventos del
teclado el formulario si es capaz de recibir los eventos provocados por el
ratón. Escribamos entonces los siguientes procedimientos de atención a
Introducción a la Programación Visual Página 96 de 168

evento:
Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As
Single)
If Button = 2 Then Form1.PopupMenu Ayuda, 2
End Sub
Colocamos un 2 como segundo parámetro para permitir que la selección
dentro del menú emergente también se pueda realizar con el botón
izquierdo, ya que es así como lo hace normalmente Windows en sus menús
contextuales.
Sub Ficha_MouseDown (Index As Integer, Button As Integer, Shift As Integer, X
As Single, Y AsSingle)
If Button = 2 Then Form1.PopupMenu Ayuda, 2
100 Introducción a la Programación Visual
End Sub
También aquí la información que nos interesa se encuentra ubicada como
segundo parámetro del procedimiento, ya que al tratarse de un arreglo de
controles se adiciona el índice del arreglo como primer parámetro.
Si prefiriésemos que el menú Ayuda sólo se presente como menú emergente
y no como parte del menú del formulario debemos con abrir la ventana de
diseño de menú y quitar la marca de chequeo a la propiedad Visible del
elemento de menú Ayuda, al que se subordina el despliegue de este menú
que queremos emplear exclusivamente como Menú Emergente.
Después de estudiar este capítulo nos encontramos en condiciones de
completar el diseño de nuestras aplicaciones con la incorporación de
elementos tan importantes como son los menús, tanto en calidad de menús
de formulario como en calidad de menús emergentes.
Introducción a la Programación Visual 101
Capítulo 7. Explotando el Ratón.
El Ratón, elemento imprescindible en la interacción hombre
máquina
El puntero del ratón es en este momento y sin lugar a dudas de ninguna
clase, el principal medio de que dispone el usuario para comunicarse con su
computadora. Desde que hizo su aparición en el mundo de la informática,
en los viejos tiempos del MS-DOS ocupó un lugar destacado en la
Introducción a la Programación Visual Página 97 de 168

comunicación hombre máquina. Y el advenimiento de los ambientes


gráficos lo elevó a planos estelares. En efecto, a nadie se le ocurre hoy en
día operar una computadora que no disponga de ratón y los sistemas
operativos gráficos están diseñados contando a tal extremo con su
presencia que resultan increíblemente complicados de manejar si no
disponemos de él. Muchas de las aplicaciones desarrolladas para Windows
pueden operares con el exclusivo uso del ratón, sin necesitar que el usuario
pulse tan siquiera una sola tecla en su teclado. Por este motivo el diseñador
de aplicaciones para Windows debe ser capaz de explotar al máximo las
posibilidades de interacción que brinda tan útil dispositivo.
Los eventos del Ratón.
El ratón es uno de los principales elementos generadores de eventos en el
interfaz gráfico de Windows. Estos eventos pueden ser detectados y
atendidos por nuestros programas en Visual Basic. En capítulos anteriores
hemos venido entrando en contacto con algunos de ellos,
fundamentalmente con el evento Click, que es el que se produce cuando,
colocado el puntero del ratón sobre un objeto (formulario o control) el
usuario oprime y libera el botón primario del ratón. Normalmente el botón
primario es el izquierdo, aunque cabe la posibilidad de que el usuario haya
modificado tal condición en el panel de cont rol de Windows, declarando
como primario al botón izquierdo. Este evento sólo puede ser causado por
el botón primario del ratón, y tiene lugar una vez que el botón es liberado.
Muy similar el evento Click resulta el evento DblClick, que tiene lugar
cuando el usuario realiza dos click consecutivos sobre un objeto. Este
102 Introducción a la Programación Visual
evento, al igual que el anterior, sólo puede ser realizado con el botón
primario del ratón.
La realización de un click está compuesta por dos acciones diferentes: la
opresión del botón del ratón y su posterior liberación. Como ya señalamos
en el capítulo anterior estas acciones provocan a su vez la ocurrencia de
dos eventos denominados MouseDown (cuando se oprime el botón) y
MouseUp (cuando se libera el botón). La ventaja fundamental que ofrecen
estos eventos sobre el popular Click radica en que pueden ser generados
por cualquiera de los botones del ratón ,y en que, como ya se dijo, permiten
Introducción a la Programación Visual Página 98 de 168

identificar al botón causante del evento.


En adición a los dos anteriores existe un tercer evento denominado
MouseMove que es detectado por cualquier objeto sobre el que se
desplace el puntero del ratón. Los procedimientos de atención a estos tres
eventos Estos tres eventos Al igual que los dos anteriores nos Este evento
ocurre con independencia de que uno o más botones estén o no oprimidos
mientras el puntero se desplaza.
Los procedimientos de atención a estos tres eventos reciben cuatro
parámetros. El primero es un número entero que indica el botón del ratón
que se encuentra oprimido (0 botón izquierdo, 2 botón derecho, 4 botón
central). El segundo parámetro también es un entero que indica cuales de
las teclas modificadoras (0 Shift, 2 Ctrl y 4 Alt) se encuentran oprimidas en el
momento de producirse el evento. Los parámetros tercero y cuarto indican
las coordenadas X y Y de la posición del puntero del ratón dentro del
objeto.
Identificando objetos por medio del ratón.
Una de las aplicaciones inmediatas de los eventos del ratón, en particular
de MouseMove es en el suministro dinámico de información. En efecto este
evento permite determinar cuando el ratón se encuentra sobre una
determinada región del interfaz de un programa y suministrar al usuario
información sobre las características particulares de esa zona.
Para ilustrar esta aplicación de MouseMove nos valdremos de la
calculadora elemental que desarrollamos en el capítulo 4. Procuraremos
adicionar a esa calculadora una etiqueta en la que se informe al usuario
sobre la función de cada uno de los diferentes objetos que componen el
Introducción a la Programación Visual 103
interfaz. La información sobre cada objeto sólo se mostrará mientras el
ratón se encuentre sobre el mismo.
El primer paso que debemos efectuar es
modificar el diseño del interfaz. Para ello, tal
como muestra la figura 7-1 aumentaremos un
poco la altura del formulario y colocaremos,
entre los botones asociados con las
operaciones aritméticas y el botón ‘Terminar’,
Introducción a la Programación Visual Página 99 de 168

un control Etiqueta. Este control nos servirá


para escribir la información que
suministraremos al usuario y pretendemos que
permanezca oculto cuando no sea necesario
mostrar ninguna información (para ello
colocaremos el valor False en su propiedad
Visible), y cuando lo ocurrencia del evento MouseMove indique que el
puntero del ratón se encuentra sobre alguno de los objetos que nos
interesan escribiremos en la propiedad Caption de la etiqueta la
información sobre el objeto en cuestión y mostraremos la etiqueta
colocando un valor True en su propiedad Visible.
A continuación presentamos una tabla con las principales propiedades del
control etiqueta que adicionamos a nuestro interfaz.
Objeto Propiedad Valor
asignado
Comentario
Label4 Caption “” No hay texto preestablecido.
Visible False Inicialmente el control es
invisible.
Alignment 2 (Centrado) Se colocan el texto en el centro
de la etiqueta.
BackColor &H00FFFFFF
(Blanco)
BorderStyl
e
1 (Borde
Sencillo)
Alignment 2 (Centrado) Se colocan el texto en el centro
de la etiqueta.
Los objetos sobre los que nos interesa brindar información al usuario son los
cuatro botones que realizan las operaciones aritméticas, o sea los botones
de órdenes Command1, Command3, Command4, Command5, el botón que
Figura 7-1. Incorporando
una etiqueta al formulario.
Introducción a la Programación Visual Página 100 de 168

104 Introducción a la Programación Visual


sirve para terminar el programa, o sea el botón de órdenes Command2, las
dos cajas de texto Text1 y Text2 donde se escriben los operandos y la
etiqueta Label3, donde se escribe el resultado de la operación. Para todos
estos controles debemos escribir procedimientos que atiendan la
ocurrencia de sus eventos MouseMove.
Cuando el puntero del ratón se desplace sobre el botón Command1 se
ejecutará el procedimiento Command1_MouseMove. En el debemos
escribir:
Sub Command1_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la suma."
‘ Se coloca el texto con la información
Label4.Visible = True ‘ y se hace visible la etiqueta
End Sub
Para los restantes controles los procedimientos resultan similares:
Sub Command2_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón termina el programa."
Label4.Visible = True
End Sub
Sub Command3_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la resta."
Label4.Visible = True
End Sub
Sub Command4_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la multiplicación."
Label4.Visible = True
End Sub
Sub Command5_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la división."
Introducción a la Programación Visual Página 101 de 168

Label4.Visible = True
End Sub
Introducción a la Programación Visual 105
Sub Text1_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As
Single)
Label4.Caption = "Aquí va el primer operando."
Label4.Visible = True
End Sub
Sub Text2_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As
Single)
Label4.Caption = "Aquí va el segundo operando."
Label4.Visible = True
End Sub
Sub Label3_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As
Single)
Label4.Caption = "Este es el resultado de la operación."
Label4.Visible = True
End Sub
Así garantizamos colocar la información necesaria en la etiqueta, de
acuerdo al control sobre el que se sitúe el puntero y mostrar la etiqueta,
pero... Habíamos dicho que deseábamos que la etiqueta se mantuviese
oculta cuando no fuese necesario mostrar información, o sea cuando el
puntero no se encuentre sobre ninguno de los controles que nos interesan.
Cuando comienza el programa no hay problemas, ya que la etiqueta está
oculta porque en el diseño colocamos False en su propiedad Visible, pero
cuando el puntero entra al primer control la etiqueta se hace visible, como
hemos visto. El problema es ¿cómo volverla a ocultar? Para hacerlo es
necesario determinar cuándo el puntero abandona el control sobre el que
se encontraba. Parece sencillo pero: ¿cómo saber que el puntero ya no está
sobre el control? ¿Cómo saber que el puntero ha salido de él? Realmente es
sencillo, cuando el puntero sale de cualquiera de los controles que nos
interesan pasa a encontrarse sobre el formulario y por tanto el formulario
siente a su vez el evento MouseMove. Tan sólo tenemos que escribir código
para ese evento ocultando la etiqueta; Esto sería así:
Introducción a la Programación Visual Página 102 de 168

Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As


Single)
Label4.Visible = False
End Sub
Con esto logramos el efecto deseado, mientras el puntero del ratón se
encuentra sobre alguno de los controles que nos interesan se coloca sobre
el formulario una etiqueta con información para el usuario del programa
106 Introducción a la Programación Visual
acerca de la función que cumple el control. Una vez que el puntero
abandona el control y pasa a situarse sobre alguno de los objetos que no
resultan de nuestro interés ( o se sitúa fuera del formulario) la etiqueta
desaparece.
Modificando la forma del puntero del Ratón.
Un recurso que puede aportar valiosa información a los usuarios de nuestros
programas, si lo sabemos emplear con habilidad, es la imagen del puntero
del ratón. La figura que se emplea como puntero del ratón es un icono que
normalmente representa una flecha, pero que puede ser cambiada a
conveniencia de nuestro programa. Windows cambia con frecuencia la
imagen del puntero para proporcionar información a sus usuarios. Por
ejemplo si la flecha es sustituida por un reloj de arena, significa que el
sistema esta ocupado realizando una tarea y que el usuario debe esperar a
que termine antes de solicitar un nuevo servicio.
Visual Basic también nos ofrece la posibilidad de modificar la imagen del
puntero del ratón para nuestros programas. Para esto los diferentes objetos
(formularios y controles) disponen de la propiedad MousePointer. Esta
propiedad recibe un valor numérico que representa las diferentes figuras
que pueden emplearse como puntero. A partir de la versión 4.0 de Visual
Basic se permite al programador definir libremente el icono que fungirá
como puntero. Para esto se incorpora a los objetos la propiedad
MouseIcon.
Entre los valores más notables de la propiedad MousePointer se encuentran
los siguientes:
Valor Forma del puntero del Ratón
0 Valor por defecto de la propiedad.
Introducción a la Programación Visual Página 103 de 168

1 Flecha. El puntero estándar de Windows.


2 Cruz. Se emplea en algunos graficadores como el Paintbrush.
3 Cursor con forma de I es el que se emplea en el interior de las
cajas de texto.
11 Reloj de Arena. Se emplea para indicar esperas mientras el
sistema trabaja .
12 Señal de acceso prohibido. Se emplea para indicar que no se
puede realizar una operación sobre un área determinada
Introducción a la Programación Visual 107
99 Icono definido mediante la propiedad MouseIcon. (A partir de
la versión 4 de Visual Basic)
Cuando la propiedad MousePointer tiene el valor 0 es porque no se desea
definir una forma particular para el puntero no del ratón. En ese caso
cuando el puntero se encuentre sobre un objeto, tomará la forma que este
definida para el formulario (o caja de imágenes) que contiene a ese objeto.
Para ilustrar el empleo de este recurso, modificaremos la forma del puntero
del ratón en nuestro programa de manera que mientras el puntero se
encuentre en regiones donde no tiene actividad nos muestre el icono de
acceso prohibido. Estas áreas son: el fondo del formulario, las etiquetas con
los signos de la operación realizada, con el signo “=“ y con el resultado de la
operación. En cambio cuando se encuentre sobre los botones, el puntero
mostrará la conocida flecha y cuando se encuentre sobre las cajas de texto
mostrará el cursor en forma de I que se emplea en estos controles.
Para lograr este resultado no es necesario escribir ni una sola línea de
programa. Basta con modificar durante el diseño la propiedad MousePointer
de los objetos de nuestro interfaz. La siguiente tabla contiene los valores
que debemos asignar a la propiedad MousePointer de los diferentes objetos.
Objeto Valor de la propiedad MousePointer
Form1 12 (No se puede Operar)
Command1 1 (Flecha)
Command2 1 (Flecha)
Command3 1 (Flecha)
Command4 1 (Flecha)
Command5 1 (Flecha)
Introducción a la Programación Visual Página 104 de 168

Text1 3 (Cursor con forma de I )


Text2 3 (Cursor con forma de I )
Como pueden ver, no hemos asignado el valor 12 a los objetos etiqueta
Label1, Label2 y Label3, que contienen el signo de la operación que se ha
realizado, el signo “=“ y el resultado de la operación. No ha sido necesario
hacerlo ya que para estos controles el puntero debe tener la misma forma
que para el formulario, y para eso basta con mantener el valor 0 que
originalmente tienen en su propiedad MousePointer.
Arrastrando objetos con el ratón.
108 Introducción a la Programación Visual
El arrastre de objetos con el ratón es una de las tareas que con mayor
frecuencia debemos realizar al trabajar, tanto en el propio sistema
operativo Windows, como en las aplicaciones elaboradas para ser
ejecutadas sobre él. Esto hace que resulte importante poder dotar a
nuestros programas de la capacidad de arrastrar objetos. Visual Basic nos
brinda los recursos necesarios para arrastrar objetos en nuestros programas.
Cuando se arrastra un objeto en Windows (por ejemplo una ventana) lo que
se desplaza junto con el ratón es el contorno o silueta del objeto y sólo
cuando termina el arrastre el objeto se traslada al lugar de destino. A este
tipo de arrastre le llamaremos ‘Arrastre de siluetas’. En cambio en algunos
casos particulares, por ejemplo en juegos de rompecabezas es necesario
arrastrar junto con el ratón la imagen real del objeto. A este tipo de arrastre
lo llamaremos ‘Arrastre real’. Por supuesto con Visual Basic podemos realizar
ambos tipos de arrastre. Comenzaremos por estudiar el arrastre de siluetas
ya que resulta el que con mayor frecuencia se realiza.
Arrastre de siluetas.
Para desarrollar el arrastre de objetos por la vía normal, o sea arrastrando
una representación del objeto, Visual Basic nos proporciona dos eventos
especiales del ratón DragOver y DragDrop. Estos eventos tienen la
particularidad de no ser detectados por el objeto que esta siendo
arrastrado, sino por aquellos objetos sobre los cuales arrastramos nuestro
objeto. Los procedimientos de atención a estos eventos reciben como
primer parámetro una variable de tipo objeto que contiene una referencia
al control que esta siendo arrastrado. Como segundo y tercer parámetros
Introducción a la Programación Visual Página 105 de 168

reciben las coordenadas X y Y de la posición relativa del objeto que esta


siendo arrastrado dentro del objeto sobre el cual es arrastrado, o sea,
dentro del objeto que ha generado el evento.
El evento DrogOver se genera cuando propiamente el objeto esta siendo
arrastrado sobre otro. Su procedimiento de atención a eventos recibe un
cuarto parámetro que sirve para indicar las características de dicho
arrastre. Este parámetro puede contener tres valores que especifican en
cada caso las características del arrastre que se esta realizando, ellos son:
0 Indica que el objeto que esta siendo arrastrado acaba de entrar al objeto
que ha provocado el evento y comienza en este mismo instante a
desplazarse sobre el. (El objeto arrastrado se mueve de un punto exterior al
objeto que genera el evento a un punto situado sobre ese objeto).
Introducción a la Programación Visual 109
1 Indica que el objeto que esta siendo arrastrado acaba de salir, de
abandonar al objeto sobre el que se estaba arrastrando. (El objeto
arrastrado se mueve de un punto situado dentro del objeto que genera el
evento hacia un punto situado en el exterior de ese objeto).
2 Indica que el objeto que esta siendo arrastrado se esta moviendo por el
interior del objeto que genera el evento. (El objeto arrastrado se mueve de
un punto situado dentro del objeto que genera el evento hacia hasta otro
punto también situado dentro del mismo objeto).
El evento DragDrop se genera cuando el usuario libera el botón primario del
ratón, dando así por concluido el arrastre. En el procedimiento de atención
a este evento se debe proceder a acomodar o reubicar la posición real del
objeto de acuerdo al lugar donde el mismo ha sido liberado por el usuario
(recuerden que lo que se ha estado moviendo es la silueta del objeto
mientras que el objeto ha permanecido en su lugar).
El arrastre automático y el arrastre manual de objetos.
Para que un objeto pueda ser arrastrado y provoque la ocurrencia de
eventos DragDrop y DragOver el programador tiene que permitir u ordenar
el arrastre del objeto. Para esto los objetos disponen de la propiedad
DragMode., que define de que forma se podrá arrastrar al objeto. Cuando
esta propiedad vale 1 realizamos el denominado arrastre automático. En
este tipo de arrastre, el usuario del programa puede pinchar y arrastrar el
Introducción a la Programación Visual Página 106 de 168

objeto en cualquier momento. En cambio cuando DragMode vale 0 (su


valor por defecto) sólo es posible realizar el denominado arrastre manual. En
este tipo de arrastre, el usuario no puede decidir cuando va a arrastrar un
objeto. El programa le brinda (mas bien le ordena) la posibilidad de arrastrar
un objeto en particular, ejecutando, desde el código del programa el
método Drag de ese objeto. La acción de este método sustituye al objeto
por su silueta la cual puede ser arrastrado por el usuario. Una importante
ventaja del arrastre manual sobre el automático radica en que durante el
arrastre manual es posible detectar el pinchazo del ratón sobre nuestro
objeto (eventos Click o MouseDown) y obrar en consecuencia, mientras en
el arrastre automático esos eventos no son detectados.
Contornos o iconos.
110 Introducción a la Programación Visual
Hemos venido diciendo que en este tipo de arrastre lo que se desplaza
junto con el ratón es la silueta del objeto que estamos arrastrando. Esto es
verdad, pero también tenemos la posibilidad de sustituir esa silueta por el
dibujo de un icono (algo similar a lo que hicimos con el puntero del ratón en
el capítulo anterior). Para indicar el icono que deseamos emplear en lugar
de la silueta del objeto debemos hacer uso de la propiedad DragIcon del
objeto que va a ser arrastrado.
El laberinto de los colores.
Para ilustrar el arrastre de siluetas, vamos a programar un juego llamado ‘El
laberinto de los colores’ que pretende ayudar al desarrollo del control
muscular necesario para el empleo del ratón.
El jugador debe desplazar cuatro fichas de colores diferentes, que se
encuentran en el área de ‘Salida’ hasta el área de la ‘Meta’ donde debe
depositarlas en cuatro casillas que se corresponden con los colores de las
fichas. El recorrido de la salida a la meta es un sinuoso laberinto por donde
el jugador debe arrastrar cuidadosamente las piezas sin salirse ni por un
instante del camino, ya que en caso de hacerlo la ficha es devuelta a la
salida y debe comenzar de nuevo. Se puede jugar contra tiempo. El interfaz
del juego se muestra en la figura 7-2.
Comenzaremos, como siempre por el diseño del interfaz. En este caso para
ubicar en pantalla tantos elementos de colores diferentes nos valdremos de
Introducción a la Programación Visual Página 107 de 168

cajas de imágenes a las que


modificaremos su propiedad
BackColor. Necesitaremos una caja
de imágenes para representar el
área de salida a la que llamaremos
precisamente ‘Salida’ dentro de
ella colocaremos cuatro cajas de
imágenes para representar las
fichas. Cada ficha deben contener
un dibujo realizado con el color que
la identifica (azul, rojo, verde y
magenta). La meta también será
una caja de imágenes, a la que
Figura 7-2. Interfaz de ‘El laberinto de llamaremos ‘Meta’ y contendrá a su
los colores.
Introducción a la Programación Visual 111
vez cuatro cajas de imágenes que representarán las casillas donde el
jugador debe depositar sus fichas. Cada una de estas casillas debe ser del
color de una de las fichas. Para el laberinto emplearemos un grupo de 22
cajas de imágenes las que agruparemos en el arreglo de controles
‘Camino’. Tanto la salida como el camino y la meta deben tener el mismo
color (seleccionamos el anaranjado), mientras para el fondo del formulario
preferimos un amarillo pálido.
Los restantes controles que intervienen en nuestro interfaz son dos
etiquetas, que empleamos para colocar los carteles ‘SALIDA’ y ‘META’ y un
menú que en el menú horizontal tan sólo coloca un elemento con el título
‘Opciones’ y en el menú vertical primario que se deriva del horizontal solo
contiene dos elementos con los títulos
‘Nuevo Juego’ y ‘Terminar’ divididos
por un separador. La figura 7-3 muestra
un estadío inicial del diseño del
interfaz, donde ya están ubicados los
controles menos el menú.
En esta vista del interfaz ya se
Introducción a la Programación Visual Página 108 de 168

encuentran coloreadas las cuatro


casillas de la meta, a las que
agruparemos en el arreglo de
controles ‘Casilla’. También hemos
colocado los cuatro dibujos que
identifican las fichas sobre las cuatro
cajas de imágenes que se encuentran
en la salida. También manejaremos
estas cuatro cajas de imagen como un arreglo de controles, al que
llamaremos ‘Ficha’. Los dibujos son muy sencillos una X del color de cada
una de las fichas. Al preparar los arreglos de controles de las fichas y las
casillas de la meta hemos tenido cuidado de garantizar la correspondencia
entre los índices y los colores, de forma que, por ejemplo la ficha y la casilla
azul tienen el índice 0, la ficha y la casilla roja el índice 1 y así
sucesivamente. Esto ayudará a identificar si la ficha se deposita sobre la
casilla correcta.
La posición de las 22 cajas de imágenes que integran el laberinto también
queda clara en esta figura.
A continuación presentamos una tabla con las propiedades más
significativas de los objetos del interfaz.
Objeto Propiedad Valor asignado Comentario
Figura 7-3. Diseño del interfaz de ‘El
Laberinto de los colores’
112 Introducción a la Programación Visual
Form1 Caption “El Laberinto de los
Colores”
BackColor &H80FFFF (amarillo
claro)
ImageBox1 Name ‘Salida’ Cambiamos el
identificador del
objeto.
BackColor &H0080FF
(anaranjado)
ImageBox2 Name ‘Meta’ Cambiamos el
Introducción a la Programación Visual Página 109 de 168

identificador del
objeto.
BackColor &H0080FF
(anaranjado)
Casilla(0) BackColor &HFFFF00 (azul claro)
Casilla(1) BackColor &H0000FF (rojo)
Casilla(2) BackColor &H00FF00 (verde)
Casilla(3) BackColor &HFF00FF (magenta)
Camino(0)
hasta
BackColor &H0080FF
(anaranjado)
Todos los elementos del
arreglo desde el 0
hasta el 21 tienen el
mismo valor
Camino(21
)
en la propiedad
BackColor.
Picture1 Visible False
Label1 Caption “META” Para Label2 tiene el
mismo valor
Alignment 2 (Centrado)
FontSize 13.5
BackStyle 0 (Transparente)
Label2 Caption “SALIDA” Las restantes
propiedades de Label2
son iguales a las de
Label1.
Para colocar los dibujos en los controles del arreglo Ficha podemos seguir
dos caminos. Durante el diseño seleccionaremos cada control del arreglo y
entrando a la ventana de propiedades haremos doble click sobre la
propiedad Picture del control. Al hacer esto aparecerá una ventana de
Introducción a la Programación Visual Página 110 de 168

búsqueda de archivos que nos servirá para localizar en el disco el archivo


donde está almacenado el dibujo que queremos colocar en nuestro control
Introducción a la Programación Visual 113
caja de imágenes. Este archivo puede estar almacenado en los formatos
.BMP (contiene un mapa de bits) .ICO (contiene un icono) o .WMF (contiene
un Metafile de Windows). El segundo camino para colocar un dibujo en una
caja de imágenes es escribir durante la ejecución del programa la
instrucción.
Ficha(0).Picture=LoadPicture(“C:\LIBRO\EJEMPLOS\DIBUJO01.BMP”)
La instrucción LoadPicture carga la imagen contenida en el archivo
indicado y la coloca en la propiedad Picture de la Caja de Imágenes
Ficha(0).
Podemos aprovechar la posibilidad de colocar un dibujo en una caja de
imágenes durante la ejecución para indicar cuando una casilla ha recibido
ya su ficha. Cuando esto suceda dibujaremos sobre la casilla una X. El dibujo
de la X lo encontramos en el archivo MISC20.ICO, que se forma parte de la
biblioteca de iconos que se suministra con Visual Basic. La instrucción para
cargarlo podría ser así:
Casilla(0).Picture=LoadPicture(“C:\VB\ICONS\MISC\MISC20.ICO”)
Sin embargo este método tiene un inconveniente, y es que para poder
ejecutar nuestro programa estamos obligados a tener en el disco el
archivo con el dibujo. Si el archivo MISC20.ICO es borrado o cambiado de
directorio nuestro programa no se ejecutará completamente.
Una alternativa viable sería colocar el dibujo en una caja de imágenes
adicional, la cual nos ocuparemos de ocultar manipulando su propiedad
Visible. En esa caja de imágenes colocaremos durante el diseño el dibujo
que necesitamos, y en el momento oportuno copiaremos el dibujo hacia la
caja de imágenes que representa a la casilla mediante una instrucción
como la siguiente:
Casilla(0).Picture = Picture1.Picture
Esa es precisamente la función de la caja de imágenes Picture1 que
aparece en la figura 7-3 ocupando la esquina inferior derecha del formulario
con una X en su interior, y de la que no habíamos dicha nada hasta ahora.
Ese mismo icono lo emplearemos durante el arrastre en lugar de la silueta. El
Introducción a la Programación Visual Página 111 de 168

procedimiento para colocar un icono en la propiedad DragIcon de un


objeto es el mismo que describimos para colocar un dibujo en la propiedad
114 Introducción a la Programación Visual
Picture de una caja de imágenes (o de un formulario). En nuestro caso
colocaremos el icono en la propiedad DragIcon de los cuatro elementos
del arreglo Fichas durante el diseño del interfaz. Cuando estemos
realizando el arrastre el puntero del ratón será sustituido por la X. El centro
de la X es lo que no se puede salir del camino.
Una vez realizado el diseño del interfaz, debemos determinar las tareas de
los diferentes objetos. Las fichas deben detectar cuándo el jugador las
pincha y dejarse arrastrar a partir de ese momento (de paso deben
desaparecer de la salida al iniciarse el arrastre). Para esto podemos
emplear el evento MouseDown si trabajamos con arrastre manual.
Las casillas de la meta deben detectar cuándo la ficha que se arrastra es
liberada sobre ellas. En ese caso, si es la ficha que le corresponde de
acuerdo al color debe colocarse una X en la casilla, de lo contrario debe
devolverse la ficha a la salida (es decir hacer visible la ficha) Para detectar
esto debemos emplear el evento DragDrop.
Los restantes controles, o sea Salida, Meta y el arreglo camino deben
detectar si el jugador por algún motivo termina el arrastre de la ficha sobre
ellos. En este caso la ficha debe volver al área de salida. Para detectar esta
situación también nos valdremos del evento DragDrop.
¿Y cómo saber si el jugador ha arrastrado la ficha fuera del camino? Muy
fácil, cuando esto suceda la ficha habrá entrado a la superficie descubierta
del formulario y por tanto provocará en él un evento DragOver. En este
caso mostraremos al jugador un mensaje indicándole el error cometido.
Seguimos preguntando. ¿Cómo saber que hemos ganado? También muy
fácil, si cuando comenzamos a arrastrar una ficha ocultamos su imagen en
el área de salida escribiendo False en su propiedad Visible, habremos
ganado cuando al colocar una ficha en la casilla que le corresponde,
podamos comprobar que todas las fichas estén ocultas. Para hacerlo,
incluiremos como parte del procedimiento de atención al evento DragDrop
de las casillas esta revisión.
Después de determinar las tareas y los eventos asociados a las mismas
Introducción a la Programación Visual Página 112 de 168

procederemos a escribir los procedimientos. Para el evento MouseDown de


las fichas escribiremos:
Sub Ficha_MouseDown (Index As Integer, Button As Integer, Shift As Integer, X
As Single, Y As Single)
Introducción a la Programación Visual 115
Ficha(Index).Visible = False ‘ Se esconde la imagen de la
‘ Ficha en el área de salida
Ficha(Index).Drag ‘ Se inicia el proceso de arrastre de la Ficha
End Sub
Para el evento DragDrop de las casillas el código será:
Sub Casilla_DragDrop (Index As Integer, Source As Control, X As Single, Y As
Single)
If Source.Index = Index Then
Casilla(Index).Picture = Picture1.Picture
If Gano() Then MsgBox "¡¡Felicitaciones, has terminado!!", 48, "El laberinto
de los colores"
Else
Source.Visible = True
End If
End Sub
Este procedimiento es muy interesante ya que en el tenemos que comparar
los índices de dos objetos que pertenecen a dos arreglos de controles
diferentes. Por un lado la casilla que recibe el evento identificada por su
nombre Casilla y por su índice Index, y por otro lado, la ficha que causa el
evento al ser liberada del arrastre sobre la casilla. Esta ficha esta
representada por la variable de objetos Source, que no tiene formato de
arreglo de controles ( no es Source(3) por ejemplo) Para conocer el índice
de esta ficha dentro de su arreglo debemos recurrir a su propiedad Index,
por esto realizamos la comparación If Source.Index = Index donde, como
dijimos, Source.Index representa el índice de la ficha dentro del arreglo de
las fichas mientras Index que es el primer parámetro que recibe el
procedimiento Casilla_DragDrop es el índice de la casilla dentro de su
arreglo. Si ambos índices coinciden significa que la ficha ha sido depositada
sobre la casilla correcta y se dibuja una X en esa casilla con la instrucción
Introducción a la Programación Visual Página 113 de 168

Casilla(Index).Picture = Picture1.Picture . A continuación se revisa si el juego


ha terminado y de ser así se emite un mensaje. Si los índices no coinciden, la
ficha no esta bien ubicada y por tanto se le hace visible de nuevo en el
área de salida, con la instrucción Source.Visible = True.
La función Gano determina si hemos culminado con éxito el juego. Se trata
de una función general o independiente de evento, que se coloca en el
área general de la ventana de código de nuestro formulario. Su contenido
será:
116 Introducción a la Programación Visual
Function Gano ( )
Dim C as Integer
C=0
For I = 0 To 3
If Ficha(I).Visible = False Then C=C + 1 ‘ Si la ficha no esta
‘ visible, la cuenta
Next
If C = 4 Then Gano = True Else Gano = False ‘ Si la cantidad de
End Function ’ fchas ocultas es 4 entonces se ha ganado el juego.
Para el evento DragOver del formulario escribiremos:
Sub Form_DragOver (Source As Control, X As Single, Y As Single, state As
Integer)
MsgBox "Te has salido del recorrido.", 16, "Laberinto"
‘ Un mensaje y la ficha vuelve a su lugar de origen
Source.Visible = True
End Sub
Las dos etiquetas Label1 y Label2 se han preparado con el fondo
transparente para que la etiqueta no se vea y el texto aparente estar
escrito directamente sobre el formulario. Para ser consecuentes con este
propósito si el objeto es desplazado sobre las etiquetas estas deben
reaccionar tal y como lo haría el formulario por tanto:
Sub Label1_DragOver (Source As Control, X As Single, Y As Single, State As
Integer)
Form_DragOver Source, X, Y, 0 ‘ Invoca el procedimiento
‘ de atención al evento DragOver del formulario
Introducción a la Programación Visual Página 114 de 168

End Sub
El procedimiento para Label2 resulta idéntico. (Se podían haber tratado
como un arreglo de etiquetas, ¿verdad?)
Liberar la ficha en cualquier lugar que no sea en las casillas de la meta es
incorrecto y por tanto la ficha debe ser visualizada nuevamente en el área
Introducción a la Programación Visual 117
de salida. Esto es válido para todos los controles que intervienen en el
juego, por tanto todos deben atender al evento DragDrop de la misma
manera:
Si la ficha se libera sobre alguna de las cajas de imagen que forman parte
del arreglo Camino:
Sub Camino_DragDrop (Index As Integer, Source As Control, X As Single, Y As
Single)
Source.Visible = True
End Sub
Si la ficha se libera sobre el área de meta donde no se encuentran las
casillas:
Sub Meta_DragDrop (Source As Control, X As Single, Y As Single)
Source.Visible = True
End Sub
Si la ficha se libera sobre el área de salida:
Sub Salida_DragDrop (Source As Control, X As Single, Y As Single)
Source.Visible = True
End Sub
Si la ficha se libera sobre alguna de las fichas que aún está en el área de
salida (que aún es visibles):
Sub Ficha_DragDrop (Index As Integer, Source As Control, X As Single, Y As
Single)
Source.Visible = True
End Sub
El menú del juego tan sólo tiene, como ya se dijo dos elementos ‘Nuevo
Juego’ y ‘Terminar’. El procedimiento para la opción ‘Nuevo Juego’ debe
ocuparse de volver a su estado inicial a los objetos que hayan podido
recibir modificaciones durante el juego. Los únicos objetos que se modifican
Introducción a la Programación Visual Página 115 de 168

son: en primer lugar las fichas que desaparecen del área de salida en la
medida en que son arrastradas exitosamente hasta las casillas de la meta; y
en segundo lugar las propias casillas que reciben una X cuando se deposita
118 Introducción a la Programación Visual
en ellas la ficha que les corresponde. El procedimiento del elemento de
menú Nuevo juego debe reparar dichas modificaciones. Lo hace así:
Sub Nuevo_Juego_Click ()
For I = 0 To 3 ‘ Para cada una de las fichas (o casillas)
Ficha(I).Visible = True ‘ Visualiza las fichas en el área de salida
Casilla(I).Picture = LoadPicture("") ‘ Elimina las X de las
Next ‘ casillas que las tuviesen
End Sub
El procedimiento para la opción ‘Terminar’ contiene una sola instrucción:
End.
Una vez escrito todo este código podemos comenzar a jugar con el
Laberinto de los Colores. Claro que aún nos falta un elemento. Habíamos
dicho que se jugaba contra tiempo. Es verdad, pero de eso nos ocuparemos
en el próximo capítulo. Por ahora seguiremos arrastrando controles!
Arrastre real.
En ocasiones, el problema que debemos resolver necesita que arrastremos
objetos completos, es decir que arrastremos las imágenes de los objetos y
no sus contornos. En tales situaciones resulta en extremo complicado
intentar atacar el problema empleando únicamente los eventos DragOver y
DragDrop y tendemos que emplear de nuevo los eventos simples del ratón,
o sea MouseDown, MouseUp y MouseMove.
Ya hemos mencionado a los rompecabezas como ejemplo de problema
donde nos enfrentamos a la necesidad de realizar el arrastre real. En efecto,
para colocar las piezas en su posición, y de forma tal que guarden
correspondencia con las que ocupan las posiciones vecinas es necesario
poder ver la pieza mientras la movemos y no observar su simple silueta.
Intentaremos resolver tal problema.
Para programar un rompecabezas, lo primero que debemos preparar es el
dibujo que separaremos en piezas. Esto nos servirá para ilustrar una fase en
la programación para Windows, que muchas veces se omite en los
Introducción a la Programación Visual Página 116 de 168

manuales y en los cursos de programación: el diseño gráfico previo a la


escritura del código. Para nuestro rompecabezas debimos preparar un
dibujo (también se puede buscar uno que ya esté elaborado). Como sólo se
Introducción a la Programación Visual 119
trata de un ejemplo preparamos un dibujo pequeño que sólo mide 300 pixels
de ancho por 200 pixels de alto y lo almacenamos en un archivo, al que
nombramos ROMPE.BMP. Ese dibujo puede verse en la figura 7-4.
Comencemos, una vez más, por el diseño del interfaz. Las piezas del
rompecabezas tendrán forma rectangular, y para representarlas
emplearemos, como es natural controles Caja de Imagen. Cuando el
rompecabezas se encuentra armado las fichas se encuentran colocadas
sobre el formulario conformando un tablero dividido en filas y columnas, que
resulta bastante similar a la formación de las fichas en el Juego del 15. Para
no hacer nuestro rompecabezas demasiado complicado tan sólo
emplearemos cuatro piezas, que se organizarán en dos filas y dos columnas,
como muestra la figura 7-4. Por supuesto, nuestros lectores pueden
modificar este ejemplo libremente, preparando sus propios dibujos y
dividiéndolos en tantas piezas como crean necesario. Al igual que hicimos
en el Juego del 15, manejaremos las piezas del rompecabezas como un
arreglo de controles, al que llamaremos ‘Pieza’.
Cada pieza debe recibir en su propiedad Picture un dibujo que contenga
una parte del dibujo original. Para hacer esto debemos cargar en nuestro
editor gráfico el dibujo que hemos elaborado. Una vez cargado debemos
seleccionar las áreas del dibujo que corresponden a cada una de las piezas,
y salvarlas una por una en archivos independientes. De esta forma
construiremos los archivos ROMPE0.BMP, ROMPE1.BMP, ROMPE2.BMP y
ROMPE3.BMP. Esta tarea puede resolverse perfectamente con el editor
gráfico ‘PaintBrush’ de Windows.
Al comienzo del juego, las piezas del rompecabezas se encuentran
ordenadas y podría resultar fácil arrastrar alguna de ellas y luego devolverla
a su posición. Sin embargo, cuando las fichas se desordenan, el jugador
debe tener alguna guía que le permita determinar donde, mas o menos,
ubicar las piezas. Con este fin colocaremos sobre el formulario una quinta
Caja de Imagen vacía, que jugará el papel del tablero sobre el cual se
Introducción a la Programación Visual Página 117 de 168

arma el rompecabezas. Este tablero, al que llamaremos ‘Fondo’ se muestra


en la figura 7-5.
120 Introducción a la Programación Visual
Nota. Al diseñar este interfaz
debemos tener cuidado de no
crear las cajas de imagen de las
piezas en el interior de la caja de
imagen del tablero. De hacerlo así,
las piezas estarían contenidas
dentro del tablero y no podríamos
lograr el efecto de desarmar el
rompecabezas de forma
convincente. Los cinco controles
deben colocarse directamente
sobre el formulario y luego
modificar convenientemente sus
dimensiones y su posición. Las piezas serán de forma rectangular y medirán
150 pixels de ancho (propiedad Width) y 100 pixels de altura (propiedad
Height), mientras el tablero también será un rectángulo, y medirá 300 pixels
de ancho por 200 de altura.
Los bordes del formulario los fijaremos, para que el usuario no pueda alterar
su forma durante el juego. Por la misma razón invalidaremos el botón que
permite maximizar la ventana. En todas las Cajas de Imagen sustituiremos
las unidades de medición implícitas de sus sistemas de coordenadas, o sea
los Twips, por las unidades físicas de la pantalla, los Pixels.
Figura 7-4. Interfaz del
Rompecabezas con las piezas en sus
posiciones.
Introducción a la Programación Visual 121
Para esto modificaremos las
propiedades ScaleMode de esos
controles. Este cambio es
necesario porque el graficador en
que realizamos los dibujos trabaja
Introducción a la Programación Visual Página 118 de 168

precisamente en pixels. Para


completar el interfaz
colocaremos en nuestro
formulario un menú horizontal con
los elementos ‘Opciones’ y
‘Ayuda’. En el menú vertical de
‘Opciones’ coloca-remos los
elementos ‘Desordenar’,
‘Ordenar’ y ‘Terminar’ y en el menú
vertical de ‘Ayuda’ pondremos los
elementos ‘Ayuda visual’ y
‘Créditos’.
A continuación mostramos la tabla con las principales propiedades de los
controles que forman parte del interfaz:
Objeto Propiedad Valor asignado Comentario
Form1 Caption “Rompecabezas”
BorderStyle 1 (borde simple fijo)
ScaleMode 3 (pixels)
MaxButton False Se invalida el botón
de maximizar
Fondo Top 10 Sobre este
rectángulo estarán
ubicadas las
(ImageBox
)
Left 10 piezas. Lo
colocaremos
centrado sobre el
Width 300 formulario a diez
pixels de distancia
de
Height 200 los bordes.
ScaleMode 3 (pixels)
Pieza(0) Top 10 Primera fila
Introducción a la Programación Visual Página 119 de 168

(ImageBox
)
Left 10 Primera columna
Figura 7-5. Interfaz del Rompecabezas
donde se observa la Caja de Imagen
empleada para representar el tablero.
122 Introducción a la Programación Visual
Width 150
Height 100
ScaleMode 3 (pixels)
Pieza(1) Top 10 Primera fila
(ImageBox
)
Left 150 Segunda columna
Width,
Height
Todas las Piezas tienen
los
mismos valores para
Width y Height.
ScaleMode 3 También tienen el Mismo valor para
ScaleMode
Pieza(2) Top 100 Segunda fila
(ImageBox
)
Left 10 Primera columna
Pieza(3) Top 100 Segunda fila
(ImageBox
)
Left 150 Segunda columna
Pasemos a determinar las tareas a realizar por cada control. Las Piezas
deben ser capaces de moverse físicamente cuando el usuario las arrastre y
una vez que sean liberadas del arrastre deben revisar si el rompecabezas
está armado, o sea, si todas las piezas están en la posición correcta (esto es
Introducción a la Programación Visual Página 120 de 168

lo mismo que tuvimos que hacer para el ‘Juego del 15’), en tal caso se
mostrará una caja de mensajes felicitando al jugador. Para realizar estas
tareas nos valdremos de los eventos MouseDown, MouseMove y MouseUp.
En este programa introduciremos una diferencia con respecto al ‘Juego del
15’. No permitiremos que el jugador mueva las piezas desde su posición
inicial. Sólo podrá moverlas una vez que las mismas se encuentren
desordenadas (para desordenarlas debe emplear el elemento
‘Desordenar’ del menú ‘Opciones’). Esto nos obligará a disponer de una
variable de estado accesible desde todo el formulario que contendrá la
información acerca del estado de orden de las piezas.
Las acciones de los distintos elementos del menú se explican casi todas por
si solas: ‘Desordenar’ como ya dijimos coloca las piezas en posiciones
aleatorias para que comience el juego. ‘Ordenar’ le permite al jugador
llevar todas las piezas de regreso a sus posiciones, en caso que no logre
hacerlo por si mismo. ‘Terminar’ finaliza el programa. ‘Ayuda Visual’
reconstruye por un momento la imagen para que el jugador se oriente, y
acto seguido la regresa al desorden. Por último ‘Créditos’ identifica al
producto y a sus desarrolladores. Como siempre cada uno de estas
Introducción a la Programación Visual 123
acciones sera desencadenada por el evento Click del elemento de menú
correspondiente.
A continuación mostramos una tabla con las principales propiedades de los
elementos de nuestro menú:
Caption Name Index Checked
“&Desordenar” Desordena
“&Ordenar” Ordena
“&Terminar” Fin
“&Ayuda Visual” Ayuda_Visual
“&Créditos” Creditos
Podemos pasar ahora a escribir el código. En el área de declaraciones
debemos ubicar la variable que emplearemos para saber si las piezas están
en orden. La declaración será:
Dim Desordenado As Integer
Para inicializar esa variable podemos emplear el procedimiento de
Introducción a la Programación Visual Página 121 de 168

atención al evento Load del formulario:


Sub Form_Load ()
Desordenado = False
Randomize
End Sub
La tarea de desordenar las piezas, que se ejecuta a partir de la selección
del elemento de menú desordenar, resulta muy sencilla:
Sub Desordena_Click ()
For I = 0 To 3 ‘ Para cada una de las fichas
X = Int(Rnd * 170) ‘ Se genera aleatoriamente un
‘ valor para su coordenada X (propiedad Left)
Y = Int(Rnd * 120) ‘ y otro para su coordenada Y
‘ (propiedad Top)
Pieza(I).Left = X ‘ Como se emplea la función
‘ RND para la generación aleatoria, se colocó
Pieza(I).Top = Y ‘ una instrucción Randomize en
‘ el procedimiento Form_Load
124 Introducción a la Programación Visual
Next
Desordenado = True ‘ Se coloca True en la variable,
‘ para indicar que las piezas han sido desordenadas.
End Sub
Ordenar las piezas cuando el jugador lo solicite seleccionando el elemento
de menú ‘Ordenar’ también es sencillo, al igual que hicimos para el ‘Juego
del 15’ a partir del índice de la Pieza podemos determinar su la fila y la
columna donde deba estar dentro del tablero, y conociendo esa fila y esa
columna podemos calcular las coordenadas en que debe estar la pieza
sobre el formulario y situarla allí. El código será así:
Sub Ordena_Click ()
For I = 0 To 3 ‘ Para cada pieza
Coordenadas_de_Pieza I, X, Y ‘ Se calculan las coordenadas
Pieza(I).Left = X ‘ de su posición original, cuando el
Pieza(I).Top = Y ‘ rompecabezas se encontraba ordenado, y
Next ‘ esos valores se colocan en sus propiedades Top y Left.
Introducción a la Programación Visual Página 122 de 168

Desordenado = False ‘ Se indica que las piezas no están


End Sub ‘ desordenadas
El procedimiento Coordenadas_de_Pieza recibe el índice de una piez a y
devuelve las coordenadas X y Y de su posición inicial sobre el formulario. Su
código es:
Sub Coordenadas_de_Pieza (Index, X, Y)
X = 150*(Index Mod 2) + 10
Y = 100*(Index \ 2) + 10
End Sub
En efecto, Index \ 2, es decir Índice \ Total de Columnas, devuelve el
número de la fila donde se encuentra ubicada la pieza se índice I, mientras
que (Index Mod 2), o sea Índice Mod Total de Columnas devuelve la
columna en que se encuentra situada la pieza de índice I. Una vez
determinados la fila y la columna en que se encuentra la pieza podemos
determinar su posición sobre el formulario por las expresiones:
X= 150 * Columna +10
Donde 150 es el ancho de la pieza y 10 la posición sobre el formulario de la
primera columna. Lo mismo sucede para la coordenada Y:
Introducción a la Programación Visual 125
Y= 100 * Fila + 10
Donde 100 es la altura de la pieza y 10 la posición sobre el formulario de la
primera columna.
El cálculo de las posiciones iniciales de las piezas lo hemos colocado en un
procedimiento general porque lo necesitaremos en var ias ocasiones a lo
largo de nuestro programa.
El procedimiento para atender la selección del elemento de menú
‘Terminar’ es el mismo que hemos empleado en programas anteriores:
Sub Fin_Click ()
End
End Sub
Después de elaborar estos procedimientos relativamente sencillos, estamos
en condiciones de pasar a desarrollar los procedimientos necesarios para
realizar el arrastre real de las piezas.
El evento de mayor importancia para la solución de este problema, el que
Introducción a la Programación Visual Página 123 de 168

tiene lugar mientras transcurre el arrastre es MouseMove, ya que para


arrastrar un objeto el ratón debe moverse continuamente. Esto último es
especialmente importante, ya que para poder resolver este problema
debemos comprender que durante el arrastre el evento MouseMove se va
a estar produciendo continuamente. Cada vez que el ratón realice un
pequeño desplazamiento, se producirá un evento MouseMove y, en
consecuencia, se ejecutará el procedimiento de atención a ese evento.
Ese procedimiento recibe (como se señalo al comienzo de este capítulo)
cuatro parámetros de los cuales tendrán capital importancia para la
resolución de nuestro problema, el primer parámetro, que indica que botón
del ratón se encuentra oprimido y los parámetros tercero y cuarto que
indican la posición (X y Y) del puntero del ratón sobre el objeto (en nuestro
caso la pieza) que es arrastrada.
Nota: En este ejemplo, como se trabaja con un arreglo de controles, todos
los parámetros se desplazan una posición hacia la derecha por la aparición
del índice. De tal forma los parámetros que nos interesan pasan a ser el
segundo, cuarto y quinto.
El valor del segundo parámetro (identificado como Button) nos permitirá
diferenciar un movimiento de arrastre de un movimiento simple del ratón
126 Introducción a la Programación Visual
sobre alguna de las piezas. Si el parámetro Button vale 0 significa que ningún
botón se encuentra oprimido, por tanto no se está realizando arrastre y por
tanto no debemos realizar ninguna acción sobre la posición de la pieza. En
cambio si su valor es 1, significa que esta oprimido el botón izquierdo, un 2
identifica al botón derecho y un 4 al botón central. Si están oprimidos varios
botones a la vez, el valor de Button es el resultado de la suma de los
números que identifican a los botones que estén oprimidos (por ejemplo si
se han oprimido los botones izquierdo y central simultáneamente Button
recibe el valor 5, o sea 1+4). En nuestro programa podríamos exigir que el
arrastre se realice oprimiendo el botón izquierdo, pero para hacer las cosas
más fáciles al jugador, permitiremos que arrastre oprimiendo cualquier
botón. Para lograr esto podemos escribir:
If Button = 0 Then Exit Sub
Pero recordemos que tampoco deseamos permitir al jugador mover las
Introducción a la Programación Visual Página 124 de 168

piezas si las mismas no han sido desordenadas, por tanto, aun cuando el
ratón se mueva con algún botón oprimido, si la variable Desordenado
contiene el valor False también debemos abandonar el procedimiento sin
modificar la posición de la pieza. Ambas condiciones se puede agrupar en
una misma línea mediante un operador OR. El resultado será:
If Button = 0 Or Not Desordenado Then Exit Sub
Ahora debemos pensar en como actualizar la posición de la pieza cada vez
que se produzca un evento MouseMove mientras se esté produciendo un
arrastre, o sea cuando algún botón esta oprimido (Button ¹ 0) y las piezas se
encuentran desordenadas (Desordenado = True).
Como ya dijimos, cada vez que se produzca un pequeño movimiento del
ratón sobre la pieza, se producirá un evento MouseMove. Nosotros
debemos aprovechar ese evento para modificar la posición de la pieza, de
acuerdo con la dirección en que se haya desplazado el puntero del ratón.
Para poder hacerlo necesitamos calcular cuantos pixels se movió el ratón
desde su posición anterior hasta la actual, tanto a lo largo del eje X como a
lo largo del eje Y, para con esas diferencias actualizar las propiedades Left y
Top de la pieza. Para calcular una diferencia de posición necesitamos
conocer dos posiciones: la posición actual del ratón sobre la pieza, que
podemos obtenerla de los parámetros X y Y del evento MouseMove, y la
posición anterior, que es la posición en que se encontraba el ratón sobre la
pieza en el momento de comenzar el arrastre. ¿Cómo obtener esa posición
inicial?
Introducción a la Programación Visual 127
Evidentemente MouseMove no nos informa ese valor, y evidentemente no
tiene forma de conocerlo. Sin embargo nosotros sí podemos obtener y
preservar ese valor. ¿Cómo? Muy sencillo, basta con analizar los eventos
que suceden durante nuestro programa. ¿Qué nos interesa conocer? La
posición del ratón sobre la pieza en el momento de comenzar el arrastre.
Preguntémonos entonces: ¿Cuándo comienza el arrastre? Cuando el
jugador oprime un botón del ratón sobre la pieza. ¿La pieza percibe algún
evento cuando se oprime un botón del ratón sobre ella? La repuesta es SI.
¿Cuál es ese evento? El evento MouseDown!!
La solución esta entonces al alcance de nuestras manos. En efecto el
Introducción a la Programación Visual Página 125 de 168

evento MouseDown también recibe como parámetros las coordenadas X y


Y del puntero del ratón. Estos son los datos que necesitamos! Pero como
esos datos se reciben en el procedimiento de atención al evento
MouseDown y nosotros necesitamos emplearlos en el procedimiento de
atención al evento MouseMove, tendremos que copiarlos en variables
declaradas a nivel de formulario, que puedan ser empleadas desde los dos
procedimientos. Para declararlas añadiremos en el área de declaraciones
de la sección general de nuestro formulario, donde ya habíamos declarado
la variable Desordenar, dos nuevas líneas:
Dim Desordenado As Integer
Dim X0 As Single
Dim Y0 As Single
Podemos escribir entonces el código del procedimiento de atención a
MouseDown:
Sub Pieza_MouseDown (Index As Integer, Button As Integer, Shift As Integer, X
As Single, Y As Single)
If Not Desordenado Then Exit Sub
X0 = X
Y0 = Y
End Sub
Es sencillo: si las piezas no están desordenadas se abandona el
procedimiento, de lo contrario se copia el contenido de los parámetros X y
Y en las variables X0 y Y0.
128 Introducción a la Programación Visual
Una vez disponibles las coordenadas de la posición inicial del puntero del
ratón sobre la pieza que se arrastra podemos escribir también el código
para el procedimiento de atención a MouseMove:
Sub Pieza_MouseMove (Index As Integer, Button As Integer, Shift As Integer, X
As Single, Y As Single)
If Button = 0 Or Not Desordenado Then Exit Sub
DX = X - X0 ‘ Se calcula la diferencia de posición para la
DY = Y - Y0 ‘ coordenada X y para la coordenada Y
Pieza(Index).Left = Pieza(Index).Left + DX ‘ y se actualiza la
‘ propiedad Left de la pieza
Introducción a la Programación Visual Página 126 de 168

Pieza(Index).Top = Pieza(Index).Top + DY ‘ también se


‘ actualiza la propiedad Top
End Sub
Si las piezas no están desordenadas o si ningún botón se encuentra oprimido
se abandona el procedimiento. De no ocurrir esto, se calculan las
diferencias DX y DY que indican el desplazamiento del puntero del ratón a lo
largo del eje X y del eje Y, y se actualizan las propiedades Left y Top de la
pieza adicionándoles estas diferencias. Al hacer esto la pieza se desplaza la
misma cantidad de pixels que se haya desplazado el ratón y por tanto se
logra el efecto visual del arrastre de la pieza.
Lo único que falta para completar con éxito el arrastre de la pieza es el
momento de liberar la pieza y terminar propiamente el arrastre. Cuando
termina el arrastre de una pieza es el momento de comprobar si todas las
piezas se encuentran ubicadas en las posiciones correctas, es decir si el
rompecabezas ya está armado. El evento que nos permitirá detectar que
ha sido liberado un botón del ratón es el evento MouseUp. El código para
atender este evento será:
Sub Pieza_MouseUp (Index As Integer, Button As Integer, Shift As Integer, X As
Single, Y As Single)
If Button = 0 Or Not Desordenado Then Exit Sub
If Armado( ) Then
A$ = "Felicitaciones !!!" + Chr$(13) + "Has armado el Rompecabezas"
MsgBox A$, 48, "Rompecabezas"
Desordenado = False
End If
End Sub
Introducción a la Programación Visual 129
Al igual que para MouseMove, si las piezas no están desordenadas se
abandona el procedimiento. En caso contrario se comprueba si el
rompecabezas ya esta armado por medio de la función Armado si la función
devuelve el valor True se exhibe una caja de mensajes y se coloca el valor
False en la variable Desordenado, para impedir que el jugador pueda
continuar arrastrando las piezas.
La función Armado compara las posiciones actuales de las piezas con las
Introducción a la Programación Visual Página 127 de 168

posiciones que deben ocupar cuando el rompecabezas se encuentra


armado, que se obtienen con el procedimiento Coordenadas_de_Pieza. Si
todas las piezas están en las posiciones debidas devuelve True , de lo
contrario False.
Function Armado ( )
Dim C As Integer
C=0
For I = 0 To 3
Coordenadas_de_Pieza I, X, Y ‘ Calcula la posición en que
‘debería estar la pieza
If Pieza(I).Left = X And Pieza(I).Top = Y Then C = C + 1
‘ la compara con la posición real
Next ‘ y si coinciden cuenta.
If C = 4 Then Terminado = True Else Terminado = False
End Function
Una vez escrito este código ya podemos comenzar a jugar con el
rompecabezas. Aunque en principio todo está bien, las primeras pruebas del
programa nos mostraron un hecho inesperado: colocar las piezas en la
posición exacta en que deben quedar, resulta extraordinariamente difícil!!
Claro está, la condición:
If Pieza(I).Left = X And Pieza(I).Top = Y Then C = C + 1
exige que la pieza este justamente en su lugar, y no un pixel mas a la
izquierda o a la derecha. Y ubicar un objeto con la precisión de un pixel
requiere de un control muscular notable. Para facilitar la tarea del jugador
pensamos que resultaría conveniente que el programa aceptara como
pieza bien ubicada a todas aquellas que se encuentren a una distancia de
hasta 5 pixels de su posición correcta.
Para calcular la distancia entre dos puntos debemos escribir una función
haciendo uso de la conocida fórmula matemática de la distancia:
130 Introducción a la Programación Visual
Function Distancia (X1, Y1, X2, Y2)
Distancia = Sqr((X1 - X2) ^ 2 + (Y1 - Y2) ^ 2)
End Function
Con esta función Distancia podemos modificar la función Armado
Introducción a la Programación Visual Página 128 de 168

sustituyendo la línea:
If Pieza(I).Left = X And Pieza(I).Top = Y Then C = C + 1
por:
If Distancia((Pieza(I).Left), (Pieza(I).Top), X, Y) < 5 Then C = C + 1
De esta forma resolvemos el problema de que el jugador no tenga que ser
tan preciso en la colocación de las piezas, pero al hacerlo vamos a crear
otro: informamos que el rompecabezas esta armado cuando visualmente se
puede apreciar que las piezas no están exactamente en sus lugares.
Para resolver este segundo problema debemos corregir la posición real de
las piezas. Cuando detectemos que una pieza esté a una distancia menor
que 5 pixels de su posición correcta modificaremos las propiedades Left y
Top de la pieza para colocarla en la posición correcta.
Pero la función Armado no es un buen lugar para realizar esta corrección, ya
que en Armado se revisan (y por tanto se intentarían corregir) las posiciones
de todas las fichas, cuando la única ficha cuya posición tiene sentido tratar
de corregir es la ficha que el jugador estaba arrastrando. Para referirnos
exclusivamente a esa ficha la corrección de la posición debe realizarse en
el procedimiento de atención al evento MouseUp:
Sub Pieza_MouseUp (Index As Integer, Button As Integer, Shift As Integer, X As
Single, Y As Single)
If Button = 0 Or Not Desordenado Then Exit Sub
Coordenadas_de_Pieza Index, X, Y ‘ Se calcula la posición
correcta de la pieza
If Distancia((Pieza(Index).Left), (Pieza(Index).Top), X, Y) < 5 Then
‘ Si la distancia entre la posición
Pieza(Index).Left = ‘ real y la posición correcta es menor que 5
Pieza(Index).Top = Y ‘ se modifican las propiedades Top y Left
End If ‘ para corregir la posición de la pieza.
If Armado() Then
Introducción a la Programación Visual 131
A$ = "Felicitaciones !!!" + Chr$(13) + "Has armado el Rompecabezas"
MsgBox A$, 48, "Rompecabezas"
Desordenado = False
End If
Introducción a la Programación Visual Página 129 de 168

End Sub
Como ya hemos corregido la posición de la pieza la función Armado podría
quedar como se encontraba al principio.
El factor de corrección 5 ha sido elegido por nosotros arbitrariamente.
Nuestros lectores pueden emplear otro cualquiera. Incluso, los invitamos a
incorporar un menú con diferentes factores de corrección para que el
jugador elija el grado de dificultad del juego. Esto puede hacerse siguiendo
el modelo del menú que preparamos en el ‘Juego del 15’ para controlar la
velocidad de la animación.
Por último nos dedicaremos a los procedimientos del menú ‘Ayuda’. En el
mismo hemos colocado dos elementos de menú, ellos son ‘Ayuda Visual’ y
‘Créditos’. Sobre los créditos no nos detendremos, pueden prepararse en la
misma forma en que elaboramos los créditos del ‘Juego del 15’ o del
‘Laberinto’.
Con la Ayuda Visual nos proponemos orientar al jugador si en un
determinado momento del juego no recuerda la ubicación correcta de las
piezas. Cuando el jugador seleccione este elemento de menú las piezas se
colocarán en la posición correcta durante un breve instante
(aproximadamente un segundo) y luego regresarán a su posición anterior.
Para poder hacer esto necesitaremos guardar las posiciones actuales de las
piezas en un arreglo, invocar el procedimiento Ordenar, esperar un segundo
y restaurar las piezas en sus posiciones.
Sub Ayuda_Visual_Click ()
For I = 0 To 3 ‘ Para cada una de las piezas
Pos(I).X = Pieza(I).Left ‘ almacenamos su posición, es
decir
Pos(I).Y = Pieza(I).Top ‘ los valores de sus propiedades
Left y
Next ‘ Top en el arreglo Pos
132 Introducción a la Programación Visual
Ordena_Click ‘ Para ordenar las piezas
aprovechamos
‘ este procedimiento
For K = 1 To 150000: Next ‘ Realizamos una espera
Introducción a la Programación Visual Página 130 de 168

For I = 0 To 3 ‘ Regresamos cada una de las


piezas a su
Pieza(I).Left = Pos(I).X ‘ posición anterior. Para
hacerlo
Pieza(I).Top = Pos(I).Y ‘ colocamos en sus propiedades
Left y
Next ‘ Top los valores que habíamos reguardado
en el arreglo Pos
Desordenado = True
End Sub
Para ordenar las piezas aprovechamos el procedimiento ‘Ordenar’ que ya
teníamos escrito. Ello nos obliga a colocar la línea:
Desordenado = True
al final de nuestro procedimiento, ya que ‘Ordenar’ coloca en esa variable
un valor False que de mantenerse nos hubiese impedido continuar
arrastrando las piezas.
Los valores de las posiciones de las piezas los reguardamos en el arreglo Pos,
que por su estructura delata pertenecer a un tipo definido por el usuario. En
efecto, para declarar este arreglo debemos disponer previamente de una
definición de tipo TYPE ... END TYPE.
Pero una definición de tipo no puede realizarse dentro de un formulario.
Para realizarla necesitaremos crear un módulo. Para hacerlo podemos
seleccionar la opción Módulo del menú Insertar en la versión 4.0 (New
Module del menú File en la 3.0) u oprimir el botón que tiene esa función en la
barra de herramientas de la ventana principal de Visual Basic. Una vez
creado el módulo accederemos a su ventana de código y en el área
general escribiremos:
Introducción a la Programación Visual 133
De esta forma dejamos declarado
el tipo Posicion, integrado por dos
campos: un número real de simple
precisión identificado como X y
otro número, también real de
simple precisión identificado
Introducción a la Programación Visual Página 131 de 168

como Y. El arreglo Pos si puede ser


declarado en el área de
declaraciones de nuestro
formulario. Allí debemos añadir la
línea:
Dim Pos(3) As Posicion
El control del tiempo transcurrido lo hemos realizado de forma tradicional,
mediante el empleo de un ciclo vacío o de espera, que por la velocidad de
la máquina en que trabajamos necesita realizar unas 150000 repeticiones
para garantizar una espera de aproximadamente un segundo.
Sin embargo, este método resulta sumamente ineficaz para el control del
tiempo, no sólo cuando se necesita realizar un control preciso del mismo,
sino inclusive, en casos como el que nos ocupa, donde nos interesa poco la
precisión. Aquí queremos esperar un segundo mas o menos, y no nos
molestaría espacialmente que fuesen dos o tres segundos en lugar de uno.
Este libro, así como los ejemplos que en el aparecen, han sido elaborados en
una PC 486 DX a 33MHz, o sea, una máquina bastante lenta para los
estándares actuales. Si en esta máquina necesitamos 150000 repeticiones
del ciclo de espera, ¿cuántas necesitaremos en un Pentium III a 700 MHz?
Para poder realizar un control estricto del tiempo es preciso que el lenguaje
de programación con que trabajemos ponga a nuestra disposición algún
recurso que nos permita desarrollar esta tarea exitosamente. En el próximo
capítulo estudiaremos los recursos que nos proporciona Visual Basic para
abordar estos problemas. En el próximo capítulo est aremos ... jugando con
el tiempo.
Figura 7-6. Ventana de código del
módulo MODULE1.BAS
134 Introducción a la Programación Visual
Capítulo 8. Jugando con el Tiempo.
Como señalamos en los últimos párrafos del capítulo anterior, el control del
tiempo es una tarea que no puede enfrentarse exitosamente si no se
dispone de los recursos apropiados. En nuestro caso Visual Basic nos
proporciona la vieja función TIME$, la misma que en los BASICs tradicionales
nos devuelve la hora actual, en una cadena de ocho caracteres con el
Introducción a la Programación Visual Página 132 de 168

formato “hh:mm:ss”. Esta función además del inconveniente de no poder


diferenciar intervalos inferiores a un segundo, cuenta también con el
inconveniente de dejar para el programador la tarea de descomponer la
cadena para poder determinar diferencias de tiempo entre dos
evaluaciones distintas de la función.
Para permitirnos un control más efectivo del tiempo, Visual Basic introduce
un control especial, dedicado a esta tarea. Se trata del control
Temporizador (Timer en inglés) este control tiene algunas características
muy particulares: en primer lugar sólo es capaz de detect ar un evento, que
es precisamente el transcurso de un determinado intervalo de tiempo. ese
evento también se denomina Timer. La segunda particularidad de este
control, es que no resulta visible durante la ejecución de los programas, por
lo que no es importante el lugar en que se le coloque durante el diseño del
interfaz, y también, como consecuencia de su invisibilidad, dispone de muy
pocas propiedades: NAME, INDEX (si se formara un arreglo de
temporizadores), TOP y LEFT (totalmente inútiles), TAG, ENABLED e INTERVAL.
Las de mayor importancia para nosotros serán las dos últimas.
La propiedad Interval nos permite establecer la magnitud del intervalo de
tiempo que va a ser controlado por el temporizador. Ese número debe ser
un entero largo positivo que se encuentre en el intervalo de 1 a 65535. La
unidad de medición del intervalo de tiempo es el milisegundo de forma que
el valor 1000 representa un segundo, mientras 10000 representa un minuto.
La posibilidad de diferenciar hasta los milisegundos representa una mejora
fabulosa, con respecto a la función TIME$.
La propiedad Enabled permite, al igual que en otros controles, activar o
desactivar la detección de eventos por parte del control. Cuando esta
propiedad recibe el valor True el control comienza a contar el tiempo y una
vez que ha transcurrido el intervalo fijado por la propiedad Interval, genera
un evento Timer, el cual debe ser atendido por nuestro programa. Pero la
cosa no queda ahí, mientras Enabled valga True el Temporizador continuará
Introducción a la Programación Visual 135
contando el tiempo, y generará un evento Timer cada vez que transcurra el
intervalo de tiempo establecido, es decir el evento Timer se estará
generando continuamente, lo cual puede ser conveniente en algunos
Introducción a la Programación Visual Página 133 de 168

casos, pero en otros puede resultar perjudicial. Si en algún momento


necesitáramos que el temporizador deje de controlar el transcurso del
tiempo, debemos colocar en su propiedad Enabled el valor False.
Incorporando temporizadores a nuestros programas.
A continuación pasaremos a resolver dos deudas que contrajimos a lo largo
del libro, tanto el ‘Rompecabezas’ como el ‘Laberinto’ necesitan del
control del tiempo. El ‘Rompecabezas’ para poder retirar la ayuda visual
después que permanezca en pantalla un segundo. cuando la misma. El
‘Laberinto’ para poder controlar el tiempo que tardó el jugador en
recorrerlo.
Controlando el tiempo en el ‘Rompecabezas’.
Para controlar el tiempo en el ‘Rompecabezas’ debemos comenzar por
colocar un control Temporizador sobre el formulario, como se muestra en la
figura 8-1. Como ya dijimos, no es importante el lugar en que se coloque el
Temporizador, ya que no será visible durante la ejecución del programa.
Como el nombre de la clase de los temporizadores es Timer, Visual Basic
identificara este Temporizador como Timer1 (propiedad Name)
136 Introducción a la Programación Visual
A continuación estableceremos los valores de las propiedades del
Temporizador. Como nos interesa que la ayuda visual permanezca en
pantalla durante un segundo asignaremos a la propiedad Interval el valor
1000 (1000 milisegundos = 1 segundo). Co mo no nos interesa que el tiempo
se controle desde el comienzo del programa, sino tan sólo a partir del
momento en que se coloca en pantalla la ayuda visual, asignaremos
durante el diseño el valor False a la propiedad Enabled del Temporizador.
A continuación modificaremos el procedimiento de atención al elemento
de menú ‘Ayuda Visual’. Eliminaremos el ciclo de espera y la restauración de
las piezas a sus posiciones originales, y en su lugar activaremos el control del
tiempo transcurrido. El procedimiento quedará así:
Sub Ayuda_Visual_Click
For I = 0 To 3 ‘ Se resguarda la posición real de la piezas
Pos(I).X = Pieza(I).Left
Pos(I).Y = Pieza(I).Top
Next
Introducción a la Programación Visual Página 134 de 168

Ordena_Click ‘ se colocan las piezas en las posiciones


Timer1.Enabled = True ‘ correctas y se activa el control
End Sub ‘ del tiempo
A continuación escribiremos el código para el evento Timer del
Temporizador:
Sub Timer1_Timer ()
Timer1.Enabled = False ‘ Se interrumpe el control del
For I = 0 To 3 ‘ tiempo y se devuelve las piezas a
Pieza(I).Left = Pos(I).X ‘ las posiciones que ocupaban
Pieza(I).Top = Pos(I).Y
Next
Desordenado = True ‘ Se indica que las piezas estan desordenadas
End Sub
Hemos dividido en dos partes el procedimiento original Ayuda_Visual_Click.
La primera parte que se ejecuta cuando el usuario selecciona el elemento
de menú ‘Ayuda Visual’ se ocupa de realizar la copia de las posiciones de
las piezas del rompecabezas en el arreglo Pos. Una vez hecho esto activa el
temporizador, colocando el valor True en su propiedad Enabled y termina.
Una vez que el temporizador ha sido activado, comienza a realizar el
control del tiempo transcurrido y cuando se completen los 1000
Introducción a la Programación Visual 137
milisegundos establecidos por la propiedad Interval el temporizador genera
su evento Timer. En el procedimiento de atención a este evento (el
procedimiento Timer1.Timer) completamos la tarea. Allí, ante todo se
desactiva el control del tiempo, y a continuación se restituyen las piezas a
las posiciones que ocupaban en el momento de solicitarse la ayuda visual.
Debemos desactivar el control del tiempo porque de no hacerlo así, el
procedimiento Timer1_Timer se ejecutará cada vez que transcurriera un
segundo, lo cual evidentemente no nos interesa que suceda. Este
procedimiento sólo debe poder ejecutarse cuando se haya ejecutado
previamente el procedimiento
Ayuda_Visual_Click.
De esta forma queda incorporado el control del tiempo en el
‘Rompecabezas’. Como puede apreciarse con facilidad, este mecanismo es
Introducción a la Programación Visual Página 135 de 168

mucho más cómodo y seguro que el ciclo de espera, o el empleo de la


función TIME$.
Controlando el tiempo en el ‘Laberinto de los Colores’.
En el caso del ‘Laberinto de los Colores’ debemos incorporar un
Temporizador para determinar el tiempo que tarda el jugador en llevar
todas las fichas hasta la Meta a través del laberinto. Debemos determinar
en que momento debemos activar el Temporizador, en que momento
debemos desactivarlo, que longitud tendrá el intervalo de tiempo que
deseamos controlar, y como vamos a medir el tiempo.
El conteo del tiempo del jugador debe comenzar una vez que el mismo
oprima el botón primario del ratón, para comenzar a arrastrar la primera
ficha. Por tanto la propiedad Enabled del Temporizador debe tener al
comienzo del programa el valor False y recibir el valor True cuando la
primera pieza detecte el evento MouseDown. Como las fichas forman un
arreglo de controles y además no afecta que la instrucción se repita,
colocaremos en al procedimiento de atención al evento MouseDown de la
ficha la instrucción:
Timer1.Enabled =True
El procedimiento quedará así:
138 Introducción a la Programación Visual
Sub Ficha_MouseDown (Index As Integer, Button As Integer, Shift As Integer, X
As Single, Y As Single)
Ficha(Index).Visible = False ’ Se oculta la ficha
Ficha(Index).Drag ‘ Comienza el arrastre
manual
Timer1.Enabled = True ‘ Se activa el Temporizador, comienza
End Sub ‘ el conteo del tiempo empleado por el
jugador
El conteo debe continuar hasta que se termine el juego, o sea, hasta que la
función Gano devuelva True . El valor de esta función se comprueba cada
vez que termina un arrastre exitosamente. Esto sucede cuando el jugador
libera una ficha sobre la casilla que le corresponde en la meta. Cuando esto
sucede la casilla de la meta detecta un evento DragDrop. Nosotros
modificaremos el procedimiento de atención a este evento para
Introducción a la Programación Visual Página 136 de 168

desactivar el control del tiempo:


Sub Casilla_DragDrop (Index As Integer, Source As Control, X As Single, Y As
Single)
If Source.Index = Index Then
Casilla(Index).Picture = Picture1.Picture
If Gano() Then
MsgBox "¡¡Felicitaciones, has terminado!!", 48, "El laberinto de los
colores"
Timer1.Enabled = False ‘ Se desactiva el Temporizador
End If
Else
Source.Visible = True
End If
End Sub
Para medir el tiempo nos limitaremos a contar los segundos transcurridos,
luego, ese total de segundos puede ser descompuesto fácilmente en
minutos y segundos. Lo único que necesitamos es declarar una variable
contador, que se incremente cada vez que transcurra un segundo. En el
área de declaraciones escribiremos:
Dim T As Integer
En una variable entera se puede almacenar un número positivo entre 1 y
32767. Creo que es suficiente 32767 segundos son algo más de 9 horas.
Nadie debe demorarse tanto!!
Introducción a la Programación Visual 139
Nuestro contador debe ser inicializado con el valor 0. Para lograr esto
debemos colocar la instrucción: T=0
en el procedimiento de atención al evento Load del formulario. Pero
también debe recibir el valor 0 cada vez que comience un nuevo juego.
Para garantizar esto debemos escribir la misma instrucción T=0 en el
procedimiento de atención al elemento de menú ‘Nuevo Juego’.
Para realizar el conteo cada un segundo colocamos en la propiedad
Interval del Temporizador el valor 1000 (1000 milisegundos = 1 segundo). De
esta forma cada vez que transcurra un segundo se producirá un evento
Timer. Escribamos entonces:
Introducción a la Programación Visual Página 137 de 168

Sub Timer1_Timer ()
T+1
End Sub
De esta forma mientras el temporizador este activado se realizará un
conteo en la variable T cada vez que transcurra un segundo.
Para informar sobre el tiempo empleado por el jugador para recorrer el
laberinto emplearemos la misma caja de mensajes con que lo felicitamos
en el procedimiento de atención al evento DragDrop de las casillas.
Debemos calcular primero la cantidad de minutos y la cantidad de
segundos transcurrida.
Los minutos transcurridos pueden calcularse así: Min = T \ 60, y los segundos
restantes Seg = T Mod 60. El procedimiento Casilla_DragDrop quedará
definitivamente así:
Sub Casilla_DragDrop (Index As Integer, Source As Control, X As Single, Y As
Single)
If Source.Index = Index Then
Casilla(Index).Picture = Picture1.Picture
If Gano() Then
Min = T \ 60
Seg = T Mod 60
A$ = "¡¡Felicitaciones, has terminado!!" + Chr$(13) + Chr$(13)
A$ = A$ + "Tiempo: " + Format$(Min, "#0") + " min. " + Format$(Seg, "#0")
+ " seg."
MsgBox A$, 48, "El laberinto de los colores"
Timer1.Enabled = False
End If
140 Introducción a la Programación Visual
Else
Source.Visible = True
End If
End Sub
La cadena de formato "#0" empleada en la función Format$ garantiza que si
el valor de las variables Min o Seg fuera 0, se escriba el ‘0’, de no emplearse
esta cadena de formato el valor 0 se convertiría en una cadena vacía.
Introducción a la Programación Visual Página 138 de 168

De esta forma hemos completado definitivamente el ‘Laberinto de los


Colores’ y de paso hemos mostrado como se puede realizar el cálculo del
tiempo transcurrido empleando para ello un Temporizador. A continuación
veremos otras interesantes posibilidades que brinda a nuestros programas el
control del tiempo.
Empleando el Temporizador para realizar esperas.
Con frecuencia los programas están obligados a realizar determinadas
esperas por uno u otro motivo. Una de las esperas más conocidas es la que
se realiza en las barras de botones de los programas de Microsoft Office . En
efecto, cuando el puntero del ratón se coloca sobre alguno de los botones
de la barra, se muestra en pantalla un pequeño cartel (una etiqueta) que nos
dice la función del botón. Un efecto similar preparamos nosotros en el
capítulo anterior para los diferentes botones de nuestra calculadora
elemental. Sin embargo, la información de los botones de Office incluye un
detalle sumamente elegante: A diferencia de nuestra calculadora, que
muestra la etiqueta con información inmediatamente después que el
puntero del ratón se coloca sobre alguno de los botones, cuando Office
detecta que el ratón se ha situado sobre un botón espera un breve lapso de
tiempo, y si una vez transcurrido ese tiempo todavía el puntero del ratón se
encuentra sobre el botón, exhibe la etiqueta con información acerca de la
función de ese botón.
Además de ser un detalle elegante, también resulta eficiente: sólo se
muestra la información, si el usuario coloca y mantiene, intencionalmente, el
puntero del ratón sobre el botón. Al hacerlo así se evita perder tiempo
mostrando información inútilmente, cada vez que el puntero se deslice, de
pasada sobre uno o más botones, que en ese momento no son de interés
ara el usuario.
El efecto es muy hermoso, y nos gustaría poder emplearlo en nuestra
calculadora elemental. Y realmente hacerlo no resulta nada complicado.
Introducción a la Programación Visual 141
Basta con colocar en el interfaz de nuestra calculadora un Temporizador.
Inicialmente el control del tiempo se encontrará inactivo
(Timer1.Enabled=False) y el intervalo de tiempo a controlar será de 300
milisegundos (Timer1.Interval =300)
Introducción a la Programación Visual Página 139 de 168

Recordemos que para colocar la información en la pantalla empleábamos


los eventos MouseMove de todos los objetos sobre los que queríamos
suministrar información. Cuando un objeto detectaba ese evento, en el
procedimiento de atención al mismo colocábamos la información en la
etiqueta oculta que habíamos preparado y a continuación hacíamos visible
dicha etiqueta. Por ejemplo revisemos el procedimiento de atención al
evento MouseMove para el botón Command1, donde se encuentra el signo
‘+’:
Sub Command1_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la suma."
‘ Se coloca la información en la etiqueta
Label4.Visible = True ‘ y se hace visible la etiqueta
End Sub
Para introducir la espera dividiremos también las tareas de este
procedimiento en dos partes. Dejaremos aquí lo que resulta particular para
este botón, es decir colocar la información en la etiqueta, y a continuación
activaremos el control del tiempo. Si transcurren los 300 milisegundos antes
de que se desactive el Temporizador, el procedimiento de atención al
evento Timer completará el trabajo, haciendo visible la etiqueta:
Sub Command1_MouseMove (Button As Integer, Shift As Integer, X As Single, Y
As Single)
Label4.Caption = "Con este botón realizamos la suma."
‘ Se coloca la información en la etiqueta
Timer1.Enabled = True ‘ y se activa el Temporizador
End Sub
Sub Timer1_Timer ()
Label4.Visible = True ‘ Se hace visible la etiqueta
End Sub
Si el ratón abandona el botón antes que transcurran los 300 milisegundos
debe desactivarse el temporizador para evitar que tenga lugar el evento
Timer y que se haga visible la etiqueta Label4. Habíamos determinado que
cuando el ratón salía fuera de los botones, se encontraba sobre el
142 Introducción a la Programación Visual
Introducción a la Programación Visual Página 140 de 168

formulario y por tanto provocaba el evento MouseMove del formulario. En


el procedimiento de atención a este evento nos limitamos a ocultar la
etiqueta Label4. Para lograr además la desactivación del Temporizador
debemos añadir una nueva línea a ese procedimiento, que quedaría así:
Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As
Single)
Label4.Visible = False ‘ Se oculta la etiqueta Label4
Timer1.Enabled = False ‘ Se desactiva el Temporizador
End Sub
Controlando la hora con el temporizador.
Otra de las posibilidades que pone a nuestra disposición el control
Temporizador, es la de realizar el control o monitoreo de la hora exacta, con
un mínimo de trabajo. Para ilustrar la explotación de esta posibilidad
desarrollaremos un programa al que denominaremos ‘Monitor de Mensajes’.
Un programa de este tipo resulta un excelente ayudante para aquellas
personas que se embeben tanto trabajando con la computadora, que
olvidan otras cosas que deben hacer. En efecto, este programa nos
permitirá almacenar, en una lista, el texto de uno, o varios mensajes, así
como la hora en que deseamos ver cada mensaje. Luego de colocar el
mensaje, podemos minimizar el programa y dedicarnos a trabajar en
cualquier otra aplicación con la tranquilidad de saber que, a la hora
señalada para cada mensaje, el programa monitor se ocupará de mostrarlo
en la pantalla. Ya no olvidaremos la hora de almorzar, ni la de tomar una
pastilla, y mucho menos la de una reunión importante, olvidos frecuentes en
los incondicionales de la informática. Por supuesto, además de colocar
mensajes en la lista, el programa permitirá al usuario revisar la lista de
mensajes cuando desee, y eliminar alguno de los mensajes, si así lo necesita.
Para comenzar procederemos a realizar el diseño del interfaz. En este caso
vamos a preparar un interfaz distribuido en dos formularios. Un formulario
principal, donde colocaremos la lista con todos los mensajes y el
temporizador que emplearemos para realizar el monitoreo del tiempo. El
mismo se muestra en la figura 8 -2.
Introducción a la Programación Visual 143
Sobre el formulario hemos colocado una etiqueta, que emplearemos para
Introducción a la Programación Visual Página 141 de 168

visualizar el cartel ‘Lista de Mensajes’ un Temporizador y un control con el


que hasta ahora no habíamos
trabajado: el control Lista. Este
control proporciona grandes
facilidades para el manejo de
listas de datos, así como para
seleccionar elementos dentro de
la lista.
Por medio de este control el
usuario de nuestro programa
podrá revisar la lista de mensajes,
y seleccionar los que desea
modificar o eliminar. El nombre de
la clase de controles Lista es ‘List’,
por tanto Visual Basic va a
identificar este control como List1 (propiedad Name).
También hemos colocado un menú horizontal con el elemento ‘Mensajes’. A
partir de este elemento se despliega un menú vertical con los elementos
‘Incorporar Mensaje’, ‘Modificar Mensaje/Hora’, ‘Eliminar Mensaje’ y
‘Terminar’. El elemento de menú ‘Incorporar Mensaje’ nos permite agregar
un nuevo mensaje a la lista, el elemento ‘Modificar Mensaje/Hora’ permitirá
editar un mensaje de la lista, variando su texto, o la hora en que debe
presentarse. Por último ‘Eliminar Mensaje’ permite remover un mensaje de la
lista.
Los mensajes que colocaremos en la lista serán cadenas de caracteres que
contendrán la hora y el texto del mensaje, con el siguiente formato: “hh:mm
texto del mensaje” . Es decir los cinco primeros caracteres contendrán la
hora en que debe mostrarse el mensaje, seguidos por un espacio en blanco
y a continuación el texto del mensaje. Por ejemplo: “12:30 Hora de
Almorzar!!!”
A continuación presentamos una tabla con las propiedades más
significativas de los objetos del formulario principal.
Objeto Propiedad Valor asignado Comentario
Form1 Caption “Monitor de
Introducción a la Programación Visual Página 142 de 168

Mensajes”
BackColor &H00C0C0C0 (gris)
Figura 8-2. Interfaz del ‘Monitor de
Mensajes’ Formulario principal.
144 Introducción a la Programación Visual
MaxButton False Para que el usuario no
pueda modificar
BorderStyl
e
1 (Borde simple fijo) las dimensiones del
formulario.
Label1 Caption “Lista de Mensajes”
List1 Sorted True Los elementos de la lista se
ordenan de forma
automática. Como el
mensaje comienza con la
hora, esto hará que queden
ordenados de acuerdo a la
hora.
Timer1 Enabled False No nos interesa controlar el
tiempo desde el comienzo
del programa.
Interval 60000 Se controlará cada minuto.
También presentamos la tabla con las principales propiedades de los
elementos del menú:
Caption Name Index Checked
“&Incorporar Mensajer” Incorporar
“&Modificar
Mensaje/Hora”
Modificar
“&Eliminar Mensaje” Eliminar
“&Terminar” Fin
Las tareas a desarrollar en este formulario son las que están asociadas a los
elementos de menú y la que debe realizar el temporizador: chequear cada
Introducción a la Programación Visual Página 143 de 168

vez que transcurra un minuto si corresponde mostrar alguno de los mensajes


de la lista. Ningún otro objeto de este formulario debe desarrollar tareas
propias.
Pasemos entonces a elaborar los procedimientos necesarios. Para resolver
la tarea de incorporar un nuevo mensaje este formulario tan sólo debe
cargar y colocar en pantalla al segundo formulario, que es quién se ocupará
de hacer el trabajo. Ahora bien, como el segundo formulario también será
empleado al atender la tarea del elemento de menú ‘Modificar Mensajes’
resulta necesario transferirle alguna información que le permita saber quién
lo ha ejecutado para actuar en consecuencia. Para ello definiremos una
variable global, a la que identificaremos como Opcion . Para definir una
Introducción a la Programación Visual 145
variable global tendremos que crear un módulo y en su área de
declaraciones escribir:
Global Opcion As Integer
Luego regresando a la ventana de código de nuestro formulario, podremos
escribir el procedimiento para atender a la selección del elemento de
menú ‘Incorporar Mensaje’
Sub Incorporar_Click ()
Opcion = 1 ‘El valor 1 identificará la opción ‘Incorporar Mensaje’
Form2.Show ‘ Se carga muestra el segundo formulario
Timer1.Enabled = True ‘ Se activa el monitoreo del tiempo
End Sub
La atención al elemento de menú ‘Modificar Mensaje’ resulta más
compleja, ya que es necesario determinar si algún elemento de la lista ha
sido seleccionado por el usuario, y en ese caso cargar el segundo
formulario. Nos ayudará en esta tarea el control Lista, ya que una de sus
propiedades ListIndex contiene el índice del elemento que se encuentre
seleccionado, y si ninguno se encuentra seleccionado contiene el valor -1.
Revisando esta propiedad se vuelve muy fácil resolver esta tarea. Por
último, para indicarle al segundo formulario que ha sido cargado desde este
procedimiento colocaremos en la variable Opcion el valor 2.
Sub Modificar_Click ()
If List1.ListIndex = -1 Then ‘ Si en la lista no hay un elemento
Introducción a la Programación Visual Página 144 de 168

A$ = "Para modificar un mensaje, primero debe seleccionarlo" + Chr$(13)


‘ seleccionado
A$ = A$ + "en la lista. Seleccionelo y repita la operación."
MsgBox A$, 16, "Modificar Mensajes. Problemas."
‘ se emite un mensaje de
advertencia.
Else ‘ De lo contrario
Opcion = 2
Form2.Show ‘ Se carga el segundo formulario
End If
End Sub
El procedimiento para atender el elemento de menú ‘Eliminar Mensaje’
resulta bastante similar al anterior. En efecto, también se debe comprobar
que se encuentre seleccionado un elemento de la lista, y en ese caso
eliminarlo. Para eliminar un elemento de una lista debemos emplear el
146 Introducción a la Programación Visual
método RemuveItem del control Lista, el cual necesita un parámetro donde
se indique el índice del elemento que se desea eliminar. Como queremos
eliminar el mensaje que el usuario haya seleccionado la propiedad ListIndex
nos proporcionará esa información. Introduciremos además una prevención
adicional: si la lista esta vacía abandonaremos el procedimiento (podría
haberse emitido también un mensaje en este caso pero no lo creímos
necesario, si nuestros lectores lo estiman pertinente pueden añadir dicho
mensaje). Para saber si la lista está vacía nos valdremos de la propiedad
ListCount, que contiene precisamente la cantidad de elementos de la lista.
El procedimiento quedará así:
Sub Eliminar_Click ()
If List1.ListCount = 0 Then Exit Sub
‘ Si la lista está vacía se abandona el
procedimiento
If List1.ListIndex = -1 Then ‘ Si en la lista no hay un elemento
A$ = "Para eliminar un mensaje, primero debe seleccionarlo"+ Chr$(13)
‘ seleccionado
A$ = A$ + "en la lista. Seleccionelo y repita la operación."
Introducción a la Programación Visual Página 145 de 168

MsgBox A$, 16, "Eliminar Mensajes. Problemas."


‘ se emite un mensaje de advertencia.
Else ‘ De lo contrario
List1.RemoveItem List1.ListIndex
‘ Se elimina el elemento
seleccionado
If List1.ListCount =0 then Timer1.Enabled =False
‘ Si la lista ha quedado vacía se desactiva el control del
tiempo
End If
End Sub
Para optimizar el empleo de los recursos del sistema, cada vez que
eliminamos un mensaje de la lista comprobamos si la misma ha quedado
vacía. En ese caso desactivamos el control del tiempo, colocando en la
propiedad Enabled del temporizador el valor False.
El procedimiento para atender el elemento de menú ‘Terminar’ es similar al
que hemos escrito en otros programas: tan solo contiene la instrucción End.
Sólo nos faltaría el procedimiento más interesante de este formulario: el que
atiende al evento Timer del temporizador, pero vamos a dejarlo para el
final, lo desarrollaremos una vez que hayamos terminado de elaborar los
Introducción a la Programación Visual 147
procedimientos del segundo formulario. Este segundo formulario, que se
ocupará de permitir la entrada de los mensajes tendrá la siguiente
apariencia visual:
A continuación presentamos una tabla con las propiedades más
significativas de los objetos de este formulario:
Objeto Propiedad Valor asignado Comentario
Form2 Caption “Incorporar Mensaje”
BackColor &H00C0C0C0 (gris)
MaxButton False Para que el usuario
no pueda
modificar
BorderStyl
e
Introducción a la Programación Visual Página 146 de 168

1 (Borde simple fijo) las dimensiones del


formulario.
Label1 Caption “Lista de Mensajes”
Label2 Caption “Hora en que se mostrará
el mensaje”
Label3 Caption “horas (0-23)”
FontSize 9.75
Label4 Caption “minutos (0-59)”
FontSize 9.75
Text1 Text “”
Text2 Text “”
Text3 Text “”
Command1 Caption “Aceptar”
148 Introducción a la Programación Visual
Command2 Caption “Cancelar”
Como es fácil comprender la caja de texto Text1 servirá para que el usuario
escriba el texto del mensaje, mientras en las cajas de texto Text2 y Text3
podrá escribir, respectivamente, la hora y los minutos en que desea que se
le muestre el mensaje. Para facilitar el trabajo del usuario hemos colocado
junto a los controles Text2 y Text3 dos controles Spin que permitirán
modificar las horas y los minutos sin necesidad de escribir en las cajas de
texto.
El botón de órdenes Command1 tendrá la tarea de incorporar el mensaje a
la lista y cerrar la ventana del formulario cuando el usuario este conforme
con el mensaje, mientras que el botón de órdenes Command2 tendrá la
tarea de cerrar la ventana del formulario si el usuario decide cancelar la
acción.
Para comenzar v eamos que debe suceder cuando se carga el formulario. La
caja de texto Text1 debe aparecer vacía, mientras en Text2 y Text3 deben
aparecer la hora y los minutos actuales, los que pueden extraerse de la
función TIME$. El procedimiento Form2.Load quedaría así:
Sub Form_Load ()
Text1.Text = “”
Text2.Text = Mid$(Time$, 1, 2)
Introducción a la Programación Visual Página 147 de 168

‘Se toma la subcadena correspondiente a la hora en TIME$


Text3.Text = Mid$(Time$, 4, 2)
‘Se toma la subcadena correspondiente a los minutos en
TIME$
End Sub
Al obrar así, estamos garantizando que los valor iniciales que mostraremos
para las horas y los minutos sean valores válidos. Es decir las horas estarán
entre 0 y 23 y los minutos entre 0 y 59. Más adelante, cuando el usuario
modifique las horas y los minutos, tendremos que preocuparnos porque los
valores resultantes también sean válidos.
Cuando el usuario realice dichas modificaciones por medio de los controles
Spin nuestra tarea resulta muy sencilla. Los controles Spin generan dos
eventos SpinUp cuando se selecciona la flecha que apunta hacia arriba y
SpinDown, cuando se selecciona la flecha que apunta hacia abajo. Veamos
que hacer cuando el usuario acceda al control Spin1 que modifica la hora:
Introducción a la Programación Visual 149
Sub Spin1_SpinDown ()
Hor = Val(Text2.Text) ‘ Se transforma a valor numérico
If Hor = 0 Then Hor = 23 Else Hor = Hor - 1
‘ Se decrementa con rotación
Text2.Text = Format$(Hor, "0#")
End Sub
Vamos a emplear la técnica de rotación por el intervalo de valores. En el
caso del evento SpinDown debemos decrementar la hora. Tomaremos el
valor actual de la hora y lo compararemos con el límite inferior, es decir
cero, si la hora es mayor, se decrementa en 1, de lo contrario, si es cero, se
le asigna el valor máximo de la hora es decir 23. Luego se coloca el
resultado en la caja de texto. La cadena de formato “0#” garantiza que el
resultado sea una cadena de dos caracteres, adicionando un “0” por la
derecha cuando el resultado es menor. Esto lo hacemos para guardar
compatibilidad con el formato de hora que emplea la función TIME$, que
siempre dedica dos caracteres a esta información cualquiera sea su valor.
En el procedimiento de atención al evento SpinUp también se emplea la
técnica de rotación, pero en sentido inverso. Se compara el valor actual
Introducción a la Programación Visual Página 148 de 168

con el extremo superior del intervalo (23), de no ser igual se incrementa, y


de ser igual se le asigna el valor del extremo inferior (0).
Sub Spin1_SpinUp ()
Hor = Val(Text2.Text) ‘ Se transforma a valor numérico
If Hor = 23 Then Hor = 0 Else Hor = Hor + 1
‘ Se incrementa con rotación
Text2.Text = Format$(Hor, "0#")
End Sub
Los procedimientos del control Spin2 que controla el valor de los minutos en
la caja de texto Text3, son muy similares, sólo cambia el límite superior, que
para los minutos es 59.
Sub Spin2_SpinDown ()
Min = Val(Text3.Text)
If Min = 0 Then Min = 59 Else Min = Min - 1
Text3.Text = Format$(Min, "0#")
End Sub
Sub Spin2_SpinUp ()
Min = Val(Text3.Text)
If Min = 59 Then Min = 0 Else Min = Min + 1
150 Introducción a la Programación Visual
Text3.Text = Format$(Min, "0#")
End Sub
Aquí también nos preocupamos por completar con un cero por la derecha,
para garantizar que el resultado sea una cadena de dos caracteres, tal y
como ocurre en la función TIME$. La razón de obrar así no es caprichosa, si
almacenamos nuestra hora con un formato similar al que emplea la función
TIME$ para la hora actual nos resultará muy fácil comparar nuestra hora con
la hora actual durante el monitoreo que realizará el temporizador.
Más complicado resulta controlar los valores de horas y minutos cuando el
usuario accede a escribirlos directamente dentro de las cajas de texto.
Para comenzar procuraremos evitar que el usuario escriba caracteres que
no representen dígitos. Para ello nos valdremos del evento KeyPress de las
cajas de texto, tal como hicimos en el capítulo cuatro cuando
desarrollamos la sumadora elemental.
Introducción a la Programación Visual Página 149 de 168

Sub Text2_KeyPress (KeyAscii As Integer)


If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 0
End Sub
Sub Text3_KeyPress (KeyAscii As Integer)
If KeyAscii < 48 Or KeyAscii > 57 Then KeyAscii = 0
End Sub
Con esto garantizamos que los valores que se muestren en las cajas de
texto Text2 y Text3 no contengan caracteres extraños, pero no aseguran ni
que los valores numéricos se encuentren dentro de los rangos permitidos, ni
que se representen en cadenas de dos caracteres de longitud. Podríamos
pensar en emplear el evento Change para resolver esta situación, pero no
resulta totalmente conveniente. La razón es simple, este evento se produce
cada vez que el usuario modifica el contenido de la caja de texto, por
tanto se va a reducir varias veces antes que el usuario de por terminada su
escritura de las horas o los minutos y abandone la caja de texto. Puede
suceder perfectamente que mientras el usuario esta editando dentro de la
caja de texto, el contenido de esta se encuentre en una situación ilícita
(bien sea porque excede el límite máximo del intervalo o porque sólo ha
quedado un carácter en el texto. Si atendiésemos esta situación con el
evento Change, el usuario sería advertido innumerables veces mientras
trabaja, sin darle oportunidad a terminar su trabajo. De esta forma nuestro
programa se tornaría fastidioso para el usuario, lo que resulta impermisible
Introducción a la Programación Visual 151
trabajando para una plataforma como Windows donde la atención al
usuario tiene la más alta prioridad.
Descartado pues el evento Change, debemos buscar otra vía para resolver
esta situación. Si no debemos actuar mientras el usuario está editando
tendremos que esperar a que termine de editar, pero... cómo saber cuándo
el usuario termina de editar? Muy fácil, cuando deje la caja de texto y pase
a trabajar con otro control del formulario. En ese caso el control que recibe
el foco detectará el evento GotFocus mientras el control que lo pierde,
nuestra caja de texto detectará un evento LostFocus. Escribiremos código
para ese evento:
Sub Text2_LostFocus ()
Introducción a la Programación Visual Página 150 de 168

Hor = Val(Text2.Text)
‘ Se transforma la cadena con la hora a valor numérico
If Hor > 23 Then ‘ Si esta fuera del intervalo permitido (de 0 a 23)
MsgBox "Elvalor de las 'horas' no es válido", 16, "Problemas" ‘ Se
emite un mensaje de advertencia
Text2.SetFocus ‘ y se devuelve el foco a la caja de texto
Text2.SelStart = 0
‘ Además, se presenta el contenido de la caja de texto como
Text2.SelLength = Len(Text2.Text) ‘ texto seleccionado
Else ‘ De lo contrario, si el valor esta en el intervalo permitido
Text2.Text = Format$(Hor, "0#")
‘ se ajusta la longitud de la hora a dos caracteres
End If
End Sub
Como señalan los comentarios, si el valor de la hora excede el límite
máximo del intervalo se muestra una caja de mensajes con una
advertencia y a continuación se regresa el foco a la caja de texto
ejecutando su método SetFocus. Para hacer las cosas mas fáciles al usuario
vamos, además, a mostrar el texto como texto seleccionado. Para ello nos
valdremos de las propiedades SelStart y SelLength de la caja de textos.
SelStart indica la posición en que comienza el texto seleccionado, le
asignaremos el valor 0, es decir el inicio del texto. SelLenhgt indica la
longitud del texto seleccionado y le asignaremos la longitud de todo el
texto que esta en la caja. No nos preocupamos por controlar el límite
inferior porque el usuario no puede escribir números negativos, ya que el
procedimiento de atención al evento KeyPress impide la entrada del signo
“-”.
152 Introducción a la Programación Visual
Para la caja de texto Text3 el tratamiento resulta similar:
Sub Text3_LostFocus ()
Min = Val(Text3.Text)
If Min > 59 Then
MsgBox "El valor de los 'minutos' no es válido", 16, "Problemas"
Text3.SetFocus
Introducción a la Programación Visual Página 151 de 168

Text3.SelStart = 0
Text3.SelLength = Len(Text3.Text)
Else
Text3.Text = Format$(Min, "0#")
End If
End Sub
Nos corresponde por último atender a los eventos Click de los botones de
órdenes. La tarea que debe realizar el botón de órdenes Command2
(“Cancelar”) es muy simple: cerrar la ventana del formulario sin incorporar el
mensaje a la lista. En consecuencia su procedimiento de atención será:
Sub Command2_Click ()
Unload Form2
End Sub
La tarea del botón de órdenes Command1 es algo más compleja, ya que
antes de cerrar la ventana del formulario debe componer el mensaje e
incorporarlo a la lista. Para componer el mensaje concatenaremos los
contenidos de las cajas de texto Text2, Text3 y Text1, en ese orden, para
formar una cadena de caracteres con el formato “hh:mm mensaje” es decir
los dos primeros caracteres contendrán la hora, el tercer carácter el
símbolo “:” los caracteres cuarto y quinto contendrán los minutos, el sexto
un espacio en blanco, y a continuación se colocará el texto del mensaje.
Sub Command1_Click ()
Mensaje = Text2.Text & ":" & Text3.Text & " " & Text1.Text ‘ Se
compone el mensaje
Form1!List1.AddItem Mensaje ‘ Se adiciona a la lista
Unload Form2 ‘ y se cierra la ventana
End Sub
Para incorporar el mensaje a la lista empleamos el método AddItem del
control lista List1, pero como ese control se encuentra en el formulario Form1
y este procedimiento se encuentra en el procedimiento Form2, debemos
incluir el nombre del formulario en la invocación. Cuando un control es
Introducción a la Programación Visual 153
invocado desde otro formulario debe emplearse como separador entre el
nombre del formulario y el nombre del control un signo de admiración “!”.
Introducción a la Programación Visual Página 152 de 168

No es necesario que nos preocupemos por el orden de los mensajes dentro


de la lista, porque al colocar en su propiedad Sorted el valor True obligamos
al control Lista a ocuparse de esa tarea. La lista será entonces ordenada
alfabéticamente (de acuerdo a la tabla ASCII) y como hemos mantenido
en todos los mensajes el formato “hh:mm mensaje” los mismos se ordenarán
de acuerdo a la hora. De no haberlo hecho así, no lograríamos el efecto del
ordenamiento, ya que mientras la cadena “07:30 Hora de ir a la escuela” es
menor y se sitúa delante de “12:30 Hora de almo rzar!!!” porque comienza
con “0” la cadena “7:30 Hora de ...” resulta mayor y se situaría detrás de
“12:30 Hora de ...” lo que resultaría desastroso para la estética de nuestro
programa.
Hasta ahora hemos trabajado este formulario pensando tan sólo en su
ejecución por el elemento de menú ‘Incorporar Mensaje’ del formulario
principal. Sin embargo debemos recordar que también puede ser
ejecutado por el elemento de menú ‘Modificar Mensaje’. En tal caso habrá
algunas diferencias en la momento de iniciar el formulario y en el momento
de almacenar el mensaje. Esto nos obliga a modificar ligeramente los
procedimientos Form_Load y Command1_Click para que actúen de
acuerdo a la opción del menú que haya ejecutado el formulario.
Recordemos también que la variable global Opción informa acerca de qué
elemento de menú ha causado la ejecución de este formulario (1-
‘Incorporar Mensaje’ 2-‘Modificar Mensaje’)
Comenzaremos por el procedimiento Form_Load. Cuando se carga este
formulario para modificar mensajes es necesario colocar en las cajas de
texto la información del mensaje seleccionado, para que el usuario pueda
observarla y modificarla con comodidad. Para hacer esto será necesario
operar con el texto del mensaje seleccionado, que se encuentra
almacenado en el control lista List1.
Para acceder a un elemento de una lista debemos emplear la propiedad List
del control lista. Esta propiedad se comporta como un arreglo, con un índice
que indica la posición del elemento dentro de la lista. Al primer elemento
corresponde el índice 0 y el índice del último elemento se puede calcular
empleando la propiedad ListCount (cantidad de elementos de la lista) como
List1.ListCount-1. En nuestro caso necesitamos trabajar con el elemento que
Introducción a la Programación Visual Página 153 de 168

está seleccionado, y como ya dijimos el índice del elemento seleccionado


se encuentra en la propiedad ListIndex. De esta forma los dos primeros
154 Introducción a la Programación Visual
caracteres del elemento seleccionado se pueden obtener mediante la
instrucción:
A$ = Mid$( List1.List(List1.ListIndex), 1, 2)
Accedemos a la propiedad List empleando como índice a la propiedad
ListIndex. De esa forma obtendremos el texto del mensaje seleccionado.
Luego la función MID$ se ocupa de extraer los dos primeros caracteres. En
esos dos primeros caracteres se encuentra la hora de mostrar el mensaje. En
los caracteres cuarto y quinto se encuentran los minutos, y a partir del
séptimo, el texto del mensaje. El procedimiento Form_Load quedará así:
Sub Form_Load ()
If Opcion = 1 Then ‘ Invocado por ‘Incorporar Mensaje’
Form2.Caption = "Incorporar Mensaje"
Text1.Text = ""
Text2.Text = Mid$(Time$, 1, 2) ‘ Se coloca en Text2.Text la hora
Text3.Text = Mid$(Time$, 4, 2) ‘ Se coloca en Text3.Text los minutos
Else
Form2.Caption = "Modificar Mensaje"
‘ Invocado por ‘Modificar Mensaje’
I = Form1.List1.ListIndex
‘ I recibe el índice del mensaje seleccionado
Text1.Text = Mid$(Form1!List1.List(I), 7)
‘ Se toma el texto del mensaje seleccionado
Text2.Text = Mid$(Form1!List1.List(I), 1, 2)
‘ Se toma la hora del mensaje seleccionado
Text3.Text = Mid$(Form1!List1.List(I), 4, 2)
‘ Se toman los minutos del mensaje seleccionado
End If
End Sub
Como un detalle estético incluimos la modificación del título del formulario
en dependencia del elemento de menú que haya causado su ejecución.
La modificación al procedimiento Command1.Click es aún más sencilla. Lo
Introducción a la Programación Visual Página 154 de 168

que se pretende es modificar un elemento que ya está en la lista, no añadir


uno nuevo, pero no existe ningún método de la lista que permita hacer eso
directamente, de modo que tendremos que eliminar el elemento
seleccionado con el método RemoveItem y luego incorporar el elemento
modificado por medio del método AddItem. El procedimiento queda así:
Sub Command1_Click ()
Introducción a la Programación Visual 155
Mensaje = Text2.Text & ":" & Text3.Text & " " & Text1.Text
If Opcion = 2 Then Form1!List1.RemoveItem Form1.List1.ListIndex
Form1!List1.AddItem Mensaje
Unload Form2
End Sub
Si la variable global Opcion contiene el valor 2, antes se elimina el
elemento seleccionado. Tanto este procedimiento como el anterior se
encuentran en el formulario Form2 y hacen referencia al control List1 del
formulario Form1. Por eso se incluye el nombre del formulario como parte de
la referencia.
Hemos concluido el trabajo con el segundo formulario, podemos regresar a
concluir lo que nos faltaba del primero: el procedimiento de atención al
evento Timer del temporizador. Este evento se detectará una vez por
minuto, ya que colocamos en la propiedad Interval del temporizador el
valor 60000. Cada vez que se produzca este evento, debemos revisar todos
los mensajes de la lista, comprobando si su hora de exhibición coincide con
la hora actual. En tal caso debemos mostrar el mensaje.
Sub Timer1_Timer ()
For I = 0 To List1.ListCount - 1
If Left$(Time$, 5) = Left$(List1.List(I), 5) Then
Beep: Beep: Beep: Beep
MsgBox List1.List(I), 64, "Mensaje."
List1.RemoveItem I
Next
End Sub
Para recorrer todos los elementos de la lista empleamos un ciclo desde 0
hasta List1.ListCount-1. En su interior realizamos la comparación de la hora
Introducción a la Programación Visual Página 155 de 168

actual con la hora del mensaje. Nuestro cuidado en almacenar la hora en


un formato similar al de la función TIME$ vuelve a rendir sus dividendos. Para
comparar las horas basta comparar los cinco primeros caracteres de
nuestro mensaje con los cinco primeros caracteres de la hora actual (se
desprecian los segundos). Ambas subcadenas tienen el mismo formato
“hh:mm”. Si las dos horas coinciden se emite una señal sonora y se muestra
el mensaje empleando para ello una caja de mensajes.
Una vez que el usuario oprime el botón aceptar de la caja de mensajes
eliminamos el mensaje exhibido de la lista. De no hacerlo así nuestro
programa tendría que comprobar, cada vez que transcurre un minuto una
lista de mensajes donde se encuentran todos aquellos que ya fueron
156 Introducción a la Programación Visual
mostrados y que por tanto no se volverán a mostrar, y sólo sirven para
ocupar memoria y hacer un poco más lento el ciclo de las comparaciones.
Por supuesto este programa podría, y debería, contar con un menú de ayuda
que instruya a sus usuarios sobre su funcionamiento, pero el limitado espacio
de este libro no permite desarrollarlo aquí. Nuestros lectores pueden
hacerlo guiándose por los menús de ayuda que hemos desarrollado para
otros programas como por ejemplo para el ‘Juego del 15’
De esta forma podemos dar por terminado nuestro programa Monitor de
Mensajes, y con él este capítulo, que hemos dedicado a mostrar las
posibilidades del control del tiempo en Visual Basic por medio del control
Temporizador.
Introducción a la Programación Visual 157
Capítulo 9. Accediendo a Bases de Datos.
Las Bases de Datos y los Lenguajes de Programación.
Hoy por hoy la mayor parte de los trabajos que se realizan en el mundo de la
informática se refieren directamente a las bases de datos o tienen al menos
alguna relación con ellas. Por este motivo resulta de gran importancia a la
hora de seleccionar un lenguaje para realizar un trabajo de programación
mas o menos complejo, evaluar su capacidad para acceder a la
información almacenada en bases de datos.
La mayor parte de los lenguajes de programación desarrollados para
trabajar en el ambiente MS-DOS no disponía de especiales facilidades para
Introducción a la Programación Visual Página 156 de 168

operar con bases de datos elaboradas en sistemas como Dbase, FoxBase


etc., quedando para el programador la ingrata tarea de descifrar los
formatos que empleaban cada uno de estos sistemas para almacenar la
información en el disco. En cambio en los últimos años ha venido
haciéndose regla el que los lenguajes de programación de propósito
general incluyan facilidades para el acceso a bases de datos desarrolladas
en los sistemas más populares. Y Visual Basic no iba a ser la excepción.
Resulta muy sencillo escribir un programa en Visual Basic que sea capaz de
abrir esa base de datos y exhibir su contenido en pantalla, registro por
registro. Para ello debemos emplear un nuevo control de
Visual Basic: el control Datos. Este control se identifica en la caja de
herramientas con el botón:
Este control se dedica exclusivamente a la manipulación de bases de
datos, y puede trabajar no sólo con bases generadas en Access, sino
también con bases generadas en Dbase, FoxPro, Btrieve y Paradox, entre
otros.
Entre las propiedades mas importantes del control Datos encontraremos la
propiedad DatabaseName, que sirve para indicar la base de datos que
debe abrir el control Datos. Cuando realizamos un doble click sobre esta
propiedad en la caja de propiedades, Visual Basic nos muestra una ventana
de búsqueda de archivos que nos servirá para localizar en el disco el
archivo donde está almacenada nuestra base de datos.
158 Introducción a la Programación Visual
La otra propiedad significativa del control Datos es la propiedad
RecordSource. Un control Datos sólo puede manipular una tabla de la base
de datos. Esta propiedad nos permite, precisamente, indicar que tabla
deseamos abrir con nuestro control Datos. Para asignar valores a esta
propiedad es imprescindible haber indicado previamente la base de datos
que deseamos trabajar, mediante la propiedad DatabaseName. Cuando
seleccionamos la propiedad RecordSource en la caja de propiedades, se
despliega una lista con los nombres de las diferentes tablas de la base de
datos, para permitirnos seleccionar cómodamente la tabla que deseamos
abrir.
Cuando colocamos sobre un nuestro formulario un control Datos, este toma
Introducción a la Programación Visual Página 157 de 168

la apariencia que muestra la figura 9-1. Como se aprecia en la figura los


cuatro botones del control sirven para situarse en el primer o en el último
registro de la tabla, así como en los registros próximo y anterior, en relación
al registro actual (registro activo).
Estos movimientos pueden ser realizados manualmente por el usuario
pulsando los botones del control Datos, pero también pueden ser realizados
desde el programa por los métodos MoveFirst (moverse al primer registro),
MoveLast (moverse al último), MoveNext (moverse al próximo) y
MovePrevious (mover al anterior). Sin embargo estos métodos no
pertenecen al control Datos, por lo que no puede escribirse una instrucción
como Data1.MoveFirst. Estos métodos pertenecen realmente a un objeto
especial, denominado Recordset, que se encuentra asociado a los controles
Datos. Para poder emplear estos métodos debemos escribir, por ejemplo:
Data1.Recordset.MoveFirst
Para mostrar en nuestro formulario la información almacenada en una tabla
de una base de datos podemos emplear controles etiqueta y caja de texto.
Estos controles pueden asociarse a un control Datos (y por tanto a la tabla a
la que esta conectado el control Datos) por medio de las propiedades
Introducción a la Programación Visual 159
DataSource y DataField. Tanto las etiquetas como las cajas de textos
disponen de estas propiedades. Cuando seleccionamos la propiedad
DataSource en la caja de propiedades, se despliega una lista con los
nombres de todos los controles Datos que se encuentren en nuestro
formulario. De esa lista escogeremos el control Datos al que deseamos
asociar nuestra etiqueta o nuestra caja de texto. Cuando seleccionamos la
propiedad DataField en la caja de propiedades, se despliega una lista con
los nombres de todos los campos de la tabla a la que esta conectada el
control Datos con el que asociamos previamente nuestra etiqueta o caja de
texto por medio de la propiedad DataSource. De esa lista seleccionaremos
el campo en particular que deseamos mostrar en nuestra etiqueta o en
nuestra caja de texto.
La principal ventaja de establecer esta as ociación entre etiquetas y/o cajas
de textos y controles Datos se encuentra en la actualización automática de
los datos que muestran estos controles. En efecto cuando cambiemos el
Introducción a la Programación Visual Página 158 de 168

registro activo de la tabla (bien sea pulsando los botones del control Datos,
o empleando los métodos MoveFirst, MoveNext etc.) la información de las
etiquetas y las cajas de texto asociadas se actualizará automáticamente
con los datos correspondientes al nuevo registro activo, sin necesidad de
que escribamos instrucciones para realizar esa actualización.
Como ya se señaló, un control Datos sólo puede estar asociado con una
tabla de una base de datos, de tal forma si nuestra base de datos estuviese
integrada por varias tablas, y nos interesara mostrar en un mismo formulario
información procedente de varias tablas, tendremos que colocar en ese
formulario tantos controles Datos como tablas de la base de datos nos
interese acceder a la vez.. Luego tendremos que colocar en el formulario
nuestras etiquetas y/o cajas de textos e irlas asociando con los distintos
controles Datos.
Con estos elementos ya nos encontramos en condiciones de escribir un
sencillo programa que nos permita mostrar en pantalla el contenido de una
base de datos.
Mostrando el contenido de una tabla.
Supongamos que tenemos a mano una base de datos elemental para una
biblioteca, creada empleando Microsoft Access. Nuestra base de datos
esta formada por una sola tabla, a la que hemos denominado Libro, en esa
160 Introducción a la Programación Visual
tabla definimos los campos Título, Autor, Editorial y Año de publicación. El
contenido de esa tabla podría ser el que se muestra a continuación:
Título Autor Editorial Año
El siglo de las luces
Alejo Carpentier Letras Cubanas 1974
La guerra y la paz León Tolstoi Arte y Literatura 1974
La arboleda perdida Rafael Alberti Arte y Literatura 1975
Las corrientes del
espacio
Isaac Asimov Martínez Roca 1992
Los negros curros Fernando Ortiz Ciencias Sociales 1986
Supongamos ahora que se nos pide preparar un programa en Visual Basic
que permita a los usuarios de la biblioteca consultar la información de esa
Introducción a la Programación Visual Página 159 de 168

tabla. ¿cómo lo haríamos?


Como siempre comenzaremos por el diseño del interfaz. En este caso
necesitaremos colocar cinco etiquetas con los nombres de los campos de
la tabla y otras cinco etiquetas en blanco donde se mostrarán los datos
almacenados en la tabla. Estas últimas etiquetas son las que asociaremos
con el control Datos que por supuesto debemos colocar en nuestro
formulario (utilizaremos etiquetas y no cajas de texto para evitar que el
usuario pueda modificar estos datos). La figura 9-2. Muestra el aspecto de
nuestro formulario.
A continuación mostraremos una tabla con las principales propiedades de
los objetos que aparecen en nuestro interfaz.
Objeto Propiedad Valor asignado Comentario
Form1 Caption “Base de Datos
elemental”
Data1 DatabaseNa
me
"C:\Libro_de_VB\
Biblioteca.mdb
La base de datos se
encuentra en el archivo
Biblioteca.mdb que está
en el directorio
Libro_de_VB
RecordSource Libro Asocia el control Data1
con la tabla Libro
Connect Access Indica que la Base de
datos ha sido preparada
con Access.
Caption "Lista de Libros"
Label1 Caption "Título"
Introducción a la Programación Visual 161
Label2 Caption "Autor"
Label3 Caption "Editorial"
Label4 Caption "Año de
Introducción a la Programación Visual Página 160 de 168

Publicación"
Label5 Caption "" Inicialmente la etiqueta
está vacía.
DataSource Data1 Se asocia la etiqueta al
control Data1
DataField Título Se asocia la etiqueta al
campo Título
Label6 Caption "" Inicialmente la etiqueta
está vacía.
DataSource Data1 Se asocia la etiqueta al
control Data1
DataField Autor Se asocia la etiqueta al
campo Autor
Label7 Caption "" Inicialmente la etiqueta
está vacía.
DataSource Data1 Se asocia la etiqueta al
control Data1
DataField Editorial Se asocia la etiqueta al
campo Editorial
Label8 Caption "" Inicialmente la etiqueta
está vacía.
DataSource Data1 Se asocia la etiqueta al
control Data1
DataField Año de
Publicación
Se asocia la etiqueta al
campo Año de …
El menú "Opciones" tiene un solo elemento, denominado "Terminar", cuya
función será la de concluir la ejecución del programa.
Una vez diseñado el interfaz, corresponde determinar las acciones que
deben realizar los distintos controles, para, a partir de esa determinación
establecer para que eventos de esos controles tendremos que escribir
código, y por último proceder a escribir el código para esos eventos.
162 Introducción a la Programación Visual
Introducción a la Programación Visual Página 161 de 168

La realización de este análisis nos


depara una nueva sorpresa: ¡¡¡no es
necesario escribir código para este
programa!!! En realidad la única
instrucción que debemos escribir es
la instrucción End en el
procedimiento de atención al
evento Click del elemento de
menú Terminar.
En efecto todas las asociaciones
necesarias para el buen
funcionamiento de este programa
han sido establecidas desde la
etapa de diseño. Asociamos el
control Data1 con la base de datos Biblioteca y dentro de ella con la tabla
Libros, y asociamos cada una de las etiquetas Label5, Label6, Label7 y
Label8 con los diferentes campos de la tabla Libros. Ya en tiempo de
ejecución los botones del control Data1 nos permiten movernos por todos
los registros de la tabla y las etiquetas se actualizan automáticamente
cada vez que cambiamos el registro activo. Para hacer todo esto no hemos
necesitado de una sola instrucción. Así de cómodo resulta el trabajo con
Visual Basic!!!
La tarea que resuelve nuestro programa, exhibir el contenido de los todos
los registros de una tabla, es la más elemental que pueda realizarse con una
base de datos. Resulta evidente que Visual Basic debe ser capaz de
permitirnos enfrentar tareas de mayor complejidad, como puede ser, por
ejemplo, realizar búsquedas en la tabla, empleando como criterio de
búsqueda el valor de uno o varios campos del registro.
Para realizar una búsqueda no podemos emplear los métodos MoveFirst,
MoveNext, etc. ya que estos métodos cambian el registro activo sin
atender a ningún criterio. En su lugar emplearemos los métodos FindFirst,
FindLast, FindNext y FindPrevious, que si permiten indicar un criterio de
búsqueda.
Estos métodos también pertenecen al objeto Recordset, así que para poder
Introducción a la Programación Visual Página 162 de 168

invocarlos desde nuestro control Datos tendremos que escribir, por ejemplo:
Figura 9-2.
Introducción a la Programación Visual 163
Data1.Recordset.FindFirst Criterio
Donde Criterio es una cadena de caracteres, bastante similar a la cláusula
WHERE de una instrucción SQL (aquí se omite la palabra WHERE), que
contiene el criterio de búsqueda. Este criterio se expresa en forma de
relaciones entre los campos y determinados valores. Por ejemplo la
instrucción:
Data1.Recordset.FindFirst " [Título] = 'La guerra y la paz' "
busca el primer registro para el cual el se cumpla que el valor del campo
Título sea "La guerra y la paz". Nótese que en la cadena de búsqueda el
nombre de los campos de escribe entre corchetes [ ] y que las expresiones
de caracteres se escriben empleando 'apóstrofes simples', en vez de
"comillas" .
Para realizar una búsqueda debe ejecutarse en primer lugar el método
FindFirst, para que encuentre al primer registro que cumpla con la criterio de
búsqueda establecido. Una vez encontrado el primer registro podemos ir
ejecutando el método FindNext para ir buscando los siguientes registros que
cumplan con el mismo criterio. Puede ocurrir que ningún registro cumpla
con el criterio de búsqueda. Nuestro programa puede detectar esa
situación consultando el valor de la propiedad NoMatch del objeto
Recordset. Esta propiedad contiene un valor lógico, que se actualiza
después de la ejecución de cada método FindFirst, FindNext, etc. Si no se
encuentra ningún registro que cumpla con el criterio de búsqueda, NoMatch
recibe el valor True , si se encuentra algún registro que cumpla, recibe el
valor False. El código para chequear NoMatch podría escribirse así:
Data1.Recordset.FindFirst " [Título] = 'El viejo y el mar' "
If Data1.Recordset.NoMatch Then ……. ' No se encontró ningún
‘ registro que cumpla con el criterio.
En los procesos de búsqueda resulta especialmente útil el operador Like,
una de las novedades de Visual Basic a las que nos referíamos en el capítulo
3. Las facilidades que brinda este operador para la comparación de
cadenas nos permiten desarrollar búsquedas muy eficaces, por ejemplo:
Introducción a la Programación Visual Página 163 de 168

Data1.Recordset.FindFirst " [Título] Like '*la*' "


busca el primer registro que contenga en cualquier posición de su campo
Título la subcadena "la". En nuestra base de datos de ejemplo esta condición
164 Introducción a la Programación Visual
es cumplida por los cuatro primeros registros que contienen en sus campos
Título los valores "El siglo de las luces", "La guerra y la paz", "La arboleda
perdida" y "Las corrientes del espacio".
Podemos incluso elaborar complejos criterios de búsqueda que involucren a
más de un campo de nuestra tabla;
Data1.Recordset.FindFirst " [Título] Like '*la*' AND [Autor] Like '*le*' "
Esta condición sólo la cumplen en nuestra tabla los dos primeros registros,
que contienen en sus campos de Título y Autor los valores El siglo de las
luces, Alejo Carpentier y La guerra y la paz, León Tolstoi.
Probemos adicionar a nuestro programa la capacidad de realizar
búsquedas en la tabla. Para no complicar demasiado las cosas realizaremos
las búsquedas por un solo campo y dejaremos al usuario decidir por cual lo
hará. Para esto incorporaremos al menú 'Opciones' un segundo elemento al
que nombraremos 'Buscar', del cual se derivará un submenú con los
elementos 'por Título', 'por Autor' y 'por Editorial' como se muestra en la figura
9-3.
Cuando el usuario seleccione uno de los
tres elementos de este submenú, nuestro
programa podrá comenzar a construir el
criterio de búsqueda. Para ello nos
valdremos de las variables Campo y
Criterio que declararemos a nivel de
formulario en el área de declaraciones:
Dim Campo As String, Criterio As String
Con el menú, el usuario selecciona el campo por el que quiere buscar, pero
con esto no es suficiente para realizar la búsqueda. Hace falta también
proporcionarle un lugar donde escribir el patrón que desea buscar en ese
campo. También resulta necesario suministrar recursos que le permitan
iniciar la búsqueda (o sea ejecutar el método FindFirst) y una vez
encontrado el primer elemento, continuar la búsqueda (o sea ejecutar los
Introducción a la Programación Visual Página 164 de 168

métodos FindNext y FindPrevious) Es evidente que para entrar el patrón de


búsqueda debemos emplear una caja de texto, y hemos decidido emplear
botones para controlar la búsqueda, de forma parecida a como opera el
control Datos. Para agrupar cómodamente todos estos controles
colocaremos sobre el formulario un control caja de imagen y en su interior
Figura 9-3.
Introducción a la Programación Visual 165
dispondremos la caja de texto y los botones. El aspecto de ese grupo se
muestra en la figura 9-4.
Como se puede ver hemos situado
este grupo en el mismo lugar que
ocupaba el control Datos en la
figura 9-2. No hemos eliminado el
control Datos, por supuesto que no.
Hemos colocado nuestra caja de
imágenes sobre él, de forma que
queda oculto. En realidad este
grupo de controles sólo debe
mostrarse sobre el formulario
cuando el usuario solicite, por medio del menú, realizar una búsqueda. Para
lograr esto asignaremos durante el diseño el valor False a la propiedad
Visible de la caja de imágenes. De esta forma cuando el programa inicie su
ejecución la caja de imágenes resultará invisible y el usuario podrá operar
con el control Datos, que se encontrará a su alcance. Cuando el usuario
solicite una búsqueda, los procedimientos de atención a los eventos click
de los elementos del menú, se ocuparán de hacer visible la caja de
imágenes, ocultando el control Datos. Cuando el usuario decida terminar la
búsqueda y oprima el botón correspondiente. El procedimiento de atención
al evento click de ese botón se encargará de volver a hacer invisible a la
caja de imágenes. Resulta conveniente que el usuario no pueda operar a la
vez con los botones del control Datos y con los botones "Anterior" y
"Próximo", ya que los primeros realizan un desplazamiento secuencial por los
registros de la tabla, mientras los segundos realizan el desplazamiento sobre
el subconjunto de los registros que cumplen con el criterio de búsqueda . La
Introducción a la Programación Visual Página 165 de 168

operación simultánea de ambos grupos de botones puede crear


confusiones al usuario.
Otro detalle acerca de los botones "Anterior" y "Próximo". Los métodos que
ejecutaremos cuando se opriman estos botones, FindPrevious y FindNext
respectivamente, no deben ejecutarse hasta tanto se haya ejecutado el
método FindFirst, que se ejecutará cuando el us uario oprima el botón "Iniciar
la búsqueda". Por este motivo es inconveniente, e incluso peligroso permitir
que el usuario pueda operar estos botones cuando aún no ha oprimido el
botón "Iniciar la búsqueda". Para neutralizar esa situación impediremos que
el usuario pueda acceder a los botones "Anterior" y "Próximo" colocando el
valor False en las propiedades Enabled de dichos controles. Cuando se
pulse el botón "Iniciar la búsqueda" el procedimiento de atención a ese
evento click se ocupará de colocar en las propiedades Enabled de los
Figura 9-4.
166 Introducción a la Programación Visual
botones "Anterior" y "Próximo" el valor True , para que el usuario pueda
utilizarlos. Por supuesto, si el usuario modifica el patrón de búsqueda (esta
modificación se detecta por el evento Change de la caja de texto) los
botones "Anterior" y "Próximo" deben desactivarse nuevamente, hasta tanto
no comience la nueva búsqueda.
A continuación mostramos una tabla con las principales propiedades de los
controles que hemos incorporado a nuestro programa:
Objeto Propiedad Valor asignado Comentario
Picture1 Visible False
Command1 Caption "Iniciar la búsqueda"
Command2 Caption "Fin de la búsqueda"
Command3 Caption "Anterior"
Enabled False
Command4 Caption "Próximo"
Enabled False
Label9 Caption "Criterio de
búsqueda"
Text1 Text "" La caja de textos se
ofrece vacía.
Introducción a la Programación Visual Página 166 de 168

Por su parte los elementos del submenú tendrán las siguientes propiedades:
Caption Name Index Checked
“&Buscar” Busca
“&Terminar” Fin
“por &Autor” Por_Autor
“por &Título” Por_Titulo
“por &Editorial” Por_Editorial
Cuando el usuario seleccione alguno de los elementos del submenú nuestro
programa debe almacenar en la variable Campo el nombre del campo que
corresponde con la selección del usuario y hacer visible la caja de
imágenes Picture1 (y con ella a todo su contenido). Veamos el
procedimiento que atiende a la selección del elemento de menú "por
Título":
Introducción a la Programación Visual 167
Sub Por_Titulo_Click( )
Campo = "[Título]" ‘ Almacena el nombre del campo ‘
‘ en el formato requerido para poder
‘ formar mas tarde el criterio de búsqueda
‘ [el nombre entre corchetes]
Picture1.Visible = True ' Hace visible la caja de imágenes Picture1
End Sub
El trabajo de los procedimientos que atienden a los otros dos elementos de
ese submenú resulta muy similar:
Sub Por_Autor_Click()
Campo = "[Autor]"
Picture1.Visible = True
End Sub
Sub Por_Editorial_Click()
Campo = "[Editorial]"
Picture1.Visible = True
End Sub
Cuando el usuario termina de escribir el patrón de búsqueda y oprime el
botón "Iniciar la búsqueda", es el momento de concluir la construcción del
criterio de búsqueda, ligando el valor almacenado en la variable Campo
Introducción a la Programación Visual Página 167 de 168

con el patrón que el usuario ha escrito en la caja de texto Text1. Una vez
hecho esto se debe ejecutar el método FindFirst para localizar el primer
registro que responda al criterio de búsqueda y, si esa búsqueda inicial
resulta exitosa podemos habilitar los botones "Próximo" y "Anterior" para
intentar el recorrido de la tabla por los restantes registros que cumplan con
el criterio de búsqueda..
Sub Command1_Click( )
Criterio = Campo & " Like '" & Text1.Text & "'"
' Se termina de elaborar el criterio de búsqueda
Data1.Recordset.FindFirst Criterio
' Se busca el primer registro que responda al
criterio
If Not Data1.Recordset.NoMatch Then
' Si existe ese primer registro
Command1.Enabled = True
' se habilitan los botones para buscar el próximo
Command2.Enabled = True ' y el anterior registro.
End If
168 Introducción a la Programación Visual
End Sub
La tarea de los botones Anterior y Próximo es sencilla:
Sub Command3_Click( )
Data1.Recordset.FindPrevious Criterio
' Busca el anterior registro que cumpla con el criterio de búsqueda.
End Sub
Sub Command4_Click()
Data1.Recordset.FindNext Criterio ' Busca el próximo registro que
cumpla
End Sub ' con el criterio de búsqueda.
Como ya se dijo, cuando el usuario modifica el patrón de búsqueda en la
caja de texto Text1 de deben inhabilitar los botones "Próximo" y "Anterior".
Sub Text1_Change()
Command3.Enabled = False ‘ Se inhabilita el botón "Anterior"
Command4.Enabled = False ‘ Se inhabilita el botón "Próximo"
Introducción a la Programación Visual Página 168 de 168

End Sub
Por último cuando el usuario decide finalizar la búsqueda se debe ocultar la
caja de imagen Picture1 para permitir al usuario continuar trabajando con el
control Datos. Pero al mismo tiempo se deben crear las condiciones para el
comienzo de la próxima búsqueda: inhabilitar los botones "Anterior" y
"Próximo" y borrar el patrón que se encuentra escrito en la caja de texto.
Sub Command3_Click()
Command1.Enabled = False ' Se inhabilita el botón "Anterior"
Command2.Enabled = False ' Se inhabilita el botón "Próximo"
Text1.Text = "" ' Se borra el contenido de la caja de texto
Picture1.Visible = False ' Se oculta la caja de imágenes.
End Sub
Con estas modificaciones nuestro programa se encuentra en condiciones
de realizar búsquedas según criterio sobre los registros de nuestra tabla.
Lamentablemente las limitaciones de espacio no nos permiten extendernos
en el rico terreno del trabajo con bases de datos desde Visual Basic, y no
podemos mostrar ejemplos del trabajo simultáneo con varias tablas ni tratar
los nuevos controles especializados en el trabajo con bases de datos que se
introducen a partir de la versión 4.0 de Visual Basic.
Introducción a la Programación Visual 169
Bibliografía.
1. Ceballos Sierra, Francisco. Enciclopedia de Visual Basic. Editorial RA-MA.
España 1994.
2. Mc Kinney, Bruce. Hard Core Visual Basic. Microsoft Press. 1995
3. CESOFTE. Curso de Visual Basic. La Habana. 1994.
4. MICROSOFT Corporation. Visual Basic 3.0 Manual del Programador. .
Microsoft Press. 1993.
5. MICROSOFT Corporation. Visual Basic 4.0 Manual del Programador. .
Microsoft Press. 1996.
6. MICROSOFT Corporation. Visual Basic 5.0 Manual del Programador. .
Microsoft Press. 1997.
7. Golden, J.T. Fortran VI Programación y Cálculo. Ediciones
Revolucionarias. La Habana 1973.

También podría gustarte