T
iene en sus manos una introducción y una guía para aprender y utilizar el sistema de programación Visual Visual Basic para Windows. Windows. Sin tener que conocer la confusa jerga de los l os expertos ni contar con experiencia previa en programación. El autor, Ross Nelson, es un conocido experto en Visual Basic y le enseñará a programar desde cero para que, paso a paso, paso, vaya creando aplicaciones de de interés en el entorno Windows. Pero el libro no se reduce sólo a explicar las características y elementos
T
iene en sus manos una introducción y una guía para aprender y utilizar el sistema de programación Visual Visual Basic para Windows. Windows. Sin tener que conocer la confusa jerga de los l os expertos ni contar con experiencia previa en programación. El autor, Ross Nelson, es un conocido experto en Visual Basic y le enseñará a programar desde cero para que, paso a paso, paso, vaya creando aplicaciones de de interés en el entorno Windows. Pero el libro no se reduce sólo a explicar las características y elementos
Primera edición, abril 1994 Primera reimpresión, agosto 1994
Paradox es una marca registrada de Ansa Software, una empresa de Borland. Apple y Macintosh son marcas registradas de Apple Computer, Inc. Borland y dBASE son marcas registradas de Borland International, Inc. Claris y FileMaker son marcas registradas de Claris Corporation. IBM es una marca registrada de International Business Machines Corporation. FoxPro, GW-BASIC, Microsoft, Microsoft Access, MS-DOS, PowerPoint, Microsoft QuickBasic, Visual Basic y Windows son marcas registradas de Microsoft Corporation. Teletype es una marca registrada de Teletype Corporation. Todas las marcas registradas son propiedad de sus respectivos propietarios.
Edición original en lengua inglesa Copyright © 1993 by Ross P. Nelson Edición publicada por acuerdo con el editor original, Microsoft Press, Redmond, Washington ©EDICIONES ANAYA MULTIMEDIA, S. A., 1994 Juan Igancio Luca de Tena, 15, 28027 Madrid Depósito legal: S. 684-1994 ISBN: 84-7614-610-8 Printed in Spain Imprime: Josmar, S. A. Polígono El Montalvo - Salamanca, 1994
A Margaret Hannah Nelson Nelson
Indice genera g enerall 1
Comenzar rápidamente con Visual Basic 1
2
Datos e instrucciones 29
3
Variables Variables y constantes 41
4
Declaraciones, Declaraciones, expresiones y p rocedimientos 63
5
El uso de los formularios y h erramientas erramientas de Visual Basic 87
ó
Control del programa 15 9
7
El uso de procedimientos y funciones 18 9
8
Depuración y gestión de errores 22 1
9
Ar ch iv os 24 3
10
Programación gráfica 28 5
11
Bases de datos y cuadrículas 31 1
12
Enlace e incrustación de objetos 33 1
13
Una aplicación para Windows com pleta 34 9
Indice Agradecimientos xiii Introduc ción xv 1
Comenzar rápidamente con Visual Basic 1 Instalación y arranque de Visual Basic 1 Exploración de la pantalla 2 Crear un interface de usuario 9 Escribir el código 15 Ejecución del programa 22 Revisar el diseño 23 Guardar el programa 25
2
Datos e instrucciones 29 Ordenadores y datos 29 Instrucciones de ordenador 35
3
Variables y con stantes 41 Especificación de los tipos de datos de Visual Basic 41 Creación de variables y constantes 45 Creación de tipos definidos por el usuario 49 Determinar el ámbito 52
4
Declaraciones, expresiones y procedimientos 63 Declaraciones de asignación 63 Expresiones y operadores 64 Procedimientos 81
ix
Indice
Objetos como parámetros 207 Procedimientos de evento avanzados 209
5 El uso de los formularios y herramientas de Visual Basic 87 Los objetos de Visual Basic 87 Formularios 89
8
Depuración y gestión de errores 221 Herramientas de depuración 222
Cuadros de dibujo e imágenes 98 Etiquetas 104
Estrategias de depuración 232
Cuadros de texto 106
Un grito de ayuda 234
Botones de comando, cuadros de control y botones de opciones 1 10
Gestión de errores 237
Marcos 114 Cuadros de lista 117
9
Cuadros combinados 120
Archivos 243 Visión general del sistema de archivos 243
Eventos 122
Operaciones con archivos 244
Barras de desplazamiento horizontales y verticales 124
Archivos secuenciales 252
Relojes 129
Archivos de acceso aleatorio 259
Líneas y formas 132
Configuración 279
Cuadros de lista de unidades de disco, de directorios y de archivos 136 Otras herramientas de Visual Basic 138
10
Cuadros de diálogo estándar 140
Programación gráfica 285 Formularios y cuadros de dibujo 285
Menús 149
El objeto Printer 307 Consideraciones sobre el hardware para los programas gráficos 309
6 Control del programa 1 5 9 Realizar elecciones 159
11
Hacer repeticiones 170
¿Qué es una base de datos? 311
El uso de matrices 179
Acceder y mostrar datos usando Visual Basic 315
El uso de matrices de controles 186
Control mediante el programa 319 Acceder dinámicamente a una base dedatos 323
7 El uso de procedimientos y funciones 189 Procedimientos generales 189 Procedimientos de función 194 Escribir procedimientos 195 Cómo funcionan los parámetros 200 Asignación local 205
x
Bases de datos y cuadrículas 311
12
Enlace e incrustación de objetos 331 OLE en Visual Basic 331 Control directo del objeto 343 Una nota sobre el DDE 347
xi
LIBRO DEL VISUAL BASIC
13 Una aplicación para Windows completa 349
Agradecimientos
Diseño general 349 Diseño del menú 351 Diseño del formulario 354 Declaraciones globales 357 Formularios a uxiliares 358 El proc edimiento M ain 362 La e structura de eventos 363 Un peq ueño flash 372 Una mirada hacia delante 374
Indice alfabético 375
En primer lugar, quiero agradecer a los equipos del proyecto Visual Basic —a los dos equipos: los que originalmente los concibieron e implementaron y los que han continuado mejorándolo. Es obvio que este libro no podría haberse escrito sin la inspiración proporcionada por este innovador producto y por sus desarrolladores. Quiero agradecer a Claudette Moore su empuje y apoyo. En Microsoft Press, el entusiasmo de Eric Stroo y los comentarios de Mike Halvorson y Mary DeJong sobre los borradores iniciales fueron de mucha ayuda. Mary Renau también se merece un reconocimiento por modular mi, en ocasiones, salvaje prosa, y las cuidadosas correcciones técnicas de Dail Magee me salvaron de la catástrofe. Gracias también a Nancy Siadek y a Maureen Zimmerman por su trabajo sobre la nueva edición. Hay otro montón de gente en Microsoft Press que trabajan "en la som bra" mecanografiando, creando el diseño, verificando el texto, creando el índice, etc. Nunca os he conocido, pero aceptad mi agradecimiento por el trabajo que habéis hecho. Finalmente, debo mencionar a Rufus y dar las gracias especialmente a mis amigos, fundamentalmente a John y Elsa Nimmo, quienes aguantaron alegremente mi parloteo sobre fechas límite y editoriales y que aceptaron que algunas veces "desapareciera" en combate.
xii xiii
Introducción El sistema de programación Visual Basic para Windows supone un importante avance para cualquiera que esté involucrado en la creación de aplicaciones para Windows. Con su corazón de programación orientada a eventos y sus innovadoras (y fáciles de usar) herramientas de diseño visual, Visual Basic permite sacar el máximo provecho del entorno gráfico Windows para crear potentes aplicaciones con rapidez. Pero, en el caso de que no seas un programador experto, puedes estar preguntándote si Visual Basic será adecuado para ti. Puede ser que seas un maestro en aplicaciones como Microsoft Excel o como Microsoft PowerPoint y quieras llegar incluso más lejos con el ordenador. Quizás sólo estés buscando un nuevo reto, y programar ordenadores suena interesante. O, mejor todavía, acabas de descubrir que ninguna aplicación comercial hace exactamente lo que tú quieres y estás pensando en escribir un programa por ti mismo que se adapte a tus propias necesidades especiales. Si cualquiera de estas suposiciones es correcta, tienes en las manos el libro adecuado. El libro del Visual Basic para Windows es una primicia sobre programación en Visual Basic. No te convertirá en un científico de ordenadores, en un superespecialista o en un ingeniero de software. Pero te mostrará cómo usar Visual Basic para convertir tus ideas en programas funcionales para tu ordenador, y poder así enfrentarte a los problemas que necesitas solucionar. ¿Por qué Visual Basic? Para comprender lo que Visual Basic representa y por qué ha producido tanto revuelo en el mundo del software gráfico, veamos primero algo de su historia.
Una mirada atrás Los primeros lenguajes de programación fueron diseñados en los años 50 y se crearon, fundamentalmente, para resolver complejos problemas matemáticos. Eran bastante complejos para la gente normal, pero ello no representaba un grave problema porque entonces los ordenadores sólo se encontraban en las principales instituciones investigadoras. Sin embargo, la gente se dió cuenta de que la tec xv
Iintroducción
nología informática podía ser útil para muchas más cosas que las matemáticas, y los ordenadores empezaron a hacerse habituales en las empresas y en las univer sidades. A medida que más gente comenzaba a utilizar los ordenadores, los eso téricos y complicados lenguajes de programación llegaron a suponer algo más que un obstáculo.
programa más simple. Por ello, cuando se presentó Microsoft Windows, los pro gramadores se sintieron a la vez excitados y deprimidos —excitados porque Win dows les proporcionaba una plataforma para escribir aplicaciones gráficas y agradables para el usuario; deprimidos porque su trabajo se hacía mucho más complicado.
Como solución, a principios de los años 60 se desarrolló un lenguaje denominado BASIC en el Dartmouth College. La versión original del BASIC (acrónimo de Be ginner’s All-purpose Simbolic Instruction Code) era un lenguaje muy simple, diseñado especialmente para hacer que resultase sencillo aprender a programar. Una generación entera de programadores dió sus primeros pasos con el BASIC y lo uso para escribir una impresionante variedad de programas.
Un sencillo programa que mostrase un mensaje en la pantalla podía escribirlo en cuatro líneas un programador que trabajase con MSDOS. Un programa similar para Windows requería dos o tres páginas de código e implicaba aprender a con trolar fuentes, mentís, ventanas, memoria y otros recursos del sistema. Pero las ventajas de Windows para el usuario final eran incuestionables, y la gente empe zó a comprar programas escritos para Windows en grandes cantidades. Así que a los programadores profesionales no les quedó más remedio que empezar a escri bir páginas y más páginas de códigos.
La simplicidad del BASIC lo hizo pequeño, y el tamaño era importante cuando los ordenadores también comenzaban a quedarse pequeños. El MITS Altair, en plena revolución de los microordenadores, apareció en 1975. Bill Gates y Paul Alien, cofundadores de Microsoft, aceptaron el reto de desarrollar una versión del BASIC para el Altair que funcionase en los 4 kilobytes de RAM de los que disponía ese ordenador. Esa versión del BASIC ha llegado a convertirse en el producto más usado de la industria de los ordenadores personales. Con el transcurso de los años, este lenguaje de programación se ha mejorado y desarrollado. Cuando los primeros micros le abrían el camino al PC de IBM, el GWBASIC de Microsoft estableció el estándar. Más adelante, la demanda de un software más rápido, pequeño y fácil de usar condujo al desarrollo del Microsoft QuickBasic. QuickBasic llevó al BASIC a la primera línea de la tecnología de los lenguajes de programación de los años 80, pero hubo un cambio aún más importante en el horizonte: el interface gráfico de usuario (GUI). Con el advenimiento de Microsoft Windows, los usuarios de PC pudieron trabajar en un entorno intuitivo y gráficamente rico. Un interface gráfico de usuario permite que las aplicaciones sean fáciles de aprender y de usar. En lugar de aprender a escribir largos comandos, el usuario, simplemente, selecciona una opción (o comando) de un menú con un "clic" de un botón del ratón. Diversas ventanas en la pantalla permiten que el usuario pueda ejecutar más de un programa a la vez. Cuando un programa necesita información o que el usuario tome decisiones aparecen los cuadros de diálogo. Aunque este entorno es maravilloso para el usuario, la vida se volvió de repente muy complicada para los programadores. Ahora tenían que crear ventanas, me nús, fuentes, cuadros de diálogo y una multitud de elementos, incluso para el
xvi
Muchos creyeron que Windows representaba el fin de la programación aficionada. En el mundo de MSDOS, los profesionales de áreas no relacionadas con la informática podían (en líneas generales) aprender lo suficiente de programación como para escribir aplicaciones sencillas que les ayudasen en su trabajo, les ahorrasen tediosos cálculos u organizasen los datos rápidamente. Pero, ¿podía alguien hacer eso mismo en Windows, donde los requerimientos de programación eran tan complicados, incluso para las aplicaciones más sencillas?
Programar para Windows con Visual Basic La respuesta surgió en 1991 cuando Microsoft presentó Visual Basic. El sistema de programación Visual Basic sortea la complejidad de Windows de una manera realmente espectacular. Combinando las probadas posibilidades del lenguaje Basic con herramientas de diseño visual proporciona simplicidad y facilidad de uso, sin sacrificar prestaciones o las características gráficas que hacen de Windows un entorno tan apetecible en el que trabajar. Los menús, fuentes, cuadros de diálogo, campos de texto con desplazamiento y todo lo demás se diseñan con facilidad, y esas características no requieren más que unas pocas líneas de programa para controlarlas. Visual Basic es también uno de los primeros lenguajes de programación que admite la programación llamada "orientada a eventos", un estilo de programación especialmente adaptado a los interfaces gráficos de usuario. Tradicionalmente, la programación ha estado muy orientada al proceso, al paso a paso, de manera muy similar al de una receta: batir los huevos, añadir la leche, mezclar con el xvii
LIBRO DEL VISUAL BASIC
azúcar, hornear durante 20 minutos. Uno de los inconvenientes de este estilo consiste en que la persona que escribió la receta (el programa) es la que determina qué hay que hacer en cada momento. Eso puede ser aceptable para cocinar galletas, pero en los modernos programas de ordenador el objetivo es que sea el usuario el que determine en cada momento qué es lo que quiere hacer. Y eso es exactamente lo que proporciona la programación orientada a eventos. En lugar de escribir un programa que determina cada uno de los pasos en un orden determinado, el programador escribe un programa que responde a las acciones del usuario: elegir un comando, hacer clic en una ventana, mover el ratón. En vez de escribir un gran programa, el programador crea una aplicación que es realmente una colección de microprogramas que cooperan entre ellos y que se ejecutan a raíz de eventos iniciados por el usuario. Y, con Visual Basic, una aplicación así se puede escribir con una rapidez y facilidad sin precedentes. El lanzamiento inicial de Visual Basic se convirtió en un éxito espectacular, vendiéndose decenas de miles de copias y ganando premios en la mayoría de las principales revistas de informática. A finales de 1992 se lanzó la versión 2 de Visual Basic, la cual ofrecía nuevas características y posibilidades. Con el lanzamiento de Visual Basic 3, el producto ha convertido en un sistema de programación maduro, al que se le han añadido muchas herramientas de programación de gran potencia. La versión 3 incluye las características nuevas que se muestran a continuación: ■ Prestaciones mejoradas. ■ Una herramienta de creación de bases de datos. ■ Acceso visual a datos mediante el control Data, de manera que se pueden crear aplicaciones que examinen los datos sin tener que escribir el código. ■ Un nuevo control OLE (enlace e incrustación de objetos) que permite la edición "in situ". ■ Un conjunto de cuadros de diálogo estándar que se ocupa de las tareas más habituales de inteface con el usuario. ■ La posibilidad de crear menús emergentes (popup) en cualquier posición de la aplicación.
El libro del Visual Basic para Windows te presentará la versión 3 de Visual Basic y te ayudará a desarrollar los conocimientos necesarios para crear aplicaciones reales. No es necesario que conozcas un amplio abanico de vocabulario informa
introducción
tico para utilizar este libro, ni que tengas experiencia en programación. Sin em bargo, debes tener instalada en el ordenador la versión 3 o una posterior del sistema operativo Windows y debes estar familiarizado tanto con él como con algunos de los principales programas creados para Windows. Serviría de ayuda que hubieses creado macros para tu programa de hoja de cálculo o de proceso de textos. Y, por último, no debes tenerle miedo al álgebra. Este libro no contiene matemáticas complejas, pero debes recordar que los lenguajes de ordenador se diseñaron, inicialmente, para ejecutar cálculos matemáticos; consecuentemente, hoy todavía queda algo de aquella herencia en los lenguajes de programación. Aprender a programar —de hecho, aprender un nuevo lenguaje— requiere algo de esfuerzo y una buena cantidad de ensayo y error. Es algo así como aprender a tocar el piano: tienes que practicar las escalas y los arpegios antes de que puedas interpretar a Chopin o a Bach. Por supuesto, cuando acabes este libro no serás capaz de alcanzar el equivalente en programación a un concierto de Chopin. Nos centraremos en los fundamentos; no trataremos todo lo que hay que saber sobre programación, ni siquiera todo lo que hay que saber sobre Visual Basic. Pero serás capaz de crear algunas aplicaciones útiles y derivadas del mundo real, y adaptarlas a tus necesidades. Lo que es más, podrás aprovecharte rápidamente de las posibilidades de algunas otras aplicaciones —Microsoft Word para Windows utiliza una versión del Basic como lenguaje de macros, por ejemplo, y Microsoft Access (un nuevo gestor de bases de datos) se basa en la misma tecnología que Visual Basic. Las herramientas, potencia y posibilidades de Visual Basic acercan la programación a un abanico de personas mucho más amplio, incluso dentro del complejo mundo de los ordenadores gráficos. Ahora es el momento de que pongas tu ordenador a trabajar para ti. Se puede descargar Visual Basic 6 de aquí: https://docs.google.com/file/d/0BzAA6hbbWbAeOUJkY2xnMlptRHc/edit?usp=sharing). Para instalar Visual Basic 6 sobre Windows 7, 8 o 10 de 64 bits o posterior, sigue las instrucciones que se indican aquí: http://www.aprenderaprogramar.com/foros/index.php?topic=286.0 https://mega.nz/#!i8UViCoT!hSWe1ynxh8c9y0gDpnqaSpb8D8u4YPuOsK7ng4276b8 http://turbobit.net/download/free/kndy2n1iwb32# Pass:www.detodoprogramacion.com http://www.mediafire.com/file/247xm175cu19yy5/Visual+Basic+6.0+32+y+64+Bits++luqueenterprises.com.rar https://mega.nz/#!sgkBVQLI!KNR3gC0bNdl7tDFd1Vy7XIyZ1hOrCNx8WJcJTW-TI2g
xviii
x ix
1 Comenzar rápidamente con Visual Basic Para demostrar lo fácil que es comenzar a trabajar con Visual Basic y lo rápidamente que se puede aprender a crear aplicaciones útiles, este capítulo te permitirá introducirte inmediatamente en materia y escribir un programa sencillo. En realidad, experimentar con Visual Basic es la mejor manera de tomar contacto con las herramientas con las que trabajarás, además de obtener una idea del extraordinario potencial de Visual Basic. Después de esta pequeña experiencia práctica, los capítulos 2 y 3 te ofrecerán una visión más detallada de los cómos y los por qués que subyacen bajo Visual Basic.
Instalación y arranque de Visual Basic Como la mayoría de las aplicaciones creadas para el entorno Windows, Visual Basic viene con un programa llamado SETUP.EXE (INSTALAR.EXE en otros programas) que instala la aplicación en el disco duro de tu ordenador. El proceso de instalación completo se describe con detalle en la documentación que viene con Visual Basic; como no tiene ninguna complicación, puede llevarlo a cabo con estos cuatro sencillos pasos: 1. Arranca Windows escribiendo win en el indicador del MSDOS y pulsando la tecla Intro. Visual Basic funciona con la versiones 3.0 y posteriores de Microsoft Windows. 2. Inserta el disco etiquetado, Disco 1, en una unidad de disquete. 3. Selecciona el comando Ejecutar del menú Archivo en el Administrador de Programas de Windows. Escribe a:setup y pulsa la tecla Intro si insertaste 1
EL LIBRO DEL VISUAL BASIC
1 Comenzar rápidamente con Visual Basic
el Disco 1 en la unidad A; si estás usando la unidad B, escribe b:setup y pulsa la tecla Intro.
Barra de menus
Barra de herramientas Ventana principal
4. Sigue las instrucciones de la pantalla y responde a las preguntas de Setup sobre las diversas opciones de instalación. Después de que hayas contestado a todas las preguntas y seguido las instrucciones del programa, Setup instalará Visual Basic en tu disco duro y añadirá una ventana de grupo y un icono de Visual Basic en la ventana del Administrador de programas.
Ventana Project (proyecto)
La manera más fácil de arrancar Visual Basic consiste en hacer doble clic sobre su icono en el Administrador de programas. Alternativamente, puedes comenzar haciendo doble clic sobre VB.EXE, el archivo de Visual Basic, en el Administrador de archivos de Windows. Además, puedes arrancar Visual Basic desde el indicador del MSDOS introduciendo el comando win vb, el cual arranca Windows y Visual Basic a la misma vez. Todos estos métodos se ilustran en la figura 1.1.
C:\>win vb Desde el Administrador de programas
Properties (propiedades)
Caja de herramientas
Ventana Form (formulario)
Figura 1.2. Desde el indicador de comandos del MS-DOS
Desde el Administrador de archivos
Figura 1.1. Arrancar Visual Basic
Exploración de la pantalla Después de que arranques Visual Basic aparecerán cinco ventanas en la pantalla, como se ilustra en la figura 1.2. (En tu pantalla inicial de Visual Basic las ventanas pueden solaparse; en la figura 1.2 se ha modificado el tamaño y la posición de las ventanas en la pantalla, de manera que todas se puedan ver claramente.) En 2
Ventana
La ventana inicial de Visual Basic
la parte superior de la pantalla está la ventana principal. Contiene los menús File (Archivo) y Edit (Edición) que son habituales y otros menús de Visual Basic, así como una barra de herramientas. En el centro de la pantalla está la ventana del formulario, una gran ventana en blanco con el título Form1. Directamente a la izquierda, puedes ver una ventana en forma de paleta de opciones denominada caja de herramientas. A la derecha de la ventana del formulario está la ventana Properties (propiedades) y debajo de ésta aparece la ventana Project (proyecto). Consejo: En la figura 1.2, todas las aplicaciones excepto Visual Basic están minimizadas (convertidas en iconos). Mantener las aplicaciones minimizadas ayuda a evitar el desorden y la confusión en la pantalla. Puedes encontrar de utilidad elegir la opción Minimizar del menú Opciones del Administrador de programas. Cuando esta opción está seleccionada. el Administrador de programas se minimiza a sí mismo automáticamente siempre que arranques un nuevo programa. 3
EL LIBRO DEL VISUAL BASIC
Casi puedo oírte murmurar "esto va a ser complicado". Indudablemente, lo va a ser. Pero la clave para gestionar la complejidad es la organización, y el entorno de Visual Basic está diseñado para conseguir que te mantengas organizado. Echemos un vistazo a cada una de las ventanas. La ventana principal
La ventana principal contiene la barra de menús con ocho menús desplegables. Uno de los más importantes, sobre todo mientras estés aprendiendo Visual Basic, es el menú Help (ayuda). Desde este menú puedes acceder a un tutorial que te presenta Visual Basic, puedes buscar la información necesaria para contactar con los servicios Microsoft de apoyo a sus productos y puedes explorar todo el sistema de Ayuda de Visual Basic. Por ejemplo, cuando selecciones Contents (contenidos) del menú Help verás una lista de todas las categorías de información contenidas en el sistema de Ayuda en línea. Haciendo clic sobre las frases subrayadas en las diversas pantallas de la Ayuda te puedes mover hacia las secciones y temas específicos que necesites ver. Cuando selecciones Search (buscar) del menú Help, la Ayuda mostrará un cuadro de diálogo que te permitirá especificar un tema y moverte inmediatamente hacia la Ayuda sobre ese tema. Además, la Ayuda proporciona información sensible al contexto. Si necesitas sa ber más sobre un botón, un cuadro de diálogo, una ventana, un mensaje de error o sobre cualquier otro elemento con el que estés trabajando en Visual Basic, simplemente pulsa la tecla F1 cuando el elemento esté resaltado, y la Ayuda mostrará inmediatamente la información apropiada. (Puedes encontrar una descripción más completa sobre el sistema de Ayuda de Visual Basic en el capítulo 8.)
1 Comenzar rápidamente con Visual Basic
hayas empezado todavía aparecen cuatro entradas en la ventana del proyecto, como viste en la figura 1.2. La primera es el nombre de archivo Form1.frm; su etiqueta (Form1) indica que el archivo está asociado con la ventana de formulario denominada Form1. Si guardas el formulario en un disco sin cambiarle el nom bre, Visual Basic usa el nombre de archivo por omisión Form1.frm. Una aplicación puede estar compuesta de muchos formularios, cada uno de los cuales se almacena en un archivo separado. (Como los archivos están separados, un formulario también puede ser compartido por otras aplicaciones.) Las tres entradas adicionales que aparecen en la ventana del proyecto son los nombres de los archivos CMDIALOG.VBX, GRID.VBX y MSOLE2.VBX. La extensión VBX indica que esos archivos son archivos de extensión de Visual Basic. Cuando se carga un archivo de extensión se añaden herramientas suplementarias a la paleta de la caja de herramientas (que se trata en el siguiente apartado). La ventana del proyecto también contiene dos botones, etiquetados View Form (ver formulario) y View Code (ver código). Por omisión, Visual Basic muestra el formulario correspondiente cuando se selecciona un archivo en la ventana del proyecto. Esta vista te permite diseñar el interfacede usuario para tu aplicación:
Botón New Form (nuevo formulario) Botón New Module (nuevo módulo) Botón Open Project (abrir proyecto) Botón Save Project (guardar proyecto) Botón Menu Design Window (ventana diseñar menú) Botón Properties Window (ventana propiedades) Botón Start Button (botón ejecutar)
La ventana principal también contiene la barra de herramientas. Los botones de la barra de herramientas —que se muestran en la figura 1.3— son atajos para los comandos que se usan con más frecuencia. Por ejemplo, en lugar de abrir el menú File (archivo) y seleccionar el comando Open Project (abrir proyecto) puedes, simplemente, hacer clic en el botón Open Project.
Botón Break (botón detener)
Botón P rocedure Step (saltar procedimiento)
Finalmente, a la derecha de la barra de herramientas en la ventana principal verás dos campos que sirven para indicar la posición y el tamaño del objeto que está seleccionado actualmente en la ventana del formulario.
Botón Single Step (un solo paso) Botón Calls (llamar) Botón Instant Watch (punto de vigía) Botón Toggle Breakpoint (activar/desactivar punto interrupción)
La ventana del proyecto
La ventana del proyecto (Project) contiene una lista de todos los archivos necesarios para ejecutar el programa de Visual Basic que estés creando. Aunque no 4
Botón End (fin)
Figura 1.3. La barra de herramientas de Visual Basic
5
EL LIBRO DEL VISUAL BASIC
la parte de la aplicación que el usuario ve y con la que interactúa. Si haces clic en el botón View Code de la ventana del proyecto, el código del archivo seleccionado aparecerá en una ventana diferente. El código se refiere a las instrucciones en un lenguaje de programación; el proceso de programar se denomina crear código o "codificar" . Cuando se crea un programa con Visual Basic, el trabajo se divide entre el diseño del formulario, el cual ve el usuario, y la creación del código, que controla el funcionamiento del programa. Para volver desde la ventana del código a la del formulario, simplemente tienes que hacer clic sobre el formulario para activarlo o en el botón View Form en la ventana del proyecto.
1 Come nzar ráp idamente c on Visual Basic
a crear objetos en pantalla y para escribir tu programa. Puedes interactuar con los objetos del formulario modificando su tamaño, posición y otros atributos. Pero ni los objetos estarán activos ni se ejecutará el código; por ejemplo, si colocas una barra de desplazamiento en un formulario podrás cambiar el tamaño y la posición del objeto, pero no podrás usarlo para desplazar nada.
Herramienta Pointer (puntero) Herramienta Label (etiqueta)
La ventana del formulario y la caja de herramientas
Un formulario es una zona de visualización que corresponde a una ventana que verás cuando tu aplicación esté funcionando. Cuando se empieza un proyecto nuevo, Visual Basic crea un formulario vacío y le da el título Form1. A medida que diseñas tu aplicación, el formulario sirve como un lienzo en el que puedes dibujar diversas partes de la aplicación. Los componentes de la aplicación que se colocan en el formulario se denominan objetos o controles —cuadros de dibujo, botones de opciones y barras de desplazamiento, por ejemplo. (De hecho, Visual Basic considera al propio formulario como un objeto.) Los controles se crean mediante la paleta de la caja de herramientas, la cual se muestra en la figura 1.4. Cada control está representado por un icono o herramienta de la caja de herramientas. La mayoría de las herramientas que puedes ver en la figura 1.4 están construidas internamente en Visual Basic. (El capítulo 5 describe las herramientas estándar con detalle.) Sin embargo, como ya se ha mencionado, la caja de herramientas puede ampliarse para incluir nuevas herramientas adicionales. Cada archivo con la extensión VBX de la ventana del proyecto proporciona una o más herramientas nuevas para la caja de herramientas. La herramienta Grid (cuadrícula), la herramienta OLE y la herramienta Common Dia log, por ejemplo, provienen de los archivos GRID.VBX, MSOLE2.VBX y CMDIA LOG.VBX que se incluyen por omisión en tu archivo del proyecto. La Edición Profesional de Microsoft Visual Basic ofrece archivos VBX adicionales y te proporciona la posibilidad de crear nuevas extensiones (si eres un programador en C o en Pascal). También hay disponibles varios paquetes de software de otros fabricantes. La apariencia de tu programa la diseñas eligiendo controles de la caja de herramientas y poniéndolos en el formulario. Cuando estás diseñando una aplicación, Visual Basic funciona de manera muy diferente a cuando estás ejecutando la aplicación. En la fase de diseño, Visual Basic proporciona herramientas para ayudarte 6
Herramienta Frame (marco)
Herramienta Picture Box Herramienta Text Box
(cuadro de
comprobación
Herramienta Combo Box -
(cuadro de
texto)
Herramienta Command Button (botón de
Herramienta Check Box
(cuadro de dibujo)
comando)
Herramienta Option Button (botón de opción) Herramienta List Box
(cuadro de
lista)
(cuadro combinado)
Herramienta Horizontal Scroll Bar (barra de desplazamiento horizontal) Herramienta Timer (reloj)
Herramienta Vertical Scroll Bar (barra de desplazamiento vertical) Herramienta Drive List Box (cuadro de lista
Herramienta Directory List Box (cuadro de lista
de directorio)
Herramienta Shape (forma)
de unidades)
Herramienta File List Box (cuadro de
lista de archivos)
Herramienta Line (línea)
Herramienta Image (imagen)
Herramienta Pata (datos)
Herramienta Common Dialog
Herramienta Grid (cuadrícula)
(diálogo común) Herramienta OLE
Figura 1.4. La caja de herramientas de Visual Basic
Sin embargo, cuando ejecutes las aplicaciones ya terminadas, Visual Basic retirará las herramientas de diseño. Se fijará el diseño de la ventana; los objetos de la pantalla pueden ser activados y el usuario puede interactuar con lo que aparezca en pantalla de la forma que hayas diseñado. La aplicación comienza a funcionar y Visual Basic ejecuta las declaraciones de tu programa. (Visual Basic te permite sa ber mediante la barra del título de la ventana principal si estás diseñando o ejecutando una aplicación.) 7
LIBRO DEL VISUAL BASIC
1 Comenzar rápidamente con Visual Basic
La ventana de pro piedades
Las propiedades de Visual Basic son mecanismos formales que sirven para descri bir los atributos de un objeto. En el mundo real puedo preguntarte, "¿de qué color es esa vaca?" En Visual Basic te preguntaría en lugar de eso, "cuál es el valor de la propiedad Color de esa vaca?" La respuesta en ambos casos sería, por supuesto, "púrpura". La raza es otra propiedad típica de las vacas. Los valores o ajustes esperados de la propiedad Raza podrían ser Guernsey, Holstein y He reford. Todo objeto de Visual Basic tiene propiedades específicas cuyos ajustes controlan la apariencia y comportamiento del objeto en una aplicación. Algunas propiedades están restringidas a ciertos valores. Por ejemplo, la propiedad Visible de un objeto puede ser ajustada a True o False (verdadero o falso); es decir, el objeto es visible o invisible. Otras propiedades, como el título de una ventana de formulario puede ajustarse prácticamente a cualquier cosa. Date cuenta de que no tienes que establecer todas las propiedades de cada objeto; los valores por omisión de muchas propiedades son, a menudo, perfectamente aceptables. Aunque muchas propiedades pueden alterarse tanto en la fase de diseño como cuando la aplicación está funcionando, la ventana Properties, que se muestra en la figura 1.5, sólo está activa durante la fase de diseño. Puedes activar la ventana Properties de varias maneras: haciendo clic simplemente sobre ella, seleccionando el comando Properties del menú Window (ventana), pulsando F4 o haciendo clic en el botón Properties Window (ventana propiedades) de la barra de herramientas.
Cuadro Object
(objetos)
Cuadro Setting (Ajustes)
Lista de propiedades
Figura 1.5. La ventana Properties (propiedades)
8
El cuadro de lista desplegable que hay en la parte superior de la ventana de propiedades se denomina el cuadro Objeto. Muestra el nombre de todos los objetos de la aplicación, así como sus tipos. Inicialmente, el cuadro Objeto solamente contiene información sobre el formulario; pero, a medida que se añaden controles al formulario, Visual Basic agrega esos objetos a la lista desplegable del cuadro Objeto. Debajo del cuadro Objeto se encuentra el cuadro Ajustes (Settings) y la lista de propiedades. Esta lista te permite desplazarte por todas las propiedades del objeto que se muestra en el cuadro Objeto y ver el valor actual de cada propiedad. Cuando se selecciona una propiedad de esta lista, su valor actual aparece en el cuadro Ajustes que hay sobre la lista de propiedades. Si quieres cambiar el valor puedes escribir un dato nuevo en el cuadro Ajustes o elegir un nuevo valor predefinido de una lista desplegable, dependiendo de la propiedad en concreto. Para demostrarte cómo puedes usar las diversas ventanas de Visual Basic para crear una aplicación, vamos a diseñar tu primer proyecto.
Crear un interface de usuario Como primer proyecto vamos a crear un programa que mida el tiempo transcurrido, de manera muy similar a lo que hace un cronómetro. Un cronómetro tiene un botón que se pulsa para que comience a contar el tiempo, otro que permite detener la cuenta y un lugar donde ver el tiempo transcurrido. Puedes usar este modelo como base para tu programa. En Visual Basic, un formulario servirá como lugar donde se vea el tiempo transcurrido y para situar los botones de inicio y parada. Para comenzar el diseño de la aplicación tendrás que examinar y modificar algunas de las propiedades del formulario. Establecer las p ropiedades del form ulario
Cuando se ejecute la aplicación, el formulario será presentado en una ventana de aplicación estándar. Si quieres que esta ventana se parezca a las que muestran otras aplicaciones escritas para Windows, debe tener ciertos atributos. Por ejemplo, uno de los atributos compartidos con las aplicaciones escritas para Windows consistirá en que el nombre de la aplicación aparezca en la barra del título. En Visual Basic muchos atributos de ese tipo se controlan mediante las propiedades de los objetos. Para comenzar a establecer las propiedades del formulario, en primer lugar, selecciona el formulario como objeto actual haciendo clic en cualquier lugar de la ven 9
EL LIBRO DEL VISUAL BASIC
tana etiquetada como Form1. Ahora mira a la ventana Properties de Visual Basic, en la que Form l aparece en el cuadro Objetos. Si quieres cambiar el título del formulario, haz clic en la propiedad Caption (título) en la lista de propiedades. El título actual (por omisión), Form1, aparecerá en el cuadro de Ajustes. Escribe Cronómetro para reemplazar el título. A medida que lo escribes, este nuevo título aparece tanto en el cuadro Ajustes como en la barra del título de la ventana del formulario. Observa los dos botones que hay a la izquierda del cuadro Ajustes que están marcados con una X y con una marca de confirmación (en forma de V). El botón de confirmación sirve para introducir el valor que hayas establecido en el cuadro Ajustes; hacer clic sobre este botón es equivalente a pulsar la tecla Intro. Si haces clic en el botón X se cancela la entrada actual y se restaura el valor anterior en el cuadro Ajustes. Cuando la propiedad seleccionada pueda tomar solamente un conjunto de valo res restringido y predefinido, el cuadro Ajustes actúa como un cuadro de lista desplegable en lugar de hacerlo como un campo para la entrada de texto. Des plázate a través de la lista de propiedades y selecciona, por ejemplo, la propiedad Visible. E1 botón con una flecha apuntando hacia abajo que hay en el cuadro Ajustes se vuelve activo, lo que significa que los ajustes para la propiedad Visible están restringidos a los que estén disponibles en la lista desplegable. Si haces clic en el botón con la flecha apuntando hacia abajo, la lista se desplegará para mos trar los ajustes True (verdadero) y False (falso), como se muestra en la figura 1.6. Asegúrate de que la propiedad Visible está establecida como True. Otra propiedad relacionada con la apariencia del formulario es BorderStyle (estilo del borde), la cual controla si el usuario podrá o no cambiar de tamaño la venta-
1 Co menzar ráp idamente c on Visual Basic
na cuando la aplicación esté funcionando. Como la aplicación Cronómetro va a tener una apariencia fija, el tamaño de su ventana no se podrá ajustar. Selecciona la propiedad BorderStyle de la lista Properties y luego ajusta la propiedad a 3 - Fixed Double (fijo y doble) seleccionando esta opción de la lista desplegable del cuadro Ajustes. (La opción Fixed Double determina que la ventana tendrá un bor de mediante el que no se podrá cambiar el tamaño de dicha ventana, y que no tendrá botones Minimizar ni Maximizar.)
La propiedad Name (nombre) Todos los objetos en Visual Basic tienen una propiedad llamada Name (nombre). Cuando se establece la propiedad Name se le está dando al objeto una identidad que se puede usar dentro del programa para referirse a él. En una ventana del formulario puedes acceder a un objeto haciendo clic sobre él. En la parte del có digo del programa debes referirte al objeto por el nombre que le hayas asignado con la propiedad Name. (Date cuenta de que las propiedades Name y Caption son diferentes: el nombre de un objeto es su identidad en el código del progra ma; el título de un objeto es lo que el usuario ve en la pantalla, el texto identificativo que se muestra en la ventana de la aplicación.)
Selecciona la propiedad Name en la lista Properties. Su valor por omisión, que aparece en el cuadro Ajustes, es Form1. Edita la propiedad Name de tu formulario escribiendo el texto M iF orm en el cuadro Ajustes. Nota: Cuando se cambia el nombre de un formulario, Visual Basic re fleja ese cambi o en la lista de nombr es de archi vos que se muest ran en la ventana del proyecto. Recuerda que la definición de cada formulario se almacena en un archivo separado. Cuando guardes tu aplicación po drás elegir el nombre de archivo que quieras para tu formulario, pero Visual Basic te sugerirá, un nombre por omisión basándose en el nombre del formulario.
Añ ad ir ob jet os
Volvamos al diseño del formulario para crear los botones que inicien y detengan la cuenta del tiempo:
Figura 1.6
1. Haz clic en la herramienta Command Button (botón de comando.) de la caja de herramientas, y luego mueve el puntero del ratón a la zona blanca de la ventana del formulario. El cursor se transforma en una cruz, lo que te indica que estás en el modo de dibujo.
Establecer la propiedad Visible del formulario
10
11
EL LIBRO DEL VISUAL BASIC
1 Come nzar ráp idamente c on Visual Basic
2. Sitúa el cursor en la esquina superior izquierda del formulario. 3. Pulsa y mantén pulsado el botón del ratón y arrastra el cursor hacia abajo y hacia la derecha. 4. Suelta el botón del ratón. Cuando sueltes el botón del ratón Visual Basic creará un objeto botón de comando en el área rectangular delimitada por la operación de arrastre. Tu botón de comando debe parecerse al que se muestra en la figura 1.7. Después de que hayas creado el botón, la herramienta Pointer (puntero) vuelve a estar activa de nuevo en la caja de herramientas. Cuando está activa la herramienta puntero puedes editar el formulario moviendo los objetos y cambiando sus tamaños. Para mover un objeto simplemente tienes que arrastrarlo a su nueva ubicación. Si quieres cambiar el tamaño de un objeto, arrastra uno de sus gestores (que se muestran en la figura 1.7) para agrandarlo o reducirlo. Si los gestores no están visibles, haz clic en el objeto para seleccionarlo. Ahora crea un segundo botón de comando, usando esta vez un atajo: haz doble clic en la herramienta Command Button de la caja de herramientas. Visual Basic crea un botón del tamaño por omisión y lo sitúa en el centro del formulario. Cambia la posición y el tamaño del segundo botón de manera que los dos botones aparezcan en el lado izquierdo de la pantalla y tengan el mismo tamaño. Estos dos botones, ahora etiquetados Command1 y Command2 por omisión, servirán como botones de inicio y parada para la aplicación Cronómetro. Para mayor claridad debes asignar sus títulos adecuadamente. Sigue el mismo proceso que
Gestores
Figura 1.7.
utilizaste al establecer las propiedades del formulario para ajustar las propiedades de los botones: 1. Haz clic en el botón de más arriba para seleccionarlo. 2. Selecciona la propiedad Caption de la lista de propiedades en la ventana Properties. 3. En el cuadro Ajustes cambia el título por el de Inicio. 4. Haz clic en el segundo botón y cambia el ajuste de su propiedad Caption para que ahora sea Parada. Incluso aunque acabes de cambiar los títulos, también debes cambiar los nom bres de los botones de manera que puedas referirte a ellos fácilmente en el códi
Elegir nombres
No es absolutamente necesario cambiar los nombres de los botones de la aplicación Cronómetro que estás creando, pero te darás cuenta de que referirte en tu programa a btnlnicio es mucho más claro que referirte a Com mandl. T.S. Eliot ya lo advirtió: "Ponerle nombre a los gatos es un asunto difícil"; lo mismo se puede decir de los objetos en los programas. Podrías pensar que los nombres cortos son más fáciles de escribir, o qué es más cómodo que el sistema ofrezca un nombre por omisión. Pero cuando vuelvas a un programa seis meses después de que lo hayas escrito, puede serte muy difícil determinar exactamente lo que el programa está haciendo si no has elegido nombres significativos. Debes tratar de usar una convención coherente para elegir los nombres que proporcione tanto el contexto como la descripción. Los nombres btnlnicio y btnParada, por ejemplo, tienen un prefijo de tres letras que identifica el tipo de objeto en el código de tu programa. En español usamos a menudo frases descriptivas para establecer el contexto —por ejemplo, en vez de mencionar simplemente a Cardenal Silvestre es habitual referirnos a "mi gato, Cardenal Silvestre", con el fin de evitar una posible confusión entre el gato y un alto cargo eclesiástico. Sin embargo, en Visual Basic no puedes hacer referencia "al botón llamado Inicio", así que resulta útil comprimir el contexto (btn) y el nombre (Inicio) en un único identificador (btnlnicio).
Un botón de comando recién creado
12
13
LIBRO DEL VISUAL BASIC
go de tu programa. (Recuerda que las propiedades Caption y Name no son lo mismo; cambiar una no afecta a la otra.) Haz clic en el botón de arriba y selecciona su propiedad Name. En el cuadro Ajustes cambia el nombre por omisión Command1 por el de btnInicio. Luego haz clic en el botón inferior y cambia su propiedad Name estableciéndola como btnParada. (Consulta el cuadro titulado "Elegir nombres".) Completar la ventana
Ahora que ya has situado en la pantalla los controles del usuario de la aplicación Cronómetro, necesitas un lugar para mostrar los resultados cuando el programa se esté ejecutando. Para ello, vamos a añadir varios cuadros de texto al formulario: 1. Haz doble clic en la herramienta Text Box para crear un cuadro de texto. El cuadro de texto aparecerá en el centro del formulario. 2. Mueve el cuadro de texto a la zona superior de la ventana del formulario, a la derecha de los botones de comando.
1 Come nzar ráp idamente c on Visual Basic
También necesitas eliminar el texto por omisión que aparece dentro de los cuadros. Selecciona la propiedad Text (texto) de la lista de propiedades para cada cuadro de texto y borra todos los caracteres del cuadro Ajustes. Esta acción esta blece el valor de la propiedad Text a "nada" (una cadena de texto de longitud cero). Todos los elementos necesarios para la parte de la aplicación relativa al interface con el usuario están ahora en su lugar. De hecho, puedes "ejecutar" la aplicación tal y como está ahora. Selecciona el comando Start (iniciar) del menú Run (ejecutar), haz clic en el botón Start de la barra de herramientas o pulsa la tecla F5. La paleta de la caja de herramientas desaparece, al igual que la versión de diseño del formulario, y la ventana Cronómetro aparece en la pantalla, como se muestra en la figura 1.8. Puedes mover la ventana por la pantalla y también puedes hacer clic en los botones Inicio y Parada (aunque no sucederá nada, ya que todavía no has escrito las instrucciones en Visual Basic que calcularán el tiempo transcurrido). Selecciona el comando End (fin) del menú Run de Visual Basic o haz clic en el botón End de la barra de herramientas para finalizar la aplicación y volver al entorno de diseño de Visual Basic.
3. Usando el mismo método, crea dos botones de texto más, y organízalos como se muestra aquí:
Figura 1.8. La ventana de la aplicación Cronómetro durante su ejecución
Escribir el código 4. Usa el ratón para "coger" la esquina inferior derecha de la ventana del formulario y cambiar su tamaño, de manera que se ajuste holgadamente alrededor de los botones y de los cuadros de texto. Tienes que darles nombres a estos objetos nuevos. Haz clic en cada uno de los cuadros de texto y cambia el ajuste de la propiedad Name, usando el nombre txtInicio para el cuadro superior, txtParada para el del medio y txtLapsus para el de abajo. 14
Crear el código —escribir las instrucciones que controlan el funcionamiento del programa— es el corazón de la programación. Ahora que has terminado el interface de tu aplicación tienes que hacer que el programa funcione. Como vas a escribir comandos en el lenguaje Visual Basic es razonable pensar que esos comandos controlan el ordenador, aunque lo hacen de manera indirecta. Para comprender esta idea piensa en un avión a reacción. Cuando el piloto quiere que el avión vuele más alto debe tirar de la palanca de control, que está en la cabina del avión, hacia atrás. El efecto de esta acción es al 15
EL LIBRO DEL VISUAL BASIC
1 Come nzar ráp idamente c on Visual Basic
terar la posición de los elevadores del avión, de manera que el avión comienza a ascender. En un avión a reacción moderno no hay conexión física entre la palanca y los elevadores. Cuando el piloto tira hacia atrás de la palanca un sensor mide la distancia que ha movido la palanca y envía una señal a un dispositivo hidráulico que mueve los elevadores. Sin embargo, desde el punto de vista del piloto, la palanca controla el avión. No es de una importancia vital que el piloto sepa si tirar de la palanca tres centímetros produce un desplazamiento de 5 grados de la posición de los elevadores o de 10 grados; es suficiente con que el piloto conozca cómo responde el avión al cambio. Al igual que el piloto del avión, tú estás en los controles del ordenador, y Visual Basic es tu panel de instrumentos. El siguiente apartado se centrará en darte una visión del sistema desde "la cabina" —es decir, el aspecto que tiene para un programador de Visual Basic. Hay muchas cosas ocurriendo bajo la superficie, desde luego, pero de momento nos centraremos simplemente en un repaso y dejaremos el análisis de los detalles relevantes para los capítulos 2 y 3. Procedimientos para eventos
Ya has visto las propiedades de los objetos y cómo estas propiedades pueden modificarse para que afecten a un objeto. De una manera similar (en cierto modo), cada objeto puede asociarse con un conjunto de procedimientos que se ejecutan en momentos específicos. Un procedimiento es un grupo de instrucciones en el lenguaje de programación Visual Basic. Las instrucciones del procedimiento se llevan a cabo cuando se ejecuta el procedimiento. Todo el código ejecutable que escribas se encapsulará en uno u otro tipo de procedimiento. Todo procedimiento asociado con un objeto está ligado a un evento particular o acción y, por tanto, se le denomina procedimiento para evento. Los eventos incluyen acciones como Click, un evento que se produce cuando el usuario hace clic con el botón del ratón, y como Resize, un evento que ocurre cuando el usuario cambia el tamaño de una ventana de formulario. Los eventos ocurren sólo durante la ejecución del programa, y no durante el diseño. A cada objeto se le pueden asociar varios eventos; estos se describen con más detalle en el capítulo 5. Volvamos a nuestra aplicación Cronómetro. En la ventana del formulario haz do ble clic en el botón Inicio. Visual Basic abrirá una ventana de código como la que se muestra en la figura 1.9. El título de la ventana de código es MiForm.frm, el cual indica la relación entre el código y el formulario. El código que introduzcas en esta ventana se almacenará en el mismo archivo que contiene los objetos del formulario. 16
Figura 1.9. Una ventana de código de Visual Basic para Cronómetro
El cuadro Object de la parte superior izquierda de la ventana de código muestra el nombre del objeto que has seleccionado: btnInicio. El cuadro Procedure (procedimiento, que se abrevia como Proc) de la zona superior derecha te muestra qué procedimiento de evento estás editando. Como todavía no has seleccionado un procedimiento, Visual Basic ha elegido uno por omisión, el procedimiento de evento Click. El procedimiento que se muestra en la ventana de código es el que se ejecutará cuando el usuario haga clic sobre el botón Inicio mientras la aplicación se esté ejecutando. Aunque todavía no has escrito el código, ya aparecen dos declaraciones en la zona de texto de la ventana de código: Sub btnInicio_Click () End Sub
Cuando creaste este botón de comando, Visual Basic creó un conjunto de procedimientos de eventos por omisión para el objeto. Como puedes adivinar, los procedimientos por omisión no hacen nada; consisten simplemente en la declaración del procedimiento (la primera línea) y la declaración que marca el final del procedimiento (End Sub).
Declaraciones de procedimiento En la declaración del procedimiento, la palabra clave Sub identifica el comienzo de un procedimiento. A continuación va el nombre del procedimiento —en este caso, btnInicio_Click. Por último aparecen unos paréntesis, los cuales completan la definición. (Los paréntesis no se usan en este procedimiento, pero a pesar de ello deben incluirse; trataremos sobre su función en un capítulo posterior.) 17
EL LIBRO DEL VISUAL BASIC
El nombre de un procedimiento sirve para distinguirlo como un procedimiento de evento. No todos los procedimientos son procedimientos de eventos. Puedes crear un procedimiento en Visual Basic y darle cualquier nombre que desees (incluso Chaf o P uf si quieres). Pero el nombre de un procedimiento de evento debe cumplir las siguientes reglas: ■
La primera parte del nombre debe coincidir con el nombre de un objeto que hayas creado en el formulario (o debe ser la palabra Form , cuando el objeto relevante sea el propio formulario).
■ La última parte del nombre debe ser el nombre de un evento. ■ Las dos partes deben estar separadas por un guión de subrayado. En el caso del procedimiento btnInicio_Click, el objeto asociado es el botón del comando Inicio (btnInicio), y el evento es Click. Cuando el programa se está ejecutando lo que ocurre es algo así: la aplicación está aburrida en un extremo de la pantalla esperando que suceda algo. En ese momento se aproxima María con su ratón. Ella mueve el puntero del ratón sobre la imagen de la pantalla y hace clic. Windows le da un puntapié a la aplicación en el trasero y le dice, "¡Eh, haz algo!" Cuando Visual Basic piensa que el clic ha ocurrido sobre el botón llamado btnInicio se va a buscar el procedimiento denominado btnInicio_Click y ejecuta las instrucciones de ese procedimiento. Como programador, tu trabajo consiste en decidir qué instrucciones deben ser. Para ver cómo funciona esto escribe la instrucción Debug.Print "¡Hola, marinero!" en la línea en blanco que hay entre las declaraciones Sub y End. La ventana de código debe parecerse ahora a esto: Sub btnInicio_Click () Debug.Print "¡Hola, marinero!" End Sub
La instrucción Debug.Print le indica a Visual Basic que escriba texto en una ventana especial denominada ventana Debug. Pulsa la tecla F5 para salir del modo de diseño y comenzar a ejecutar la aplicación (tal y como está). Cuando hagas clic en el botón Inicio, las palabras Hola, marinero aparecerán escritas en la ventana Debug. Ahora selecciona el comando End del menú Run de Visual Basic. Visual Basic detendrá la aplicación y volverá al modo de diseño, donde podrás continuar diseñando tu aplicación. (Antes de continuar acuérdate de borrar la línea Debug.Print del procedimiento btnInicio_Click.) 18
1 Co menzar ráp idamente c on Visual Basic
Consejo: Date cuenta de que las palabras clave como Sub, Debug, Print y End aparecen en pantalla en la ventana de código en un color diferente que el resto del código. Visual Basic señaliza diferentes partes del código con varios colores para que los componentes individuales sean fácile s de encon trar. Pued es contro lar los color es que se usan selec cionando el comando Environment (entorno) del menú Options (opciones). Ello hará que aparezca el cuadro de diálogo Environment Options (opciones del entorno), en el cual puedes determinar los colores del texto y del
fondo
para
las
palabras
clave,
para
los
identificadores,
comentarios
y div ersos eleme ntos d e cód igo ad iciona les.
Declaraciones de variables
Cuando el usuario hace clic sobre el botón Inicio de la aplicación Cronómetro, el programa debe saber qué hora es (la hora de comienzo). Luego, cuando el usuario haga clic en el botón Parada, el programa debe restar la hora de comienzo de la hora de finalización para calcular el tiempo total transcurrido. Evidentemente, necesitas escribir el código que le permita al programa llevar a cabo todas estas acciones. Visual Basic usa una función llamada N ow para proporcionar la hora actual. Una función es un tipo especial de procedimiento que devuelve un valor. (Las funcio
Visual Basic te está mirando
Si cometes un error mientras estés escribiendo en la ventana de código, Visual Basic puede avisarte resaltando el error y mostrando un cuadro de diálogo informativo. Este sistema de vigilancia, denominado comprobación automática de la sintaxis, se activa cada vez que se pulsa la tecla Intro. Por supuesto, Visual Basic no puede detectar todos los posibles errores a medida que vas escribiendo, pero sí puede darse cuenta de los errores de sintaxis; o sea, los errores referentes a la forma en que se ha usado el lenguaje Visual Basic, como una palabra clave mal escrita, palabras con el orden alterado en una instrucción, puntuación incorrecta, etc. Si escribes txtParada..Text en lugar de txtParada.Text , por ejemplo, Visual Basic te informará de tu error. Puedes desactivar la comprobación automática de la sintaxis si quieres: selecciona el comando Environment del menú Options y establece la opción Syntax Checking (comprobación de la sintaxis) como No en el cuadro de diálogo Environment Options.
19
1 Comenzar rápidamente con Visual Basic
EL LIBRO DEL VISUAL BASIC
nes de Visual Basic tienen un estrecho parecido con el concepto matemático de funciones. Por ejemplo, las funciones de Visual Basic denominadas Si n, Cos y Tan devuelven el seno, el coseno y la tangente de un ángulo.) Cuando el usuario haga clic en el botón Inicio, tu programa debe llamar a la función Now, la cual devolverá un valor: la hora actual (de comienzo). Entonces el programa debe "recordar" este valor para que pueda sustraerlo de la hora de parada cuando el usuario haga clic en el botón Parada. Para almacenar este valor en un programa de ordenador debes reservar un lugar para él en la memoria del ordenador. Esto se hace con declaraciones de variables. En la ventana de código, haz clic en el botón con la flecha apuntando hacia abajo del cuadro Object para desplegar la lista de todos los objetos del formulario. En esta lista selecciona la entrada que corresponde a la categoría de todo el código que no está asociado con ningún objeto en particular (general). Visual Basic cam biará entonces, automáticamente, el ajuste en el cuadro Procedures a (declara tions), o sea, declaraciones. (Nos referiremos a esto a lo largo del libro como la sección del código dedicada a las declaraciones generales.) Ahora introduce las siguientes líneas en la ventana de código: Dim HoraInicio As Variant Dim HoraParada As Variant Dim Lapsus As Variant
Estas declaraciones le dicen a Visual Basic que quieres reservar un lugar de almacenamiento para los valores de la hora de inicio, de la de parada y del tiempo transcurrido en las variables denominadas HoraInicio, HoraParada y Laspsus. Las variables son, esencialmente, nombres de zonas reservadas de la memoria del ordenador. (En los capítulos 2 y 3 se trata más este tema.) La declaración D im le dice a Visual Basic cuánta memoria tiene que reservar y cómo se va a llamar a esa porción de la memoria. D im es una declaración porque le dice a Visual Basic cómo debe configurarse el programa. Cada una de las tres líneas que hemos visto más arriba declara una sola variable, y las tres tienen esta forma: Dim nombre As Variant
D im y A s son palabras clave, palabras reservadas que tienen un significado especial para Visual Basic. Las declaraciones difieren sólo porque cada variable debe tener un nombre distinto. La palabra clave Variant le dice a Visual Basic que reserve suficiente memoria para cualquier tipo de valor. (Se pueden usar otras pala bras clave para hacer las declaraciones más específicas. Usando Integer en lugar 20
Terminología
Si te parece que D im es una palabra algo insulsa y piensas que otra pala bra como Declare sería más apropiada, estás en lo cierto. Sin embargo, D im es una versión abreviada de Dimensión y es una reliquia de las primeras versiones del lenguaje Basic, que data de los años 60. A medida que los lenguajes de programación evolucionan tienden a retener ciertas características de las versiones previas por el asunto de la compatibilidad. Todo esto te resultará de interés, claro está, sólo si dominas el idioma inglés.
de Variant, por ejemplo, se indicaría a Visual Basic que reservase memoria suficiente sólo para un número entero.) Instrucciones ejecutables
Ahora que ya has reservado memoria para guardar los valores del tiempo puedes pasar a escribir el código ejecutable del programa. En contraste con una declaración, que se utiliza para configurar el programa, una instrucción ejecutable provoca que algo suceda cuando es ejecutada. Por ejemplo, la instrucción Debug.Print que usaste antes es una instrucción ejecutable. Selecciona el objeto btnInicio en el cuadro Object de la ventana de código. Edita el procedimiento btnInicio_Click introduciendo las siguientes instrucciones entre la línea Sub btnI nicio_C li ck( ) y la línea End Sub. HoraInicio = Now txtInicio.Text = Format(HoraInicio, "hh:mm:ss") txtParada.Text= "" txtLapsus.Text= ""
Cuando tu programa esté funcionando y el usuario haga clic en el botón Inicio, se ejecutarán estos comando. La primera línea de código usa la función Now para obtener la hora actual, y luego la guarda en el lugar de almacenamiento denominado HoraInicio. La siguiente línea muestra la hora en el cuadro de texto superior (txtInicio) estableciendo para ello la propiedad Text de este objeto; también le da formato a la hora de comienzo para que aparezca como horas, minutos y segundos, usando para ello una función de Visual Basic denominada Format. Las siguientes dos líneas borran cualquier cosa que hubiera en pantalla en los otros dos cuadros de texto (txtInicio y txtLapsus), estableciendo sus propiedades Text como cadenas vacías. 21
EL LIBRO DEL VISUAL BASIC
Ahora completa el programa seleccionando el objeto btnParada en el cuadro Ob ject de la ventana de código. Edita su procedimiento de evento Click como se muestra a continuación: Sub btnParada_Click () HoraParada = Now Lapsus = HoraParada - HoraInicio txtParada.Text = Format(HoraParada, "hh:mm:ss") txtLapsus.Text = Format(Lapsus, "hh:mm:ss") End Sub
Este procedimiento se ejecuta cuando el usuario hace clic en el botón Parada. En primer lugar, la función Now devuelve la hora actual, la cual es guardada en la variable HoraParada. La siguiente línea calcula el tiempo transcurrido restando a HoraParada el valor de HoraInicio. Luego, la hora de parada y el tiempo transcurrido se escriben en la pantalla, estableciendo para ello la propiedad Text de los objetos txtParada y txtLapsus. Como ocurría en el procedimiento btnInicio_Click, la función Format convierte los valores del tiempo al formato que muestra horas, minutos y segundos.
Ejecución del programa Simplemente, pulsa F5 para arrancar la aplicación. Usa el "cronómetro" haciendo clic en el botón Inicio, espera unos segundos y luego haz clic en el botón Parada. Debes ver algo como el resultado que se muestra en la figura 1.10. Puedes hacer clic de nuevo en el botón Inicio para volver a poner en marcha el cronómetro. Para cerrar la aplicación Cronómetro puedes hacer clic en el botón End de la barra de herramientas, pulsar Alt+F4 o seleccionar el comando Cerrar del menú de control (el menú que aparece cuando se hace clic en el extremo superior izquierdo de una ventana, y al que algunas veces se denomina menú del sistema).
1 Comenzar rápidamente con Visual Basic
Revisar el diseño Resulta muy fácil pasar por alto detalles de programación por no pensar en el usuario del programa. Miremos de nuevo al diseño del interface de Cronómetro: dos botones, tres cuadros de texto. Muy simple. Pero piensa en la persona que no conozca el propósito del programa. Los términos inicio y parada se explican a sí mismos, pero ¿qué información puede desprenderse de los tres cuadros de texto en blanco? Una mejora obvia que puedes realizar al diseño del formulario es añadir una etiqueta a esos cuadros, de manera que quede claro cuál es la información que proporcionan. El icono Label (etiqueta) de la caja de herramientas se parece a una A mayúsculas. Usando la herramienta Label, dibuja un objeto etiqueta al lado del cuadro de texto superior en la ventana del formulario. Puede que sea necesario que le cam bies el tamaño al formulario y que muevas los cuadros de texto para hacer sitio a la etiqueta. Puedes seleccionar los tres cuadros a la vez de manera que puedas moverlos como un grupo: simplemente, haz clic en el cuadro de texto superior y luego mantén pulsada la tecla Ctrl mientras haces clic en los otros dos cuadros de texto. A continuación, haz clic en el nuevo objeto etiqueta, selecciona la propiedad Caption de la etiqueta en la lista Properties y escribe Hora de inicio: en el cuadro Ajustes. Luego crea dos etiquetas similares junto a los otros dos cuadros de texto y establece sus propiedades Caption a Hora de parada: y Tiempo transcurrido: respectivamente, como muestra la figura 1.11. ¿Alguna otra mejora de diseño que considerar? Pulsa F5 para ejecutar la aplicación otra vez, y luego trata de hacer clic en el botón Parada antes de hacer clic en el botón Inicio. La aplicación debería responder de una manera razonable a este error del usuario, pero en lugar de ello obtienes un extraño resultado: la hora de parada y el tiempo transcurrido aparecen en la pantalla sin la hora de ini Cronómetro Inicio
Hora de inicio: Hora de parada:
Parada Tiempo transcurrido:
Figura 1.10. Ejecución de la aplicación Cronómetro
22
Figura 1.11. Añadir etiquetas a los cuadros de texto
23
EL LIBRO DEL VISUAL BASIC
cio. Tienes que cerrar la aplicación y volver al modo de diseño para solucionar el problema. Dado el diseño actual, la manera más simple de solucionar este problema consiste en impedir el uso del botón Parada hasta que el usuario haya hecho clic en el botón Inicio. Para ello, haz clic sobre el botón Parada en la ventana del formulario para seleccionarlo, y luego elige la propiedad Enabled (activado) de la lista Properties. Establece la propiedad a False en el cuadro Ajustes. Ahora, el botón Parada estará desactivado cuando la aplicación arranque por primer vez. Abre la ventana de código y edita el procedimiento btnInicio_Click para que aparezca como se muestra aquí (añadiéndole las dos líneas que aparecen en un color distinto). Puedes usar las teclas del cursor para mover el punto de inserción en la ventana del código, o simplemente, hacer clic con el ratón para situar el punto de inserción.
1 Comenzar rápidamente con Visual Basic
Los cambios que acabas de hacer son únicamente una muestra de los muchos posibles cambios que pueden mejorar el programa. Por ejemplo, como muchos cronómetros tienen solamente un botón, podrías implementar el programa con un botón de comando, y cambiar el título del botón de Inicio a Parada (o viceversa) cada vez que se hiciera clic sobre él. Probablemente, a ti mismo se te ocurrirán muchas mejoras. Cronómetro Inicio
Hora de inicio:
:
00 18:39
Hora de parada: Patada Tiempo transcurrido:
Figura 1.12. Sub btnInicio_Click () HoraInicio = Now txtInicio.Text = Format(HoraInicio, "hh:mm:ss") txtParada.Text= "" txtLapsus.Text= "" btnParada.Enabled = True btnInicio.Enabled = False End Sub
El nuevo código vuelve a activar el botón Parada después de que el usuario haga clic en el botón Inicio. Entonces desactiva el botón Inicio, lo cual elimina otro error posible: hacer clic en el botón Inicio dos veces consecutivas. Para completar los cambios, también necesitas editar el procedimiento btnParada_Click, añadiéndole dos líneas como se muestra aquí: Sub btnParada_Click () HoraParada = Now Lapsus = HoraParada - HoraInicio txtParada.Text = Format(HoraParada, "hh:mm:ss”) txtLapsus.Text = Format(Lapsus, "hh:mm:ss") btnParada.Enabled = False btnInicio.Enabled = True End Sub
La figura 1.12 muestra la versión final del interface de la aplicación. En este caso, el usuario ha hecho clic en el botón Inicio y el cronómetro está corriendo. 24
La versión final de la aplicación Cronómetro
Guardar el programa Aun te queda un asunto de interés: guardar el programa. En este caso tu primer paso debe consistir en seleccionar el archivo CMDIALOG.VBX en la ventana Pro ject y elegir el comando Remove File (eliminar archivo) del menú File (archivo). Repite el proceso para los archivos GRID.VBX y MSOLE2.VBX. Como no has utilizado estas herramientas no necesitas guardar los archivos como parte de este proyecto. Ahora selecciona el comando Save Project (guardar proyecto) del menú File de Visual Basic o haz clic en el botón Save Project de la barra de herramientas. En el cuadro de diálogo Save File As (guardar archivo como), que se muestra en la figura 1.13, Visual Basic te pide el nombre del archivo y el directorio en el que quieres guardar el código del formulario y su diseño de pantalla, sugiriéndote el nombre por omisión MIFORM.FRM (el nombre del formulario más la extensión FRM) para la aplicación Cronómetro. Después de que suministres la información necesaria haz clic en OK (aceptar). A continuación Visual Basic muestra el cuadro de diálogo Save Project As (guardar proyecto como), que se plasma en la figura 1.14, lo cual te permitirá guardar el archivo del proyecto. El archivo del proyecto contiene los nombres de todos los archivos de formularios y alguna información adicional sobre el proyecto. (La 25
EL LIBRO DEL VISUAL BASIC
1 Comenzar rápidamente con Visual Basic
chivos de proyecto (todos los archivos que tengan la extensión MAK). Abre el archivo CRONO.MAK haciendo doble clic sobre su nombre en la lista o seleccionando el nombre del archivo y haciendo clic en el botón OK. Pulsa F5 para ejecutar la aplicación, o si deseas modificarla de nuevo, abre las ventanas del formulario o del código, haciendo clic sobre los botones correspondientes en la ventana Project.
Figura 1.13. El cuadro de diálogo Guardar como
aplicación Cronómetro tiene sólo un archivo de formulario.) Visual Basic sugerirá el nombre por omisión PROJECT1.MAK para el archivo del proyecto de esta aplicación. Puedes utilizar un nombre de archivo diferente, pero en los archivos de proyecto debes incluir la extensión MAK. De momento, guarda la aplicación Cronómetro con el nombre CRONO.MAK. (Volveremos a este proyecto en un capítulo posterior.)
Figura 1.14. El cuadro de diálogo Save Project As
Para cargar y ejecutar tu aplicación más tarde, primero debes ejecutar Visual Basic. (Si quieres crear una versión de la aplicación que se ejecute como cualquier otro programa de Windows, sin Visual Basic, debes compilar el programa, como verás en el capítulo 2.) Luego elige el comando Open Project (abrir proyecto) del menú File de Visual Basic o haz clic en el botón Open Project de la barra de herramientas. El cuadro de diálogo Open Project mostrará una lista con todos los ar 26
27
2 Datos e instrucciones Seguro que estarás familiarizado con gran parte de la terminología que se usa en la industria del ordenador: bits, bytes, RAM, ROM, CPU, etc. Pero si sólo tienes una idea general de lo que estos términos significan, los apartados siguientes están pensados para ti. Comprender qué es lo que sucede dentro del ordenador es una parte muy importante del proceso de aprender a programar. Desde luego puedes limitarte, simplemente, a "aprender las reglas" y realizar el trabajo de forma más o menos adecuada, pero un poco de conocimiento adicional puede hacerte avanzar un gran trecho en el proceso que debes seguir para sentirte a gusto con los ordenadores y para ser productivo.
Ordenadores y datos Los ordenadores son herramientas que sirven para manipular información, de la misma manera que las sierras y los cepillos son herramientas que sirven para manipular la madera. La madera se mide en centímetros; la información se mide en bits. Un bit es la unidad fundamental que mide cuánta información se puede transferir de un lugar a otro. Es el bloque de información más pequeño del universo de la información. La respuesta a una cuestión, por ejemplo, requiere, al menos, un bit de información —si no hay bits no hay respuesta. Sobre el papel un bit se representa, por convenio, con el número 0, o con el número 1. En un ordenador digital, un bit es representado por la existencia o inexistencia de corriente eléctrica. Si tienes 10 centímetros de madera sabes que estás trabajando con una cantidad fija de material tangible. ¿Pero qué significa que tienes tres bits de información? Significa, como Humpty Dumpty le dijo a Alicia, "sólo lo que yo quiera que signifique". Como se ilustra en la figura 2.1, 3 bits pueden representar respuestas a las tres cuestiones "¿Es más grande que una panera? ¿Tiene colores brillantes? ¿Sabe 29
2 Datos e instruccione s
EL LIBRO DEL VISUAL BASIC
Figura 2.1.
Figura 2.2.
Bits representando información
Los valores posicionales en el sistema numérico decimal
cantar? (no, sí, no); una serie de giros a la izquierda o a la derecha (izquierda, derecha, izquierda); o cualquier otro ejemplo.
de varias potencias de 10: el número 10, por ejemplo, representa a la suma de 1 diez (101) y de 0 unos (100); el número 423 representa a la suma de 4 cientos (102), 2 dieces (101) y 3 unos (10 0); y así sucesivamente.
El significado de la información representada por bits depende del contexto. Para entender esto imagina que un amigo camina hacia ti por la calle y dice, "Cuarenta y dos". Tu primera reacción será, probablemente, de extrañeza. Pero si previamente has saludado a tu amigo con una cuestión como "¿qué edad tienes?" ó "¿cuál es la frecuencia, Francisco?" su respuesta tendrá un significado evidente. Tu pregunta ha creado un contexto para dicha respuesta. En un ordenador, algunos contextos son más adecuados que otros. Un contexto muy común es el numérico. Como los bits se escriben como ceros y unos, un grupo de ellos puede representar un número binario (un valor en el sistema numérico en base dos). Representación de v alores numéricos
El sistema numérico decimal (base 10) utiliza diez símbolos para representar los valores numéricos: 0, 1 , 2 , 3, 4, 5, 6, 7, 8 y 9. (Recuerda siempre que estos dígitos son meramente símbolos: los romanos, por ejemplo, usaban el símbolo V para representar el valor numérico 5, y la X para representar el valor 10.) Para representar un valor mayor que 9 en el sistema numérico decimal —el 10, por ejemplo— se combinan dos de los símbolos, y las posiciones de los símbolos adquieren un significado especial. La progresión de los valores representados por las posiciones, como se muestra en la figura 2.2, corresponden a las sucesivas potencias de 10. Un número decimal que conste de más de una posición es la suma
Este método general de representación de números se puede usar con otras bases que no sean la base 10. Por ejemplo, el sistema numérico en base 7 utiliza los siete dígitos 0, 1, 2, 3, 4, 5 y 6, y el valor de cada posición se incrementa en función de las potencias de 7, como se muestra en la figura 2.3. (Un subíndice que siga a un número denota la base; los números sin subíndice se presume que están en base 10, a no ser que se indique otra cosa.) Seguro que ya has captado la idea. El sistema binario usa dos dígitos (0 y 1), y cada posición representa un incremento en valor correspondiente a una potencia de 2. (Mira la figura 2.4.) El sistema binario es la solución ideal para que los ordenadores representen números. Por supuesto, tú puedes realizar operaciones aritméticas en cualquier sistema numérico tan fácilmente como lo harías en base 10; los ordenadores deben sumar, restar, multiplicar y dividir usando solamente números binarios. Representación de caracteres
En la mayoría de los casos, representar solamente información numérica resulta insuficiente. ¿Cómo se puede ir más allá del contexto de los meros números? Un posible camino es utilizar un código estándar. En el código Morse, de carácter internacional y que se usa para enviar señales telegráficas, ciertos patrones de sonidos representan letras del alfabeto: tres "puntos" en rápida sucesión representan a 31
30
EL LIBRO DEL VISUAL BASIC
2 Datos e instrucc iones
UNICODE, un estándar que admite los caracteres de los alfabetos no románicos, como el árabe y el cirílico.) La versión extendida del código ASCII que se usa en la mayoría de los ordenadores modernos utiliza 8 bits para representar cada letra, número, signos de puntuación y otros códigos usados en datos de texto. En la figura 2.5 se muestran algunos ejemplos del código ASCII. Carácter
Figura 2.3. Los valores posicionales en el sistema numérico en base 7
A B a b $ 3 + Z
Valor ASC II (binario)
Valor ASC II (decimal)
01000001 01000010 01100001 01100010 00100100 00110011 00101011 01011010
65 66 97 98 36 51 43 90
Figura 2.5. La codificación en ASCII de un grupo de caracteres
Figura 2.4. Los valores posicionales en el sistema numérico binano
la letra S; tres "puntos" seguidos por una "raya" representan a la letra V; y así sucesivamente. El estándar ASCII (American Standard Code for Information Interchange, o sea, código estándar americano para el intercambio de información) especifica un código de ese tipo. Los códigos ASCII usan valores numéricos para definir el con junto de caracteres estándar del idioma inglés, incluyendo las letras mayúsculas y minúsculas, los números, los signos de puntuación y símbolos. (Como comentario, el anglocéntrico código ASCII será reemplazado en la próxima década por el 32
Sin embargo, recuerda que el mero examen de un grupo de bits no indica el contexto. Por ejemplo, el patrón de dígitos 01000001 representa a la letra A en el código ASCII, pero también es la representación binaria del número 65. La interpretación depende del contexto. Algunas veces se puede aprovechar esta circunstancia, usando el valor a la vez como un carácter y como un número entero. Por ejemplo, el hecho de que cada carácter tenga un valor numérico significa que puedes comprobar si un carácter en particular es una mayúscula viendo si su valor numérico es mayor o igual que 65 ("A" en ASCII) y menor o igual que 90 ("Z" en ASCII). El uso de b its, bytes y palabras
Mediante el uso de bits para representar información, un ordenador puede almacenar o "recordar" esa información. Sin embargo, organizar la memoria sobre una base de bits es un inconveniente, debido a que un bit realmente no representa mucha información. Con el código ASCII extendido, por ejemplo, como mínimo se necesitan 8 bits para representar un solo carácter. De hecho, lo que ocupa un carácter de información sirve como unidad estándar de medida. La unidad estándar de 8 bits se denomina byte. Para referirse a canti 33
EL LIBRO DEL VISUAL BASIC
dades grandes de datos se añaden al término byte los prefijos numéricos kilo, mega y giga. Debido a la afición de los informáticos por las potencias de 2, un kilobyte representa 1024 (2 10) bytes, y un megabyte representa 1048576 (2 20) bytes. Detrás del gigabyte (230) viene el terabyte (240) y luego el petabyte (250) No tienes que preocuparte de lo que viene después. Pero un byte no es apropiado para representar la mayoría de los valores numéricos. El estándar de 8 bits solamente puede representar los números decimales desde el 0 al 255. Por ello, la mayoría de los ordenadores trabajan con los datos en unidades que son mayores que un byte, con el objeto de permitir unas operaciones aritméticas eficientes. El número de bits que un ordenador "prefiere" se denomina el tamaño de palabra del ordenador, y no es estándar. Muchos ordenadores mainframe (de gran tamaño) y los modernos microordenadores tienen un tamaño de palabra de 32 bits, lo cual permite números binarios del orden de miles de millones. (Aunque el hardware se optimiza para usar este tamaño de palabra, estos ordenadores no están limitados a los valores de 32 bits.) Al m ac en am ien to de la in fo rm ac ió n en el or de na do r
La figura 2.6 muestra un diagrama simple de un ordenador. En los términos del diagrama, se puede pensar en la memoria como en la caja en la que se almacenan los bits cuando el ordenador está funcionando. Por el momento, restringiremos nuestro estudio a la memoria electrónica denominada RAM (random access memory, es decir, memoria de acceso aleatorio).
Figura 2.6. Un diagrama de un ordenador
34
2 Datos e instruccione s
Puedes pensar en la RAM como en una larga fila de cajas, siendo cada caja lo suficientemente grande como para contener un byte de datos, y estando cada caja identificada por un número. Por ejemplo, uno podría decir, "pásame el byte de datos de la caja 27441", o "pon la letra g en la caja 13". Al número identificativo de una posición de memoria se denomina su dirección. Como viste en el capítulo 1, Visual Basic te permite usar nombres en vez de números para referirte a posiciones de memoria. (Al ordenador le basta con usar direcciones numéricas, pero los humanos se sienten más a gusto con nombres de variables simbólicos.) Cada variable, en Visual Basic, se corresponde con una po sición de memoria, aunque en Visual Basic se le puede dar un nombre a un con junto secuencial de bytes, en vez de usar cada byte independientemente. En el capítulo 3 aprenderás más sobre la manera en que Visual Basic almacena y representa los diferentes tipos de datos.
Instrucciones de ordenador Veamos ahora qué hace el ordenador con los datos que contiene. Dentro del ordenador hay uno o dos chips que actúan como la unidad central de proceso (CPU). La CPU manipula los datos de la memoria de acuerdo con una colección de instrucciones denominadas un programa. Para que la CPU pueda ejecutar las instrucciones el programa debe residir en la RAM. Por tanto, las instrucciones, al igual que los datos, deben estar representadas por secuencias de bits. Las instrucciones le dicen al ordenador que lleve a cabo operaciones simples y específicas, como sumar, restar, comparar o copiar bits de una posición de memoria a otra. Otras instrucciones envían información a dispositivos externos de entrada/salida (input/output, I/O) como un disco duro o un monitor. Por ejemplo, un patrón particular de bits podría representar la instrucción "añade 1 al número que hay en la posición de memoria 732", o "escribe la letra M en el dispositivo de salida número 3". Estos patrones de bits que controlan el procesador difieren de una CPU a otra. (Esta es la razón de que un programa escrito para un IBM PC no funcione en un Apple Macintosh, y viceversa.) A la lista completa de todas las instrucciones que controlan un procesador en particular se le denomina el conjunto de instrucciones del procesador. Es posible escribir programas introduciendo directamente los patrones de bits que constituyen cada instrucción. Este método, al que se le llama programar en len guaje máquina , se utiliza muy raramente. Algo más habitual resulta que la gente programe en lenguaje ensamblador ; en el cual ciertas cadenas especiales de caracteres, como AD D o TEST, corresponden a cada instrucción del lenguaje máqui 35
EL LIBRO DEL VISUAL BASIC
2 Datos e instruccione s
na. Un programa denominado ensamblador traduce las cadenas de caracteres escritas por el programador en lenguaje máquina, como se ilustra en la figura 2.7. Aunque programar en lenguaje ensamblador es, significativamente, menos traumático (y menos proclive a que se cometan errores) que programar en lenguaje máquina, el programador todavía necesita especificar cada una de las instrucciones que el procesador debe realizar. La simple acción de recibir una pulsación de tecla procedente del teclado conlleva decenas de instrucciones máquina. Consecuentemente, el programa más sencillo requiere la ejecución de miles de instrucciones, y los programas complejos constan de millones de ellas. Compiladores e intérpretes
Unos programas especiales denominados compiladores pueden ayudarte a evitar los gravosos detalles de la programación en lenguaje ensamblador. Un compilador permite al programador escribir comandos que son muchísimo más productivos que las instrucciones en lenguaje máquina o ensamblador; un comando Basic, por ejemplo, se traduce, normalmente, en muchas instrucciones de lenguaje máquina. El programador escribe comandos en el lenguaje fuente del compilador, el cual traduce entonces el lenguaje fuente en lenguaje máquina. Los lenguajes fuente en uso más comunes hoy día son el C, el Pascal y el Basic. La figura 2.8 ilustra la manera en que trabaja un compilador. Figura 2.8. Compilación desde lenguaje fuente a lenguaje máquina
Para simplificar, un compilador o un ensamblador lee un archivo de instrucciones escritas por el programador y produce un archivo de código máquina como salida. El programa en código máquina se ejecutará, entonces, para obtener el resultado deseado. En los sistemas operativos MSDOS y Windows, un archivo con las extensiones EXE o COM contiene código máquina y puede ser cargado directamente en memoria y ejecutado.
Figura 2.7. Un ensamblador funcionando
36
Los intérpretes , que también traducen las instrucciones en código fuente, son similares a los compiladores. Sin embargo, un intérprete traduce una sola línea de código y entonces ejecuta, inmediatamente, el código máquina resultante. El intérprete vuelve luego al código fuente y traduce la siguiente línea. En la figura 2.9 puedes ver una comparación de los intérpretes y de los compiladores. Otra manera de comprender la diferencia consiste en imaginar la diferencia que hay entre la traducción de un libro a un idioma extranjero y la traducción en "tiempo real" 37
EL LIBRO DEL VISUAL BASIC
2 Datos e instrucc iones
comienza a ejecutarlo. El capítulo 8 explica cómo suspender el programa mientras se está ejecutando y enviar comandos directamente al intérprete para encontrar y solucionar errores que haya en el código del programa. Cuando el intérprete está funcionando, tanto el programa Visual Basic como tu aplicación deben estar en memoria a la misma vez. También puedes compilar tu aplicación. Una aplicación compilada puede ejecutarse en cualquier ordenador en el que esté funcionando Windows; no requiere el programa Visual Basic para poder funcionar. Compilación del programa Cronómetro
Tratemos ahora de compilar el programa que escribiste en el capítulo 1. Si no estás ejecutando Visual Basic, arráncalo ahora. Carga el programa Cronómetro seleccionando el comando Open Project del menú Archivo. Abre CRONO.MAK, que es el archivo de proyecto del programa Cronómetro. Para compilar la aplicación, selecciona el comando Make EXE File (crear archivo EXE) del menú File. En el cuadro de diálogo Make EXE File, que se muestra en la figura 2.10, cambia el título de la aplicación por el de Cronómetro (en el cuadro Application Title). Esta blece el directorio que desees, introduce el nombre de archivo CRONO.EXE y haz clic en el botón OK para cerrar el cuadro de diálogo. Visual Basic compilará entonces tu programa en código máquina y lo escribirá en el archivo CRONO.EXE. Figura 2.9. Compilación e interpretación
Ahora prueba a ejecutar la versión compilada del programa Cronómetro sin Visual Basic. Sal de Visual Basic seleccionando el comando Exit (salir) del menú File. En el Administrador de programas de Windows selecciona el comando Ejecutar del menú Archivo. En el cuadro de texto Línea de comando del cuadro de
proporcionada por los intérpretes de las Naciones Unidas. El proceso de traducir un libro es similar al trabajo que realiza un compilador: un traductor recibe la edición rusa de Guerra y paz y, tras muchos años de trabajo, produce un libro nuevo con el mismo texto en urdú. Sin embargo, los intérpretes de la ONU trabajan con cada frase dicha inmediatamente, como hace un intérprete de ordenador. Los compiladores y los intérpretes tienen cada cual sus ventajas. Los compiladores hacen su trabajo de traducción una sola vez y luego te dan un archivo ejecutable que puede ser ejecutado en cualquier momento. Los intérpretes te dan una respuesta rápida y pueden ayudarte a detectar errores. Visual Basic contiene am bos, un intérprete y un compilador. Ya has conocido la versión intérprete de Visual Basic. Cuando se selecciona el comando Start del menú Run, Visual Basic traduce el código que tú has escrito y 38
Figura 2.10. El cuadro de diálogo Make EXE File, el cual se usa para compilar programas
39
EL LIBRO DEL VISUAL BASIC
diálogo Ejecutar, escribe la ruta de acceso al programa; por ejemplo, \vb\crono.exe y haz clic en Aceptar. La aplicación se carga y se ejecuta. Puedes dar copias de tu programa a tus amigos y compañeros de trabajo, los cuales podrán ejecutarlas, aunque Visual Basic no esté instalado en sus ordenadores. Sin embargo, necesitarán un archivo adicional denominado VBRUN300.DLL (el cual fue añadido a tu directorio de Windows cuando instalaste Visual Basic). Todo aquel que ejecute una aplicación compilada por Visual Basic necesita una copia de este archivo. (Como Microsoft permite explícitamente distribuir este archivo, si entregas una copia de VBRUN300.DLL junto con un programa compilado no estarás violando el acuerdo de licencia de Visual Basic.)
Las versiones anteriores de Visual Basic tienen archivos con nom bres similares, en los que sólo varía la extensión: VBRUN100.DLL en la versión 1 y VB RUN 200.DLL en laversión 2.
3 Variables y constantes
Nota:
VBRUN300.DLL contiene un conjunto de rutinas que tu programa necesita. Visual Basic no compila todas las instrucciones directamente en código máquina. Algunas instrucciones —por ejemplo las que calculan la hora actual— se necesitan tan a menudo, que Visual Basic mantiene disponible una copia del código necesario en VBRUN300.DLL. Cuando tu programa solicita la hora actual se ejecuta el código que hay en VBRUN300.DLL. Como el archivo también contiene las rutinas que gestionan elementos básicos como las ventanas y los menús, incluso un programa muy simple, necesitará los recursos que VBRUN300.DLL proporciona. A medida que desarrolles aplicaciones más sofisticadas, es posible que necesites añadir archivos DLL adicionales que también forman parte de Visual Basic. Visual Basic puede ayudarte a crear un disco de instalación (como los que vienen en los programas profesionales) que incluya todos los componentes necesarios. Consulta la sección "Application Setup Wizard" (asistente para la instalación de la aplicación) del manual del programador cuando alcances este nivel.
El capítulo 2 puso en evidencia el problema de discernir si un determinado dato es numérico, un carácter o algo completamente diferente. Visual Basic te ayuda a solucionar el problema permitiéndote especificar distintos tipos de información.
Especificación de los tipos de datos de Visual Basic Como viste en el capítulo 2, los bits 01000001 representan a la letra A si el dato es un carácter ASCII, o al valor 65 si el dato es un entero binario de 8 bits. Podrías resolver esa ambigüedad mediante el desarrollo de códigos especiales de bits para todos los tipos de información, pero, afortunadamente, es posible ahorrarse esa tarea gracias a que Visual Basic tiene definido un conjunto de representaciones de datos estándar, denominadas tipos de datos. La figura 3.1 muestra los nombres y las características de todos los tipos de datos de Visual Basic. Nombre del tipo
Descripción
Rango
Espacio
de datos
del dato
de valores
requerido
Integer ( entero)
Numérico, entero Numérico, entero Texto
de 32768 a 32767
16 bits (2 bytes)
de 2147483648 a 2147483647 de 0 a 65500 caracteres aproximadamente
32 bits (4 bytes)
Long (largo) String (cadena)
Figura 3.1.
8 bits (1 byte) por carácter (continúa)
Los tipos de datos de Visual Basic
41 40
EL LIBRO DEL VISUAL BASIC
3 Variables y constantes
pos que acabamos de ver; y un código que indica el tipo de valor (currency o string, por ejemplo).
Figura 3.1. continuación
Nombre del tipo
Descripción
Rango
Espacio
de datos
del dato
de valores
requerido
Rango
de -922337203685477,5807 a 922337203685477,5807 de ±1,40x1045 a ±3,40x1038 de ±4,94x10324 a ±l,79xl0308 Cualquiera de los anteriores
64 bits (8 bytes)
La característica más importante de los tipos de datos numéricos es su rango, el cual limita los valores que un tipo de datos puede tomar. Estos límites se basan en el número de bits que se usan para codificar el valor. Por ejemplo, piensa en la figura 3.2, la cual ilustra qué sucede cuando se intenta contar de 0 a 9 usando un número binario de 3 bits. Con tres bits sólo se pueden definir ocho valores. Consiguientemente, alguna información se pierde, circunstancia a la que se denomina overflow (desbordamiento) debido a que el número de bits requeridos para almacenar la información sobrepasa al número de bits disponibles.
Currency (moneda) Single (simple) Double (doble) Variant (variable)
Numérico, decimal fijo Numérico, real Numérico, real Adaptable
32 bits (4 bytes) 64 bits (8 bytes) Depende del valor almacenado
Los tipos integer y long son simplemente enteros de 16 y 32 bits respectivamente, representados por valores binarios como los que se vieron en el capítulo 2. Estos dos tipos representan solamente números que no tienen parte fraccional. Los enteros requieren sólo 16 bits de memoria pero tienen un rango más restringido que los largos. (Hablaremos enseguida con más profundidad sobre los rangos) Una str ing es una secuencia de caracteres, cada uno de los cuales está representado mediante el sistema de codificación ASCII. Una secuencia que no contiene ningún carácter se denomina cadena vací a.
Como programador tú debes decidir el tipo de datos que se debe utilizar para un valor dado. Si estás escribiendo programas muy sencillos puedes ignorar, razonablemente, la cuestión usando siempre el tipo de datos variant, el cual puede representar cualquier valor. Sin embargo, cuando tus programas se hagan más complejos tendrás que elegir más cuidadosamente, para poder gestionar con éxito los problemas de espacio y de eficiencia. (El tipo variant es, en cierto modo, poco eficiente, ya que Visual Basic tiene que estar continuamente comprobando todos los valores para determinar de qué tipo son.)
El tipo de datos currency está especialmente diseñado para representar valores monetarios. Un valor monetario tiene siempre una precisión de cuatro decimales; o sea, puedes representar el valor 11,1625 pero no el valor 21,00003. (Este último valor se redondearía a 21,0000.) Los tipos si ngle y double permiten expresar números en coma flotante. Los números en coma flotante (también denominados números reales , o simplemente rea les para acortar) representan valores que tienen partes fraccionales. El nombre coma flotante proviene de la coma decimal "flotante", la cual puede aparecer en cualquier lugar del número, como en ,000001, 356,876, y 100000,0. Esto contrasta con el tipo monetario, que es un ejemplo de un tipo de datos de coma fija. Visual Basic también hace un uso especial del tipo doble para codificar las fechas y las horas; puedes encontrar más información sobre esta técnica de codificación en el manual de referencia de Visual Basic. Finalmente, Visual Basic incluye el tipo variant, una especie de camaleón que puede tomar cualquier valor. Los datos del tipo variant realmente contienen dos elementos de información: un valor que puede pertenecer a cualquiera de los ti42
figura 3.2. Pérdida de información como consecuencia de un desbordamiento 43
EL LIBRO DEL VISUAL BASIC
Un primer contacto con la coma flotante
Cuando trabajes con números en coma flotante te darás cuenta de que su precisión es casi tan importante como su rango. Los números en coma flotante tienen tanto un rango, que define los valores más grandes y más pequeños que pueden representar, como una precisión, que es el número de dígitos significativos que contiene el valor. Visual Basic almacena los números en coma flotante mediante una versión binaria de la notación científica. En la notación científica los valores se expresan como el producto de dos números: una fracción y un exponente. En la notación científica decimal, por ejemplo, se puede representar la distancia entre la tierra y el sol como 2,29x1012 centímetros. La paite fraccional de un dato single es un valor binario que expresa apenas 6 dígitos decimales de precisión. El exponente permite al valor variar en un rango que va desde números muy pequeños (10 45) a muy grandes (10 38). El tipo dou ble representa valores en un rango incluso aún mayor (de 10 324 a 10308 ) con, aproximadamente, 13 dígitos de precisión decimal. Si piensas que es algo extraño que un número de 300 dígitos tenga solamente 13 dígitos de precisión, considera esto: el número 0,00000000017 parece muy preciso. En realidad, ese número tiene sólo dos dígitos de precisión. Esto es más fácil de observar cuando se escribe el número en notación científica: 1,7x10 10. La fracción es sólo 1,7; el resto de la información (el exponente) te dice dónde situar la coma decimal. Veamos otro ejemplo. Piensa en el valor 2,29xl0 12 centímetros. Aunque representa a un número de 13 dígitos sólo los tres primeros dígitos representan la precisión. La medida puede estar equivocada en miles de centímetros, pero el error no se considera importante. La distinción entre precisión y rango es sutil pero importante. Supon que te contrata la Inmensamente Buena Megaempresa, S.A. para que escribas un programa que controle las cuentas de la sociedad. Esta compañía tiene ingresos de miles de millones de pesetas anualmente. Podrías pensar que el tipo single es adecuado para tu programa ya que su rango se extiende hasta 10 38 , lo que es considerablemente más de cien mil millones (10 11). Por desgracia, debes ser extremadamente preciso cuando lleves las cuentas y saber que el tipo single no tiene la precisión que te permite ese nivel de exactitud. Si empezaste con un saldo de 121734 240722 pesetas, por ejemplo, necesitarás 12 dígitos de precisión para representar el saldo debido a que cada uno de los 12 dígitos del valor es significativo. Un número real de precisión simple (single) puede representar un valor que 44
3 Variables y constantes
esté en ese rango, pero sólo puede tener un máximo de 6 dígitos significativos; o sea, podría representar solamente el valor 1,217342x1011 o 121,734,200000. ¡Tu primer día de trabajo y ya has perdido 40722 pesetas!
El tipo de datos currency de Visual Basic es perfecto para trabajar con cantidades monetarias. Proporciona 8 dígitos de precisión y siempre mantiene cuatro de esos dígitos a la derecha de la coma decimal. Una variable del tipo double proporciona el mismo rango y precisión, pero el tipo currency, que es de coma fija y no está sujeto a redondeo, es preferi ble cuando trabajes con monedas.
Nota:
Evidentemente, no tienes que despreciar el tipo single si es apropiado. Por ejemplo, si estás trabajando con ecuaciones físicas y midiendo el número de átomos que hay en una onza de silicio (aproximadamente 6,02x10 23), un número real de precisión simple servirá para este propósito admirablemente —¡a no ser que pretendas contar los átomos muy, muy cuidadosamente!
Creación de variables y constantes Independientemente de su tipo, el mero hecho de almacenar datos en memoria no tiene ninguna utilidad a no ser que te puedas referir a ellos de alguna manera. Visual Basic te permite dar nombres a posiciones de memoria de manera que puedas acceder a los datos que están almacenados allí. A una posición de memo ria a la que se le ha dado un nombre se le llama variable. La declaración Dim, la cual informa a Visual Basic de tu intención de reservar espacio, tiene la siguiente sintaxis o formato: Dim variable [As tipo] Cuando uses esta declaración debes escribir la palabra clave Di m (que aparece en tipo roman en la línea donde se muestra la sintaxis) seguida del nombre específico de la variable que quieres usar (que aparece en cursiva en la línea donde se muestra la sintaxis). La parte que aparece entre corchetes es opcional; si la utilizas, escribe la palabra clave As y luego especifica el tipo, sin incluir los corchetes. (En el capítulo 5 se tratará más en profundidad la notación de la sintaxis.) Por ejemplo, la siguiente línea de código le dice a Visual Basic que reserve suficiente memoria para un dato del tipo currency (8 bytes) y que se refiera a esa posición de memoria con el nombre Ahorros-. Dim Ahorros As Currency
Utilizando el nombre de la variable puedes ordenar más tarde a Visual Basic que almacene un dato nuevo en esa posición, que lo recupere, que lo modifique, et 45
EL LIBRO DEL VISUAL BASIC
cétera. Si omites la cláusula As, Visual Basic asume por omisión que la variable es del tipo variant Puedes pensar en las variables como si estuvieran contenidas en cajas. La declaración Di m crea una caja nueva de un cierto tamaño y le da un nombre, como se ilustra en la figura 3.3. Cuando uses el nombre de una variable en un programa, Visual Basic te proporcionará el contenido actual de la caja (el valor que está almacenado allí en ese momento). El programa que escribiste en el capítulo 1 usaba tres variables: HoraInicio, HoraParada y Lapsus. Cuando el programa se ejecuta almacena valores que representan la hora actual y el tiempo transcurrido en esas variables. Cuando se reserva memoria para una variable numérica, Visual Basic le da a la variable un valor inicial de 0. Pero no suele ser una buena idea confiar simplemente en esa inicialización automática. En lugar de esto, si quieres que una variable tome un valor, debes asignarle ese valor en el programa. Asignar explícitamente un valor a una variable hace que el programa sea más fácil de leer y evita las presunciones ocultas. Además, debes recordar que la inicialización automática es una característica específica de Visual Basic. Si conviertes tu programa a algún otro entorno de programación, el nuevo sistema puede no contemplar la inicialización y, por tanto, tu programa no funcionará. De vez en cuando también querrás usar valores que no cambian —por ejemplo, el valor de pi, el número de Avogadro o el número de gramos de una onza. Aunque puedes usar directamente en un programa estos valores numéricos, es más fácil usar un nombre como PI que poner en su lugar el número 3,1415926 cada vez que sea necesario.
3 Variables y constantes
Para esos valores fijos, Visual Basic te permite declarar constantes, que son posiciones de memoria cuyo contenido no cambia (al contrario que el contenido de las variables). Si tratas de modificar una constante, Visual Basic generará un mensaje de error. La declaración Const sirve para crear una constante, y presenta la siguiente sintaxis: Const nombre =expresión No tienes que declarar el tipo de constante, ya que Visual Basic determina el tipo a partir del valor de expresión. Si escribes Const RESPUESTA = 42, Visual Basic usa un entero; si introduces Const NOMBRE = "Rosa", crea una constante de cadena de caracteres. (Los nombres de las constantes, normalmente, se escriben en mayúsculas.) Con frecuencia se produce cierta ambigüedad sobre el tipo de constante que Visual Basic debe crear. Por ejemplo, el valor 3,01 puede ser single, double o cu rrency. Por omisión, Visual Basic elige la representación que requiere una menor cantidad de memoria. Sin embargo, se puede forzar la elección poniendo detrás del nombre un carácter especial. Utiliza este carácter solamente en la declaración, y no en el propio programa. Los caracteres que determinan el tipo de dato en Visual Basic aparecen en la figura 3.4.
Carácter % & ! # @ $
Tipo de dato especificado Integer (entero) Long (largo) Single (real simple) Doble (real doble) Currency (coma fija) String (cadena de caracteres)
Figura 3.4. Los caracteres que determinan el tipo de dato en Visual Basic
Figura 3.3. Reserva de espacio con las declaraciones de variables
46
De esta manera, la declaración Const UNO& = 1 reserva 4 bytes de memoria para una constante long, y la declaración Const UNO# = 1 reserva 8 bytes y almacena el valor mediante una representación en coma flotante. En ambos casos, en tu programa debes usar el nombre UNO (sin el carácter especial) para referirte al valor. Debes adquirir la costumbre de definir constantes para los valores estándar; esta práctica hará tus programas mucho más fáciles de leer. 47
EL LIBRO DEL VISUAL BASIC
En ocasiones puedes necesitar definir una constante grande, un valor como el número de Avogadro, por ejemplo. El número de Avo gadro, el cual estoy seguro que recuerdas, vale 6,02x10 23. Afortuna damente, no tienes que escribirlo como 602000000000000000000000. Visual Basic te permite introducir constantes del tipo single especifican do la parte fraccional del número (la mantisa) seguida por la letra E y del exponente (6,02E23 en este caso). Para constantes dobles usa la letra D en lugar de la E (6,02D23).
3 Variables y constantes
Consejo:
Reglas para los nombres
Cuando le des nombres en Visual Basic a variables y constantes, debes seguir estas reglas: ■ El primer carácter del nombre debe ser una letra. ■ Los caracteres siguientes sólo pueden ser letras, números o el carácter de subrayado. ■ El nombre no puede tener más de 40 caracteres. ■
Las palabras clave que tienen un significado especial en Visual Basic, como
Sub, Now y End no se pueden utilizar como nombres. (Si no estás seguro de si una palabra es una palabra clave de Visual Basic, pulsa El para que aparezca el sistema de Ayuda y busca el tema Reserved words palabras reservadas.) Estas declaraciones utilizan nombres ilegales: Dim 1ceEraseUnaVez 'Comienza con un número Const PRINT = 2 ’Print es una palabra reservada Dim Esto*lo*es As Currency ’Los asteriscos no están permitidos
Las siguientes declaraciones son válidas en Visual Basic: Dim EsteEsUnNombreDeVariableLargo As Integer Dim RX7 As String Const CMS_P0R_PULGADA = 2,54
Visual Basic no le presta atención al hecho de que las letras que se usan en los nombres de las variables estén en mayúsculas o en minúsculas; HOLA, HoLa y bola son el mismo nombre de variable. Después de que definas un nombre de variable, Visual Basic se asegura de que cada referencia a esa variable se adapte a las mayúsculas y minúsculas que utilizaste al introducida por última vez. Los programas son más legibles cuando se usan tanto letras mayúsculas como minúscu 48
Comentarios
Un carácter apostrofe precede a un comentario del programador en el código de Visual Basic. El apostrofe, o carácter del comentario, te permite insertar comentarios sobre tu programa en cualquier lugar del código. Como Visual Basic ignora todos los caracteres que hay a la derecha del apostrofe, ese texto sólo debe contener información o descripciones que sean útiles a aquellos que lean el programa. Cuando un apostrofe es el primer carácter de una línea, toda la línea es un comentario. Date cuenta de que si un comentario excede de una línea, debes poner un apostrofe delante de cada una de las líneas. Aquí tienes el aspecto que podría presentar el procedimiento del evento btnInicio_Click de la aplicación Cronómetro del capítulo 1 si añadieses comentarios: Sub btnInicio_Click ( ) ’Este procedimiento captura la hora a la que el usuario hizo ’clic en el botón Inicio HoraInicio = Now ’Almacena la hora de inicio txtInicio.Text = Format (Hora Inicio, "hh:mm:ss") ’Muestra en pantalla la hora de inicio txtParada.Text= ’Borra la hora de parada txtLapsus.Text= ’Borra el tiempo transcurrido btnParada.Enabled = True ’Activa el botón Parada btnInicio.Enabled = False ’Desactiva el botón Inicio End Sub
las: el uso de ambas clarifica, por ejemplo, comenzar por mayúsculas cada pala bra de los nombres de variables que contienen varias palabras, y poner todas las letras de las constantes en mayúsculas.
Creación de tipos definidos por el usu ario Los tipos de datos que están creados en Visual Basic normalmente son todos los que necesitas para la información que se divide con facilidad en componentes individuales de texto o números, como nombres, tamaños, temperaturas, etc. Pero estos tipos de datos pueden ser inadecuados cuando se trabaja con componentes de la información que deban estar unidos o agrupados juntos. Veamos un ejemplo específico. 49
EL LIBRO DEL VISUAL BASIC
Supon que tu hobby es criar animales exóticos y que has adquirido dos comadre jas copetudas alemanas llamadas Siegmund y Sieglinde. Ansioso por poner a prueba tus nuevas habilidades como programador decides mantener unos datos descriptivos de tus mascotas en el ordenador, incluyendo datos sobre el color, el peso, la longitud y la fecha de nacimiento, así como el tamaño y el color de sus copetes. (Los copetes largos y sedosos representan la característica más apreciada de las comadrejas copetudas alemanas.) Podrías empezar escribiendo declaraciones como estas: Dim Dim Dim Dim Dim Dim
Siegmund_Color As String Siegmund_Peso As Integer Siegmund_Longitud As Integer Siegmund_FechaNacimiento As Double Siegmund_ColorCopete As String Siegmund_LongitudCopete As Integer
Y luego tendrías que volver a hacerlo todo para Sieglinde: Dim Dim Dim Dim Dim Dim
Sieglinde_Color As String Sieglinde_Peso As Integer Sieglinde_Longitud As Integer Sieglinde_FechaNacimiento As Double Sieglinde_ColorCopete As String Sieglinde_LongitudCopete As Integer
Sería mucho más fácil declarar, simplemente, la información relevante una vez. Visual Basic ofrece la solución perfecta: crear tus propios tipos de datos. Un tipo definido por el usuario se crea a partir de los tipos existentes en Visual Basic: integers, strings, doubles, etc. La palabra clave Type señala en Visual Basic el comienzo de una declaración de tipo definido por el usuario, como se muestra a continuación: Type ComadrejaCopetudaAlemana Peso As Integer Longitud As Integer FechaNacimiento As Double ColorCopete As String LongitudCopete As Integer End Type
La declaración Type consolida toda la información que consideres importante so bre tus pequeños amigos peludos. Observa que todavía no has reservado ningún espacio para los datos; simplemente, le has descrito a Visual Basic la estructura o diseño de los datos. Puedes pensar en esta declaración como en un esquema de 50
3 Variables y constantes
la posición de almacenamiento. Después de que hayas definido el nuevo tipo puedes crear variables de la manera habitual: Dim Siegmund As ComadrejaCopetudaAlemana Dim Sieglinde As ComadrejaCopetudaAlemana
Estas dos declaraciones crean las variables Si egmund y Si egli nde —o sea, reservan espacio y le dan el nombre apropiado. Cada variable contiene todos los componentes del tipo de dato que has definido. En la mayoría de los lenguajes de programación, las variables que contienen varios componentes se denominan re cords (registros), y cada componente individual es un elemento del registro. Cuando uses la variable Si egmund te estarás refiriendo a todos los datos (color, peso, fecha de nacimiento, etc.) simultáneamente. Cuando quieras referirte solamente a un componente individual deberás usar el nombre de la variable seguida por un punto (.) y por el nombre del componente. Así, Si egmung.P eso es el componente de tipo entero que contiene el valor del peso del macho, y Si egli nde .C o lor es la cadena de texto que describe el color del pelo de la hembra. Ventajas prácticas
Debes considerar el empleo de tipos definidos por el usuario en tus programas siempre que sea posible. No sólo son adecuados sino que hacen que los programas sean más fáciles de leer y de actualizar. Piensa en el ejemplo de los datos de las comadrejas. Tu primer intento de crear las variables conllevó 12 declaraciones Dim, cada una de las cuales definía un atributo de una de las comadrejas. Si quieres saber qué está ocurriendo debes leer las 12 declaraciones para determinar qué atributos de Siegmund y de Sieglinde se están declarando. Incluso, entonces, no está claro si se han definido otros atributos en cualquier otro lugar, ni puedes afirmar con certeza que Si egmund y Si egli nde sean datos relacionados. Esta confusión contrasta con la claridad de la declaración del tipo definido por el usuario. Los atributos de la declaración Type pertenecen claramente a Comadreja CopetudaAlemana. Con una mirada a las variables Si egmund y Si egli nde podrás decir que ambas son del mismo tipo, y podrás averiguar fácilmente la información que contienen. Todavía más, si actualizas el programa en el futuro —si decides, por ejemplo, añadir el color de los ojos al grupo de datos que mantienes sobre los animalitos— simplemente tendrás que cambiar la declaración Type para actualizar la definición de todas las variables. De la misma manera, si las dos comadrejas empiezan a comportarse amorosamente y se presentan con un bebe comadreja, podrás añadir al programa una variable para el pequeño Siegfried con la simple declaración D im Si egfried As C omadrejaCopetudaAlemana. 51
EL LIBRO DEL VISUAL BASIC
3 Variables y constantes
Déjà Vu
La manera en que se accede a los campos en los tipos definidos por el usuario recuerda a la manera en que estableciste las propiedades en la aplicación Cronómetro (capítulo 1). En el programa Cronómetro utilizaste la instrucción txtLap sus.Text = Format(Lapsus, "hh.mm.ss") para establecer la propiedad Text del objeto txtLapsus. Observa la similitud entre la referencia a txtLapsus. Text (que aparece en la forma objeto.propiedad) de esa declaración y las referencias a los componentes de las variables como Siegfried.Color (que aparece con la forma variable.elemento). Cada objeto está representado en la memoria; cuando modificas una propiedad alteras un componente de ese objeto. En algunos lenguajes de programación, Siegmund y Sieglinde también serían considerados objetos y habría que referirse a sus elementos como propiedades. Otra terminología también habitual denomina record (registro) a una variable con muchos componentes, y field (campo) a cada elemento individual del registro. Este libro usa los términos campo y elemento de manera intercambiable, pero reserva la palabra propiedad para describir los componentes de los elementos que están diseñados específicamente como objetos en Visual Basic.
Sub Command1_Click () Dim TuNombre As String TuNombre = InputBox("¿Cuál es tu nombre?") MsgBox "Tu nombre es " + TuNombre End Sub
Probemos un experimento:
Examinemos este conjunto de instrucciones. La primera línea es la declaración del procedimiento. La segunda línea reserva espacio para una variable de cadena de caracteres llamada TuNombre. La tercera línea llama a la función InputBox( recuadro de introducción de datos), una función interna que muestra un cuadro de diálogo en la pantalla. El usuario escribe texto en el cuadro de diálogo y la función devuelve el texto como su valor. El resultado se almacena en la variable Tu Nombre. La cuarta línea de código utiliza el procedimiento interno MsgB ox (recuadro de mensajes) para mostrar en pantalla un cuadro de diálogo que contiene el texto Tu nombre es, seguido del valor almacenado en TuNombre. El operador más ( + ) concatena o "pega juntas" dos cadenas; por ejemplo, la expresión "Hol" + "a, marinero" es equivalente a la cadena "Hola, marinero". Finalmente, la última línea marca el final del procedimiento.
1. Arranca Visual Basic o selecciona el comando New Project del menú File para crear un proyecto nuevo.
5. Ahora selecciona el botón Command2 del cuadro Object de la ventana de código e introduce el siguiente código como su procedimiento Click.
Determinar el ámbito
2. Crea dos botones de comando en el formulario, uno debajo del otro. Puedes hacer doble clic en la herramienta Command Button de la caja de herramientas o seleccionar la herramienta y dibujar los botones en el formulario. 3. Selecciona el primer botón (Command1) y luego selecciona la propiedad Caption de la lista de propiedades de la ventana Properties. Establece el título de este botón como EstablecerYMostrar escribiendo este nuevo valor en el cuadro Ajustes. Luego selecciona el segundo botón y establece su título como Mostrar, produciendo el resultado que se muestra al comienzo de la página siguiente. 4. Haz doble clic en el botón EstablecerYMostrar para que aparezca la ventana de código. Luego define en ella el siguiente procedimiento. 52
Sub Command2_Click () Dim TuNombre As String MsgBox "Hola " + TuNombre End Sub
Este procedimiento, simplemente, mostrará en pantalla la palabra Ho la y el valor de TuNombre. Puedes usar el procedimiento MsgB ox y el operador de concatenación (+), igual que hiciste en el procedimiento anterior. 6. Cierra la ventana de código y pulsa F5 para arrancar esta aplicación. 7. Haz clic en el botón EstablecerYMostrar. Escribe un nombre en el cuadro de diálogo y pulsa Intro o haz clic en el botón Aceptar. Si escribiste San dra, por ejemplo, el resultado debe parecerse a la figura siguiente. 53
EL LIBRO DEL VISUAL BASIC
3 Variables y constantes
bles locales. La segunda vez declaraste una sola variable en la sección de declaraciones generales del formulario, haciéndola, por tanto, una variable de nivel de módulo. Las variables declaradas de esta manera son accesibles desde cualquier procedimiento del formulario. (La palabra módulo en este contexto se refiere esencialmente a un archivo; recuerda que todo el código de un formulario se almacena en un solo archivo.) La diferencia entre las dos versiones del programa se ilustra en la figura 3.5. 8. Haz clic en el botón Aceptar para cerrar el cuadro de diálogo. Ahora haz clic en el botón Mostrar. El cuadro de diálogo muestra la palabra Hola, pero nada más.
Limitar el ámbito de una variable es útil ya que permite utilizar varias veces el mismo nombre de variable. Por ejemplo, si sumas ciertos números en un procedimiento puedes almacenar el resultado en una variable local llamada Suma. Si más adelante escribes otro procedimiento que lleve a cabo una tarea similar pero sin
¿Por qué no ha preservado Visual Basic el valor de la variable TuNombre? ¿Porqué se comporta esta aplicación de manera distinta que la aplicación Cronómetro del capítulo 1? Hay una explicación muy sencilla: el programa Cronómetro contiene sólo una declaración Dim, y no está situada dentro de un procedimiento. Vamos a intentarlo otra vez, usando ahora el formato que tuvo éxito en la aplicación Cronómetro: 1. Selecciona el comando End del menú Run para terminar la aplicación. 2. Haz doble clic en el botón EstablecerYMostrar de la ventana del formulario para ir a la ventana de código, y una vez allí borra la declaración D im del procedimiento Click. 3. Selecciona el botón Command2 (Mostrar) del cuadro Object y borra tam bién su declaración Dim. 4.
Selecciona (general) del cuadro Object. En esta sección de declaraciones generales escribe la declaración D im TuNombre As Str ing.
5. Cierra la ventana de código y ejecuta la aplicación otra vez. Esta vez el botón Mostrar es coherente con el botón EstablecerYMostrar. Acabas de ver los efectos del ámbito de una variable. Variables locales y de nivel de mó dulo
El ámbito de una variable determina qué procedimientos tienen acceso a esa variable. La primera vez que ejecutaste el ejemplo anterior creaste dos copias de la variable TuNombre, cada una de las cuales era accesible solamente desde dentro de su procedimiento específico. A este tipo de variables se les denomina varia 54
Figura 3.5. Variables locales frente a variables de nivel de módulo 55
EL LIBRO DEL VISUAL BASIC
3 Variables y constantes
relación, puedes volver a usar el nombre de variable Suma sin que ello afecte al resultado del otro cálculo. El ámbito local permite que cada procedimiento sea una unidad autocontenida —o sea, que cambios en otras partes del programa no interfieren con el funcionamiento de un procedimiento determinado. Variables globales
Las variables de nivel de módulo son visibles únicamente desde dentro de un formulario. Si escribes un programa con varios formularios necesitarás alguna forma de compartir información entre los formularios. Por tanto, Visual Basic proporciona un tercer nivel de ámbito, las variables globales. Las variables globales se declaran en módulos de código y son accesibles desde cualquier parte del programa. (Trataremos los módulos de código, en el siguiente apartado.) Puedes ver en la figura 3.6 un ejemplo de los tres niveles del ámbito de las variables.
Usa la palabra clave Global en lugar de Di m para crear variables locales. El resto de la sintaxis es idéntica a la de la declaración Dim: Global variable [As tipo) Las reglas del ámbito también se aplican a las constantes. Las constantes declaradas con la palabra clave Const serán de ámbito local o de nivel de módulo, dependiendo de si las has definido en un procedimiento o en un módulo. Para crear constantes globales sitúa la declaración en la sección de declaraciones generales de un módulo y usa la palabra clave Global para comenzar la declaración Const, como se muestra a continuación: Global Const VELOCIDADLUZ! = 186000 Global Const CAPITAL_DE_GALICIA = "La Coruña"
El signo de exclamación de la constante VELOCIDADLUZ le dice a Visual Basic que la almacene como un número real de precisión simple. Recuerda, sin embargo, que las variables y constantes globales no se pueden definir en un formulario. Módulos de código
Como has visto, la definición de un formulario y todo su código asociado se almacena en un solo archivo con la extensión FRM. Es posible crear aplicaciones que tengan varios formularios y, por tanto, varios archivos de código. También puedes tener archivos de aplicación que no contengan nada más que código. Estos módulos de código, cuyos archivos tienen la extensión BAS, se crean cuando se elige el comando New Module (nuevo módulo) del menú File de Visual Basic o se hace clic en el botón New Module de la barra de herramientas. Los módulos de código separados son útiles, principalmente, para compartir código y para organizar los programas. Las declaraciones globales de un módulo de código pueden ser compartidas por todo el programa. (Las declaraciones de variables de un formulario sólo son accesibles desde el módulo del formulario.) Cuando estés creando programas grandes y complejos, es posible que también encuentres de utilidad poner todo el código relacionado con una faceta particular del programa en un módulo separado. Procedimiento
A B C
Figuro 3.6. Variables globales, de nivel de módulo y locales
56
Puede acceder a las variables
L, Y y X M, Y y X N, Z y X
Declaraciones por o misión
Puedes declarar una variable local sin necesidad de utilizar una declaración Di m: simplemente, comienza a utilizar el nombre de la variable cuando lo necesites. Puedes utilizar uno de los caracteres especiales (%, &, !, # ó $) para especificar el tipo de datos de la variable; si no lo haces así, Visual Basic asignará el tipo va 57
EL LIBRO DEL VISUAL BASIC
El archivo CONSTANT.TXT
Visual Basic proporciona un archivo de texto extremadamente práctico llamado CONSTANT.TXT. El archivo contiene decenas de constantes globales que te pueden resultar útiles. Puedes incluir todas estas constantes en tu programa de manera automática, si sigues estos pasos: 1. Selecciona el comando New Module (nuevo módulo) del menú File. En la ventana de código del módulo selecciona la sección de declaraciones generales. 2. Elige el comando Load Text (cargar texto) del menú File. 3. Selecciona el archivo CONSTANT.TXT del cuadro de diálogo Load Text y haz clic en el botón Merge (combinar).
3 Variables y constantes
Define el procedimiento de evento Click para el botón de comando como se muestra aquí: Sub Command1_Click Respuesta$ = InputBox("¿Me quieres?") If Respuestas = "si" Then MsgBox "Me quiere" El se MsgBox "No me quiere" End If End Sub
En este fragmento de código, la variable Respuesta$ no está declarada formalmente. Sin embargo, el signo de dólar indica que es una variable de cadena de caracteres. Por omisión, Visual Basic crea una variable de ámbito local. Aunque las declaraciones por omisión son prácticas, es de sabios (y prudentes) evitarlas y declarar en su lugar todas las variables que use tu programa. El uso de declaraciones por omisión puede conducir a que se produzcan errores en tus programas. En el caso anterior, por ejemplo, podrías declarar una variable de nivel de módulo llamada Respuesta como parte de una modificación posterior del programa. Cuando ejecutases el procedimiento, Visual Basic asumiría que la variable Respuesta del procedimiento Command1_Click. se refiere a la variable de nivel de módulo porque se ha omitido tina declaración local explícita. Consiguientemente, después de que se ejecute este procedimiento, se habrá sobreescrito cualquier dato que hubiera almacenado en la variable Respuesta de nivel de módulo.
Si haces clic en el botón Replace (reemplazar) del cuadro de diálogo Load Text sustituirás todas las declaraciones que haya en ese momento en la sección de declaraciones generales.
Las declaraciones por omisión siempre generan variables locales. Las variables de nivel de módulo y globales deben declararse usando las palabras clave Di m o Global en la parte de declaraciones generales de una ventana de código. Una declaración Di m dentro de un procedimiento declara una variable local.
Para hacer que el tamaño del programa se mantenga pequeño puedes borrar todas las constantes que no necesites. Si sólo necesitas algunas constantes puede que te resulte más fácil usar el programa Bloc de notas de Windows para abrir CONSTANT.TXT y, simplemente, copiar y pegar las constantes que quieras desde el archivo a su aplicación.
Visual Basic puede ayudarte a evitar las declaraciones por omisión. Selecciona el comando Environment (entorno) del menú Options. En el cuadro de diálogo En vironment Options (opciones del entorno), establece la opción Require Variable Declarations (requerir declaraciones de variables) como Yes (sí), como se muestra en la figura 3.7.
riant por omisión. A modo de ejemplo, abre un nuevo proyecto y pon un solo botón de comando en el formulario.
Ahora, cada vez que crees un archivo nuevo, Visual Basic añadirá la declaración Option Explicit a la sección de declaraciones generales del código. (También puedes introducir esta declaración directamente en la sección de declaraciones generales si quieres.) Si luego tratas de ejecutar un programa que contenga una
Precaución:
58
59
EL LIBRO DEL VISUAL BASIC
variable no declarada, Visual Basic resaltará la variable y mostrará el mensaje Va riable not defined (variable no definida).
3 Variables y constantes
máticamente la versión actual de tus archivos de formulario y de proyecto antes de ejecutar la aplicación. Ello te asegurará que no pierdes nada de tu trabajo en el caso de que se produzca un bloqueo del sistema. Es posible que quieras mantener desactivada esta opción si tiendes a realizar cambios temporales y experimentales a tus programas y no quieres guardarlos. Las otras opciones del cuadro de diálogo te permiten establecer los colores del texto en la ventana de código. Modificando estos colores te será más fácil reconocer comentarios, variables, palabras clave, etc., y distinguir los distintos componentes de tu programa.
Figura 3.7. El cuadro de diálogo Environment Options
Otras opciones del entorno
El cuadro de diálogo Environment Options te permite especificar, además, otras opciones. La opción Tab Stop Width (anchura de las tabulaciones), normalmente establecida como 4, puede alterarse para cambiar la posición del tabulador en tus ventanas de código. Sin embargo, ten en cuenta que Visual Basic no inserta caracteres ASCII reales en el código, sino que inserta espacios hasta la siguiente posición del tabulador. La opción Syntax Checking (comprobación de la sintaxis), cuando está establecida como Yes, activa la comprobación de cada línea de código a medida que las introduces. Puedes establecer la opción Default Save As Format (formato por omisión de guardar como) como Binary (binario) o Text (texto). El ajuste por omisión es Bi nary, y es el más eficaz. De este modo, tus formularios y archivos de proyecto se guardan con un formato que sólo Visual Basic puede entender. Selecciona la opción Text si quieres que tu aplicación sea compatible con Visual Basic para MSDOS o con el Application Setup Wizard. El ajuste por omisión de la opción Save Project Before Run (guardar el proyecto antes de ejecutarlo) es No. Si la estableces como Yes, Visual Basic guardará auto60
61
4 Declaraciones, expresiones y procedimientos Este capítulo centra tu atención en declaraciones (o instrucciones) sencillas de Visual Basic. Una declaración en el lenguaje Visual Basic es la exposición completa de un comando al ordenador, el equivalente de una frase en español. Dentro de las declaraciones se pueden crear expresiones combinando valores y operadores. Este capítulo describe las diferentes clases de operadores y cómo usarlos. Tam bién proporciona una explicación más detallada de los procedimientos, con los cuales ya trataste cuando construiste tu primera aplicación.
Declaraciones de asignación La declaración más simple y probablemente la más común que se puede encontrar en un programa es la declaración de asignación. Consta del nombre de una variable, seguido del operador de asignación (=) y de algún tipo de expresión. En su forma más básica una expresión consta, simplemente, de un valor constante; sin embargo, también puede consistir en una referencia a otra variable o en la mezcla de variables y constantes en la cual se ejecutan ciertas operaciones. Todas las declaraciones que vienen a continuación son declaraciones de asignaciones legales: HoraInicio = Now Explorador.Nombre = "Capitán Spaulding" NumeroDeBits = NumeroDeBytes * 8 NombreDeMono = "Chita" Energia = Masa * VELOCIDADLUZ ^ 2 NetoPatrimonial = TotalActivo - TotalPasivo 63
EL LIBRO DEL VISUAL BASIC
4 Declarac iones, expresiones y proce dimientos
Las declaraciones de asignación almacenan información. Se calcula el valor de una expresión, el cual aparece a la derecha del operador de asignación, y el resultado se almacena en la variable que hay a la izquierda del operador. El tipo de datos de la variable debe ser apropiado al valor de la expresión calculada. Por ejemplo, una constante o una expresión de tipo cadena de caracteres no puede almacenarse en una variable de tipo entero o de tipo doble (coma flotante). Si los tipos de datos están relacionados pero no son exactamente el mismo —por ejemplo, si quisieras almacenar un valor entero en una variable de coma flotante—, Visual Basic convertirá el resultado de la expresión al tipo de datos de la variable. Sin embargo, si almacenas el resultado de una expresión en una variable de tipo variant, el tipo de datos de la expresión se preserva. Las variables variant mantienen tanto el tipo de datos como el valor.
operandos de la operación de suma. Además de los operadores aritméticos, Visual Basic también dispone de un operador de concatenación de cadenas de caracteres, de operadores de comparación y de operadores lógicos (todos los cuales se tratarán más adelante en este capítulo).
Por desgracia, el operador de asignación es el mismo símbolo que se utiliza en matemáticas para representar la igualdad (el signo igual, como en la ecuación 2+1=1+2). La igualdad en el contexto matemático expresa una condición que es cierta. En la declaración de asignación de Visual Basic, el símbolo = es un comando que pone el resultado de la expresión que le sigue en la variable que le antecede. Representa una acción que el ordenador debe llevar a cabo en lugar de una declaración de hecho. La ecuación 2+1=1+2 no es una declaración válida en Visual Basic porque carece de una variable a la izquierda del signo igual. Si tratas de introducir esta línea como si fuera una declaración completa, Visual Basic devolverá un error.
■ Un valor constante es una expresión.
Todas las declaraciones que hay en el programa Cronómetro que creaste en el capítulo 1 son declaraciones de asignación. En algunas declaraciones, como en btnParada.Enabled = True, asignaste un simple valor constante. En otras, como en la declaración Lapsus = HoraParada Hora Inicio , utilizaste una expresión. En declaraciones como txtInicio.Text = Forma(HoraInicio, "hh:mm:ss"), llamaste a una función interna. El resto de este capítulo explora las posibilidades de Visual Basic en esas facetas.
Expresiones y op eradores Como se ha mencionado, una expresión puede ser tan sencilla como una simple constante. Sin embargo, lo más habitual es que las expresiones representen cálculos que se deben ejecutar. Normalmente, hay un operador que determina el tipo de cálculo. Sin duda estarás familiarizado con los operadores aritméticos, como el signo más (+) y el signo menos (), que indican suma y resta respectivamente. La expresión 2+1 le dice a Visual Basic que sume los valores 2 y 1. El 2 y el 1 son 64
Las expresiones no son declaraciones válidas por ellas mismas, ya que no están completas. Introducir simplemente la línea 2+7 en tu programa de Visual Basic, por ejemplo, producirá un error. Si en Visual Basic una declaración es como una oración, una expresión es como una frase. Las expresiones están permitidas, normalmente, en cualquier sitio donde puedas utilizar un valor constante. Dar una definición de expresión es complicado. La mejor definición es realmente autoreferente. Una definición parcial puede incluir estas reglas: ■ La combinación de una expresión seguida por un operador y seguida por otra expresión también es una expresión. De acuerdo con estas reglas, 3 es una expresión, de la misma manera que 7; por tanto, 3+7 también es una expresión. Y ello nos lleva a que 3*3+1 también sea una expresión, al igual que 3+3+1+1. Puedes ver lo que está ocurriendo: las expresiones pueden ser arbitrariamente complejas.
El tipo de un a expresión
El tipo de una expresión se determina por el tipo de los operandos. En el caso de un valor constante, el tipo de la expresión es el mismo que el tipo de la constante. En el caso de una expresión que contenga una operación, Visual Basic usa el tipo de los dos operandos para determinar el tipo del resultado. Naturalmente, si sumas dos enteros el resultado será un entero; si sumas dos valores de doble precisión, el resultado será del tipo doble (real). Si mezclas tipos diferentes —por ejemplo, multiplicando un integer por un single, como en la expresión 2 * 7 , 5— Visual Basic, generalmente, hará que el tipo del resultado tenga el rango más amplio; en este caso sería un single (real). Sin embargo, para prevenir una posible ambigüedad no se deben mezclar diferentes tipos en una expresión. Para evitar que se mezclen tipos en una expresión puedes usar los caracteres de declaración de tipo con las constantes numéricas. Estos caracteres fuerzan a una constante a ser de un tipo determinado. Por ejemplo, 100 sería, normalmente, un integer, pero 100! es un single y 100@ es un valor monetario. (Los caracteres de declaración de tipo de Visual Basic aparecerán en la figura 3.4 del capítulo 3.) 65
EL LIBRO DEL VISUAL BASIC
Nota: Visual Basic no permite usar caracteres de declaración de tipos para truncar constantes reales en enteros. De este modo, no es posible utilizar el nombre 3,14% para el entero 3■ Pero si quieres convertir una variable de coma flotante en un entero, Visual Basic dispone de funcio nes especiales de conversión, las cuales están documentadas en el ma nual dereferencia de Visual Basic.
Las expresiones no tienen que estar limitadas a operadores y constantes. Así, la expresión 1773397 + (IngresosAjustados 32450) * 23 / 100 podría calcular una cuota de la renta (al 23 por 100). Esta expresión incluye una variable y dos paréntesis, así como operadores y constantes. Cuando las expresiones son más complejas que dos operandos y un simple operador, algunas veces es posible evaluar la expresión de más de una forma. Por ejemplo, en la expresión 2+6/2 podrías sumar primero el 2 y el 6 para obtener 8 y luego dividir el 8 por 2 y obtener 4. O podrías sumar 2 al resultado de dividir 6 entre 2 (que es 3), obteniendo un resultado final de 5. Los paréntesis se utilizan para eliminar este tipo de ambigüedades. La subexpresión contenida dentro de los paréntesis siempre se evalúa primero. Escribir una expresión como 2+(6/2) indica claramente que la operación de división debe ejecutarse primero. Las expresiones muy complejas pueden contener múltiples grupos de paréntesis. Se evalúan primero las xpresiones más internas, o las más profundamente anidadas. Ante la ausencia de los paréntesis, Visual Basic usa un conjunto de reglas denominadas precedencia de operadores para determinar qué operadores deben ejecutarse primero. For ejemplo, como la multiplicación y la división tienen un nivel de precedencia más alto que la suma y la resta, Visual Basic siempre evalúa la ex presión 2+6/2 como si se hubiera escrito 2+(6/2). Los apartados siguientes de este capítulo describen los operadores disponibles en Visual Basic, agrupados de acuerdo con su función y seguidos por una tabla de precedencia que ilustra cómo se relaciona cada operador con cualquier otro.
4 Declarac iones, expresiones y proc edimientos
rápido que el uso de números en coma flotante, pero a no ser que realices operaciones muy complejas lo más probable es que no notes la diferencia. Oper ador
Oper aci ón
+
Suma Resta Multiplicación Exponenciación División en coma flotante División entera Módulo
* ^ / \ Mod Figura 4.1.
Operadores aritméticos
La suma, la resta y la multiplicación se comportan como sería de esperar. Debes usar el operador de exponenciación porque no se pueden utilizar números supe ríndices en Visual Basic. Y los tres operadores relacionados con la división son un poco más complicados. Exponenciación
El operador de exponenciación permite calcular potencias y raíces. En matemáticas, la exponenciación se indica con superíndices. Por ejemplo, el valor 2 8 es 2 elevado a la octava potencia y es calculado por Visual Basic cuando se encuentra con la expresión 2^8. La raíz cuadrada de 2, que es 2 elevado a la 1/2 potencia, puede calcularse usando tanto la expresión 2 ^ (1/2) como la expresión 2 ^ 0,5. La figura 4.2 presenta algunos ejemplos de exponenciación. Expresión
Resultado
Valor calculado
10 ^ 2 10 ^ 3
100
10 al cuadrado, ó 10 * 10
Operadores aritméticos
1000
Los operadores más familiares son los que llevan a cabo operaciones aritméticas simples. La figura 4.1 muestra una lista de los operadores aritméticos de los que dispone Visual Basic.
^ -2 25 ^ 0 ,5 8 ^ ( 1 / 3 )
0,01
10 al cubo, ó 10 * 10 * 10 El inverso de 10 2 , ó 1/100 La raíz cuadrada de 25, ó 25 1/2 La raíz cúbica de 8, u 8 1/3
En las operaciones de suma, resta y multiplicación, los resultados son números del mismo tipo que los operandos. (Los tipos mezclados se han tratado en el apartado anterior.) En general, el uso de números enteros o de coma fija es más 66
10
5 2
Figura 4.2. Ejemplos de exponenciación
67
EL LIBRO DEL VISUAL BASIC 4 Declarac iones, expresiones y proc edimientos
División entera o en coma flotante
El operador de división en coma flotante (/) ejecuta una división normal, pero devuelve un número en coma flotante. Así, la expresión 3/2 produce el resultado 1,5 como sería de esperar. Esto contrasta con el operador de división entera (\), el cual devuelve un valor entero. Cuando se utiliza este operador, la expresión 3 \ 2 da como resultado 1. Justo lo que necesitábamos, me ha parecido oirte decir, una operación aritmética que devuelve una solución equivocada. Supongo que depende del punto de vista. Imagina que eres un empaquetador de pimientos en vinagre que necesita saber cuántos pimientos en vinagre puede meter en un bote de una pinta de capacidad. Como experto en el tema sabes que puedes meter 150 pimientos en vinagre en un bote de un galón de capacidad y que nunca se mete un pimiento que no esté completo. Un bote de un galón es 8 veces más grande que un bote de una pinta, así que puedes meter 150 \ 8 —o sea, 18— pimientos en vinagre en cada bote de una pinta de capacidad. Debes usar el operador de división entera para este cálculo, como se muestra en la figura 4.3, porque sólo quieres meter pimientos completos; ejecutar esta operación con el operador de división en coma flotante (150 / 8) daría como resultado 18,75, lo cual no es un valor razonable en estas circunstancias. Como Visual Basic puede convertir números de unos tipo de datos a otros, podrías pensar que obtendrías el mismo resultado asignando simplemente el resulta
do de una división en coma flotante a una variable entera, como se muestra en este trozo de código: Dim BoteDePinta As Integer BoteDePinta = 150 / 8
En realidad, después de que se ejecuta la declaración de asignación el valor de BoteDePinta será 19, en lugar de 18. Visual Basic primero calcula la expresión 150 / 8, la cual da 18,75. Como tú quieres que el valor se almacene en una varia ble entera, Visual Basic redondea el número en coma flotante al entero más próximo, que en este caso es 19. Cuando se usa el operador de división entera, cualquier parte fraccional del resultado es truncada, o eliminada, en lugar de redondeada. La figura 4.4 compara el truncado con el redondeo.
Valor inicial 24,1 24,5 24,50001 24,9999
Se trunca a
24 24 24 24
Se redondea a
24 24 25 25
Figura 4.4. Trancado y redondeo
Visual Basic es un lenguaje de programación. En la mayoría de los lenguajes de programación, no se puede usar la coma decimal en los cálculos; en su lugar, se utiliza el punto decimal. Visual Basic no es una excepción. Por tanto, aunque aquí estemos hablando de cifras como 1,2, a la hora de asignar dicho valor a una variable—por ejemplo — habrá que usar 1.2.
Aviso:
El módulo
El operador módulo, que está relacionado estrechamente con el de división entera, devuelve el resto que queda al dividir el primer operando entre el segundo. Por ejemplo, si se divide 7 entre 4, el resultado es 1 con un resto de 3. Así, 7 M od 4 da como resultado 3. De la misma manera, 21 M od 4 da como resultado 1 (21 dividido entre 4 es igual a 5, con un resto de 1). Figura 4.3. El uso del operador de división entera
68
Veamos esto en el ejemplo de los pimientos en vinagre otra vez. Sabes que puedes empaquetar 18 pimientos en vinagre en una bote de pinta. Si tienes 75 pi 69
EL LIBRO DEL VISUAL BASIC
4 Decla racione s, expresiones y proced imientos
mientos para empaquetar, la expresión 75 \ 18 te da el número de jarras de pinta que puedes llenar (4), y la expresión 75 Mod 18 calcula el número de pimientos en vinagre que sobrarán (3), como se ilustra en la figura 4.5.
Figura 4.5. El uso de la división entera y del operador Mod
Precedencia de l os operadores aritméticos
La figura 4.6 indica la precedencia en la jerarquía de los operadores aritméticos. La exponenciación tiene la precedencia más alta; las operaciones de suma y resta son las más bajas en la jerarquía. Los operadores que aparecen en la misma línea tienen la misma jerarquía. Operador
Operaci ón
A
Exponenciación Multiplicación, división en coma flotante División entera Módulo (resto) Suma, resta
*/ \ Mod + Figura 4.6.
los operadores aritméticos en orden de precedencia
70
La figura 4.7 contiene algunas expresiones de Visual Basic de ejemplo y los valores que resultan cuando se calculan esas expresiones. Puedes consultar la jerarquía de precedencia que aparece en la figura 4.6 para saber cómo Visual Basic llega al resultado. Expresión
Resultado
Explicación
3+2*7
17
(3 + 2) * 7 1 + ((2 + 3) * 2) * 2
35 21
14 / 5 * 2
5,6
14 \ 5 * 2
1
27 ^ 1 / 3
9
27 ^ (1 / 3)
3
La multiplicación tiene la precedencia más alta. Los paréntesis anulan la precedencia. Los paréntesis anidados se evalúan primero. La división en coma flotante y la multiplicación tienen igual precedencia; las operaciones van de izquierda a derecha. La multiplicación tiene una mayor precedencia, y la división entera trunca. La exponenciación tiene una mayor precedencia. Los paréntesis anulan la precedencia.
Figura 4.7. El uso de las reglas de precedencia para calcular valores
El operador de concatenación de cadenas
Cuando los operandos de una expresión son cadenas de caracteres, el operador signo más (+) concatena, o combina, las cadenas. Puedes usar la concatenación para "pegar" dos o más cadenas juntas con el fin de formar una más grande. El resultado de la concatenación es una cadena enteramente nueva; ninguno de los operandos originales se modificaría de ninguna manera. Este fragmento de programa emplea la concatenación para generar algunas línea de Lewis Carroll: x$ = "murciélagos" y$ = "gatos" Debug.Print "¿Comen " + y$ + " los " + x$ + "?" ’¿Comen gatos los murciélagos? Debug.Print "¿Comen " + x$ + ” los ” + y$ + "?" ’¿Comen murciélagos los gatos?
71
EL LIBRO DEL VISUAL BASIC
4 Declaraciones, expresiones y procedimientos
Interactuar directamente con Visual Basic
Interactuar directamente con Visual Basic (continuación)
Ya en el capítulo 1 utilizaste la instrucción Debug.Print para escribir en la ventana Debug (debug quiere decir depurar), que aparece cuando el programa está funcionando. La ventana Debug es más que un sitio útil donde poner mensajes; en esta ventana se puede interactuar directamente con el intérprete.
Se pueden evaluar (calcular) expresiones y llamar a funciones en la ventana Debug. También se puede llamar a un procedimiento y, en general, ejecutar casi cualquier instrucción que pudieses poner en un programa. Pasar a la ventana Debug es una manera muy fácil y rápida de comprobar una línea de código. Cuando lo hayas hecho, pulsa F5 para continuar con la ejecución normal del programa, o elige End en el comando Run para terminar la aplicación.
Crea un proyecto nuevo seleccionando el comando New Project del menú File. Pulsa F5 para ejecutar la "aplicación". Aunque no has escrito código ni puesto ningún objeto en el formulario, Visual Basic "ejecutará" el formulario en blanco. Ahora selecciona Break (interrumpir) del menú Run o haz clic en el botón Break de la barra de herramientas. Este comando suspende la aplicación, independientemente de lo que estuviera haciendo (no mucho en este caso), y hace que la ventana Debug pase a ser la ventana activa. Escribe la instrucción Debug.Pri nt " Hola" en la ventana Debug y pulsa la tecla Intro. Visual Basic procesa y ejecuta inmediatamente el comando:
Observa que los operandos deben ser cadenas de caracteres. Si necesitas concatenar un número con una cadena para mostrarlo en pantalla, debes utilizar una de las funciones internas de Visual Basic para convertir el número en una cadena. La función de este tipo que resulta más simple es la denominada Str $. En la expresión " La raí z cuadrada de 2 es " +Str$(2 ^ 0,5), por ejemplo, convierte el número que está entre paréntesis en una cadena. Debes acordarte de incluir espacios en blanco en las cadenas de caracteres cuando sea necesario, o Visual Basic combinará las dos cadenas sin espacios. Operadores de comparación
Como la ventana Debug es el formulario activo en el momento en el que el intérprete ejecuta tu comando, no es necesario que incluyas el nombre del objeto Debug cuando llames al método Print; es suficiente con usar simplemente Print. Además, Visual Basic te permite abreviar Print como ? de manera que puedas obtener los resultados rápidamente, como se muestra aquí:
Los seis operadores de comparación aparecen en la figura 4.8. Cuando se comparan dos valores, el resultado de la operación en un valor booleano o lo que es lo mismo, True (verdadero) o False (falso). (La palabra booleano proviene del nom bre del matemático inglés George Boole.) Visual Basic dispone de las constantes internas llamadas True y False que representan los valores enteros 1 y 0 respectivamente. La representación binaria de 0 es un número con todos sus bits puestos a 0, y la representación de 1 es un número binario cuyos bits están todos puestos a 1, lo que hace que True sea lo opuesto a False. Operador
> <
Comparación
Mayor que Menor que
Figura 4.8. Operadores de comparación
72
73
EL LIBRO DEL VISUAL BASIC 4 Declarac iones, expresiones y proce dimientos
Figura 4.8. continuación Operadores lógicos Operador
Los operadores lógicos son denominados, a veces, operadores booleanos porque se derivan del álgebra de la lógica matemática, la cual fue desarrollada por Geor ge Boole. Estos operadores tienen valores booleanos como operandos, y devuelven valores booleanos. La figura 4.10 muestra una lista con los operadores lógicos en su orden de precedencia. (Todos los operadores lógicos tienen menor precedencia que los operadores de comparación.)
Comparación
>= <= = <>
Mayor o igual que Menor o igual que Igual que Distinto que
La figura 4.9 da el resultado de algunas operaciones de comparación típicas, a la vez que las explica. Los operadores de comparación se conocen también como operadores relacionales porque evalúan la relación entre los dos operandos. Aunque los operadores de comparación tienen igual precedencia entre ellos, la precedencia de cualquier operador de comparación es menor que la de cualquier operador aritmético. Probablemente te habrás dado cuenta de que el operador "igual que" usa el mismo símbolo (=) que el operador de asignación. Esto no debe producir confusión, ya que el operador de asignación es válido sólo en una posición: inmediatamente detrás de una variable en una declaración de asignación. En todos los demás casos, el signo igual es un operador relacional o de comparación. Por ejemplo, en la declaración Test = a = b de Visual Basic, la expresión a = b da como resultado o True o False. Así pues, el valor resultan te es asignado a la variable Test.
Expresión
Resultado
3 +1 > 3 "abc" < > "a" + "b" + "c"
True False
"quid" <= "pro quo"
False
2,3 >= 1,1 * 2 0 = (2 < 1)
True True
Figura 4.9. El uso de los operadores de comparación
74
Explicación
4 es mayor que 3. Después de la concatenación ambas cadenas son iguales ("abc"). Las cadenas se comparan en orden alfabético, no por su longitud. 2,3 es mayor que 2,2. 2 < 1 es falso, lo cual es igual que 0.
Operador
Not And Or Xor Eqv Imp
Operación
No lógico Y lógico O lógico O exclusivo Equivalencia lógica Implicación lógica
Figura 4.10. Los operadores lógicos, o booleanos, en orden de precedencia
El operador lógico más simple se denomina Not. Precede a un solo operando y devuelve su opuesto lógico —o sea, niega el operando. Por ejemplo, la expresión Not False da como resultado True (lo opuesto de False); y la expresión Not (4<3) da como resultado True, ya que la expresión 4<3 es False. El operado r Not tiene, además, la más alta precedencia de todos los operadores booleanos. El siguiente operador en el orden de precedencia es And (Y). Devuelve el resultado True si (y sólo si) ambos operandos son True. En caso de que alguno de los operadores sea False, el operador And devuelve el resultado False. Este operador corresponde al uso de la palabra and del idioma inglés (que quiere decir y en español), como se expresa en la declaración "quedaré impresionada sólo si tiene un doctorado en filosofía y mide más de un metro ochenta". Expresión
False And False False And True True And False True And True
Resultado
False False False True 75
EL LIBRO DEL VISUAL BASIC
4 Declarac iones, expresiones y proc edimientos
El operador Or (o) devuelve el resultado True si cualquiera de los dos operandos es True, o si los dos son True. De nuevo, su significado booleano es similar al uso de la palabra or en inglés (que es o en español) —por ejemplo, "compraré el gato si cuesta menos de 5000 pesetas o si es siamés". Expresión
False Or False False Or True True Or False True Or True
Resultado
False True True True
Aunque los operadores Not, And y Or son, con mucho, los más utilizados, Visual Basic también dispone de otros tres operadores: Xor, Eqv e Imp. El operador Xor (o exclusivo) devuelve el resultado True si cualquiera de los dos operandos es True, pero no si ambos lo son. En otras palabras, funciona como el operador Or, excepto en el caso de que ambos operadores sean True. Expresión
Resultado
False Xor False False Xor True True Xor False True Xor True
False True True False
El operador Eqv (equivalencia) devuelve el resultado True cuando sus dos operandos tienen el mismo valor. Expresión
False Eqv False False Eqv True True Eqv False True Eqv True
Resultado
True False False True
Cuando utilices el operador Imp (implicación), el resultado será False, únicamente cuando el primer operando sea True y el segundo False. En todos los demás casos el resultado será True. El operador Imp es el único operador booleano para el cual el orden de los operadores hace que el resultado sea distinto. La Implicación se utiliza algunas veces junto con el operador And, como se ilustra en el fa76
moso silogismo "Sócrates es un hombre y todos los hombres son mortales implica que Sócrates es mortal". Expresión
False Imp False False Imp True True Imp False True Imp True
Resultado
True True False True
Se puede usar más de un operador lógico en una expresión. La figura 4.11 proporciona algunos ejemplos; prueba a evaluar cada una de las expresiones, y luego comprueba el resultado teniendo en cuenta el orden de precedencia que se muestra en la figura 4.10. Expresión
Resultado
Not False And True
True
True And False Xor False
False
True Eqv True Xor True
False
Explicación
Equivale a la expresión (Not False) And True , según la precedencia. Equivale a la expresión (True And False) X or False, según la precedencia. Equivale a True Eqv (True Xor True) según la precedencia.
Figura 4.11. El uso de varios operadores lógicos en una expresión
Precedencia
La figura 4.12 muestra la lista completa de los operadores de Visual Basic (excepto el operador de concatenación de cadenas), en orden de precedencia del mayor al menor. Cuando te encuentres con una expresión compleja debes determinar qué operador tiene el orden de precedencia más alto y evaluar esa subexpresión primero. Luego determina qué operador está el segundo en el orden de precedencia, evalúa esa subexpresión, y así sucesivamente hasta qué llegues al cálculo del resultado final. Algunos operadores, como el de suma y el de resta o el conjunto completo de operadores de comparación, tienen igual precedencia. Cuando te encuentres con 77
EL LIBRO DEL VISUAL BASIC
4 Decla racione s, expresiones y proced imientos
operadores que tengan la misma precedencia, debes evaluar las expresiones de izquierda a derecha. Por ejemplo, considera la siguiente expresión: Temperatura >= 120 And Inflamable = True
Como los dos operadores de comparación (>= e =) comparten el mismo nivel de precedencia, Visual Basic los evalúa de izquierda a derecha. Luego, Visual Basic ejecuta la operación And. En este caso, si Temperatura es menor que 120 o Infla mable es False, Visual Basic determinará que el valor de la expresión es False.
Operador
Operación
^
Exponenciación
*/
Multiplicación, división en coma flotante
\
División entera
Mod +-
Suma, resta
Módulo
><>=<= = <>
Comparación
Not
No lógico
And
Y lógico
Or
O lógico
Xor
O exclusivo
Eqv
Equivalencia lógica
Imp
Implicación lógica
Figura 4.12. Los operadores de Visual Basic en orden de precedencia
Aquí tienes un ejemplo más complejo: Cuenta * 2 < 15 Or Color = "Azul" And Cu enta * ^2) < 21
Recorriendo de arriba a abajo la tabla de precedencia, Visual Basic primero ejecu tará las dos operaciones de multiplicación; luego evaluará las tres comparaciones de izquierda a derecha. A continuación, llevará a cabo la operación And y, final mente, la operación Or. Si piensas que ésta es una buena manera de perderte, estás en lo cierto. Incluso aunque no quieras anular la precedencia por omisión de Visual Basic, es una
78
buena idea que añadas paréntesis para asegurarte de que Visual Basic y tú estáis de acuerdo en el orden de las operaciones. Copiando la manera en que Visual Basic ve el ejemplo anterior se obtendría algo como esto: ((Cuenta * 2) < 15) Or ((Color = "Azul") And ((Cuenta * 2) < 21))
Errores habituales Prácticamente todos los programadores que están empezando cometen ciertos errores relacionados con las expresiones. Veamos algunos de los problemas que se presentan con más frecuencia, de manera que seas capaz de evitarlos o, al me nos, de identificarlos. Un error de ese tipo consiste en dejar de poner un operador relacional cuando se comprueba si una variable está en un rango. Por ejemplo, si estás trabando con la variable Temperatura, puede que se dé el caso de que necesites saber si su valor es mayor de 10 grados pero menor que 100. Esto se consigue con la expresión Temperatura > 10 And Temperatura < 100. Es posible que hayas tratado de utili zar la expresión 10 < Temperatura < 100, la cual tiene un aspecto fantástico des de el punto de vista matemático, pero no funciona correctamente en Visual Basic. Esta expresión más corta es sintácticamente correcta, pero da la solución equivo cada. ¿Por qué? Comienza por evaluar las dos subexpresiones de izquierda a derecha. (Los dos operadores tienen igual precedencia.) Debido a que los operadores relacionales siempre devuelven True o False, lo cual equivale a los enteros -1 y 0 respectiva mente, el resultado de la subexpresión 10 < Temperatura será -1 ó 0. Por tanto, la segunda subexpresión será -1 < 100 ó 0 < 100, las cuales son True. En conclu sión, la expresión 10 < Temperatura < 100 siempre devolverá el resultado True, independientemente del valor que tenga la variable. Este proceso se muestra grá ficamente en la figura 4.13. Otro error típico consiste en escribir las expresiones lógicas con la misma imprecisión que a menudo se encuentra cuando se habla en español. La expresión del ejemplo anterior se formuló cuidadosamente para encontrar un valor que "fuese mayor de 10 grados pero menor que 100 grados". Sin embargo, si le estuvieras hablando a un colega podrías haber planteado el problema de esta manera: "quiero saber si la temperatura es mayor de 10 grados o menor de 100 grados". Esta formulación es menos precisa (de hecho, inexacta), pero la gente consigue sortear la ambigüedad bastante bien y tu colega, probablemente, entendería lo que querías decirle. Sin embargo, articular la declaración de esa manera podría
79
EL LIBRO DEL VISUAL BASIC 4 Declarac iones, expresiones y proc edimientos
Figura 4.13. Figura 4.14.
Una manera incorrecta de comprobar un rango de valores
Otra manera incorrecta de comprobar un rango de valores
llevarte a escribir la expresión Temperatura > 10 es incorrecta.
Or
Temperatura < 100 , la cual
Al examinar de nuevo la expresión a medida que Visual Basic gestiona, podrás ver el problema. Las dos expresiones relacionales se evalúan primero, y luego se lleva a cabo la operación booleana Or. La subexpresión Temperatura > 10 es True para todos los números mayores de 10; la otra subexpresión relacional, Temperatura < 100, es True para todos los números menores de 100. Ahora mira lo que sucede cuando unes estas dos subexpresiones con el operador Or. Si la variable tiene un valor de 5 grados, la primera expresión será False (5 > 10) y la segunda True (5 < 100). El operador Or devolverá un resultado de True porque uno de los operandos es True. De la misma manera, con un valor de 900 la primera subexpresión dará True y la segunda False, haciendo que la operación Or dé un resultado de True. Cuando Temperatura tenga un valor de 70 ambas subexpresiones serán True y el resultado será de nuevo True. Al usar el operador Or en lugar del operador And has creado otra expresión que siempre devuelve True. La figura 4.14 ilustra el problema. Un tercer error que se comete con frecuencia consiste en pensar en una declaración de asignación como en una condición matemática, en lugar de pensar que implica la manipulación de los datos que ocurre en un momento determinado. El problema se ilustra en el siguiente fragmento de código: A = 10 B=A/2 A = 20
Después de ejecutar estas tres declaraciones, A tiene el valor 20 y B el valor 5. Si habías pensado que B debería tener el valor 10 has caído en la trampa que men 80
donábamos. La segunda declaración no expresa una condición que sea cierta para todo momento; en lugar de ello, es una expresión que sólo se evalúa una vez, con un valor específico de la variable. En este ejemplo, la declaración se evalúa cuando A tiene el valor 10. Las declaraciones posteriores pueden alterar el valor de A , pero B quedará sin cambiar a no ser que se ejecute una declaración de asignación diferente. Veamos otro error común. Hasta este momento sólo hemos usado los valores True y False en las operaciones booleanas porque es lo que te encontrarás más frecuentemente. Sin embargo ten siempre en mente que como True y False son equivalentes a los enteros 1 y 0, Visual Basic no generará un mensaje de error si tratas de usar And, Or, Imp o cualquier otro operador lógico con operandos enteros, como 6 ó 237. Visual Basic, realmente, ejecutará las operaciones booleanas especificadas en cada bit de los operandos. Esto puede conducir a que se produzcan extraños errores. Por ejemplo, digamos que quieres saber si la variable x es igual a 5 ó a 6. Podrías tratar de codificar la declaración como Debug.Print x = 5 Or 6. Visual Basic ejecutaría la operación Or sobre los enteros 5 y 6 de bit en bit, lo cual daría un resultado de 7. Entonces compararía el valor de x con 7, que no es exactamente lo mismo que tú habías pensado. En lugar de esto deberías codificar la declaración del siguiente modo: Debug.Pri nt (x = 5) Or (x = 6).
Procedimientos Aunque ya has escritos algunos procedimientos y probablemente tienes cierto conocimiento de los que son y cómo funcionan, no estará de más que formalicemos 81
EL LIBRO DEL VISUAL BASIC
ese conocimiento un poco. Este apartado se concentra, fundamentalmente, en los procedimientos internos de Visual Basic; más adelante, el capítulo 7 se centrará en el diseño y escritura de procedimientos nuevos, en lugar de utilizar simplemente los existentes. Un procedimiento es un conjunto de instrucciones que ejecutan un servicio concreto. El servicio se solicita usando el nombre del procedimiento. Por ejemplo, en el capítulo 3 escribiste un pequeño programa que utilizaba el procedimiento M sgB ox. Cuando se ejecuta esa porción de tu programa, Visual Basic muestra un cuadro de diálogo con el texto que tú le has proporcionado. Cuando se cierra el cuadro de diálogo, el programa continúa. Visual Basic proporciona el servicio de dibujar un cuadro de diálogo alrededor de tu mensaje, de crear un botón Aceptar, de vigilar al ratón hasta que se hace clic y de borrar el cuadro de diálogo de la pantalla; todo lo que tú tienes que hacer es suministrar el mensaje. Los servicios que proporciona Visual Basic pueden compararse con los que se prestan en la vida diaria. Por ejemplo, si acabas de comprar un cuadro de Van Gogh y estás preocupado porque el cheque que enviaste a Sotheby’s pueda ser rechazado, podrías llamar al banco y solicitar una transferencia. Le proporcionas al banco el número de las cuentas y la cantidad que quieres transferir, y el banco proporciona el servicio, sin más intervención por tu parte. En otros casos, el que proporciona el servicio devuelve un objeto tangible. Por ejemplo, podrías visitar al vendedor local de pollos asados, hacerle un pedido, darle dinero y obtener un pollo asado a cambio. Como podrás recordar, los procedimientos de Visual Basic que devuelven valores se denominan funciones. En el programa de ejemplo del capítulo 3, llamaste a la función InputBox. Le suministraste el texto que debía mostrar y ella mostró en pantalla un cuadro de diálogo y te devolvió el texto introducido en el cuadro de diálogo. Visual Basic dispone de muchas funciones internas que pueden usarse sin necesidad de definirlas. Algunas de estas funciones se describen en la figura 4.15. Puedes utilizar la Ayuda de Visual Basic y el manual de referencia para explorar estas funciones internas con más profundidad.
La sintaxis para los procedimientos y funciones
Para llamar a un procedimiento o función debes utilizar su nombre. Además de eso, Visual Basic tiene reglas adicionales específicas para la sintaxis de una declaración —es decir, cómo debe escribirse la declaración y organizaría dentro del código. (Aunque las funciones también son procedimientos, para simplificar esta 82
4 Declaraciones, expresiones y procedimientos
exposición sobre la sintaxis usaremos el término procedimiento para referirnos a los servicios que no devuelven un valor, y el término función para referirnos a los servicios que sí lo devuelven.)
Función
A bs A sc Chr$ cos CurDir$ Date$ Format InputBox Len M id$ N ow R nd Si n Sqr Str $ Time$ Val
Valor devuelto
El valor absoluto de un número. El código ASCII ó ANSI de un carácter. El carácter correspondiente a un código ASCII ó ANSI dado. El coseno de un ángulo. El nombre del directorio de trabajo actual. La fecha actual como una cadena de texto. Una fecha o un número convertida en una cadena de texto. El texto introducido en un cuadro de diálogo por un usuario. El número de caracteres de una cadena de texto. Una porción seleccionada de una cadena de texto. La fecha y hora actuales. Un número aleatorio. El seno de un ángulo. La raíz cuadrada de un número. Un número convertido en una cadena de texto. La hora actual como una cadena de texto. El valor numérico de una cadena de texto dada.
Figura 4.15. Algunas funciones internas de Visual Basic
Para llamar o hacer uso de un procedimiento debes escribir una declaración en Visual Basic, en la cual el nombre del procedimiento sea lo primero que aparezca. Una llamada a un procedimiento es una declaración completa en Visual Basic, y el procedimiento puede no requerir ninguna otra información por tu parte. En el caso de que necesites más información debes introducir los valores que quieras enviar al procedimiento, separados por comas. Los valores que se le pasan a un procedimiento (o a una función) se denominan argumentos. En el caso del procedimiento M sgB ox, utilizaste un solo argumento: la cadena de texto que había que mostrar en pantalla. Las siguientes declaraciones son ejemplos de llamadas a procedimientos de Visual Basic: 83
EL LIBRO DEL VISUAL BASIC
MsgBox "Hola marinero" ChDir ”\test\datos" Beep SavePicture NocheEstrellada, "vicente.bmp"
La sintaxis de llamada a una función es diferente. Como una función devuelve un valor puede usarse en cualquier lugar donde sería válida una expresión. Pero las expresiones aisladas no son declaraciones válidas en Visual Basic. Consiguientemente, una llamada a una función siempre se encuentra en el contexto de otra declaración, la mayoría de las veces una declaración de asignación. Cuando una función no requiere argumentos, simplemente se usa el nombre de la función como si fuera el nombre de una variable, como en la declaración Ho raInicio = Now. La función N ow no requiere argumentos y devuelve un valor hora rio. Visual Basic llama a la función y asigna el valor devuelto a la variable Hora-
Inicio.
Cuando una función requiere uno o más argumentos, se debe poner un paréntesis de apertura detrás del nombre de la función, introducir los argumentos separados por comas, y marcar el final de la función con un paréntesis de cierre. Las siguientes expresiones contienen llamadas a funciones válidas (aunque no sean declaraciones completas de Visual Basic): Sin(x) ^ 2 ’Obtiene el seno de x y eleva al cuadrado el resultado Chr$(65) ’Devuelve el carácter ASCII representado por el número 65 Format(Now, "hh:mm") ’Da formato a la hora actual
Observa que en el tercer ejemplo la expresión contiene una llamada a una función dentro de otra. En este caso, el valor de la función Now se pasa como argumento a la función Format. Métodos
Los procedimientos y las funciones han formado parte de los lenguajes de progra mación durante muchos años. Más recientemente, los diseñadores de lenguajes de programación orientados a objetos han introducido tipos especiales de procedimientos y funciones denominados métodos. Aunque Visual Basic no está realmente orientado a objetos, incluye métodos para cada uno de sus objetos, como los formularios y los botones de comandos. Los métodos funcionan de la misma manera que los procedimientos y las funciones, pero son componentes de objetos específicos, de la misma manera que lo son las propiedades y los nombres de los campos. Para llamar a un método se utiliza el nombre del objeto y el nombre del método, separados por un punto —por ejemplo, Debug.Print. 84
4 Declaraciones, expresiones y procedimientos
Esto es un poco más complejo que utilizar simplemente el nombre de un procedimiento, pero tiene la ventaja de permitir que más de un método tengan el mismo nombre. En versiones anteriores de Basic, el procedimiento PRINT escribía una cadena de texto en el terminal del usuario. Para escribir en la impresora, el usuario tenía que llamar a un procedimiento distinto: LPRINT. Ambos procedimientos funcionan de manea similar, pero debido a pequeñas diferencias requerían dos comandos separados. Visual Basic no tiene el procedimiento Print. En su lugar, todos los objetos en los cuales se pueden escribir disponen de un procedimiento llamado Print. Para escribir la cadena " Hola” en un formulario llamado M iForm escribirías el siguiente código: MiForm.Print "Hola”
Para escribir en la impresora, que está representada en Visual Basic por un objeto especial denominado Printer, usarías este código: Printer.Print "Hola”
La ventana Debug (depurar), que está representada por un objeto llamado De bug, también tiene un método Print. Como Visual Basic proporciona un método Print para cada uno de estos objetos no son necesarios distintos comandos de impresión con nombres diferentes. Si tienes menos comandos que aprender tu tra bajo será un poco más fácil. A menudo, Visual Basic permite omitir el nombre del objeto cuando se usa un método. Si haces esto, Visual Basic dirigirá el método al objeto al que cree que te estás refiriendo —normalmente, el formulario actual. Si hubieses escrito Print "Hola” en los ejemplos anteriores, la salida hubiera ido al formulario que estuviese activo cuando el programa estuviera funcionando. Para evitar la ambigüedad debes usar siempre la convención objeto.método completa. Los métodos pueden actuar como procedimientos o como funciones —es decir, pueden limitarse a prestar un servicio, como hace el método Print, o pueden devolver un valor. Algunos métodos —como Move, que cambia la ubicación de un objeto— están implementados, prácticamente, para todos los tipos de objetos. Otros son más especializados. El método Print, por ejemplo, está implementado sólo para unos pocos objetos como los formularios y la impresora. El siguiente capítulo explorará los objetos de Visual Basic y sus propiedades y métodos.
85
5 El uso de formularios y herramientas de Visual Basic Los objetos de Visual Basic Una de las grandes ventajas de un interface gráfico de usuario estriba en que el usuario puede interactuar con un conjunto estándar de objetos, como ventanas, botones y barras de desplazamiento. Las aplicaciones que utilizan estos objetos estándar se comportan de una manera estándar, haciendo que las aplicaciones sean fáciles de aprender. Parte de tu trabajo como programador consiste en seleccionar el estilo de interacción que sea más apropiado para la situación y en escri bir tus programas de una manera intuitiva para el usuario. En un entorno GUI (grapbical user interface, interface gráfico de usuario), el usuario interactúa con los objetos que hay en pantalla para iniciar los eventos (abrir una ventana, hacer clic en un icono, seleccionar un elemento de un menú), y haciendo eso controla la aplicación. Visual Basic traduce un evento iniciado por el usuario en una actividad programada, llamando a un procedimiento que está asociado con ese evento. El código que tú proporcionas para ese evento imple menta la respuesta adecuada a la interacción del usuario con el objeto. Una nota sob re este capítulo
Este capítulo describe la mayoría de los objetos que tendrás disponibles cuando construyas aplicaciones en Visual Basic, incluyendo los formularios y los objetos 87
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
creados con las diversas herramientas de la caja de herramientas. Ya te has encontrado con alguno de esos objetos en capítulos anteriores; sin embargo, aquí echaremos una mirada más profunda a algunas de las propiedades que se pueden establecer y a cómo afectan a esos objetos, a los eventos que se generan cuando un usuario manipula esos objetos en una aplicación, y a algunos de los procedimientos y métodos que se pueden utilizar con cada objeto. También exploraremos el proceso de diseño y creación de menús para tus aplicaciones. Al final de la mayoría de los apartados de este capítulo hay un proyecto de ejemplo que muestra cómo puedes usar el objeto de Visual Basic que se acaba de describir. Las instrucciones de los dos primeros proyectos son detalladas y explícitas; sin embargo, las instrucciones para los proyectos siguientes son más generales —simplemente te dicen "crea un nuevo proyecto—, por ejemplo, en lugar de explicar los comandos que hay que seleccionar ya que presumimos que, a esta altura, conocerás la manera de realizar las cosas. La decisión de guardar o no las aplicaciones de ejemplo es, en general, tuya. En la mayoría de los casos, probablemente no sea necesario. Pero si sabes que vas a utilizar un objeto o una herramienta específica en un futuro cercano, puede que te sea útil guardar el proyecto asociado de manera que puedas volver atrás y examinarlo más adelante. Debes estar prevenido para que la lista de propiedades, eventos, procedimientos y métodos de este capítulo no sea exhaustiva; en lugar de ello, el objetivo, simplemente, es proporcionarte las herramientas suficientes para escribir programas útiles. Puedes comprobar que las listas completas son un poco excesivas en este momento, pero las tienes disponibles en el sistema de Ayuda y en el manual de referencia de Visual Basic, por si necesitaras fuentes de información adicionales. Además, algunos capítulos posteriores de este libro introducirán algunas propiedades y procedimientos adicionales. Observa que muchos de los objetos descritos aquí tienen idénticas propiedades o gestionan eventos similares. En tales casos, las descripciones completas de las propiedades, eventos, procedimientos, etc., no se repiten para cada objeto. Empezaremos por describir los formularios; te encontrarás con las descripciones más extensas en este apartado.
Una nota sobre la sintaxis
Muchas de las descripciones de procedimientos y métodos incluyen la sintaxis de las declaraciones apropiadas en Visual Basic. En estas declaraciones de sintaxis, 88
los elementos en cursiva indican el tipo de información que debes proporcionar —por ejemplo, cuando veas la palabra variable debes introducir un nombre de variable en esa posición de la declaración. Los elementos que se muestren en el tipo de letra roman (texto) indican palabras clave o caracteres que debes introducir tal y como aparecen. Los elementos que se muestran entre corchetes ([ ]) son opcionales —es decir, la declaración será válida incluso si se omiten esos elementos. Los elementos que se muestran entre llaves ({ }) que están separados por una barra vertical (|) indican una elección; debes seleccionar uno de los elementos que hay dentro de los corchetes. Si unos corchetes o llaves aparecen seguidos por unos puntos suspensivos, la secuencia que hay dentro de los corchetes o de las llaves puede repetirse. Aquí tienes un ejemplo: El nombre es [muy] {grande | pequeño} [y {audaz | tímido | verde }]... A partir de la notación sintáctica que acabamos de describir, puedes usar este ejemplo para construir cualquiera de las siguientes frases: La factoría es muy grande. El submarino es pequeño y verde. La ventana es muy pequeña y audaz y tímida y verde. Como puedes ver, la sintaxis correcta no produce, necesariamente, una declaración con sentido; ya verás que es muy fácil escribir programas que son sintácticamente correctos pero que no funcionan adecuadamente. Trataremos este problema en el capítulo 8.
Formularios Como viste en el capítulo 1, los formularios son los lienzos en los que puedes crear tu aplicación visualmente. Cada formulario se corresponde con una ventana cuando se ejecuta la aplicación. Propiedades
Hay muchas propiedades que pueden afectar a la apariencia y comportamiento de un formulario cuando éste aparece en pantalla; aquí sólo vamos a tratar las propiedades que se usan con más frecuencia. Excepto cuando se diga lo contrario, las propiedades pueden establecerse usando tanto la ventana Properties a medida que realizas el diseño de una aplicación, como escribiendo el código del programa, para que establezca las propiedades cuando el programa se esté ejecutando. 89
EL LIBRO DEL VISUAL BASIC
("redibujarse" automáticamente). La propiedad AutoRedraw (que se trata con detalle en el capítulo 10) gestiona la manera en que se redibujan las imágenes en pantalla. Cuando se vuelve a un formulario de Visual Basic después de trabajar en otra ventana que haya tapado el formulario, Visual Basic refrescará o redibujará automáticamente cualquier gráfico que haya en el formulario, si la propiedad AutoRedraw está establecida como True. Cuando esta propiedad está establecida como False, Visual Basic deberá llamar a un procedimiento de evento para llevar a cabo esta tarea.
Au to Redr aw
( color del fondo). Esta propiedad determina el color del fondo. Cuando se selecciona BackColor en la lista de propiedades de la ventana Properties, se ve el ajuste por omisión &H80000005&, una constante hexadecimal (base 16) que define un color en Visual Basic. (Estas constantes están contenidas en el archivo CONSTANT.TXT.) El capítulo 10 proporciona más detalles sobre los ajustes de los colores, aunque no es necesario saber mucho sobre ellos para establecer la propiedad BackColor: simplemente, hay que hacer clic en el botón con puntos suspensivos que hay al lado del cuadro Ajustes en la ventana Properties, y Visual Basic mostrará una paleta de colores como ésta:
BackColor
5 El uso de formularios y herramientas de Visual Basic
0 None (ninguno) La ventana no tiene borde. 1 Fixed Single (fijo sencillo) La ventana tiene un tamaño fijo (que se especifica durante el diseño) y un borde de línea sencilla. 2 Sizable (ajustable en La ventana es ajustable en tamaño y tiene tamaño) un borde estándar de línea doble. 3 Fixed Double (fijo doble) La ventana tiene un tamaño fijo (que se especifica durante el diseño) y un borde de línea doble. (título). Esta propiedad contiene el texto de la barra del título de la ventana del formulario.
Caption
(cuadro del menú de control). Esta propiedad booleana debe establecerse como True, si quieres que se muestre un cuadro para el menú de control en el extremo superior izquierdo de la ventana. Puedes modificar esta propiedad sólo durante el diseño. Establecer la propiedad ControlBox como True no produce ningún efecto, si has ajustado BorderStyle a 0 None.
ControlBox
(activado). Todos los objetos de Visual Basic tienen una propiedad Ena bled que puede establecerse como True o como False para activar o desactivar el objeto. En el caso de un formulario, esta propiedad, normalmente, se establece como True, pero puedes ajustarla a False para evitar que se envíe al formulario ningún evento del ratón o del teclado.
Enabled
Fontltalic, FontStrikethru, FontUnderline (fuente en negrita, en cursiva, tachada, subrayada). Puedes establecer estas propiedades booleanas como True si deseas que el texto que se imprima en el formulario aparezca en negrita, cursiva, tachado o subrayado (o con cualquier combinación de estos atributos). Sólo se verán afectados por el nuevo ajuste los caracteres que se impriman después de modificar algunas de estas propiedades.
FontBoId,
(nombre de la fuente). Esta propiedad se ajusta al nombre de la fuente que se utilizará para imprimir un formulario. Si cambias la fuente, el texto ya escrito en el formulario no se verá modificado, pero sí toda impresión posterior. Por ejemplo, si ejecutas el siguiente código, la letra C se imprimirá en la fuente Courier New, y todas las demás en Times New Roman:
FontName
Se puede seleccionar un color de la paleta haciendo clic sobre el cuadro apropiado, o se puede hacer clic en el botón X que hay al lado del cuadro Ajustes para cerrar la paleta. (estilo del borde). Puedes establecer esta propiedad a uno de los cuatro ajustes predefinidos. La propiedad BorderStyle sólo se puede establecer en la fase de diseño. El ajuste no afecta a la forma en que el formulario aparece en la pantalla durante la fase de diseño, pero modifica la apariencia de la ventana en el momento de la ejecución de la siguiente manera:
BorderStyle
90
FontName = "Times New Roman" Print "AB” FontName = "Courier New" Print "C"
91
EL LIBRO DEL VISUAL BASIC
FontName = "Times New Roman" Print "DE"
(tamaño de la fuente). Esta propiedad te permite especificar un tamaño (en puntos) para el texto que se imprima en el formulario. (Un punto es una unidad estándar tipográfica que sirve para medir el tamaño del tipo; 1 punto equivale, aproximadamente, a 1/72pulgadas.) Este ajuste no afecta al tamaño de cualquier texto impreso.
FontSize
(color del primer plano). Esta propiedad define el color del primer plano del texto o de los gráficos. La propiedad se establece eligiendo un color de una paleta, de la misma manera que la propiedad BackColor (veremos más detalles en el capítulo 10). Todas las declaraciones Print escriben el texto usando el color del primer plano.
ForeColor
(altura, anchura). Estas propiedades determinan la altura y la anchura del formulario, medidas en unidades llamadas twips, o veinteavas partes de punto. (Un twip equivale a 1 / 1440 pulgadas.)
Height, Width
(icono). Puedes asignarle como valor a esta propiedad el nombre de un archivo que contenga un icono. El icono representará al formulario cuando esté minimizado. Si quieres establecer esta propiedad durante el diseño, selecciónala de la lista de propiedades de la ventana Properties y luego haz clic en el botón con los puntos suspensivos que aparece al lado del cuadro Ajustes. Selecciona un archivo de icono en el cuadro de diálogo que aparece. Si quieres establecer la propiedad durante la ejecución, debes utilizar la función LoadPicture o asignar el valor de la propiedad Icon de algún otro formulario.
Icon
MinButton (botón maximizar, botón minimizar). Debes establecer estas propiedades booleanas como True, si quieres que aparezcan botones Maximizar y Minimizar en la esquina superior derecha de la ventana. Estas dos propiedades se ignoran si has establecido la propiedad BorderStyle a 0 None. Observa (que los botones Maximizar y Minimizar no desaparecen del formulario durante el diseño, incluso aunque establezcas las propiedades MaxButton y MinButton a False; el efecto de estos ajustes no es visible en la ventana hasta el momento de la ejecución.
MaxButton,
(nombre). Esta propiedad define el nombre del formulario en el código del programa. No puede cambiarse durante la ejecución.
Name
(dibujo). Puedes establecer esta propiedad para indicar que se muestre siempre en el formulario un dibujo bitmap. Si quieres establecer esta propiedad durante el diseño, selecciónala de la lista de propiedades y haz clic en el
Picture
92
5 El uso de formularios y herramientas de Visual Basic
botón con los puntos suspensivos que aparece al lado del cuadro Ajustes en la ventana Properties. En el cuadro de diálogo que aparece, selecciona un archivo que contenga el dibujo que quieres mostrar. Para cambiar esta propiedad durante la ejecución debes utilizar la función LoadPicture. (arriba, izquierda). Estas propiedades controlan la posición del formulario en la pantalla, definiendo la ubicación de la parte superior de la ventana y de su extremo izquierdo, medidos por omisión en twips.
Top, Left
(visible). El ajuste de esta propiedad booleana indica si la ventana del formulario será visible o no. Si se establece esta propiedad como False se ocultará el formulario de la vista.
Visible
(estado de la ventana). Esta propiedad determina si la ventana aparecerá en su estado normal (el valor 0), en un estado minimizado como un icono (el valor 1) o en un estado maximizado (el valor 2).
WindowState
Eventos
Click, DblClick y Load son los eventos más comunes que procesa un formulario. (Los eventos KeyPress y el proceso de arrastrarysoltar se introducen en los capítulos 6 y 7.) (clic). Cuando el usuario hace clic en el formulario, Visual Basic llama al procedimiento Form_Click. Si el usuario hace clic sobre un objeto contenido en el formulario, el evento Click no se pasa al formulario, incluso aunque el otro objeto no procese el evento.
Click
(doble clic). Este evento se recibe si el usuario hace clic dos veces en rápida sucesión. El proceso, realmente, envía dos eventos: un evento Click para el primer clic del ratón, y un evento DblClick para el segundo.
DblClick
(cargar). Este evento ocurre automáticamente cuando se carga un formulario, por ejemplo, cuando se arranca una aplicación. Un procedimiento de evento Load es muy útil para dar un valor inicial a las propiedades y variables al comienzo de un programa (proceso que recibe el nombre de "inicializar'').
Load
Procedimientos y métodos
Los métodos más interesantes de un formulario son los métodos gráficos. Como son bastante complejos les hemos dedicado un capítulo entero del libro (el capítulo 10). Por ahora echaremos una rápida mirada a un par de métodos (y a una función) para ir abriendo boca. 93
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
C/s(borrar). Este método borra del formulario todos los gráficos y el texto. La sin-
taxis completa del método Cls es la siguiente: [nombreDelFormulario].Cls
1.
Arranca la aplicación Paintbrush en Windows, dibuja una gráfico sencillo y guárdalo en un archivo en el disco duro. Aquí tienes un ejemplo usando un famoso icono cultural de los años 70:
LoadPicture (cargar dibujo). Esta función se puede utilizar para establecer la propiedad Picture de un formulario. Aquí está la sintaxis de la función: LoadPicture[( nombreDelArchivo]) El nombre del archivo debe ser una expresión de cadena que identifique a un archivo que contenga un icono, un bitmap (un gráfico de mapa de bits) de Windows o un metaarchivo (metafile) de Windows. (Estos archivos tienen, normalmente, las extensiones ICO, BMP y WMF.) Si no especificas un nombre de archivo, LoadPicture devuelve un dibujo blanco. Prínt (imprimir). Este método escribe texto en el
formulario. Utiliza esta sintaxis:
nombreDelFormulario] .Print [[expresión] [{ ; | , }]...
Cada expresión va seguida de un punto y coma o de una coma. Si se usa un punto y coma, la siguiente expresión irá inmediatamente a continuación del último carácter escrito. Si se utiliza una coma, la posición de salida en el formulario será la siguiente columna. (Las columnas están definidas cada 14 caracteres.) Si la expresión final en la declaración Print termina en un punto y coma o en una coma, no se escribirá un retorno de carro en el formulario; en caso contrario, la posición de salida se establecerá en la siguiente línea. Aquí tienes algunos ejemplos del uso del método Print en la ventana Debug:
2. Vuelve a Visual Basic y crea un proyecto nuevo seleccionando el comando New Project del menú File. 3. Selecciona la propiedad Picture en la ventana Properties, y luego haz clic en el botón con los puntos suspensivos que hay a la derecha del cuadro Ajustes. Aparecerá el cuadro Load Picture (cargar dibujo):
A pesar de lo extraño que pueda sonar, el método Print es, realmente, un método gráfico; puedes encontrar más información sobre él en el capítulo 10. La aplicación Sonrisa
Ahora trata de construir el proyecto de ejemplo, que muestra algunos de los ajustes de las propiedades, métodos y procedimientos asociados con los formularios. 94
4. Especifica en el cuadro de diálogo el nombre del archivo gráfico que creaste con Paintbrush, y luego haz. clic en el botón OK. Mi versión del formulario tiene ahora el aspecto que puedes ver en la parte superior de la página siguiente: 95
EL LIBRO DEL VISUAL BASIC
5. Selecciona la propiedad FontBold de la lista de propiedades y establécela como False en el cuadro Ajustes. 6.
Abre la ventana de código para Form1 haciendo clic en el botón View Code de la ventana del proyecto o haciendo doble clic en el formulario.
7. Selecciona Form en el cuadro Object que hay en la parte superior de la ventana de código y luego selecciona Click en el cuadro Procedure. Introduce el código necesario para crear el procedimiento Form_Click, como se muestra aquí en gris: Sub Form_Click () Form1.Print "Tenga un Form1.FontBold = True Form1.Print "buen"; Form1.FontBold = False Form1.Print " día" End Sub
8. Selecciona DblClick en el cuadro Procedure. Introduce la línea de código
que se muestra en gris para crear el procedimiento Form_DblClick: Sub Form_DblClick () Form1.Cls End Sub
9. Ahora ejecuta la aplicación seleccionando el comando Start del menú Run, haciendo clic en el botón Start de la barra de herramientas o pulsando F5. Haz clic en varios puntos del formulario. La aplicación debe comportarse como se muestra aquí: 96
5 El uso de formularios y herramientas de Visual Basic
10. Mientras que la aplicación esté funcionando todavía, prueba a hacer doble clic sobre el formulario. Esta acción hace que el programa ejecute el procedimiento Form_DblClick. Si miras atentamente verás que el programa ejecuta el procedimiento Form_Click antes de que Form_DblClick borre el formulario. Observa también que el método Cls borra sólo la información que se ha añadido al formulario, y no el dibujo del fondo. El código escrito para este ejemplo es bastante preciso: especifica el uso del método Print para Form1, y modifica, explícitamente, la propiedad FontBold de Form1. Por desgracia, esta precisión puede ocasionarte problemas algunas veces. Para verlo, termina la aplicación (pulsando Alt+F4 o haciendo clic en el botón End de la barra de herramientas), y vuelve al modo de diseño. Ahora cambia la propiedad Name del formulario a Sonrisa. Cuando trates de ejecutar el programa otra vez, Visual Basic mostrará el mensaje de error que aparece en la figura 5.1 (en la página siguiente). Visual Basic se queja de que no tiene conocimiento de que haya algún objeto llamado Forml. Realmente, el programa no contiene tal objeto; el único formulario de tu programa se llama ahora Sonrisa. Aunque no es probable que quieras perder mucho tiempo cambiando el nombre de los formularios de tus programas, sí que puedes desear incorporar parte de un programa a otro en algún momento posterior. En tal caso, podrías encontrarte con este problema. Visual Basic ofrece una solución sencilla. Los métodos y las propiedades tienen un ámbito, de la misma manera que las variables. Si utilizas el nombre de un método o de un procedimiento sin definir explícitamente el objeto al que pertenece, Visual Basic usará el contexto de ejecución actual para determi 97
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
mente requiere más memoria y tiempo cuando se utiliza. Los cuadros de dibujo son los más adecuados para entornos dinámicos —por ejemplo, cuando se dibu jan gráficos directamente en la pantalla mientras el programa está funcionando o cuando se anima un icono moviéndolo por la pantalla. (Los métodos gráficos, que te permiten dibujar líneas y pintar texto, se describen en el capítulo 10.) Los objetos imagen son mejores para situaciones estáticas —o sea, cuando el bitmap o el icono que has creado y situado en la pantalla no se va a modificar.
Figura 5.1. Un mensaje de error sobre un objeto no identificado
Figura 5.2.
nar el objeto afectado. Si borras todas las referencias a Form1, el código de la aplicación Sonrisa se parecerá a esto: Sub Form_Click () Print "Tenga un "; FontBold = True Print "buen"; FontBold = False Print " día" End Sub Sub Form_DblClick () Cl s End Sub
Como los procedimientos Form_Click y Form_DblClick siempre se ejecutan en el contexto del formulario (independientemente del nombre del formulario), los métodos Print y Cls y la propiedad FontBold deben estar dentro del ámbito del formulario actual. De esta manera puedes usar fácilmente código más general (y tendrás que escribir menos).
Cuadros de dibujo e imágenes Los controles Picture Box (cuadro de dibujo) e Image (imagen) permiten situar información gráfica en una posición específica del formulario. Puedes ver en las figuras 5.2 y 5.3 las herramientas cuadro de dibujo e imagen de la caja de herramientas. El control cuadro de dibujo es el más flexible de los dos y, consecuente98
La herramienta Picture Box (cuadro de dibujo)
Figura 5.3. La herramienta Image (imagen)
Propiedades
Los controles cuadro de dibujo e imagen tienen las propiedades Enabled, Height, Left, Name, Picture, Top, Visible y Width. La mayoría de estas propiedades se comportan exactamente como se ha descrito en el apartado anterior sobre los formularios, excepto que las coordenadas Height, Left, Top y Width se miden con respecto a la localización del objeto en el formulario, no en coordenadas absolutas de pantalla. (Esto es así para todos los controles creados con la caja de herramientas.) La propiedad Picture puede establecerse para que muestre un bitmap o un icono: durante el diseño utiliza la ventana de propiedades y el cuadro de diálogo Load Picture (como lo haremos en el proyecto de ejemplo que viene a continuación); durante la ejecución tendrás que utilizar la función LoaclPicture. Los cuadros de dibujo, que se comportan casi como pequeños formularios dentro del formulario principal, tienen las siguientes propiedades (de las cuales carece el control imagen): AutoRedraw, FontBold, FontItalic, FontName, FontSize y FontUn derline. Estas propiedades se comportan igual que en los formularios. Los contro 99
EL LIBRO DEL VISUAL BASIC
les imagen poseen sólo una propiedad que los cuadros de control no tienen: la propiedad Stretch (extender). Por omisión, Stretch está establecida como False, lo que produce que el control imagen ajuste su propio tamaño para que coincida con el del gráfico que contiene. Si estableces Stretch como True, el gráfico ajustará su tamaño al del control. Los controles imagen y cuadro de dibujo también difieren en otro aspecto. La zona de visualización de un formulario está compuesta por tres rejillas, como se ilustra en la figura 5.4. Toda la información mostrada directamente en el formulario (por ejemplo, imprimiendo o dibujando con los métodos gráficos) aparece en la rejilla inferior. La información de tres controles gráficos (los controles imagen, forma —Shape— y línea —Line) aparecen en la rejilla intermedia, y todos los demás objetos se muestran en la rejilla superior. Consiguientemente, el texto impreso en un formulario puede ser ocultado por una imagen, que a su vez puede ser ocultada por un cuadro de dibujo.
5 El uso de formularios y herramientas de Visual Basic
miten los métodos Cls y Print, así como los otros métodos gráficos descritos en el capítulo 10. Lo p aleta de direcciones
Este proyecto de ejemplo te permite usar una serie de imágenes para crear una paleta de iconos similar a la caja de herramientas de Visual Basic. El programa debe funcionar exactamente de la misma manera, tanto si usas controles del tipo cuadro de dibujo como controles imagen; sin embargo, recuerda que los cuadros de dibujo son menos eficientes cuando lo que se muestra en pantalla es algo estático. 1. Crea un proyecto nuevo en Visual Basic seleccionando el comando New Project del menú File. 2. Establece las propiedades del formulario como se muestra aquí. (La notación [ninguna] indica que el ajuste debe ser una cadena vacía.) Propiedad
Rejilla inferior: formulario Rejilla intermedia: imagen, forma, línea Rejilla superior: otros controles
BorderStyle Caption MaxButton MinButton Name
Aju ste
1Fixed Single [ninguno] False False Direcciones
3. Haz clic en la herramienta Image de la caja de herramientas y arrastra el puntero del ratón sobre el formulario para crear un pequeño control imagen en la esquina superior izquierda del formulario:
Figura 5.4.
Las rejillas dela zona de visualización deun formulario Eventos
Al igual que los formularios, tanto el control cuadro de dibujo como el control imagen pueden recibir los eventos Click y DblClick, los cuales están entre los más simples y los que se encuentran con más frecuencia. Procedimientos y métodos
Puede llamarse a la función LoadPicture para establecer la propiedad Picture de un control cuadro de dibujo o de una imagen. Los cuadros de dibujo también ad100
4. Crea tres controles Image más del mismo tamaño, y organízalos en un cuadrado de 2 por 2. Utiliza el ratón para modificar los límites de la ventana 101
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
del formulario para que se ajusten a los cuatros controles imagen. Tu formulario debe parecerse ahora al que se muestra aquí:
Sub Image4_Click () Debug.Print "Has seleccionado derecha" End Sub
8. Para separar visualmente los iconos puedes poner bordes a su alrededor.
5. Haz clic en el control Image del extremo superior izquierdo del formulario (Image1) para seleccionarlo. En la ventana Properties, selecciona de la lista de propiedades la propiedad Picture para Image1. Luego haz clic en el botón con los puntos suspensivos que hay al lado del cuadro Ajuste para abrir el cuadro de diálogo Load Picture (que viste en la página 95). Establece el tipo de archivo en el cuadro de diálogo para que se vean archivos de icono (con la extensión ICO). En el subdirectorio ARROWS situado dentro del directorio ICONS que viene con Visual Basic encontrarás el archivo ARW02UP.ICO. Cuando selecciones ese archivo, aparecerá el icono que contiene en el control Image seleccionado:
Haz clic en la imagen del extremo superior izquierdo para seleccionarla, y luego mantén pulsada la tecla Ctrl mientras haces clic en las otras tres imágenes para seleccionarlas todas a la vez. En la ventana Properties selecciona la propiedad BorderStyle de la lista de propiedades, y establécela como 1 Fixed Single. Cuando ejecutes esta aplicación (pulsando F5), tu formulario será una paleta de "Direcciones". Cuando hagas clic en algunos iconos debes ver un resultado como el que se muestra en la figura 5.5.
6. Haz doble clic en la imagen y define el siguiente procedimiento en la ven-
tana de código: Sub Image1_Click () Debug.Print "Has seleccionado arriba" End Sub
7. Repite el mismo proceso para los otros tres controles Image, cargando los archivos ARW02DN.ICO, ARW02LT.ICO y ARW02RT.ICO, e introduciendo los tres procedimientos del evento Click como sigue: Sub Image2_Click () Debug.Print "Has seleccionado abajo" End Sub Sub Image3_Click () Debug.Print "Has seleccionado izquierda" End Sub
102
Figura 5.5. liso de la paleta de direcciones
incluyes un código similar en una aplicación más grande, podrás crear una paleta de iconos que sean apropiados al programa que estés creando. La caja de herramientas de Visual Basic, que se usa en el modo de diseño, es un ejemplo de este tipo de paletas.
Si
Consejo: Visual Basic viene con cientos de iconos, así como con un pro grama editor de i conos que te permite crear los tuyos propi os. El propi o editor de iconos se escribió en Visual Basic. Puedes atrancar el editor de iconos cargando el proyecto ICONWRKS.MAK (del directorio SAMPLES) y ejecutando la apli cación. E l editor de iconos tiene su propia A yuda.
103
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
Etiquetas Una etiqueta proporciona un área donde se puede presentar texto que no pueda ser editado por el usuario. El contenido se establece modificando la propiedad Caption de la etiqueta. No se puede imprimir ni dibujar en una etiqueta. Las etiquetas se crean con la herramienta Label de la caja de herramientas de Visual Basic, que se muestra en la figura 5.6.
Eventos
Los objetos Label reciben los eventos Click y DblClick, al igual que los cuadros de dibujo, los controles imagen, los formularios, etcétera. Procedimientos y métodos
Los objetos Label sólo tienen la misión de mostrar pequeños bloques de texto. Como el texto se define estableciendo la propiedad Caption, ninguno de los métodos asociados con etiquetas son particularmente útiles o necesarios para el principiante.
Figura 5.6.
Modificar la aplicación Cronómetro
La herramienta Label (etiqueta)
Hagamos un cambio más al programa Cronómetro que creaste en el capítulo 1. En este programa usamos cuadros de texto para mostrar la salida de la aplicación. Como recordarás, los cuadros de texto puede modificarlos el usuario. Para ilustrar esto, carga y ejecuta la aplicación Cronómetro. Después de detener el tiempo, selecciona el texto del cuadro Hora de inicio y escribe xyz —se embarulla la pantalla, ¿no? Desde luego, es difícil imaginarse la razón por la cual un usuario quisiera hacer una cosa así, pero muchos programadores se han pasado largas y solitarias noches preguntándose por qué los usuarios hacen lo que hacen. En cualquier caso, puedes simplemente estructurar la aplicación para que evite este problema usando etiquetas en lugar de cuadros de texto.
Propiedades
Las etiquetas tienen las propiedades FontBold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible y Width, que funcionan de manera estándar. A continuación se describen algunas propiedades adicionales: (alineación). Esta propiedad determina cómo se sitúa el título de la etiqueta. Por omisión, la propiedad Alignment se establece en 0, lo cual justifica el título a la izquierda. También puedes establecer la alineación en 1 Right Justify (justificación a la derecha) o en 2 Center (centro).
Ali gnm ent
(autotamaño). Si esta propiedad se establece como True, el tamaño de la etiqueta se ajusta automáticamente al texto que se especifique con la propiedad Caption. Si AutoSize se establece como False, el tamaño de la etiqueta quedará como se definió durante el diseño; en ese caso, si el título es demasiado largo sólo se verá lo que quepa.
Au to Size
(estilo del borde). Esta propiedad puede establecerse en 0 (que es como aparece por omisión) para que no haya borde, ó en 1 para que aparezca un borde de una línea.
BorderStyle
1. Detén el programa y vuelve al modo de diseño. Borra los tres cuadros de texto haciendo clic en cada uno para seleccionarlos y pulsando luego la tecla Supr, o eligiendo el comando Delete (borrar) del menú Edit. En lugar de los tres cuadros de texto dibuja tres etiquetas. 2. Establece la propiedad BorderStyle de cada etiqueta a 1 Fixed Single para crear un borde de una sola línea. Borra cualquier texto que aparezca en el cuadro Ajustes de la propiedad Caption, dejando esta propiedad vacía para todas las etiquetas.
(título). La propiedad Caption contiene el texto que aparecerá en el campo de la etiqueta, o área de pantalla.
3. Establece la propiedad Name de la etiqueta superior a lblInicio. Luego establece la propiedad Name de la etiqueta intermedia a lblParada y la propiedad Name de la etiqueta inferior a lblLapsus.
(activada). Esta propiedad normalmente está establecida como True, pero se puede establecer como False para que el texto aparezca atenuado en la pantalla (en color gris) y para desactivar cualquier evento del ratón.
4. También debes modificar el código para los botones Inicio y Parada. La versión previa del programa mostraba sus resultados estableciendo la propiedad Text de los cuadros de texto. Sin embargo, las etiquetas tienen una
Caption
Enabled
104
105
EL LIBRO DEL VISUAL BASIC
propiedad Caption en lugar de una propiedad Text. Y, por supuesto, has sustituido los propios cuadros de texto por etiquetas. Tienes que editar los procedimientos del evento Click de los dos botones, de manera que puedas modificar cualquier referencia a los cuadros de texto y a la propiedad Text. El nuevo código debe ser como éste: Sub btnInicio_Click () HoraInicio = Now lblInicio.Caption = Format(HoraInicio, "hh:mm:ss") lblParada.Caption = " " lblLapsus.Caption = " " btnParada.Enabled = True btnInicio.Enabled = False End Sub Sub btnParada_Click () HoraParada = Now Lapsus = HoraParada - HoraInicio lblParada.Caption = Format(HoraParada, "hh:mm:ss") lblLapsus.Caption = Format(Lapsus, "hh:mm:ss”) btnParada.Enabled = False btnInicio.Enabled = True End Sub
Ejecuta la aplicación otra vez para comprobar los cambios. La pantalla debe tener exactamente el mismo aspecto que tenía cuando ejecutaste la aplicación en el capítulo 1, pero ya no podrás seleccionar ni modificar ninguno de los textos que aparecen en la pantalla.
Cuadros de texto Ya has trabajado con cuadros de texto en capítulos anteriores, usando la herramienta Text Box que se muestra en la figura 5.7. Dicho con sencillez, los cuadros de texto crean un área de pantalla en la cual el usuario puede introducir texto. Propiedades
Los cuadros de texto tienen las propiedades estándar BorderStyle, Enabled, Font Bold, FontItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible y Width, además de las siguientes: (longitud máxima). Esta propiedad, normalmente, se establece en 0 (por omisión), indicando que el cuadro de texto aceptará tantos caracteres
MaxLength
106
5 El uso de formularios y herramientas de Visual Basic
Figura 5.7. La herramienta Text Box (cuadro de texto)
como el usuario teclee. Pero, si estableces MaxLength en un valor que no sea cero, Visual Basic restringirá la entrada al número de caracteres especificados. (líneas múltiples). Lo más frecuente será que quieras establecer esta propiedad como False, lo que evitará que el usuario pueda introducir más que una línea de texto. Cuando la propiedad MultiLine se establece a True, el usuario podrá pulsar la tecla Intro para insertar un retorno de carro en el texto y continuar la introducción de texto en la siguiente línea.
MultíLine
(carácter de contraseña). Esta propiedad indica si un cuadro de texto es un campo de contraseña o no. Cuando el usuario escribe en un campo de contraseña, los caracteres que aparecen en la pantalla son diferentes de los que se escriben. Por omisión, esta propiedad está establecida como una cadena vacía, lo que significa que el usuario verá los caracteres que está introduciendo. Si la propiedad PasswordChar se establece en un carácter como un asterisco (*), ése será el carácter que aparezca en pantalla cada vez que el usuario pulse una tecla. No lo entiendas mal: el contenido real del cuadro de texto es lo que escriba el usuario; sólo se modifica lo que aparece en pantalla.
PasswordChar
(barras de desplazamiento). Puedes establecer esta propiedad en 0 (el cuadro de texto no tendrá barras de desplazamiento), 2 (sólo una barra de desplazamiento vertical), ó 3 (las dos barras de desplazamiento: vertical y horizontal).
ScroIlBars
(longitud de la selección). Esta propiedad contiene el número de caracteres seleccionados actualmente. Su valor cambia cuando el usuario selecciona texto en el cuadro de texto. También puedes alterar la selección desde el programa estableciendo esta propiedad en un valor entero en el código. Si SelLenght es 0 no habrá ningún carácter seleccionado. Esta propiedad, al igual que las propiedades SetStart y SelText son accesibles solamente durante la ejecución.
SelLenght
(comienzo de la selección). El valor de esta propiedad indica dónde comienza la selección actual. Un valor de 0 indica que la selección (o el punto de inserción) comienza delante del primer carácter; un valor de 1 indica que
SelStart
107
EL LIBRO DEL VISUAL BASIC
comienza delante del segundo carácter; y así sucesivamente. Esta propiedad también se puede modificar desde el programa. (texto seleccionado). Esta propiedad contiene la cadena de texto que está seleccionada actualmente. Si estableces SelText en el código del programa, sustituirás el texto seleccionado en el cuadro de texto por el que hayas determinado con el ajuste de SelText. Por ejemplo, si un cuadro de texto llamado Text1 contiene la línea "Juan, vébete la leche" y está seleccionada la palabra vébete , puedes corregir la frase ejecutando la instrucción Text1.SelText = "bebe". Observa que esto también modifica el valor de SelLenght. Sin embargo, como la selección comienza en la misma posición, SelStart no varía.
SelText
Text
(texto). El programa lee esta propiedad para ver qué ha introducido el usuario. El programa también puede modificar la propiedad Text para cambiar el texto que aparece en pantalla.
Eventos
5 El uso de formularios y herramientas de Visual Basic
La aplicación EditNota
Ya has utilizado cuadros de texto para textos simples de una sola línea; veamos ahora el comportamiento del texto en el modo de líneas múltiples, implementando un pequeño bloc de notas que permita cortar, pegar y una edición simple. Comienza abriendo un proyecto nuevo. Establece las propiedades Caption y Name del formulario como EditNota. Añade un nuevo cuadro de texto al formulario, y establece sus propiedades como sigue: Propiedad
MultiLine Name ScrollBars Text
Ajuste
True txtCuadro 3 Both [ninguno]
Tu formulario EditNota debe parecerse ahora a éste:
Los cuadros de texto no procesan eventos producidos con el ratón, pero pueden controlar todas y cada una de las pulsaciones de teclas producidas por el usuario. Esto es muy importante, pero aplazaremos el estudio de algunos de los eventos de teclado para el capítulo 7. (cambio). Este evento se produce cuando se modifica la propiedad Text del cuadro de texto, ya sea porque el usuario introduzca nueva información, o porque el programa establezca un valor nuevo para la propiedad. Ten en cuenta que si el usuario escribe la palabra Hola, se produce cuatro veces el evento Change, una por cada letra tecleada.
Change
(foco perdido). Este evento se produce cuando el usuario usa la tecla Tab para salir del cuadro de texto o utiliza el ratón para seleccionar algún otro objeto en el formulario. Si quieres examinar el contenido de la propiedad Text, normalmente, es más eficiente hacerlo como parte del procedimiento del evento LostFocus, que usando el procedimiento del evento Change.
LostFocus
Procedimientos y métodos
El método más útil asociado con los cuadros de texto es SetFocus, el cual sitúa el cursor en un cuadro de texto específico. Cuando se crea un formulario con varios cuadros de texto, se puede utilizar este método para dirigir la atención del usuario al cuadro de texto más importante. La sintaxis es simple: [objeto]. SetFocus 108
El cuadro de texto gestionará la introducción y la edición del texto sin que tú tengas que escribir nada de código. Cuando ejecutes la aplicación podrás introducir texto, editarlo y cortar, copiar y pegar con los atajos de teclado estándar de Windows Ctrl+X, Ctrl+C y Ctrl+V. Para conseguir que la aplicación tenga una apariencia más profesional, puedes hacer que el cuadro se ajuste perfectamente a la ventana del formulario. Para ello, edita el procedimiento Resize (cambiar el tamaño) del formulario como se muestra aquí: Sub Form_Resize txtCuadro.Top = 0 109
EL LIBRO DEL VISUAL BASIC
txtCuadro.Left = 0 txtCuadro.Width = ScaleWidth txtCuadro.Height = ScaleHeight End Sub
Este procedimiento se ejecuta cada vez que se cambia de tamaño al formulario, incluyendo la primera vez que el formulario se muestra en pantalla. Estableciendo las propiedades Top (arriba) y Left (izquierda) del cuadro de texto en 0, te asegurarás de que su esquina superior izquierda se ajusta perfectamente a la paite superior del formulario, como se muestra en la figura 5.8. Las propiedades Width (anchura) y Height (altura) del cuadro de texto se establecen para que coincidan con las propiedades ScaleWidth y ScaleHeight del formulario (las dimensiones completas del área de visualización del formulario). Observa que podrías haber escrito esas dos líneas como txtCuadro. Width = E d itNota.ScaleWidth y txtCua dro.Height = EditNota.ScaleHeight. Sin embargo, como el código siempre se ejecutará en el contexto del formulario, no es necesario que utilices el nombre del mismo. Además, si cambias el nombre del formulario no tendrás que volver y editar el código.
5 El uso de formularios y herramientas de Visual Basic
hace clic sobre ellos, mientras que los cuadros de control y los botones de opciones indican un estado y permiten que el usuario cambie dicho estado. El usuario hace clic en un cuadro de control para seleccionar o "deseleccionar" una cierta característica u opción; cuando aparece una X en el cuadro de control, la característica está seleccionada o activada. Cada cuadro de control opera independientemente. Por el contrario, los botones de opciones aparecen en conjuntos y permiten al usuario elegir una opción de un conjunto de ellas. Cuando se activa un botón de opción, los demás se desactivan. (A los botones de opciones algunas veces se les denomina botones de radi o.) Las herramientas de la caja de herramientas que se utilizan para crear estas tres clases de botones se muestran en las figuras 5.9, 5.10 y 5.11.
Figura 5.9. La herramienta Command Button (Botón de comando)
Figura 5.10. La herramienta Check Box (Cuadro de control)
Figura 5.8. Ejecución de la aplicación EditNota tras cambiarle el tamaño
Figura 5.11. La herramienta Opcion Button (Botón de opción)
Botones de comando, cuadros de control y b otones de opciones Estos tres objetos de Visual Basic son muy similares desde el punto de vista de un programador. Sin embargo, desde el punto de vista del usuario, difieren visualmente y tienen propósitos diferentes. Los botones de comando, normalmente, producen que ocurra una acción (o sea, que se ejecute un comando) cuando se 11 0
Propiedades
Los botones de comando, los cuadros de control y los botones de opciones tienen las siguientes propiedades entre otras: Caption, Enabled, FontBold, EontItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible y Width. 111
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
Además, destacan debido a la cantidad de veces que se utilizan estas otras pro piedades: (cancelar). Esta propiedad sólo la tienen los botones de comando. Cuando la propiedad Cancel de un botón se establece como True, pulsar la tecla Esc produce el mismo efecto que hacer clic en dicho botón (como el botón Can celar de un cuadro de diálogo, por ejemplo). En un formulario, sólo un botón de comando puede tener su propiedad Cancel establecida en True.
Cancel
(por omisión). Esta propiedad sólo la tienen los botones de comando. Cuando esta propiedad se establece como True, pulsar la tecla Intro produce el mismo efecto que hacer clic en el botón (como el botón Aceptar de un cua dro de diálogo). En un formulario, sólo un botón de comando puede tener su propiedad Default establecida en True.
Default
(valor). Esta propiedad indica el estado de un cuadro de control o de un bo tón de opción. La propiedad Value de un botón de opción puede establecerse como False o como True; cuando se establece como True, el botón está "acti vado" —es decir, el centro del botón se resalta. La propiedad Value de un bo tón de control puede establecerse en 0, 1 ó 2: un ajuste de 0 indica que el cuadro de control no está activado; un ajuste de 1 indica que está activado; y un ajuste de 2 indica que el cuadro aparece en gris.
Value
Establece las propiedades de los objetos como se muestra en la figura 5.12. Des pués de que hayas establecido las propiedades, el formulario debe parecerse al que se muestra en la figura 5.13.
Objeto
Propiedad
Ajuste
Option1
Caption Value
1 Jugador True
Option2
Caption
2 Jugadores
Option3 Option4
Caption Caption
3 Jugadores 4 Jugadores
Los tres objetos reciben el evento Click, aunque, normalmente, usarás un procedi miento para el evento Click sólo en el caso de los botones de comando. Los bo tones de opciones y los cuadros de control muestran automáticamente su estado cuando se hace clic sobre ellos; generalmente, no hace falta programar nada.
Check1
Caption
Sonido
Check2
Caption
Puntos de bonos
Command1
Caption
Devolución de moneda
Command2
Caption Default
Comenzar True
Procedimientos y métodos
Command3
Cancel Caption
True Salir
Eventos
No se puede imprimir ni dibujar en los botones de comando, los cuadros de con trol o los botones de opciones. Ninguno de los métodos tratados hasta ahora se aplican a esta clase de objetos.
Figura 5.12. El ajuste de las propiedades para la aplicación Juego
La aplicación Juego Este proyecto representa el tipo de aspecto que podrías encontrar en un vídeo juego. Comienza por abrir un proyecto nuevo. Crea tres botones de comando, cuatro botones de opciones y dos cuadros de control, y organízalos como se muestra a continuación:
112
Finalmente, edita los procedimientos Click de los botones Command2 y Command3 para incluir este código: Sub Command2_Click ( ) MsgBox "Game over" End Sub
113
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
Sub Command3_Click ( ) En d End Sub
herramienta Erame de la caja de herramientas de Visual Basic, la cual se muestra en la figura 5.14.
Ejecuta el programa varias veces para ver cómo se comporta. Prueba a pulsar las teclas Intro y Esc para ver qué comandos ejecutan. Si quieres que en la ventana Debug aparezca el estado de los botones de opciones y de los cuadros de control, puedes modificar el procedimiento clic de Com mand2 como se muestra aquí: Sub Command2_Click ( ) Debug.Print Option1.Value Debug.Print Option2. Value Debug.Print Option3.Value Debug.Print Option4.Value Debug.Print Check1.Value Debug.Print Check2.Value End Sub
Figura 5.14. La herramienta Frame (Marco)
Propiedades
La propiedad Name del marco se utiliza para identificarlo en el código del programa, y la propiedad Caption define el texto que se verá como parte del marco. Los marcos también tienen las propiedades Enabled, FontBold, FontItalic, FontNa me, FontSize, FontUnderline, Height, Left, Name, Top, Visible y Width. La ya familiar propiedad Enabled de comporta de una manera ligeramente distinta en los marcos. Esta propiedad, normalmente, se establece como True; cuando se establece como False, el texto del título del marco se atenúa (se pone en gris), y todos los objetos que contiene el marco se desactivan, incluyendo los cuadros de texto, los botones y los demás objetos. Eventos
Los marcos no responden con eventos de ratón ni con entradas del usuario. Procedimientos y Métodos
Figura 5.13. HI interface de Juego
No se puede imprimir texto ni dibujar en los marcos, ni se pueden asociar con gráficos. Modificación de la aplicación Juego
Marcos Los marcos existen para separar grupos de otros objetos en la pantalla. En el caso de los botones de opciones, los marcos también afectan al comportamiento de los botones, como demostrará el proyecto de ejemplo. Para los otros objetos, los marcos proporcionan una separación visual así como la posibilidad de activarlos y desactivarlos en grupo. Si quieres poner un marco en un formulario utiliza la 114
Como los marcos no son terriblemente interesantes por sí mismos, vamos simplemente a modificar el proyecto Juego del apartado anterior en lugar de crear una aplicación nueva. 1. En la ventana del formulario de la aplicación Juego, borra los botones de opciones etiquetados como 3 Jugadores y 4 Jugadores. En su lugar dibuja un marco como el que se muestra aquí: 115
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
Cuadros de lista
Los cuadros de lista permiten ofrecer al usuario una serie de opciones para que elija. El cuadro de lista muestra las opciones que están disponibles, y el usuario selecciona un elemento, o entrada de la lista, haciendo clic sobre él. Visual Basic añadirá barras de desplazamiento al cuadro de lista si la lista completa es demasiado larga para ser vista toda a la vez. Para funcionar correctamente, un cuadro de lista debe tener al menos tres líneas de altura. Si quieres añadir un cuadro de lista a un formulario, utiliza la herramienta List Box de la caja de herramientas, la cual se muestra en la figura 5.16. (Los cuadros de lista desplegable, como el cuadro Ajuste que aparece en la ventana Properties de Visual Basic, son una variante de los cuadros combinados, los cuales se tratan en el siguiente apartado.) 2. Pon dos nuevos botones de opciones dentro del marco. Observa que de bes dibujarlos dentro del marco; en este caso no puedes hacer doble clic sobre la herramienta Botón de opción para crear los botones y luego arrastrarlos dentro del marco. 3. Establece la propiedad Caption del marco como Modo. 4. Establece la propiedad Value del botón Option3 como True. 5. Establece la propiedad Caption del botón Option3 como Principiante y la propiedad Caption del botón Option4 como Avanzado. El resultado debe parecerse al interface que se muestra en la figura 5.15. Cuando ejecutes el programa, observa que los botones de opciones que hay dentro del marco operan de manera independiente de los que están fuera de él.
Figura 5.16.
La herramienta List Box (Cuadro de lista)
El contenido de un cuadro de lista no se puede definir durante el diseño. En su lugar, el programa debe utilizar el método A ddItem (añadir elemento) para introducir elementos en la lista. Lo mejor suele ser inicializar un cuadro de lista en el procedimiento del evento Load del formulario que contiene el cuadro de lista.
Propiedades
Los cuadros de lista aceptan las propiedades habituales: Enabled, FontBold, Fon tItalic, FontName, FontSize, FontUnderline, Height, Left, Name, Top, Visible y Width. Las propiedades especiales de los cuadros de lista son las siguientes: (columnas). Cuando esta propiedad se establece en 0 (que es el valor por omisión), todos los elementos de la lista se muestran en una sola columna. Si la propiedad se establece en 1 o) más, los elementos de la lista se organizan con un diseño de varias columnas; el valor que se le haya dado a la propiedad indica cuántas columnas se verán en un momento dado. Se añadirán barras de desplazamiento horizontal a la lista cuando sea necesario.
Columns
List Figura 5.15.
(lista). Esta propiedad, que no se puede modificar durante la etapa de diseño, contiene la matriz de todos los valores almacenados en el cuadro de lista. (Las
El interface de Juego rediseñado
117 116
EL LIBRO DEL VISUAL BASIC
matrices se tratan en el capítulo 6.) Se puede acceder a los elementos indivi duales del cuadro de lista usando esta sintaxis:
objeto.List(índice) (contar lista). La propiedad ListCount, que no puede modificarse directa mente, contiene el número de elementos del cuadro de lista.
ListCount
(índice de la lista). El ajuste de esta propiedad indica el número del ele mento de la lista más recientemente seleccionado. El valor índice del primer elemento es el 0, el del siguiente el 1, y así sucesivamente. Si no hay seleccio nado ningún elemento, ListIndex se establece en -1. Si estableces la propiedad ListIndex desde el programa, el resultado en la lista cambiará para reflejar el ajuste. Se puede determinar el texto del elemento seleccionado leyendo la propiedad Text.
Listlndex
(selección múltiple). Esta propiedad controla cuántos elementos de la lista se pueden seleccionar. Si la propiedad se establece en 0 - None, el usua rio sólo podrá seleccionar un elemento cada vez. Si el ajuste es 1 - Simple, el usuario podrá seleccionar más de un elemento. Cuando MultiSelect se ajustan en el capíded, el usuario puede seleccionar un rango de elementos haciendo clic en el primero de ellos, manteniendo pulsada la tecla Mayús y haciendo clic en el último elemento del rango. El usuario también podrá mantener pul sada la tecla Ctrl y hacer clic en los elementos para seleccionarlos o "dese leccionarlos" uno a uno. Ten en cuenta que, incluso cuando se seleccionan varios elementos, las propiedades ListIndex y Text indican sólo la selección más reciente. Deberás examinar cada elemento de la propiedad Selected para determinar qué elementos están seleccionados.
MultiSelect
(seleccionado). La propiedad Selected es una matriz que contiene un ele mento establecido como True o como False por cada uno de los elementos del cuadro de lista. Un ajuste de True indica que el elemento está selecciona do; un ajuste de False indica que el elemento no está seleccionado. Para com probar el estado de un elemento dado, especifica el índice del elemento usando la siguiente sintaxis:
Selected
5 El uso de formularios y herramientas de Visual Basic
Text
(texto). Esta propiedad, la cual no se puede modificar directamente, contiene el texto del elemento más recientemente seleccionado.
Eventos Los cuadros de lista reciben los dos eventos Click y DblClick. Normalmente, no escribirás código para un procedimiento Click, ya que el usuario podría seleccio nar un elemento y luego decidir seleccionar otro distinto. En lugar de esto, el programa debe leer la propiedad Text cuando el usuario haga clic en un botón de comando o cuando ocurra un evento DblClick.
Procedimientos y métodos Los métodos utilizados con una mayor frecuencia en los cuadros de lista son AddItem , Clear y RemoveItem. Estos tres métodos, que analizamos a continuación, permiten modificar el contenido del cuadro de lista durante la ejecución del pro grama. AddIte m
(añadir elemento). Este método permite insertar una línea de texto en un cuadro de lista. Se debe especificar el texto que se va a insertar y, opcional mente, el índice del elemento insertado. Si no especificas un índice, Visual Ba sic insertará el elemento detrás de los ya existentes. Si la propiedad Sorted está establecida como True, no especifiques un valor de índice; Visual Basic insertará el elemento en orden alfabético. Aquí puedes ver la sintaxis del mé todo AddItem:
objeto.AddItem texto[, í ndice] Clear
(borrar). Este método elimina todos los elementos del cuadro de lista. La sin taxis para el método Clear es sencilla:
objeto.Clear (eliminar elemento). El método RemoveItem te permite eliminar una lí nea de texto del cuadro de lista. Debes especificar el índice del elemento que quieras eliminar, usando la siguiente sintaxis:
RemoveItem
objeto.RemoveItem í ndice
objeto. Selected(índice) (ordenada). Si quieres que Visual Basic mantenga la lista de elementos or denada alfabéticamente, debes establecer esta propiedad en True. Cuando se establece como False (lo que ocurre por omisión), los elementos de la lista aparecen en el orden en el que se añadieron.
Sorted
118
La aplicación Queso Este proyecto de ejemplo transfiere elementos entre dos cuadros de lista. Los ele mentos de un cuadro estarán ordenados alfabéticamente; los del otro cuadro apa recerán en el orden en el que se añadan. 119
EL LIBRO DEL VISUAL BASIC
Comienza creando un proyecto nuevo. En el formulario dibuja dos cuadros de lista, como se muestra en la figura 5.17, y establece la propiedad Sorted del cuadro de lista de la derecha (List2) a True. El resto de la aplicación se crea con el código mostrado en la figura 5.18. El procedimiento Form_Load inicializa el cuadro de lista. Los procedimientos List1_DblClick y List1_DblClick son prácticamente idénticos, excepto porque transfieren los elementos de la lista en direcciones opuestas. Cuando hagas doble clic sobre un elemento de uno de los cuadros de lista, el elemento será eliminado de ese cuadro y añadido al otro. El cuadro de lista List2 continuará ordenando sus entradas en orden alfabético, mientras que List1 mantendrá las suyas en el orden en que sean añadidas.
5 El uso de formularios y herramientas de Visual Basic
Sub Form_Load ( ) List1.AddItem "Gouda" List1.AddItem "Camembert” List1.AddItem "Cheddar" Listl.Addltem "Roquefort" List1.AddItem "Gruyere" List1.AddItem "Edam" List1.AddItem "Brie" End Sub Sub List1_DblClick ( ) List2.AddItem List1.Text List1.RemoveItem List1.ListIndex End Sub Sub List2_DblClick ( ) List1.Addltem List2.Text List2.RemoveItem List2.ListIndex End Sub
Figura 5.17.
El diseño del formulario para la aplicación Queso
Figura 5.18.
El código del programa de la aplicación Queso
Cuadros combinados Los cuadros combinados se crean mediante la herramienta Combo Box de la caja de herramientas, que se muestra en la figura 5.19. El cuadro combinado se llama así porque puede combinar un cuadro de texto y un cuadro de lista en un solo control. Sin embargo, al contrario que un cuadro de lista, no permite varias columnas. Se pueden especificar tres tipos de comportamiento para un cuadro com binado estableciendo la propiedad Style. Propiedades
Además de las propiedades habituales, los cuadros combinados tienen dos propiedades de interés: Style y Text. (estilo). La propiedad estilo, la cual determina el tipo de cuadro combinado y cómo se comporta, se puede establecer en 0, 1 ó 2.
Style
120
Figura 5.19.
La herramienta Cuadro combinado
Cuando Style se establece en 2, el cuadro combinado se convierte en un cuadro de lista desplegable. Inicialmente, sólo un elemento de la lista es visible; pero cuando el usuario hace clic en el botón en el que aparece una flecha apuntando hacia abajo (que hay al lado del cuadro), la lista completa se despliega, mostrando todos los elementos y permitiendo al usuario seleccionar uno, de la misma manera que en un cuadro de lista. El cuadro Object de la ventana Pro perties de Visual Basic es un ejemplo familiar. 121
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
cuadro com Si se ajusta la propiedad Style a 1 se crea lo que se denomina binado sencillo: un área de edición en la que el usuario puede introducir texto, con un cuadro de lista estándar directamente debajo de ella. El usuario podrá, de este modo, seleccionar un elemento de la lista o introducir texto en el área de edición. un
Si se establece la propiedad Style en 0 se crea un cuadro combinado desplega ble, que tiene el aspecto de un cuadro de lista desplegable, pero también permite que el usuario introduzca texto o seleccione en la lista. El cuadro Ajuste de la ventana Properties de Visual Basic, a menudo funciona como un cuadro combinado desplegable. (texto). Esta propiedad puede contener el texto del elemento seleccionado de la lista o el texto introducido directamente en el área de edición por el usuario.
Text
Eventos La manera en que un cuadro combinado responde a los eventos depende de su estilo de funcionamiento —o sea, del ajuste de la propiedad Style. Por ejemplo, el evento DblClick se recibe sólo si la propiedad Style está ajustada a 1 (un cuadro combinado simple). En los otros dos estilos sólo se recibe el evento Click. Los dos estilos que permiten la introducción de texto reciben el evento Change, cuando el usuario escribe en el área de edición del cuadro combinado. En general, simplemente querrás que tu programa lea la propiedad Text del cuadro combinado después de que el usuario haya hecho una selección.
2. Establece la propiedad Default del botón Aceptar a True y la propiedad Cancel del botón Cancelar a True. 3. Debajo de la etiqueta Destino dibuja un cuadro combinado y establece su propiedad Style a 1 y su propiedad Name como cboDest. Hazlo suficientemente grande como para mostrar cuatro o cinco líneas de texto en la parte que representa el cuadro de lista. 4. Crea otro cuadro combinado debajo de la etiqueta Preferencia de asiento, y establece la propiedad Style a 2 y la propiedad Name como cboAsiento. 5. Crea un cuadro combinado debajo de la etiqueta Preferencia de comida. Establece la propiedad Name del cuadro como cboComida y su propiedad Style a 0. Tu formulario debe parecerse ahora al que se muestra aquí:
Procedimientos y métodos
Los métodos AddItem , Clear y RemoveItem, que se describieron para los cuadros de lista, también están implementados para los cuadros combinados, y se usan de la misma manera. La aplicación Vuelo
Este proyecto incluye los tres estilos de cuadro combinado uno al lado de otro, de manera que puedas experimentar con ellos. La aplicación simula un cuadro de diálogo que interroga al usuario sobre sus preferencias personales para un próximo vuelo aéreo. 1. Crea un proyecto nuevo. Sitúa tres etiquetas y dos botones de comando en el formulario, estableciendo la propiedad Caption de cada objeto para que concuerde con los títulos que se muestran aquí: 122
6.
Necesitarás escribir dos procedimientos: uno que informe de los resultados de las acciones del usuario cuando éste haga clic en el botón de comando Aceptar, y otro para inicializar los cuadros combinados. Esto último formará parte del procedimiento Form_Load. Estos procedimientos se muestran en la figura 5.20.
Cuando ejecutes la aplicación observa qué cuadros combinados te permiten escribir entradas. Observa también que la apariencia de cada cuadro combinado, como se muestra en la figura 5.21, te da una pista sobre cómo continuar. 123
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
Sub Command1_Click ( ) Debug.Print cboDest.Text Debug.Print cboAsiento.Text Debug.Print cboComida.Text En d End Sub Sub Command2_Click ( ) En d End Sub
Figura 5.21. Ejecución de la aplicación Vuelo
Sub Form_Load ( ) cboDest.Text = " " cboDest.AddItem "Paris" cboDest.AddItem "Moscú" cboDest.AddItem "Nueva York" cboDest.AddItem "El Cairo" cboDest.AddItem "Melbourne" cboDest.AddItem "Rio de Janeiro" cboDest.AddItem "Tokyo" cboAsiento.AddItem "Pasillo" cboAsiento.AddItem "Ventana" cboAsiento.AddItem "Centro" cboAsiento.ListIndex = 1
Estos objetos simplemente informan de la posición del cuadro de desplazamiento dentro de la barra; tienes control sobre el rango de la barra de desplazamiento y sobre los incrementos a los que el cuadro de desplazamiento puede avanzar. Por ejemplo, si estuvieras usando una barra de desplazamiento que representase el acelerador de un automóvil, éste podría variar en un rango de 0 a 100 mediante incrementos de 5. Un control de volumen podría variar en un rango de 0 a 10 mediante incrementos de 1.
— Cuadro de
cboComida.AddItem "Pollo" cboComida.Addltem "Lasaña" cboComida.AddItem "Vegetariano" cboComida.AddItem "Diabético" cboComida.Text = "Sin preferencias End Sub
desplazamiento Flechas
de
/
desplazamiento
Cuadro de
desplazamiento
Flechas de desplazamiento
Figura 5.20. El código del programa para la aplicación Vuelo
Figura 5.22. Barras de desplazamiento horizontales y verticales
Barras de desplazamiento horizontales y verticales Las barras de desplazamiento horizontales y verticales (las cuales se muestran en la figura 5.22) se comportan de la misma manera, excepto por sus direcciones. 124
Para crear estos objetos debes usar las herramientas Horizontal Vertical Scroll Bar (Barra de desplazamiento horizontal, que se muestra en la figura 5.23) ó Vertical 125
EL LIBRO DEL VISUAL BASIC
Scroll Bar (Barra de desplazamiento vertical, que se muestra en la figura 5.24) de la caja de herramientas de Visual Basic.
Figura 5.23.
La herramienta Horizontal Scroll Bar (Barra de desplazamiento horizontal)
Figura 5.24.
La herramienta Vertical Scroll Bar (Barra de desplazamiento vertical)
5 El uso de formularios y herramientas de Visual Basic
(valor). Esta propiedad contiene el número que representa la posición actual del cuadro de desplazamiento en el interior de la barra. Si estableces esta propiedad desde el programa, Visual Basic moverá el cuadro de desplazamiento hasta la posición adecuada. Establecer la propiedad Value con un número que esté fuera del rango definido por las propiedades Max y Min, produce un mensaje de error.
Value
Eventos
Los eventos principales asociados con una barra de desplazamiento son los eventos Change y Scroll. El evento Scroll es emitido repetidamente, mientras que el cuadro de desplazamiento está siendo arrastrando por el interior de la barra de desplazamiento. El evento Change se produce después de que se haya modificado la posición del cuadro de desplazamiento. Utiliza el evento Scroll para controlar dinámicamente los cambios que se produzcan en la barra de desplazamiento, y utiliza el evento Change para obtener el valor final de la posición del cuadro de desplazamiento en la barra. Procedimientos y métodos
Propiedades
Las propiedades estándar, que tienen las barras de desplazamientos, incluyen las siguientes: Enabled, Height, Left, Name, Top, Visible y Width. Entre las propiedades especiales, tanto de las barras horizontales como de las verticales, están Lar geChange, Max, Min, SmallChange y Value. (gran cambio). El ajuste de esta propiedad representa el valor añadido o sustraído al número contenido en la propiedad Value cuando el usuario hace clic dentro de la barra de desplazamiento.
LargeChange
Max
Min
Ninguno de los procedimientos o métodos que se utilizan comúnmente y que se han tratado previamente se aplican a las barras de desplazamiento. La aplicación Barra d e desplazamiento
Este proyecto simplemente te proporcionará una referencia de cómo funciona una barra de desplazamiento. 1. Crea un proyecto nuevo. Añade una etiqueta y una barra de desplazamiento horizontal al formulario vacío, como se muestra aquí:
(máximo). Esta propiedad puede establecerse en un rango que va de 32768 a 32767. Cuando el cuadro de desplazamiento está en su posición lo más a la derecha o abajo posible, la propiedad Value se establece a este número. (mínimo). Esta propiedad puede establecerse en un rango que va de 32768 a 32767. Cuando el cuadro de desplazamiento está en su posición más a la izquierda o arriba posible, la propiedad Value se establece en este número. (cambio pequeño). El ajuste de esta propiedad representa el valor que se le añade o resta al número contenido en la propiedad Value cuando el usuario hace clic en una de las flechas de desplazamiento que hay en los extremos de la barra de desplazamiento.
SmallChange
126
2. Establece la propiedad BorderStyle de la etiqueta a 1 Fixed, y la propiedad Caption a una cadena vacía. Establece las propiedades de la barra de desplazamiento horizontal como sigue: 127
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
Propiedad
Aju ste
LargeChange Max Min SmallChange
10 100 0 2
Figura 5.25. 3 . Haz doble clic en la barra de desplazamiento para que aparezca la ventana
Ejecución de la aplicación Barra de desplazamiento
de código, e introduce el siguiente procedimiento para gestionar el evento Change: Sub HScroll1_Change ( ) Label1.Caption = Str$(HScroll1.Va lue) End Sub
Como la propiedad Caption de la etiqueta sólo acepta cadenas de caracteres, debes utilizar la función Str$ para convertir el valor de HScroll1.Value en una cadena.
Relojes Los relojes, que se crean mediante la herramienta Timer que se muestra en la figura 5.26,. son objetos que pueden producir eventos que sean emitidos a intervalos regulares. Los relojes se programan estableciendo su propiedad Interval (intervalo) al número de milisegundos ( 1/1000 segundos) que deben transcurrir entre los eventos que emita.
4. Introduce el siguiente procedimiento para tratar el evento Scroll: Sub HScroll_Scroll ( ) Label1.Caption = "Moviéndose a" + Str$(HScroll1.Value) End Sub
Ahora ejecuta la aplicación. Cuando hagas clic en el área gris de la barra de desplazamiento, el valor que aparece en la etiqueta cambiará en unidades de 10. Cuando hagas clic en la flecha de desplazamiento de cualquiera de los extremos de la barra, el valor cambiará en unidades de 2. Arrastrando el cuadro de desplazamiento con el ratón puedes ajustar el valor en otras unidades que no sean ni 2 ni 10. El valor que aparece en la figura 5.25, por ejemplo, podría haberse producido bien haciendo clic en las flechas de desplazamiento, bien arrastrando el cuadro de desplazamiento. Observa que el procedimiento del evento Scroll actualiza el título de la etiqueta a medida que arrastras el cuadro de desplazamiento. Elige el comando Break (interrumpir) del menú Run o haz clic en el botón Break de la barra de herramientas y a continuación introduce la declaración HScroll1.Value = 17 en la ventana Debug. Observa que la posición del cuadro de desplazamiento cambia cuando el valor varía. Ahora introduce la declaración HScroll1.Max = 500. La posición del cuadro de desplazamiento cam bia otra vez, manteniendo la posición relativa apropiada a los ajustes de las propiedades Max y Min. 128
Figura 5.26. La herramienta Timer (Reloj)
Un reloj está limitado por la capacidad de tu ordenador. La mayoría de los ordenadores personales admiten una resolución del reloj no superior a 18 eventos por segundo, o lo que es lo mismo, que transcurran 56/1000 segundos entre eventos. En términos prácticos, esta resolución significa que los valores menores de 56 no son particularmente útiles —en otras palabras, los valores de intervalo que difieran en 5, 10 e incluso 20, producirán el mismo resultado. Esta limitación no significa que debas ser optimista en tus cálculos —después de todo, el hardware que está por venir, probablemente, tendrá mejores relojes— pero significa que no de berías confiar en los relojes para ser extremadamente preciso. Además, algunos eventos de reloj simplemente pueden perderse en el éter. Su pón que tu programa recibe un evento de reloj una vez por segundo, pero que parte del programa realiza un cálculo muy complejo que lleva 10 segundos reali 129
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
zarlo. Cuando el cálculo haya finalizado podrías esperar que hubiera 10 eventos de reloj apilados de alguna manera. En realidad, sólo ocurrirá 1 evento de reloj al terminar los cálculos. Antes de generar un evento de reloj, el sistema siempre comprueba si hay algún otro evento de reloj anterior que esté pendiente; si lo hay no se genera un evento de reloj nuevo.
escala, 200 pulsos por minuto son 3 1/3 pulsos por segundo, ó 1 pulso cada 300 milisegundos. De esta manera, los valores 300 y 1500 pueden servir como los puntos máximo y mínimo de una barra de desplazamiento que pongamos en la aplicación. (Ten en cuenta que cuanto más alto sea el valor, más lento será el pulso; por tanto, 1500 es el valor mínimo, no el máximo.)
Sin duda te estarás preguntando qué utilidad tienen los relojes dadas estas restricciones. En realidad pueden ser bastante útiles, aunque no como una fuente de cálculo exacta del tiempo. Puedes pensar en los eventos de reloj como en un "cachete de atención" para tu aplicación. A intervalos regulares, un reloj puede sacudir a tu programa y decirle, en efecto, "Eh, es el momento de comprobar las cosas."
1. Crea un proyecto nuevo nuevo y añade una barra de desplazamiento desplazamiento al formulaformulario. A continuación crea un objeto reloj haciendo doble clic en la herramienta Timer de la caja de herramientas. No tienes que dibujar o cambiar de tamaño los objetos reloj, ya que aparecen en el formulario durante la fase de diseño, pero son invisibles cuando el programa se está ejecutando.
Propiedades
Los relojes tienen las propiedades Name y Enabled. La propiedad más importante de los objetos reloj es la propiedad Interval. Esta propiedad se establece al número de milisegundos que deben transcurrir entre dos eventos de reloj, con un valor que va desde 0 hasta 65535 —lo que, teóricamente, genera eventos a una relación de 1000 por segundos hasta algo menos de un evento por minuto. Un intervalo de 0 es equivalente a desactivar el reloj. Si quieres generar un evento n veces por segundo utiliza la fórmula 1000 / n para encontrar el ajuste para la propiedad Interval. Por ejemplo, si quieres que un evento ocurra cada medio segundo (dos veces por segundo), la operación 1000 / 2 te indicará un ajuste de 500 en la propiedad Interval.
3. Establece la propiedad propiedad Interval del del objeto reloj a 1000. 1000.
Eventos
4. Establece las propiedades propiedades de la barra de desplazamiento desplazamiento horizontal como sigue:
El evento Timer se genera a intervalos regulares cuando el reloj está activado. Procedimientos y métodos
No hay procedimientos ni métodos que funcionen sobre los objetos reloj. La aplicación Metrónomo
Este proyecto —el cual crea un metrónomo usando un reloj y una barra de desplazamiento— muestra lo que sucede cuando se intenta utilizar un reloj como si fuera un cronómetro de alta precisión. Los metrónomos operan, normalmente, en un rango que va desde los 40 pulsos por minuto, para la música muy lenta, hasta los 200 para la música muy rápida. 40 pulsos por minuto es lo mismo que / de pulso por segundo, ó 1 pulso cada 1500 milisegundos. En el otro extremo de la 2
130
2. Pon una etiqueta etiqueta debajo del extremo izquierdo izquierdo de la barra de desplazamiento, y establece su propiedad Caption a Lento. Debajo del extremo derecho de la barra crea otra etiqueta con el título Rápido. Esto es lo que debes tener en pantalla:
3
Propiedad
Ajuste
LargeChange Max Min SmallChange Value
100 300 1500 25 1000
5. Tendrás que añadir dos dos líneas de código al programa programa para esta aplicación, aplicación, una en el procedimiento Change de la barra de desplazamiento, y otra en el procedimiento Timer del del objeto reloj. El procedimiento Change mantie 131
EL LIBRO DEL VISUAL BASIC
ne al objeto reloj sincronizado con la barra de desplazamiento, y el procedimiento Timer genera genera el tic del metrónomo (o, en este caso, su beep). Sub HScroll1_Change Timer1.Interval = HScroll1.Value End Sub Sub Timer1_Timer Beep End Sub
Cuando ejecutes la aplicación, el metrónomo hará tic una vez por segundo. Si mueves la barra de desplazamiento alterarás la velocidad del tictac. Prueba a mover la ventana por la pantalla o a ejecutar otra aplicación en segundo plano. Cuando no está sucediendo nada más, el reloj es bastante preciso, pero puedes ver que algunos de los eventos de reloj se pierden cuando el ordenador dedica su atención a alguna otra tarea.
Líneas y formas Para mejorar la apariencia de los formularios en tus aplicaciones puedes añadirles líneas sencillas y gráficos de forma sólida, usando las herramientas Line (línea) y Shape (forma) de la caja de herramientas, las cuales aparecen en las figuras 5.27 y 5.28. Los objetos creados con estas herramientas aparecen en la misma rejilla gráfica que las imágenes. Los controles línea y forma (al igual que el control forma) son útiles, principalmente, para proporcionarle fondos visuales a los formularios. La herramienta Line
5 El uso de formularios y herramientas de Visual Basic
crea segmentos de línea, simples y rectos. Se puede alterar el tamaño, el color y el diseño de las líneas modificando sus propiedades. La herramienta Shape siempre crea un rectángulo en la pantalla, pero estableciendo las propiedades del ob jeto Shape se pueden crear círculos, óvalos y rectángulos redondeados. Además, se pueden establecer los colores y los diseños de las formas. Propiedades
Ambos objetos tienen las propiedades habituales Name y Visible. Los objetos Sha pe también tienen las propiedades Height, Left, Top y Widht. Los objetos Line tienen las propiedades posicionales X1, Y1 y X2, Y2, que son las coordenadas de los dos puntos de los extremos de la línea. Otras propiedades determinan cómo aparecerá el objeto en la pantalla. (color del borde). objeto (o, en el caso de BorderColor se establece forma que se hacía con mulario.
BorderColor
Esta propiedad determina el color del contorno del los objetos línea, el color de la línea). La propiedad seleccionando un color de una paleta, de la misma las propiedades BackColor y ForeColor de un for-
(estilo del borde). La propiedad BorderStyle controla cómo se dibuja la línea o el contorno de una forma. Se pueden usar cualquiera de estos siete ajustes:
BorderStyle
(transparente) 0 Transparent (transparente) 1 Solid (sólido) 2 Dash (guiones) 3 Dot (puntos) 4 DashDot (guiónpunto) (guiónpunto)
Figura 5.27. La herramienta Line Line (Línea)
5 DashDotDot (guiónpuntopunto) (guiónpuntopunto) (interior sólido) 6 Inside Solid (interior (anchura del borde). Esta propiedad permite especificar la anchura de la línea o del contorno de la forma. Si estableces BorderWidth con un valor distinto de 1 no podrás utilizar ninguno de los valores de puntos o guiones de la propiedad BorderStyle.
BorderWidht
Figura 5.28. La herramienta Shape Shape (Forma)
132
Los objetos Shape también tienen las propiedades FillColor y FillStyle. A continuación se muestra una explicación de cada una de ellas. 133
EL LIBRO DEL VISUAL BASIC
(color del relleno). Análogamente a la propiedad BorderColor, FillColor permite definir el color interior de una forma. Esta propiedad se establece de la misma manera que la propiedad BorderColor: usando la paleta de colores.
FilIColor
(estilo del relleno). El ajuste de la propiedad FillStyle determina el diseño interior de un objeto forma:
FillStyle
0 Solid (sólido) (transparente) 1 Transparent (transparente) 2 Horizontal Line (línea horizontal) horizontal) 3 Vertical Line (línea vertical) vertical) 4 Upward Diagonal (diagonal hacia arriba) 5 Downward Diagonal (diagonal (diagonal hacia abajo)
5 El uso de formularios y herramientas de Visual Basic
2. Selecciona la propiedad propiedad Picture de Picture1 en en la ventana Properties. Properties. Haz clic en el botón con los puntos suspensivos que hay al lado del cuadro Ajustes para que aparezca el cuadro de diálogo Load Picture. En él, establece el tipo de archivo a archivos (en el cuadro List Files of Type) de imágenes con la extensión ICO. En el subdirectorio MISC del directorio ICONS, que viene con Visual Basic, encontrarás el icono FACE0l.ICO. Selecciona este archivo para cargar el icono en el cuadro de dibujo. De la misma manera, establece la propiedad Picture de Image1 para cargar el icono FACE02.ICO en el control de imagen. 3. Establece la propiedad propiedad FillStyle de Shape1 Shape1 a 0 Solid, y la propiedad propiedad Fi llColor a rojo. (Haz clic en el botón con los puntos suspensivos que hay al lado del cuadro Ajustes y selecciona el color rojo en la paleta.) Establece la propiedad BorderWidth de Line1 a 4. El formulario debe parecerse ahora al siguiente:
6 Cross (cruz)
7 Diagonal Cross (cruz diag diagonal) onal) Eventos
Los objetos línea y forma no reciben ningún evento. Procedimientos y métodos
Ninguno de los métodos tratados en este capítulo se aplican a líneas ni a formas. El proyecto Rejilla
Este proyecto de ejemplo no es una aplicación completa; en lugar de ello, simplemente te permite experimentar con objetos de pantalla de manera que te llegues a sentir más familiarizado con estas herramientas. 1.
4. Mueve la forma hacia el centro del formulario, formulario, y luego mueve los otros ob jetos sobre la forma, de manera que se solapen de alguna forma, como se muestra aquí:
Crea un proyecto nuevo. nuevo. En el formulario formulario pon un cuadro de dibujo, un botón de comando, una forma, una línea y un control de imagen:
Observa que en cada rejilla de la pantalla, el objeto más recientemente creado aparece encima de los creados previamente. (El cuadro de dibujo y el botón de comando residen en la rejilla superior, y la forma, la línea y la imagen están en la rejilla intermedia.) 134
135
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
El orden en el que ciertos objetos solapan a otros objetos se denomina el orden Z, y puede ser alterado. Haz clic en Line1 para seleccionarlo, y elige el comando Bring To Front (traer al frente) del menú Edit de Visual Basic. La línea, que ya aparecía sobre la forma, ahora también aparece sobre la imagen. Sin embargo, date cuenta de que cuando mueves la línea por la pantalla no tapa al cuadro de dibujo ni al botón de comando. Los comandos Bring To Front y Send To Back (enviar al fondo) sólo funcionan dentro de una rejilla; los objetos que estén en la rejilla intermedia siempre aparecerán detrás de los que estén en la rejilla superior. Puedes utilizar estos dos comandos con todos los controles, lo cual te permitirá ajustar el orden Z dentro de cada rejilla. Prueba a usar el comando Send To Back después de seleccionar el botón de comando.
Cuadros de lista de unidades de disco, de directorios y de archivos Las tres herramientas de Visual Basic que muestran las figuras 5.29, 5.30 y 5.31 permiten crear cuadros de diálogo personalizados que hagan de interface con el sistema de archivos. Cada control del sistema de archivo gestiona un componente distinto del sistema: un cuadro de lista de unidades de disco aparece como una lista desplegable que contiene los nombres de las unidades de disco que tiene el ordenador; un cuadro de lista de directorios muestra todos los subdirectorios del directorio actual; y un cuadro de lista de archivos muestra todos o algunos de los archivos que contiene el directorio actual.
Figura 5.31.
La herramienta herramienta File List Box (Cuadro (Cuadro de lista de archivos)
La mayoría de las veces no utilizarás los cuadros de lista de unidades de disco o de directorios individualmente. En lugar de ello, cuando el usuario esté seleccionando un archivo para abrirlo o guardarlo, le proporcionarás el acceso a todos los componentes del sistema de archivos a la vez. En este caso puedes usar el control de cuadro de diálogo común, el cual incluye las funciones Archivo Abrir y Archivo Guardar Como empaquetadas eficientemente. eficientemente. Sin embargo, en ocasiones puedes necesitar un cuadro de diálogo con componentes que estén más allá de los que proporcionan los cuadros de diálogo estándar Archivo Abrir y Archivo Guardar Como. Por ejemplo, Microsoft Word tiene botones adicionales en el cuadro de diálogo Guardar como para Compartir archivos y para las Opciones. En esos casos podrías usar las herramientas Drive List Box, Directory List Box y File List Box. (Consulta el capítulo 9 si quieres ver una aplicación de ejemplo.) Propiedades
Los tres controles del sistema de archivos tienen muchas de las propiedades habituales: Enabled, FontBold, FontItalic, FontName, FontSize, Height, Left, Name, Top, Visible y Width. Además, son importantes estas propiedades: (unidad). Esta propiedad, que se aplica sólo a cuadros de lista de unidades de disco, contiene el nombre de la unidad de disco seleccionada actualmente.
Drive
(nombre de archivo). Sólo los cuadros de lista de archivos tienen la propiedad FileName, la cual contiene el nombre del archivo seleccionado actualmente en un cuadro de lista de archivos.
FileName Figura 5.29.
La herramienta Drive Drive List Box (Cuadro (Cuadro de lista de unidades unidades de disco)
(lista, índice de la lista). Estas propiedades sólo las tienen los cuadros de lista de archivos y son idénticas a las propiedades List y ListIndex de los cuadros de lista.
List, ListIndex
Path Figura 5.30.
La herramienta herramienta Directory List Box (Cuadro (Cuadro de lista de directorios) directorios)
136
(ruta). En los cuadros de lista de directorios y de archivos, esta propiedad contiene la ruta de acceso actual. La propiedad Path no se aplica a los cuadros de lista de unidades de disco. 137
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
(patrón). Esta propiedad de los cuadros de lista de archivos contiene una cadena que determina los archivos que se mostrarán. Admite los caracteres comodín * y ? en los nombres de archivos. Por ejemplo, si se establece la propiedad Pattern como *.DAT se mostrarán todos los nombre de archivo que tengan la extensión DAT.
Pattern
proyecto que use una cuadrícula debe incluir el archivo GRID.VBX en su archivo de proyecto. Consulta el capítulo 11, "Bases de datos y cuadrículas", si necesitas información más detallada sobre la herramienta Grid.
Eventos
Los cuadros de lista de directorios y de archivos responden al evento Click, aunque los cuadros de lista de unidades de disco no. Otros dos eventos son importantes para los controles del sistema de archivos: (cambio). Este evento es reconocido solamente por los cuadros de lista de unidades de disco y de directorios. Es emitido cada vez que el usuario o el programa cambian la selección en el cuadro de lista.
Figura 5.32.
La herramienta Grid (Cuadrícula)
Change
(cambio de ruta). Este evento se aplica sólo a los cuadros de lista de archivos. Ocurre cada vez que el usuario hace doble clic en una carpeta de directorio o bien el programa haya cambiado las propiedades FileName o Path. Esto le permite a tu programa actualizar el contenido del cuadro de lista de directorios correspondiente.
PathChange
Datos
La herramienta Data, que se muestra en la figura 5.33, permite crear un control de datos a través del cual puedes ofrecer el acceso a datos específicos de una base de datos. El control datos tiene diversas propiedades que definen la conexión entre tu aplicación Visual Basic y la base de datos a la que tienes pensado acceder. Antes de usar la herramienta Datos en Visual Basic tendrás que activar la posibilidad de compartir archivos. Consulta el capítulo 11 si necesitas información más detallada sobre la herramienta Datos.
Procedimientos y métodos
Ninguno de los procedimiento o métodos descritos hasta ahora son aplicables a los controles del sistema de archivos.
Otras herramientas de Visual Basic La caja de herramientas de Visual Basic también incluye algunas pocas herramientas que se van a describir brevemente aquí. Estas herramientas y los objetos que crean se tratan más adelante en el libro, ya que requieren un mayor esfuerzo de programación y unas técnicas más avanzadas. Consulta los capítulos 11 y 12 si necesitas más información sobre estas herramientas avanzadas. Cuadrículas
La herramienta Grid, que aparece en la figura 5.32, permite crear un control de cuadrícula. Una cuadrícula es un bloque de celdas de dos dimensiones que recuerda a las filas y a las columnas de una hoja de cálculo. Puedes usar una cuadrícula para implementar funciones del tipo hoja de cálculo en Visual Basic. Un 138
Figura 5.33.
La herramienta Data (Datos)
OLE 2.0
La tecnología OLE (object linking and embedding, incrustación y enlace de objetos) de Microsoft, permite crear en una aplicación un objeto que contenga datos de otra aplicación que no esté relacionada con la primera. Por ejemplo, se podría poner en tu programa de Visual Basic un gráfico procedente de un programa gráfico o un detallado dibujo procedente de un programa CAD (Computer aided design, diseño asistido por ordenador). En lugar de tomar, simplemente, una foto grafía del gráfico o del dibujo, OLE mantiene un vínculo con la aplicación original de manera que si se modifican los datos originales, la copia que hay en la aplicación de Visual Basic se actualizará automáticamente. 139
EL LIBRO DEL VISUAL BASIC
La herramienta OLE de la caja de herramientas de Visual Basic, que se muestra en la figura 5.34, permite añadir las posibilidades del enlace y la incrustación de ob jetos a un programa de Visual Basic. Veremos en el capítulo 12 el tema del OLE con detalle.
Figura 5.34.
La herramienta OLE
5 El uso de formularios y herramientas de Visual Basic
Basic proporciona el acceso a esas funciones a través de la herramienta Common Dialog (diálogo estándar). El uso de la herramienta Common Dialog te asegura que tu aplicación se adapta al aspecto y funcionamiento de las operaciones que realizan. Al igual que la herramienta Timer, la herramienta diálogo estándar, que aparece en la figura 5.35, es invisible durante la ejecución. Sin embargo, cuando se pone un icono en un formulario, se puede llamar a cualquiera de las cinco funciones estándar que proporciona la herramienta. Estas funciones son los cuadro de diálogo estándar de Windows para Abrir, Guardar como, Color, Fuente e Impresora. Además, la herramienta Common Dialog puede llamar al sistema de Ayuda de Windows. Debes cargar el archivo CMDIALOG.VBX en la ventana Project para acceder a la herramienta diálogo estándar.
El archivo AUTOLOAD.MAK
Como habrás notado, Visual Basic incluye de forma automática, los archivos GRID.VBX, CMDIALOG.VBX y MSOLE2.VBX en todos los proyectos que creas. Sin embargo, a no ser que estés usando una cuadrícula, un cuadro de diálogo estándar o un control OLE, se pueden borrar estos archivos del archivo del proyecto. Para impedir que Visual Basic los incluya automáticamente en tus proyectos, elige el comando Open Proyect del menú File y abre el aicación VisuaOAD.MAK en el cuadro de diálogo Open Proyect. Cada vez que creas un proyecto nuevo, Visual Basic copia el contenido de AUTOLOAD.MAK en el nuevo proyecto. Si eliminas los archivos GRID.VBX y MSO LE2.VBX de AUTOLOAD.MAK (seleccionando el comando Remove File del menú File), éstos no volverán a aparecer en los nuevos proyectos. Deja CMDIA LOG.VBX en el archivo AUTOLOAD.MAK de momento. De hecho, las herramientas Grid y OLE desaparecerán de la caja de herramientas. Sin embargo, puedes incluir estos archivos y herramientas proyecto por proyecto usando el comando Add File del menú File.
Cuadros de diálogo estándar Con el objeto de proporcionar al usuario un interface estándar para las operaciones más comunes de las aplicaciones Windows, Microsoft creó un conjunto de cuadros de diálogo para funciones estándar de Windows. El código de estas funciones se incluyó por primera vez en Windows 3.1, pero se puede usar con Windows 3.0 si se añade el archivo COMMDLG.DLL al directorio SYSTEM. Visual 140
Figura 5.3S.
La herramienta Common Dialog (Diálogo estándar)
La ejecución de las funciones seleccionadas comienza cuando se establece la propiedad Action (acción) del control diálogo estándar. Las instrucciones de Visual Basic se suspenden hasta que el usuario sale del cuadro de diálogo. Entonces se pueden examinar las propiedades del control para determinar qué acción se produjo. No hay eventos ni métodos asociados con un control diálogo estándar. Su funcionamiento se especifica estableciendo los valores de las propiedades y, después, asignando un valor a la propiedad Action. Además de la propiedad Action, todas las funciones de Common Dialog usan la propiedad CancelError (cancelar error). CancelError es False por omisión, pero si se establece como True, Visual Basic producirá un error si el usuario selecciona el botón Cancelar en el cuadro de diálogo. Si tienes pensado establecer CancelError como True, debes usar las posibilidades de gestión de errores de Visual Basic que se describen en el capítulo 8. Los párrafos siguientes describen las funciones de la herramienta Common Dia log. Como hay muchas, no hemos proporcionado un programa de ejemplo completo, pero sí se muestra un fragmento de programa que ilustra el uso típico del control. 141
EL LIBRO DEL VISUAL BASIC
Ab ri r
El cuadro de diálogo Abrir, que se muestra en la figura 5.36, aparece cuando se asigna el valor 1 a la propiedad Action. Puedes establecer cualquiera de las propiedades siguientes para controlar la apariencia del cuadro de diálogo. Ten en cuenta que este cuadro de diálogo realmente no abre ningún archivo; simplemente, permite que el usuario seleccione el nombre del archivo.
5 El uso de formularios y herramientas de Visual Basic
"Documentos (*.DOC) |*.DOC|Archivos de texto (*.TXT)|*.txt|Todos los archivos|*.*”
El primer filtro limita la lista de archivos a aquellos que tengan la extensión DOC, el segundo filtro es para los archivos que tengan la extensión TXT, y el tercer filtro permite que se pueda seleccionar cualquier archivo. Observa que no hay espacios delante ni detrás de la raya vertical. (filtro del índice). Esta propiedad tendrá como valor un número entero, el cual indica qué pareja de componentes del filtro será la que actúe por omisión. En el ejemplo anterior, los valores admisibles para la propiedad FilterIndex serían 1, 2 y 3.
Filterlndex
(banderas). La propiedad Flag se puede establecer como una combinación de uno o más valores que controlan características especiales del cuadro de diálogo. Los valores que se pueden usar para las banderas aparecen en el archivo CONSTANT.TXT y se describen en la Ayuda en pantalla de Visual Basic. Un ejemplo es la bandera OFN_FILEMUSTEXIST, la cual obliga al usuario a seleccionar un archivo existente.
Flags
Figura 5.36.
Ejemplo
El cuadro de diálogo Abrir
Este fragmento de programa muestra un cuadro de diálogo Abrir. Obliga al usuario a elegir un archivo que ya exista y aplica un filtro (o máscara) por omisión para los archivos de datos (*.DAT). Asume que el objeto diálogo estándar se llama Dlogo.
Propiedades
(título del cuadro de diálogo). Esta propiedad se puede establecer en cualquier cadena de caracteres. La cadena se muestra en la barra del título del cuadro de diálogo. Por omisión el título es "Abrir".
DialogTitle
(nombre de archivo). Esta propiedad se usa para establecer el nombre inicial que aparecerá en el cuadro Nombre de archivo del cuadro de diálogo. Después de que se cierre el cuadro de diálogo se puede leer esta propiedad para determinar el nombre del archivo seleccionado.
FíleName
(filtro). La propiedad Filter se puede establecer para restringir los nombres de archivos que aparecerán en el cuadro de lista. La propiedad filtro debe ser una cadena de texto con una o más parejas de componentes. Las parejas de componentes están constituidas por una descripción y por un carácter comodín, separados por la raya vertical (|). Las distintas parejas también se separan por la raya vertical. Por ejemplo, la siguiente cadena especifica tres parejas de componentes:
DIogo.FileName = "" Dlogo.Filter = "Archivos de datos (*.DAT)|*.DAT| Todos los archivos (*.*) |*.*" DIogo.FilterIndex = 1 Dlogo.Flags = OFN_FILEMUSTEXIST Or OFN_PATHMUSTEXIST Dlogo.Action = 1 If DIogo.FileName = "" Then MsgBox "No se ha seleccionado ningún archivo."
Filter
142
Guardar como
El cuadro de diálogo Guardar como, que se muestra en la figura 5.37 (en la parte superior de la página siguiente), aparece cuando se asigna el valor 2 a la propiedad Action. Las propiedades para Guardar como son idénticas a las ya descritas para Abrir, excepto que el valor por omisión de la propiedad DialogTitle es Guardar como. 143
EL LIBRO DEL VISUAL BASIC
5 El uso de formularios y herramientas de Visual Basic
Figura 5.37.
El cuadro de diálogo Guardar como Figura 5.38.
El cuadro de diálogo Color
Propiedades
(extensión por omisión). Esta propiedad se puede establecer a una cadena de entre 1 y 3 caracteres, la cual se usará como extensión por omisión si el nombre del archivo se especifica sin extensión.
DefaultExt
Ejemplo
Este fragmento de programa muestra un cuadro de diálogo Guardar como. Asume que el objeto diálogo estándar se llama Dlogo. En este ejemplo, la propiedad CancelError se establece como True; en caso contrario, sería imposible determinar si se ha seleccionado o no un nombre de archivo. Observa que este código realmente no guarda ningún archivo; simplemente, permite que el usuario seleccione un nombre de archivo. DIogo.Cancel Error = True DIogo.DefaultExt = "DAT" Dlogo.FileName = DEFAULT.DAT" Dlogo.Filter = "Archivos de datos (*.DAT)|*.DAT | Todos los ar chivos ( *.*) | *.* "
DIogo.FilerIndex = 1 Dlogo.Flags = 0FN_0VERWRITEPR0MPT Or OFN_PATHMUSTEXIST Dlogo.Action = 2 MsgBox "Escribiendo el archivo " + DIogo.FileName
Propiedades
(color). Esta propiedad se usa para establecer el color inicial. Después de que se cierra el cuadro de diálogo, se puede leer esta propiedad para determinar el color seleccionado por el usuario.
Color
(banderas). Esta propiedad se debe establecer como CC_RGBINIT para esta blecer o leer la propiedad Color.
Flags
Ejemplo
Este fragmento de programa muestra un cuadro de diálogo Color para que el usuario muestre un color. Asume que el objeto diálogo estándar se llama Dlogo y utiliza el color seleccionado para establecer el color del fondo del formulario actual mediante la propiedad BackColor. Dlogo.Color = BackColor Dlogo.Flags = CC_RGBINIT Dlogo.Action = 3 BackColor = Dlogo.Color
’Color actual ’Mostrar el cuadro de diálogo ’El color nuevo, o el mismo ’si se cancela
Fuentes Color
El cuadro de diálogo Color, que se muestra en la figura 5.38, aparece cuando se asigna el valor 3 a la propiedad Action. Puedes establecer las propiedades siguientes para controlar la apariencia del cuadro de diálogo. 144
El cuadro de diálogo Fuentes, que se muestra en la figura 5.39 (al principio de la página siguiente), aparece cuando se asigna el valor 4 a la propiedad Action. Puedes establecer las propiedades siguientes para controlar la apariencia del cuadro de diálogo. 145
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
Figura 5.39.
El cuadro de diálogo Fuente
Propiedades
(color). Esta propiedad permite establecer o leer el color de la fuente. (Sólo está activa si la propiedad Flags incluye la bandera CF_EFFECTS.)
Sub EstablecerPropsDel Texto (TxtCntl As Control) D l o g o . C o l o r = TxtCntl . F o r e C o l o r ’Obtener valores actuales DIogo.FontBold = TxtCntl . FontBold DIogo.FontItalic = TxtCntl.FontItalic DIogo.FontStrikethru = TxtCntl.FontStrikeThru Dlogo.FontUnderline = TxtCntl.FontUnderline DIogo.FontName = TxtCntl.FontName DIogo.FontSize = TxtCntl.FontSize Dlogo.Flags = CF_EFFECTS Or CF_F0RZEF0NTEXIST Or CF_BOTH Dlogo.Action = 4 ’Mostrar cuadro de diálogo TxtCntl.ForeColor = Dlogo.Color ’Establecer los nuevos valores TxtCntl.FontBold = Dlogo.FontBold TxtCntl.FontItalic = Dlogo.FontItalic TxtCntl.FontStrikethru = Dlogo.FontStrikethru TxtCntl.FontUnderline = Dlogo.FontUnderline TxtCntl.FontName = Dlogo.FontName TxtCntl.FontSize = Dlogo.FontSize End Sub
Color
(banderas). Esta propiedad se puede establecer para modificar el comportamiento del cuadro de diálogo. Sin embargo, debe incluir uno de estos valores: CF_PRINTERFONTS, CF_SCREENFONTS ó CF_BOTH. Estos valores determinan qué fuentes aparecerán en el cuadro de diálogo (sólo fuentes de impresora, sólo fuentes de pantalla ó ambas).
Flags
(fuente negrita, cursiva, tachada, subrayada). Estas son propiedades booleanas que se pueden establecer o leer para determinar la información del estilo de la fuente. El ajuste de la propiedad Flags debe incluir CC_EFFECTS para activar el ajuste de los estilos.
FontBoId, Fontltalic, FontStrikethru, FontUnderline
Imprimir
El cuadro de diálogo Imprimir, que se muestra en la figura 5.40, aparece cuando se asigna el valor 5 a la propiedad Action. Puedes establecer las propiedades siguientes para controlar la apariencia del cuadro de diálogo. Propiedades Copies (copias). Esta propiedad, que admite un número entero, controla el
número
de copias que se imprimirán.
(nombre de la fuente). Esta propiedad se puede establecer para indicar la fuente por omisión y para determinar la selección de fuente que ha hecho el usuario.
FontName
(tamaño de la fuente). Esta propiedad se puede establecer o leer, y determina el tamaño en puntos de la fuente.
FontSize
Ejemplo
Esta subrutina permite que se modifiquen los atributos de la fuente de un control de texto. El control se pasa como parámetro. Asume que el objeto diálogo estándar se llama Dl ogo. 146
Figura 5.40.
El cuadro de diálogo Imprimir
147
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
(banderas). Esta propiedad gestiona características especiales del cuadro de diálogo. Puedes consultar el archivo CONSTANT.TXT y el manual de Visual Basic si necesitas más información.
Flags
Ejemplo
Este fragmento de programa muestra un cuadro de diálogo para imprimir. Asume que el objeto diálogo estándar se llama Dlogo. Ten en cuenta que llamar al cuadro de diálogo Imprimir realmente no inicia el proceso de impresión. Debes escribir en el objeto impresora en Visual Basic. El cuadro de diálogo simplemente permite que el usuario seleccione ciertas opciones de impresión.
Ejemplo
Este fragmento de programa llama a la Ayuda de Windows sobre la función MsgBox. Dlogo.HelpCommand = HELP_KEY Dlogo.HelpFile = "VB.HLP" Dlogo.HelpKey = "MsgBox" D l o g o . Action = 6’Llamar a la Ayuda
PrimeraPagina = 1 UltimaPagina = 57 Dlogo.Cancel Error = True ’Abortar si se cancela el cuadro de diálogo Dlogo.Copies = 1 ’Ajustes por omisión Dlogo.Min = Primera Pag ina Dlogo.Max = UltimaPagina Dlogo.Flags = PD_USEDEVMODECOPIES Or PD_NOSELECTION ’Permitir más de una copia Dlogo.Action = 5 ’Mostrar el cuadro de diálogo ImprimirTodas = Dlogo.Flags And PD_ALLPAGES If Not ImprimirTodas Then PrimeraPagina = Dlogo.FromPage UltimaPagina = Dlogo.ToPage End If
Llamar a la ayuda
La aplicación Ayuda de Windows, que se muestra en la figura 5.41, aparece cuando se asigna el valor 6 a la propiedad Action. Puedes establecer las propiedades siguientes para controlar la apariencia del cuadro de diálogo. Propiedades
(comando de ayuda). Esta propiedad especifica el tipo de Ayuda que quieres obtener. Normalmente, se utiliza la constate HELP_KEY, lo que indica que se solicita ayuda sobre una palabra clave específica. La definición de HELP_KEY aparece en CONSTANT.TXT.
Figura 5.41.
La aplicación Ayuda
Menús
(archivo de ayuda). Esta propiedad especifica el nombre del archivo de Ayuda.
Aunque ya has creado varias aplicaciones pequeñas, puede que te haya dado la sensación de que ninguna de ellas parecían "aplicaciones de verdad". ¿Por qué no? Para empezar, porque ninguna de ellas tenía barra de menús. Sin embargo, esta situación se puede remediar, ya que Visual Basic hace que sea muy sencillo crear menús. Los menús funcionan de una manera "orientada hacia los eventos", muy similar a los objetos que hemos tratado.
(clave de ayuda). Esta propiedad especifica la palabra clave que se debe usar para la pantalla inicial de Ayuda.
Para crear el menú de una aplicación debes usar la ventana Menu Design (diseño del menú) de Visual Basic, la cual se muestra en la figura 5.42. Crea un proyecto
HelpCommand
HelpFile
HelpKey
148
149
5 El uso de formularios y herramientas de Visual Basic
EL LIBRO DEL VISUAL BASIC
nuevo y abre esta ventana seleccionando el comando Menu Design del menú Window (ventana) o haciendo clic en el botón Menu Design Window de la barra de herramientas de Visual Basic. La barra de menús de la aplicación se construye creando una jerarquía de elementos en la ventana Menu Design. A cada elemento del menú se le debe definir una propiedad Caption y una propiedad Name. En Caption, hay que insertar el texto que se desea que aparezca en la barra de menús o en el menú desplegable. Name, por su parte, es el nombre que identifica al elemento en el código del programa. Se necesita un nombre porque cada elemento del menú tiene un procedimiento Click. Supon que tu ordenador incluye un hardware que muestre imágenes de televisión en una ventana. Los menús de la aplicación que controlen el hardware podrían recordar a un mando a distancia. Aquí tienes el posible diseño de la estructura del menú, con tres niveles de jerarquía: Archivo Encender Apagar Salir Canal Seleccionar... Siguiente Anterior Volumen Anular Preestablecido Bajo Medio Alto Subir Bajar 150
Figura 5.42.
El menú de diseño de ventana de Visual Basic
Observa que aparecen unos puntos suspensivos (...) detrás del elemento Seleccionar para indicarle al usuario que esta selección producirá que aparezca un cuadro de diálogo. Vamos a definir la parte del menú de esta aplicación. Sin embargo, antes de que salgas de la ventana Menu Design, debes retocar un poco más la lista del menú actual. En la mayoría de las aplicaciones para Windows se puede utilizar el teclado para elegir comandos de los menús sin necesidad del ratón. Estos atajos de teclado se denominan teclas de acceso y, normalmente, consisten en pulsar la tecla Alt y los caracteres que están subrayados en el menú. Por ejemplo, en Visual Basic puedes escribir Alt, E, S para seleccionar el menú File y de él, el comando Save. En la ventana Menu Design puedes especificar la tecla de acceso para un elemento del menú insertando un ampersand (&) delante del carácter que va a estar subrayado en el menú de la aplicación. (El ampersand no aparece en el menú.) Utiliza siempre el primer carácter del título de un elemento del menú como tecla de acceso, a no ser que exista un conflicto. En nuestra aplicación, por ejemplo, tanto Seleccionar como Siguiente empiezan con la letra S, así que tendrás que elegir otro carácter en uno de ellos. A continuación, puedes ver las entradas del menú para la aplicación de ejemplo, con los caracteres en las teclas de acceso especificados. 151
EL LIBRO DEL VISUAL BASIC
&Archivo &Encender &Apagar &Salir &Canal
5 El uso de formularios y herramientas de Visual Basic
tos del segundo nivel, utiliza mnu seguido por una abreviatura de tres letras que indique el elemento del primer nivel al que están subordinados los elementos del segundo nivel, y seguido por el título del elemento: mnuAchEncender, por ejemplo, o mnuCanSeleccionar. De la misma forma, para los elementos del tercer nivel incluye dos abreviaturas de tres letras que indiquen los elementos "padre". Aquí tienes los nombres sugeridos para esta aplicación:
&Seleccionar...
mnuArchivo
&Siguiente
mnuAchEncender
&Anterior
mnuAchApagar
&Volumen
mnuAchSalir
&Anular
mnuCanal
&Preestablecido
mnuCanSeleccionar...
&Bajo
mnuCanSiguiente
&Medio
mnuCanAnterior
&Alto
mnuVolumen
&Subir
mnuVolAnular
&Bajar
mnuVolPreestablecido
Junto con el título (Caption) y la tecla de acceso, cada elemento del menú necesita un nombre (Name). Aunque podría parecer lógico usar la misma palabra para el título y para el nombre, con frecuencia es imposible hacerlo así. Por ejemplo, Exit es una palabra clave de Visual Basic y se puede usar como título, pero no como nombre de un objeto en el código.
mnuVolPreBajo
Lo mejor es utilizar un esquema de nombres estándar que te permita reconocer inmediatamente cada elemento. Es importante que los nombres sean claros, porque cada elemento del menú tiene un procedimiento Click, cuando se está traba jando en el código es fácil olvidarse de cuál es el elemento del menú sobre el que se trabaja. Por ejemplo, en este proyecto de ejemplo, prueba a usar el prefijo mnu para todos los nombres de objetos; ello identificará los objetos como menús, en oposición, por ejemplo, a los botones de comando o a las barras de desplazamiento.
mnuVolBajar
Para los elementos del menú que están en el primer nivel de jerarquía, pon el título del menú detrás del prefijo mnu: mnuArchivo, por ejemplo. Para los elemen152
mnuVolPreMedio mnuVolPreAlto mnuVolSubir
Ahora ya estás listo para ir a la ventana Menu Design y crear el menú de esta aplicación. 1. Haz clic en el cuadro de texto Caption de la ventana Menu Design y escri be &Archivo. Luego pulsa Tab para pasar al cuadro Name. Escribe mnuArcbivo en este cuadro de texto y pulsa la tecla Intro. El título (pero no el nombre) aparecerá en el cuadro de lista de la parte inferior de la ventana. 2. Haz clic en el botón que tiene la flecha apuntando hacia la derecha, que está sobre el cuadro de lista. Aparecerán cuatro puntos en la línea que hay 153
EL LIBRO DEL VISUAL BASIC
debajo de &Archivo para indicar que los siguientes elementos que se inserten aparecerán en el segundo nivel de la jerarquía del menú. 3. Vuelve al cuadro de texto Caption y escribe & Encender. Pulsa la tecla Tab para pasar al cuadro Name, escribe mnuAchEncender y pulsa Intro. Vuelve al cuadro Caption y escribe & Apagar, luego pulsa Tab para pasar al cuadro Name, escribe mnuAchApagar y pulsa Intro. Usa el mismo procedimiento para el título &Salir y el nombre mnuAchSalir. Tu ventana Menu Design debe ahora parecerse a ésta:
5 El uso de formularios y herramientas de Visual Basic
mentís. Ese menú de desplegará, mostrando los comandos que contiene, como se muestra en la figura 5.43. Si en el formulario haces clic sobre una entrada del menú, Visual Basic abrirá una ventana de código para el correspondiente procedimiento Click. En esa ventana se escribe el código para las operaciones que tendrán lugar cuando el usuario seleccione el elemento del menú. Por ejemplo, haz clic en el elemento Salir del menú Archivo para abrir la ventana de código del procedimiento del evento mnuAchSalir_Click. El comando de Visual Basic que se usa para terminar una aplicación es End; así, el procedimiento para Salir debe parecerse a éste: Sub mnuAchSalir_Click ( ) En d End Sub
Experimenta con la aplicación poniendo instrucciones Debug.Print en diversos procedimientos del menú y luego ejecutándola otra vez. A medida que selecciones distintos comandos del menú, ve mirando la ventana Debug para comprobar que los procedimientos del menú se están ejecutando. Opciones adicionales para el diseño de los menús
La ventana Menu Design también ofrece otras opciones diversas muy interesantes. Por ejemplo, si introduces un guión () como título, Visual Basic colocará una barra separadora en el menú, lo que visualmente establece grupos de elementos del menú relacionados. (También debes asignarle un nombre a la entrada del guión, incluso aunque no se vaya a usar en el programa.) 4. Haz clic en el botón que tiene la flecha apuntando hacia la izquierda para volver al primer nivel de la jerarquía. Ahora introduce el resto de los títulos y nombres de la lista. Para introducir los elementos del tercer nivel de la jerarquía, haz clic dos veces previamente sobre el botón con la flecha apuntando hacia la derecha. Si cometes algún error al poner un elemento en la jerarquía, puedes seleccionar el nombre del elemento en el cuadro de lista y hacer clic en los botones con las flechas apuntando a izquierda y derecha para ajustar su nivel. Los botones con las flechas apuntando arriba y abajo mueven el nombre a una posición diferente en la lista. 5. Cuando hayas terminado de introducir los elementos del menú haz clic en el botón OK. La barra de mentís aparecerá ahora en el formulario principal de la aplicación. Puedes ver los elementos del menú haciendo clic sobre su nombre en la barra de 154
También puedes asignar teclas de atajo a los elementos del menú. Abre la ventana Menu Design otra vez y selecciona &Salir. Luego haz clic en el botón con la flecha apuntando hacia abajo que hay al lado del cuadro Shortcut (atajo). Puedes asignar al comando Salir cualquiera de las combinaciones de teclas que aparecen en la lista desplegable. Los cuadros de control Checked (marcado), Enabled (activado) y Visible (visible) de la ventana Menu Design corresponden a propiedades del elemento del menú que está seleccionado. Cada propiedad puede establecerse como True (lo cual se indica mediante un X en el cuadro de control) o False (el cuadro de control vacío). Establecer la propiedad Checked como True hace que aparezca una marca de control en el menú al lado del elemento, lo que indicará que la opción está activa. (Puedes ver una marca de este tipo junto al elemento Toolbar del menú View de Visual Basic.) La propiedad Enabled se establece como True por omi 155
5 El uso de formularios y herramientas de Visual Basic
LIBRO DEL VISUAL BASIC
Figura 5.44.
Un menú con barras separadoras , una marca de activación y una opción desactivada
objeto.propiedad = {True | False} Figura 5.43.
Un formulario con una barra de menús y menús desplegables
sión; si estableces esta propiedad como False, el elemento del menú aparecerá atenuado y no se podrá seleccionar en el menú. Si estableces la propiedad Visible como False, el elemento del menú no aparecerá en el menú. La figura 5.44 muestra el aspecto que tendría el menú Volumen de tu aplicación de mando a distancia del televisor si añadieses dos barras separadoras al primer nivel, establecieses la propiedad Chechee del elemento mnuVolPreAlto como True, añadieses un nuevo elemento llamado Realmente alto y, como deferencia a tus vecinos, establecieses su propiedad Enalbes como False. Los ajustes Chechee, Enalbes y Visible de la ventana Menu Designó indican los ajustes al comienzo. Cualquiera de estos ajustes se pueden cambiar desde el código del programa con declaraciones de la forma siguiente: 156
Las otras opciones que aparecen en la ventana Menu Design —Window List, Index y HelpContextID— son posibilidades avanzadas que están más allá del ámbito de este libro. Puedes encontrar información sobre estas tres posibilidades en tu manual de referencia de Visual Basic. Menús popup o emergentes
Aunque los menús normalmente se llaman desde la barra de menús, algunas veces puedes querer que aparezca un menú desde un control. Este tipo de menús se llama emergente, porque no es visible normalmente, pero aparece de repente cuando se hace clic sobre un control. Puedes hacer que cualquier menú aparezca como un menú emergente usando el método PopupMenu. Por ejemplo, podrías asociar el menú Volumen que se muestra en la figura 5.45 con el dibujo de un botón de volumen. Usa la herramienta Picture para crear un cuadro de dibujo en la pantalla, y luego utiliza la herramienta Shape para dibujar un botón de control circular dentro del cuadro de dibujo. (La forma será inicial 157
EL LIBRO DEL VISUAL BASIC
mente un rectángulo. Para crear un círculo debes establecer la propiedad Shape con el valor 3 Circle.) Introduce el siguiente código para el evento MouseDown (ratón abajo) del cuadro de dibujo. Sub Picture1_MouseDown (Boton As Integer, Cambio As Integ er, X As Single, Y As Single) PopupMenu mnuVolumen End Sub
Cada vez que el usuario pulse el botón del ratón dentro del área del cuadro de dibujo, aparecerá el menú Volumen, como muestra la figura 5.45.
6 Control del programa Los pequeños programas que has escrito hasta ahora han sido extremadamente simples: ejecutan declaraciones secuenciales, llevan a cabo tareas bastante directas y, en general, carecen de complicación. Este capítulo introduce los conceptos que te ayudarán a obtener un mayor control sobre la manera en que se ejecutará un programa, permitiéndote escribir código que puede gestionar diversas circunstancias y opciones, con la posibilidad de repetición y con un rango más amplio de datos.
Realizar elecciones Los programas que has escrito en los capítulos anteriores constaban única y exclusivamente de comandos y expresiones, los equivalentes de las declaraciones imperativas en español. Pero nadie, ni siquiera el dictador más exaltado, puede funcionar solamente dando ordenes. En la vida real la gente debe realizar elecciones. La herramienta principal de Visual Basic para tratar con las opciones es la declaración If Figura 5.45, Un menú popup
Observa que en este ejemplo el menú Volumen está disponible tanto como un popup como a través de la barra de menús. Si quieres que un volumen sea visi ble sólo como un popup deberás establecer su propiedad Visible como False en la ventana MenuDesign. La propiedad Visible de un elemento del nivel más alto se aplica sólo a los elementos de la barra de menús y es ignorada por el método
PopupMenu.
158
If Imagina que le estás enseñando a un amigo lo que significan las señales de tráfico. En concreto, lo que debe hacer cuando se encuentre una señal de estrechamiento sin preferencia. Podrías explicar qué se debe hacer cuando se encuentra una señal de ese tipo con las siguientes palabras: "baja la velocidad a 60 Km/h. Si no viene nadie, continúa tu camino; en caso contrario, detente y deja pasar al otro coche. La declaración
En el caso de Visual Basic, la forma de hacerlo no es muy distinta. Observa el siguiente ejemplo. 159
6 Control del programa
EL LIBRO DEL VISUAL BASIC
Velocidad = 6 If Coches_Viniendo = 0 Then Velocidad = 100 Else Velocidad = 0 End If
’ S e a p r o x i m a u n a s e ñ a l d ee s t r e c h a m i e n t o ’No viene ningúncoche 'Volver a la velocidad inicial ’Viene alguien ’Detenerse
La forma clásica de la declaración If ( que en inglés es similar al si condicional que usamos en castellano) especifica una elección entre dos opciones. Las pala bras "dos caminos divergentes" lo expresan bastante bien con una imagen visual, aunque el poeta Robert Frost no estaba contemplando un programa de ordenador. Frost estaba preocupado porque solamente era posible viajar por uno de los dos caminos, mientras que un programador debe preocuparse por los dos (ya que no sabe cuál va a escoger el usuario). Como programador, debes darle instrucciones al ordenador. Como no puedes conocer siempre con exactitud qué condiciones se encontrará el programa en cada momento mientras se esté ejecutando, tendrás que incluir instrucciones para gestionar diversos casos. En el ejemplo de la señal de estrechamiento no sabes si tu amigo se encontrará con coches viniendo, así que le darás las instrucciones correctas para ambas posibilidades. En el código de un programa se crea lo que se denomina una ramificación condicional , utilizando la declaración If Aquí tienes la sintaxis de la declaración If o n Visual Basic: If expresión booleana Then
[declaración]...
[Else
[declaración]...]
End If Tras la palabra clave If va una expresión booleana, la cual (como recordarás del capítulo 4) es una expresión que se evalúa como True o False. Aquí tienes otros ejemplos para llevar el mundo binario a la vida real: True o False, camino izquierdo o camino derecho, If o Else (else quiere decir en caso contrario en inglés). Si la expresión booleana resulta True se ejecutan todas las instrucciones que haya detrás de la palabra Then (que quiere decir entonces en inglés) y hasta la palabra Else. (Los puntos suspensivos en la descripción de la sintaxis indican que puede haber más de una instrucción.) El programa se salta entonces las instrucciones siguientes y continúa la ejecución detrás de las palabras clave End If. Si la expresión booleana es False, se omiten las instrucciones que haya inmediatamente detrás de la palabra T hen. Cuando el programa encuentra una parte que empieza 160
por la palabra clave Else , sigue a partir de ahí. Las dos posibles vías de ejecución son las siguientes: If True Then ’Se ejecutan estas ’ instrucciones El se ’Se omiten estas ’ instrucciones End If ’La ejecución continúa aquí
If False Then ’Se omiten estas ’ instrucciones El se ’Se ejecutan estas ’ instrucciones End If 'La ejecución continúa aquí
La declaración If es una declaración compuesta —es decir, se evalúa como una sola unidad, aunque puede contener muchas otras declaraciones en su interior. Muchos programadores acostumbran a sangrar esas otras declaraciones para que sea más fácil ver lo que hay dentro de la declaración If Observa lo difícil que es leer nuestro ejemplo anterior cuando no está sangrado: Velocidad = 60 If Coches_Viniendo = 0 Then Velocidad = 100 Else Velocidad = 0 End If
Velocidad = 60 If Coches_Viniendo = 0 Then Velocidad = 100 Else Velocidad = 0 End If
Si examinas la definición de la sintaxis de la declaración If podrás ver que la parte Else de la declaración es opcional. Ello te permite evitar la programación innecesaria en el caso de que no haga falta poner ninguna declaración en la cláusula Else. De esta manera, estos dos fragmentos de código son equivalentes: If Conde = "Drácula" Print "¡Aieeeeeeee! Else End If
If Conde = "Drácula" Print "¡Aieeeeeeee! End If
Varias opciones
La declaración If permite que un programa gestione una elección realizada entre dos opciones posibles. Pero, ¿cómo puede un programa gestionar una elección realizada entre muchas opciones? En realidad, con la declaración If tienes todo lo que necesitas para encargarte de una situación en la que se presenten varias opciones. A modo de ejemplo, piensa en el problema de identificar a uno de los Tres Cerdi tos. Evidentemente, tienes tres posibilidades entre las que elegir. En este caso, el 161
EL LIBRO DEL VISUAL BASIC
material de construcción de la casita es una buena característica distintiva. Puedes construir un test sencillo, como se muestra en la figura 6.1. El uso de la declaración If para realizar selecciones de uno entre muchos puede recordarte el juego de las preguntas, en el que una persona piensa en una cosa de un tipo acordado previamente y el resto de los jugadores tratan de adivinar qué es haciendo preguntas que sólo se pueden contestar con "Sí" ó "No". Con cada pregunta se van eliminando ciertas características, y el juego se mueve en una dirección concreta. El código de Visual Basic diseñado para implementar la prueba de los Tres Cerdi tos de la figura 6.1 se muestra aquí; la segunda declaración If es una declaración anidada, la cual está contenida completamente dentro de la primera: If Casita = "Paja" Then Cerdito = "Perezoso" El se If Casita = "Madera" Cerdito = "Indiferente" El se Cerdito = "Aplicado" End If End If
Cuando se necesitan más de tres o cuatro pruebas If el anidamiento de declaraciones If puede ser complicado. Visual Basic admite una variante de la cláusula Else denominada Else If, la cual combina una cláusula Else con la funcionalidad
6 Control del programa
de otra declaración If. Aquí tienes una versión del código anterior que ha sido rehecha usando Else lf a su lado aparece la sintaxis completa de la declaración If de Visual Basic. If Casita = "Paja" Then Cerdito = "Perezoso” ElseIf Casita = "Madera" Then Cerdito = "Indiferente" El se Cerdito = "Aplicado” End If
If expresión booleana Then [declaración]... [ElseIf expresión booleana Then [ declaración]...]
[Else [declaración]...] End If
Como se indica en la descripción de la sintaxis, la cláusula ElseIf puede repetirse muchas veces, lo que elimina la necesidad de escribir varias declaraciones If anidadas. La aplicación Tragaperras
Para explorar más a fondo la declaración If v amos a construir una simulación de una máquina tragaperras. Con un botón de comando, a modo de "palanca", el programa Tragaperras mostrará tres iconos aleatorios cada vez que "tires" de la palanca. Si los iconos coinciden, el usuario gana. El programa incluso llevará el control de las ganancias del jugador. Visual Basic incluye algunos iconos muy apropiados para jugar: puedes usar los iconos corazón, trébol, diamante y pica, denominados respectivamente MISC34, MISC35, MISC36 y MISC37. El programa cogerá uno de estos iconos aleatoriamente para cada una de las tres posiciones. Cada juego le cuesta 100 pesetas al jugador. Si los tres iconos coinciden, el jugador gana 1000. Si los tres son diamantes, el jugador gana 2500. Crea un proyecto nuevo para diseñar la pantalla. En la parte superior del formulario añade tres controles imagen, los cuales servirán para contener las pantallas de la máquina tragaperras. Debajo de los controles imagen pon un botón de comando que servirá como "palanca" de la máquina. A la izquierda, añade una etiqueta para mostrar las ganancias del jugador; a la derecha, crea otro botón de comando que permita al jugador terminar de jugar. Finalmente, añade cuatro controles imagen más para que contengan los cuatro iconos que vamos a usar. Tu formulario debe parecerse al que se muestra en la figura 6.2.
Figura 6.1.
Identificación de un cerdito
162
Para configurar los cuatro controles imagen de abajo, comienza por seleccionar el que está más a la izquierda y establece su propiedad Name como imgCorazones. Luego establece su propiedad Picture seleccionando Picture en la lista de propie 163
EL LIBRO DEL VISUAL BASIC
6 Control del programa
Piénsatelo Revisa cuidadosamente las presunciones que hagas cuando programes con la declaración If. Debes tener cuidado de no incluir accidentalmente opcio nes no deseadas o, por el contrario, de no excluir opciones que debieran incluirse. No seas demasiado rápido en presumir que tu primer intento al escribir una cláusula Else cubre la única alternativa posible. Por ejemplo, el código que escribiste para identificar a los Tres Cerditos asume que si Perezoso e Indeferente son eliminados, la única posibilidad que queda es Aplicado. Pero, en otras circunstancias, podría ocurrir que hubiese más posibilidades. Un ejemplo similar de objeto. Si el objeto no es azul. Esto funciona bandera norteamericana; no ser válida.
esta clase de errores es la prueba del color de un es ni rojo ni blanco, podrías asumir que, por tanto, si sabes que todos los objetos son elementos de la sin embargo, en caso contrario la prueba podría
controles imagen, llamándolos imgTreboles, imgDiamantes e imgPicas, y estable ciendo sus propiedades Picture para cargar los archivos MISC35.ICO, MISC36.ICO y MISC37.ICO en este orden. A continuación establece las propiedades de los distintos elementos de la pantalla como se muestra en la figura 6.3. Cuando termines, tu formulario debe parecerse a la figura 6.4.
Objeto
Propiedad
Ajuste
Forml
BorderStyle Caption Name
3 - Fixed Double Tragaperras Tragaperras
Image1
BorderStyle Name Stretch
1 - Fixed Single imgTraga1 True
Image2
BorderStyle Name Stretch
1 - Fixed Single imgTraga2 True
Image3
BorderStyle Name Stretch
1 - Fixed Single imgTraga3 True
Caption Name
Girar btnGirar
Command1 Label1
BorderStyle Caption Name
1 - Fixed Single (ninguno) lblTotal
Command2
Caption Name
Salir btnSalir
Figura 6.3.
los ajustes correctos para la aplicación tragaperras
Figura 6.2. El diseño inicial para la
aplicación Tragaperras
dades y haciendo clic en el botón con los puntos suspensivos que hay al lado del cuadro Ajustes. En el cuadro de diálogo Load Picture elige el archivo MISC34.ICO del directorio de iconos correspondiente (\VB\ICONS\MISC si instalaste Visual Basic usando los directorios por omisión). Repite este proceso para los otros tres 164
Para comenzar a trabajar en el código del programa, haz doble clic sobre el for mulario con el fin de abrir una ventana de código. Introduce las siguientes líneas de código en la sección de declaraciones generales: Const TREBOL% = 1, CORAZON% = 2. DIAMANTE% = 3 , PICAS% = 4 Dim Ganancias As Currency
165
EL LIBRO DEL VISUAL BASIC
Los enteros del 1 al 4 relacionarán los números seleccionados aleatoriamente con los iconos apropiados. Las declaraciones de constantes te permitirán utilizar los nombres TREBOL, CORAZON, DIAMANTE y PICA en el programa, haciendo que resulte más fácil de leer y de entender. La variable Ganancias, que es de nivel de formulario, se usa para contabilizar las ganancias del jugador. Ahora selecciona Form en el cuadro Object de la ventana de código, y Load en el cuadro Procedure. Añade estas líneas de código, las cuales se ejecutarán cuando el formulario se cargue por primera vez (o sea, al comienzo del programa): Sub Form_Load ( ) Randomize Ganancias = 0 End Sub
El comando Randomize instruye a Visual Basic para que "mezcle" los números producidos por su generador de números aleatorios; sin esta declaración, las se ries de jugadas siempre serían iguales cada vez que se ejecutase el programa. Como el jugador todavía no ha empezado a jugar, debes establecer la variable Ganancias a 0. Aquí tienes el código del botón Salir: Sub btnSalir_Click ( ) En d End Sub
Figura 6.4.
El formulario con el diseño completo para la aplicación
166
6 Control del programa
El procedimiento para el botón Girar aparece en la figura 6.5. Las variables lo cales P1, P2 y P3 contendrán cada una un número aleatorio que se utilizará para seleccionar los iconos que aparecerán en los tres controles imagen de arriba (lla mados, respectivamente, imgTraga1, imgTraga2 y imgTraga3). La variable Pago contendrá las ganancias del jugador correspondientes a una jugada (un "giro" de la máquina tragaperras).
Sub btnGirar_CIick ( ) Dim P1 As Integer, P2 As Integer, P3 As Integer Dim Pago As Currency 'Pago para jugar Ganancias = Ganancias - 100 'Generar resultados aleatorios P1 = Int(4 * Rnd + 1) P2 = I n t ( 4 * R n d + 1) P3 = I n t ( 4 * R n d + 1) 'Mostrar el icono 1 If P1 = CORAZON Then imgTraga1.Picture = imgCorazones.Picture ElseIf P1 = TREBOL Then imgTraga1.Picture = imgTreboles.Picture ElseIf PI = DIAMANTE Then imgTraga1.Picture = imgDiamantes.Picture ElseIf PI = PICAS Then imgTraga1.Picture = imgPicas.Picture End If 'Mostrar el icono 2 If P2 = CORAZON Then imgTraga2.Picture = imgCorazones.Picture ElseIf P2 = TREBOL Then imgTraga2.Picture = imgTreboles.Picture ElseIf P2 = DIAMANTE Then imgTraga2.Picture = imgDiamantes.Picture
Figura 6.5.
(continúa)
El procedimiento btnGirar_Click para la aplicación Tragaperras
167
6 Control del programa
EL LIBRO DEL VISUAL BASIC
Figura 6.5. continuación
ElseIf P2 = PICAS Then imgTraga2.Picture = imgPicas.Picture End If
R nd + 1) utiliza la función interna R nd de Visual Basic para devolver un número aleatorio entero del rango comprendido entre 1 y n. El programa examina, a continuación, luego el número aleatorio P1 y establece la propiedad Picture de imgTraga1 según dicho número, copiando el dibujo de uno de los iconos predefinidos de la parte inferior del formulario. Este proceso se repite para imgTraga2 e imgTraga3.
'Mostrar el icono 3 If P3 = CORAZON Then imgTraga3.Picture = imgCorazones.Picture ElseIf P3 = TREBOL Then imgTraga3.Picture = imgTreboles.Picture ElseIf P3 = DIAMANTE Then imgTraga3.Picture = imgDiamantes.Picture ElseIf P3 = PICAS Then imgTraga3.Picture = imgPicas.Picture End If
Una vez que se han completado la pantallas de la máquina tragaperras, el programa comprueba si hay una combinación ganadora. Si los tres números aleatorios son iguales, el jugador gana. Además, el programa comprueba si la combinación ganadora consta de tres diamantes. La variable Pago toma entonces el valor 1000 o 2500, de acuerdo con la combinación concreta. Si el jugador no ganó, la varia ble Pago se establece en 0.
'Comprobar si el jugador ha ganado If P1 = P2 And P2 = P3 Then If P1 = DIAMANTE Then Pago = 2500 MsgBox "¡¡Ganaste el GRANDE!!" Else Pago = 1000 MsgBox "¡GANASTE!" End If Else Pago = 0 Beep End If
Cuando cierres la ventana de código estarás listo para ejecutar la aplicación. Sin embargo, antes de que lo hagas, cambia el tamaño de la ventana para ocultar los cuatro iconos predefinidos de la parte inferior, como se muestra en la figura 6.6. Seguirán formando parte de la aplicación, pero no aparecerán en el interface del usuario.
Finalmente, el programa añade el pago a las ganancias del jugador y muestra el importe total en la etiqueta. La función Format de Visual Basic se asegura de que la cantidad aparezca en pesetas.
'Calcular y mostrar el total de ganancias Ganancias = Ganancias + Pago lblTotal.Caption = Format(Ganancias, "0 Pts") End Sub Figura 6.6.
El formulario redimensionado para la ejecución de la aplicación
Lo primero que hace el programa al ejecutarse es disminuir las ganancias del jugador en 100 ptas., el coste de una jugada. Después, genera tres números aleatorios que necesita para saber qué dibujo incluir en cada caso. La fórmula Int(n * 168
¿Te sientes con suerte? Pulsa F5 para probar tu habilidad con las tragaperras. Cuando termines de jugar es posible que quieras guardar este programa, de manera que puedas volver a él más adelante. 169
EL LIBRO DEL VISUAL BASIC
6 Control del programa
Hacer repeticiones
programa termine de hacer el bucle en algún punto y que continúe con el resto de instrucciones. Visual Basic te permite realizar esto de varias formas.
Las posibilidades de ejecutar declaraciones de asignación y de realizar elecciones utilizando la instrucción lf te proporcionan, teóricamente, las herramientas necesarias para escribir cualquier programa. Una vez más, las cosas son más fáciles en la teoría que en la práctica. Considera el problema de imprimir todos los números que van del 1 al 1000. La solución obvia —escribir un programa con 1000 instrucciones Print (Print 1 , Print 2, Print 3, y así sucesivamente)— sería algo más que tedioso. Afortunadamente, Visual Basic dispone de una manera mejor. La declaración Do de Visual Basic puede procesar repetidas veces un conjunto de instrucciones. Aquí tienes la sintaxis más sencilla de esta declaración: Do
[declaración]...
Loop La palabra clave Do (haz en inglés) marca el comienzo de una declaración compuesta, la cual incluye todas las declaraciones que haya hasta la palabra clave Loop (bucle en inglés). Las instrucciones se ejecutan en orden hasta que se llega a la palabra clave Loop; en ese punto la ejecución comienza de nuevo al comienzo del bloque que contiene la declaración Do. El conjunto de instrucciones que se repiten se denominan un bucle. Cuando un programa ejecuta repetidamente esas declaraciones, se dice que está iterando o haciendo un bucle. El bucle obtiene su nombre del diagrama circular del flujo del programa, como se muestra en la figura 6.7. El bucle que se muestra en la figura 6.7 es un bucle infinito —o sea, Visual Basic ejecutará la declaración para siempre. Desde luego, normalmente querrás que el
Puedes añadir una cláusula While (mientras) a la declaración Do o a la declaración Loop. El ejemplo de imprimir números del 1 al 1000 se resuelve fácilmente con un bucle Do While (haz mientras), como se muestra aquí: Contador = 1 Do While Contador <= 1000 Print Counter Counter = Counter + 1 Loop
La variable Contador se establece en 1. Luego una declaración Do While , que se ejecuta "mientras" Contador es menor o igual que 1000, y que termina cuando Contador pasa de 1000, envuelve una declaración Print y una declaración de asignación. Cuando el bucle finaliza, la ejecución continúa en las instrucciones del programa que hay a continuación de la palabra clave Loop. La palabra clave While debe ir seguida de una condición en forma de expresión booleana. Si la expresión es False, se saltan las instrucciones que vienen a continuación, hasta la palabra Loop , y la ejecución continúa en las instrucciones que van detrás de la palabra Loop. En este ejemplo, Contador se comprueba al comienzo de cada bucle, incluyendo el primero. (Si Contador se hubiera inicializado a 50000 no se habrían ejecutado ninguna de las instrucciones existentes en el interior del bucle.) Observa que a no ser que se incluya la declaración Contador = Contador + 1, la expresión booleana siempre sería True (porque Contador siempre se quedaría como 1), y el bucle se ejecutaría indefinidamente. Crear bucles infinitos inadvertidamente es un error muy común, incluso entre programadores experimentados. Recuerda que en Visual Basic siempre puedes pulsar Ctrl+Pausa para interrumpir la ejecución de un programa y detener un bucle infinito. La palabra clave While puede asociarse con la palabra Loop en lugar de hacerlo con Do, y lograr un efecto ligeramente distinto, como se muestra en este código: Do Contraseña = InputBox("Introduce la palabra secreta") Loop While Contraseña <> "Groucho"
Figura 6.7.
Un diagrama de un bucle Do
170
Poniendo la cláusula While al final del bucle te aseguras de que las instrucciones del interior del mismo se ejecutarán al menos una vez, debido a que la prueba que se realiza para determinar su finalización viene detrás de la palabra clave 171
EL LIBRO DEL VISUAL BASIC
6 Control del programa
Loop. En el ejemplo, un cuadro de diálogo que le pide al usuario que introduzca la "palabra secreta", aparece repetidamente hasta que el usuario introduce la pala bra correcta. Finalmente, para hacer que los programas sean más legibles, puedes usar la pala bra clave Until (hasta en inglés) en lugar de While. Usar U n til invierte la condi ción lógica. Compara los dos ejemplos anteriores en los que se usaba While con los mismos ejemplos usando Until. Ejemplos con While
Ejemplos con Until
Contador = 1 Do While Contador <= 1000 Print Counter Counter = Counter + 1 Loop Do Contraseña = InputBox("Introduce la palabra secreta") Loop While Contraseña <> "Groucho"
Contador = 1 Do Until Contador > 1000 Print Counter Counter = Counter + 1 Loop Do Contraseña = InputBox("Introduce la palabra secreta") Loop Until Contraseña = "Groucho"
Aquí tienes la sintaxis completa de la declaración Do de Visual Basic: Comprobación al comienzo del bucle
Do { While | Until }
expresión
[declaración]... Loop
mando para calcular la media y una etiqueta para mostrar el resultado. Diseña un formulario que contenga esos tres objetos, y establece las propiedades de los ob jetos como se describe en la figura 6.8. Tu formulario debe parecerse al que se muestra en la figura 6.9.
Objeto
Propiedad
Ajuste
Form1
Caption Name
Calcular Calcular
Command1
Caption Name
Media btnMedia
Label1
BorderStyle Caption Name
1 - Fixed Single [ninguno] lblMedia
Combo1
Name Style Text
cboEntradas 1 - Simple Combo [ninguno]
Figura 6.8. El ajuste de las propiedades para la aplicación Calcular
Comprobación al final del bucle
Do
[declaración]...
Loop { While | Until } expresión
La aplicación Calcular Utilicemos tus recien adquiridos conocimientos para escribir un programa que sir va como calculadora de ciertas operaciones específicas. Cuando el usuario in troduzca en un cuadro combinado el importe de todos los cheques que haya emitido durante un cierto período, el programa le dirá la cantidad media gastada por cheque. Para hallar la media, el programa suma todos los valores individuales y divide el total por el número de cheques —un trabajo ideal para un bucle Do While. Crea un proyecto nuevo en Visual Basic. El interface de Calcular requiere un cua dro combinado para contener todos los importes de los cheques, un botón de co 172
Figura 6.9. El diseño del formulario para la aplicación Calcular
Ahora tienes que modificar el cuadro combinado un poco. Normalmente un cua dro combinado proporciona una lista de opciones para el usuario. En este caso, tú lo usarás para construir una lista de entradas. Cada vez que el usuario intro duzca un valor en la parte de texto del cuadro combinado, el programa añade el 173
6 Control del programa
EL LIBRO DEL VISUAL BASIC
valor a los elementos de la parte de lista. Para ello necesitas usar un procedimiento de evento que no se trató en el capítulo 5, uno que está basado en el evento KeyPress (pulsar tecla). El evento KeyPress tiene lugar cada vez que el usuario pulsa una tecla. Haz doble clic en el cuadro combinado y selecciona KeyPress del cuadro Procedures de la ventana de código. La definición del procedimiento que aparece en la pantalla se parecerá a esto: Sub cboEntradas_KeyPress (KeyAscii As Integer) End Sub
Una variable llamada KeyAscii está definida dentro de los paréntesis. Esta variable es un parámetro. Los parámetros son como las variables locales, excepto porque están inicializadas por el procedimiento que llama, en lugar de serlo por el procedimiento que contiene la declaración. (Los parámetros en los procedimientos se explican con más profundidad en el capítulo 7.) Por el momento, solamente necesitas saber que el procedimiento del evento KeyPress viene con una variable predeclarada llamada KeyAscii. Cuando el procedimiento se comienza a ejecutar, el valor de KeyAscii es el código ASCII del carácter que el usuario acaba de pulsar. Por ejemplo, si el usuario escribe la letra A, el valor de KeyAscii será el 65. Escribir una a genera un valor de 97; escribir un 3 genera un valor de 51. El código de KeyPress puede modificar la variable KeyAscii. Si lo hace, Visual Basic introducirá en el cuadro combinado el carácter modificado, en lugar del carácter que escribió el usuario. Prueba esta posibilidad por un momento. Define el procedimiento KeyPress como sigue: Sub cboEntradas_KeyPress (KeyAscii As Integer) If KeyAscii = 83 Or KeyAscii = 84 Then KeyAscii = 42 End If End Sub
cboInput.Text = "" KeyAscii = 0 End If End Sub
'Borra la parte de texto 'Ignora la pulsación de tecla
Este procedimiento sirve para detectar la tecla Intro (código ASCII 13). Si la tecla que el usuario pulsa no es la tecla Intro, Visual Basic simplemente insertará en la parte de texto del cuadro combinado el carácter que tecleó el usuario. Sin embargo, cuando el programa detecta la tecla Intro, este procedimiento toma la parte de texto del cuadro combinado y la inserta en la parte de lista como un nuevo elemento. Entonces borra la entrada de la parte de texto y establece KeyAscii a 0. Como 0 es el código ASCII del carácter nulo, Visual Basic simplemente ignora ese carácter. Calcular la media
Después de que el usuario haya introducido todos los valores puede hacer clic en el botón Media para que el programa calcule la cantidad media. Haz ahora doble clic en el botón de comando Media e introduce el siguiente código: Sub btnMedia_Click ( ) Dim Actual As Integer, Total As Single Total = 0 ’La suma de todos los cheques Actual = 0 ’El cheque actual Do While Actual < cboEntradas.ListCount Total = Total + Val(cboEntradas.List(Actual)) 'Calcula la suma Actual = Actual + 1 'Siguiente cheque Loop lblMedia.Caption = Str$(Total / cboEntradas.ListCount) 'Mostrar ’la media como texto End Sub
Pulsa F5 para ejecutar la aplicación y escribe TEST en la parte de texto del cuadro combinado. Las letras T y S son reemplazadas por asteriscos. (El código ASCII del asterisco es el 42.) Finaliza la aplicación y edita el código de KeyPress otra vez, para que quede así:
La declaración Di m define dos variables locales: Actual que identifica el valor del cheque con el que el programa está trabajando en cada momento por el número del elemento; y Total, que contiene la suma de todos los valores. Total es iniciali zada luego a 0, y el elemento actual puesto a 0. (Los elementos de un cuadro de lista o de un cuadro combinado se identifican como elemento 0, elemento 1 y así sucesivamente.)
Sub cboEntradas KeyPress (KeyAscii As Integer) If KeyAscii = 13 Then 'Si la tecla es Intro cboEntradas.Addltem cboInput.Text 'Inserta el nuevo texto 'del usuario
La declaración Do While hace que Visual Basic continúe procesando mientras el número del elemento actual sea menor que el número total de elementos. (No puedes esperar que el programa encuentre 21 elementos si sólo se han introducido 7.) La siguiente declaración contiene la expresión cboEntradas.List(Actual), la
174
175
EL LIBRO DEL VISUAL BASIC
cual identifica el elemento de la lista. Como los elementos de un cuadro de lista o de un cuadro combinado siempre se almacenan como texto, se utilizará la función Val de Visual Basic para convertir el texto de los dígitos en un valor numérico. De la misma manera, la función Str $ convierte más tarde la media calculada en una cadena de texto, antes de que el programa la escriba en el título de la etiqueta. Ahora puedes ejecutar el programa Calcular. Escribe una serie de importes de cheques en la parte de texto del cuadro combinado, y pulsa la tecla Intro después de cada importe. Cuando hayas introducido toda la lista, haz clic en el botón Media. El resultado debe ser similar al que se muestra en la figura 6.10.
6 Control del programa
Un bucle For se puede escribir como una declaración While, pero es más normal utilizar el bucle For al ser más sencillo. La sintaxis de los bucles While se muestra a continuación: Incremento positivo
Incremento negativo
variable = pri merV alor vari able = pri merV alor Do While variable <= ultimoValor Do While variable >= ultimoValor [declaraciones]... variable = variable + incremento
Loop
[ declaraci ones]... variable = vari able - incremento
Loop
Observa que la expresión To del bucle For es equivalente a la comparación menor o igual que del bucle While cuando el incremento es positivo, y equivalente a la comparación mayor o igual cuando el incremento es negativo. Esto implica que el valor final de variable puede no ser igual que ultimoValor. Como ejemplo, mira este bucle y su salida. For Contador = 1 To 10 Step 4 Print Contador Next Contador Salida
Figura 6.10. Ejecución de la aplicación Calcular
Bucles que cuentan
La declaración For es una declaración especializada de Visual Basic que gestiona bucles que tienen un contador que aumenta o decrece regularmente. Tiene la siguiente sintaxis: For variable = pri merValor To ultimoValor [Step incremento]
[declaración] ...
Next variable La declaración For crea un bucle en el que la variable contador se inicializa a pri merValor y luego se va incrementando en incremento cada vez que el programa ejecuta el bucle, hasta que alcanza el valor ultimoValor. Si omites la cláusula Step, se asumirá que el incremento será 1. El valor de pri merV alor debe ser menor que el de ultimoValor, a no ser que el incremento sea negativo; en tal caso, el valor de pri merV alor debe ser mayor que el de ultimoValor. 176
1 5 9
Si quieres, puedes reescribir el código del programa Calcular usando un bucle For. Compara tus cambios con esta versión (la cual muestra las líneas modificadas en gris): Sub btnMedia_Click ( ) Dim Actual As Integer, Total As Single Total = 0 ’La suma de todos los cheques For Actual = 0 To cboEntradas.ListCount 1 Total = Total + Val(cboEntradas.List(Actual)) ’Calcula la suma Next Actual lblMedia.Caption = Str$(Total / cboEntradas.ListCount) ’Mostrar la media como texto End Sub
Cuando escribiste tu versión del código, ¿estableciste el valor final del bucle For a cboEntradas. ListCount - 1? Este cambio es importante, pero resulta fácil pasarlo 177
6 Control del programa
EL LIBRO DEL VISUAL BASIC
por alto. Recuerda que los números de los elementos de un cuadro combinado de Visual Basic comienzan por el 0 —es decir, si hay tres elementos, estarán numerados como 0, 1 y 2. La versión original del código utilizaba un bucle con una comparación menor que, pero el bucle For utiliza una comparación menor o igual que. Estas sutiles diferencias pueden producir errores que hagan que el bucle se ejecute demasiadas veces o muy pocas. Incluso los programadores con experiencia cometen estos errores, así que asegúrate de comprobar tus programas cuidadosamente. Por ejemplo, cuando hice el programa Calcular por primera vez, lo ejecuté con los valores de prueba 1, 2, 3 y 4. Como sabía la media de esos valores, 2,5, puede verificar que el código estaba funcionando correctamente. Cuando un programa no produce ningún tipo de resultado, se sabe que contiene un error de forma inmediata. Sin embargo, cuando el programa produce un resultado, es demasiado tentador presumir que el resultado es el correcto. Esperar lo inesperado
Incluso cuando un programa produce resultados correctos durante un cierto tiempo, puede que no sean producidos siempre. Eso sucede con el programa Calcular. El programa Calcular fallará si el usuario hace clic en el botón Media sin haber introducido ningún dato en el cuadro combinado. Podrías pensar que nadie va a hacer algo así. Pero parte de tu trabajo como programador consiste en comprender que cualquier cosa que sea posible hacer, probablemente acabará haciéndose. Y debes tratar de anticiparte a tales eventos lo mejor que puedas. En el programa Calcular, el bucle Do While (el bucle For si hiciste los cambios) evita sumar valores al total si el cuadro combinado está vacío, lo cual es correcto. El problema surge en el cálculo de la media. Como el programa no encuentra elementos en el cuadro combinado, la expresión Total / cboEntradas.ListCount produce una división por cero. En este caso, Visual Basic proporciona una cierta gestión del error al mostrar un cuadro de diálogo en el que dice Division by zero (división por cero), lo cual no es de mucha utilidad al usuario. Y algunos sistemas (como el MSDOS) simplemente finalizarán el programa que trata de dividir por cero. Claramente, es mejor que tú como programador te anticipes a este error a que confíes en que el sistema lo gestione de alguna manera (que, posiblemente, no sea la adecuada). Puedes enmendar el programa Calcular de dos maneras distintas. Una consiste en insertar el código que se muestra a continuación al comienzo del procedimiento btnMedia_Click. 17 8
If cboEntradas.ListCount = 0 Then Exit Sub End If
Este código produce que el programa se limite a ignorar el clic del ratón cuando es inapropiado, haciendo que el procedimiento no se siga procesando. Parecerá que el botón Media no responde, lo que podría, desde luego, confundir al usuario. Si te preocupa esta posibilidad puedes mostrar un cuadro de diálogo como hace el código que se muestra aquí: If cboEntradas.ListCount = 0 Then MsgBox "No hay datos para calcular la media" Exit Sub End If
El uso de matrices En el programa Calcular has usado la variable cboEntradas.List, que es una matriz. Las variables matriz pueden contener múltiples valores. Esto puede sonar un poco como los valores definidos por el usuario que vimos en el capítulo 3, pero no es lo mismo. Una variable registro contiene un número fijo de componentes, cada cual con un nombre y un tipo de datos distinto. En una matriz, todos los componentes son del mismo tipo, y cada componente o elemento individual está numerado, en lugar de tener un nombre distinto. Para referirse a un campo de un registro se usa tanto el nombre de la variable como el del campo, como en Sie glinde.Color. Para referirse a un elemento de una matriz se usa el nombre de la variable seguido por el número del elemento entre paréntesis — cboEntra das. List(3), por ejemplo. El número que especifica un elemento de una matriz se llama índice. Los valores índice siempre son números enteros. Visual Basic almacena los valores de la matriz en el orden del índice, comenzando (por omisión) en el elemento 0. La figura 6.11 compara el almacenamiento en memoria de variables simples y de registros (tipos definidos por el usuario) con el almacenamiento en memoria de matrices. Reservar memoria para las matrices
Visual Basic permite crear matrices de cualquier tipo de datos, incluyendo los tipos definidos por el usuario. El programa Calcular utilizaba una matriz de cadenas de caracteres ( cboEntradas.List) que era una propiedad definida del cuadro combinado. Si tú quieres crear una matriz, debes usar una declaración de variable para reservar memoria para ella. Como las otras variables, las matrices se declaran 17 9
EL LIBRO DEL VISUAL BASIC
con la palabra reservada Dim. Aquí tienes la sintaxis de una declaración estándar de matriz: { Dim | Global } nombre( maximoTamaño) [As tipo] El valor entre paréntesis ( maximoTamaño) se denomina dimensión de la matriz; le dice a Visual Basic cuánta memoria debe asignar a la matriz. La declaración crea una matriz con índices que comienzan en el 0 y que continúan hasta máximoTamaño. Por ejemplo, la declaración Dim X(3) As Integer , que declara una matriz con un valor máximoTamaño de 3, realmente crea una matriz con cuatro elementos: X(0), X(l), X(2) y X(3). El valor máximoTamaño debe ser un tipo entero, lo que significa que una matriz no puede nunca tener un índice que sea mayor de 32767. Experimentar con matrices
Las matrices son increíblemente útiles, y permiten escribir programas que son más generales y menos dependientes de los datos específicos. Para mostrar esto, vamos a usar a unas viejas amigas nuestras que ya vimos en el capítulo 3: las comadrejas copetudas alemanas.
6 Control del programa
Para evaluar tus progresos como criador de comadrejas, decides calcular la longitud media de tus comadrejas y compararla con la media nacional (que es de 22 centímetros). La expresión que calcula esta media es ( Siegmund.Longitud + Sie glinde.Longitud + Siegfried.Longitud) /3. Por supuesto, el programa que incorpore esta expresión será válido sólo para esas comadrejas específicas. Cada vez que tu población de comadrejas cambie tendrás que modificar el programa. Por tanto, lo que necesitas es una manera más general de almacenar información. En lugar de almacenar las estadísticas vitales de cada comadreja en una variable con nombre distinto, puedes modificar la descripción del tipo que contiene el nombre de la comadreja. El nuevo tipo de datos, BTFComadreja, se muestra a continuación: Type BTFComadreja Nombre As String Color As String Peso As Integer Longitud As Integer FechaNacimiento As Double ColorCopete As String LongitudCopete As Integer End Type
Ahora puedes almacenar toda la información sobre las comadrejas colectivamente en una sola variable matriz: Comadrejas. Puedes declarar la variable Comadrejas con la declaración Dim Comadrejas(20) As BTFComadreja. Como la matriz contendrá información sobre varias comadrejas (21 para ser exactos), también necesitarás declarar otra variable que contenga el número de comadrejas que tienes actualmente. Usa la declaración Dim PoblacionComadrejas A s I nteger.
Integer (entero)
Long Integer (entero largo)
Una vez que declares las variables puedes almacenar datos sobre las comadrejas, de manera muy parecida a la que usas cuando empleas variables separadas. Las declaraciones que vienen a continuación muestran cómo se pueden inicializar esos valores:
Record (registro (Tipo definido por el usuario) Entero Cadena de longitud fija Entero largo Coma flotante (doble precisión)
Matriz de 10 enteros
PoblacionComadrejas = 3 Comadrejas(0).Nombre = "Siegmund" Comadrejas(0).ColorCopete = "marrón" Comadrejas(0).Peso = 18
Figura 6.11.
La asignación de memoria para variables sencillas, registros y matrices
180
181
6 Control del programa
EL LIBRO DEL VISUAL BASIC
Comadrejas(1).Nombre = "Sieglinde" Comadrejas(1).Peso = 14
Comadrejas(2).Nombre = "Siegfried" Comadrejas(2).Peso = 8
Ahora, suponiendo que ya has almacenado toda la información sobre las comadrejas, puedes escribir un programa que calcule la longitud media de tus animalitos, independientemente del número de ellas que tengas. No es sorprendente que se parezca al código del programa Calcular: Dim Actual As Integer, Total As Integer, LongitudMedia As Single Total = 0 For Actual = 0 To PoblacionComadrejas - 1 Total = Total + Comadrejas(Actual).Longitud Next Actual LongitudMedia = Total / PoblacionComadrejas
Este código continuará siendo útil a medida que la población de comadrejas cam bie. La clave para lograr una buena programación consiste en examinar el problema para ver si puede generalizarse, y luego escribir un programa cine solucione el caso general, en lugar de escribir un programa que solucione un solo problema pero que tenga que modificarse constantemente a medida que el problema cambie. Usar bucles con matrices
Como sin duda te han sugerido los programas de este capítulo, las matrices y los bucles están estrechamente relacionados, como una mano y un guante. Operaciones como sumas, cálculo de medias y buscar máximos y mínimos, todos ellos se prestan a ser resueltos con matrices. Todas estas operaciones tienen que examinar la matriz completa. Otras operaciones, como las de búsqueda, no. Piensa en la matriz de comadrejas. Ahora que las estadísticas vitales están almacenadas de forma anónima, no puedes utilizar una variable que tenga nombre, como Siegmund para extraer los datos de una comadreja concreta. En lugar de ello, debes buscar en la matriz hasta que encuentres una comadreja cuyo elemento Nombre sea Siegmund. Por ejemplo, si quisieras obtener el peso de Si egmund, la manera más rápida de lograrlo sería algo como esto: 182
Dim W As Integer, Encontrado As Integer Encontrado = -1 ’No encontrado todavía For W = 0 To PoblacionComadrejas - 1 ’Recorrer la matriz If Comadrejas(W).Nombre = "Siegmund" Then ’Si se encuentra Siegmund Encontrado = W ’Guardar el Indice en Encontrado End If Next W ’Continuar la búsqueda Print Comadrejas(Encontrado).Peso
Por desgracia, este programa examinará todos los elementos de la matriz, incluso si Siegmund es la primera comadreja de la matriz. Este problema no es grave si la población de comadrejas es pequeña, pero la búsqueda podría consumir bastante tiempo si tuvieras miles de comadrejas. Tienes que alterar la condición del bucle de manera que finalice cuando se encuentre la comadreja. Puedes escribir este bucle de dos formas. El primer método consiste en convertir el bucle en una declaración Do While en el que la condición del bucle compruebe tanto que no se ha alcanzado el final de la matriz como que no se haya encontrado el nombre buscado: Dim W As Integer, Encontrado As Integer Encontrado = -1 ’No encontrado todavía W = 0 ’Hacer el bucle mientras no se acabe la matriz ’y mientras no se encuentre Do While (W <= PoblacionComadrejas - 1 ) And Encontrado = -1 If Comadrejas(W).Nombre = "Siegmund” Then 'Si se encuentra Siegmund Encontrado = W ’Guardar el índice en Encontrado End If W = W + 1 Loop ’Continuar la búsqueda ’Imprimir el resultado Print Comadrejas(Encontrado).Peso
Al convertir el bucle For en un bucle Do While puedes definir una condición de búsqueda más precisa. Este bucle finalizará cuando W se pase del máximo o cuando la variable Encontrado cambie de valor (lo cual sucederá sólo cuando se encuentre a Siegmund). El método alternativo consiste en mantener el bucle For, y salir de él cuando se encuentre la comadreja. Visual Basic dispone de la instrucción Exit para este propósito. 183
EL LIBRO DEL VISUAL BASIC
Dim W As Integer, Encontrado As Integer Encontrado = -1 'No encontrado todavía For W = 0 To PoblacionComadrejas - 1 ’Recorrer la matriz If Comadrejas(W).Nombre = "Siegmund" Then ’Si encuentra Siegmund Encontrado = W ’Guardar el indice en Encontrado Exit For ’Salir del bucle End If Next W ’Continuar la búsqueda Print Comadrejas(Encontrado).Peso
Cuando se alcanza la instrucción Fxit (salir), el flujo de control se transfiere a la declaración que hay detrás de Next W. Ambos métodos de programación son soluciones aceptables. La primera tiene la ventaja de indicar explícitamente las condiciones de finalización en el bucle, haciendo que el código sea más fácil de comprender. El segundo método es ligeramente más eficiente, porque el bucle no tiene que procesar la prueba adicional de la variable Encontrado cada vez que se repita el bucle. Sin embargo, la declaración Exit que finaliza el bucle, está sepultada en el cuerpo del bucle, y puede ser fácilmente pasada por alto por alguien que lea el código. Mi preferencia personal es el algo más eficiente y ligeramente menos complicado bucle For. Las tres versiones de este código contienen un problema común: la declaración Print. El código presume que se ha encontrado lo que se buscaba, incluso aunque éste podría no ser el caso. Una versión corregida sustituiría la declaración Print por el siguiente código: If Encontrado = -1 Then MsgBox "No se ha encontrado" El se Print Comadrejas(Encontrado).Peso End If
Determinar el tamaño de la matriz durante la ejecución
Cuando se escribe una instrucción D im para declarar una matriz, se está predeterminando, efectivamente, el tamaño de la matriz. Quizás se conozca exactamente el tamaño que debe tener la matriz, o quizás se sepa su valor máximo. (Por ejemplo, podrías saber perfectamente que tener más de 21 comadrejas sería un trabajo excesivo.) En tales casos, una matriz de tamaño fijo funciona muy bien. Sin em bargo, el problema surge cuando el tamaño de la matriz es desconocido. Supon, por ejemplo, que quisieras vender tu programa de control de los datos de las co184
6 Control del programa
madrejas a otros criadores de comadrejas. ¿Cómo podrías dimensionar correctamente la matriz? Podrías, simplemente, coger cualquier número arbitrariamente grande y confiar en que sea suficientemente grande. Sin embargo, te encontrarías con dos problemas si eliges este camino. Uno, gasta memoria; la declaración D im reserva memoria para toda la matriz, tanto si se usa como si no. Dos, estás asumiendo un riesgo al confiar simplemente en la buena suerte. Si le vendes tu programa a un criador que tenga más comadrejas de las que caben en el programa, el programa fallará, y tú tendrás un cliente descontento. Para solucionar este problema, Visual Basic dispone de la sentencia ReDim, la cual redimensiona una matriz. ReDim no es una declaración; es un comando que se puede ejecutar muchas veces durante el curso de un programa. Para usar R e D im debes eliminar la dimensión máximoTamaño de la declaración original de la matriz. Omitir máximoTamaño le dice a Visual Basic que cree una matriz dinámica (una cuyo tamaño puede cambiar) en lugar de una matriz de tamaño fijo. Examina este fragmento de programa, el cual no hace nada, excepto ilustrar cómo funciona ReDim: Dim Prueba( ) As Integer
’En la sección de declaraciones
’En algún procedimiento de evento For Tamaño = 10 To 50 S tep 10 ReDim Prueba(Tamaño) As Integer ’Cambiar tamaño a la matriz Prueba Next Tamaño
Como la declaración original de la matriz Prueba no tiene componente máximo Tamaño, Visual Basic la reconoce como una matriz dinámica. En algún punto se ejecutará el bucle For. En la primera vuelta del bucle, Prueba es dimensionada como una matriz de 11 elementos (con los elementos numerados del 0 al 10). En la siguiente vuelta del bucle, Prueba es redimensionada como una matriz de 21 elementos. Cuando se completa el bucle, Prueba está dimensionada como una matriz de 51 elementos. Aquí tienes la sintaxis de la declaración ReDim: ReDim [Preserve] variable(máximoTamaño) [As tipo] La sintaxis recuerda a la de la declaración D im excepto, porque puede incluirse la palabra clave Preserve (preservar) y porque el valor máximoTamaño , puede ser cualquier expresión entera. Cuando ReDim se usa sin Preserve , cualquier copia existente de la matriz es eliminada y se crea una matriz completamente nueva. Si se usa ReDim con Preserve, los valores de la matriz antigua son preservados en la nueva matriz. Sin embargo, si la dimensión de la nueva matriz es más pe 185
6 Control del programa
EL LIBRO DEL VISUAL BASIC
queña que la dimensión de la antigua, se perderán los valores con índices mayores que la nueva dimensión.
El uso de matrices de control es Además de las matrices de datos, Visual Basic permite definir matrices de objetos de control, los cuales son útiles cuando se tienen varios controles que ejecutan esencialmente la misma acción. Las matrices de control comparten los mismos procedimientos de eventos. Por ejemplo, si tienes una matriz de tres botones de comando, se llamará al mismo procedimiento Click independientemente del botón sobre el que se haya hecho clic. Visual Basic permite diferenciar entre los elementos de una matriz de control pasando un valor índice al procedimiento. Veamos cómo funciona esto. Crea dos botones de comando nuevos en un formulario vacío. Establece la propiedad Name de ambos botones como btnTest. Cuando trates de establecer el valor de la propiedad Name del segundo botón, Visual Basic presentará un cuadro de diálogo que te preguntará si estás tratando de crear una matriz de control:
El primer botón tiene un valor índice de 0, y el valor índice del segundo es 1. Si quieres darle a los botones valores especiales de índice, puedes cambiar la propiedad Index en la fase de diseño. Esta propiedad no se puede modificar mientras se está ejecutando el programa. Los elementos de la matriz de control se identifican por el nombre de la matriz, seguido por el valor índice entre paréntesis. Por ejemplo, este procedimiento Click establece los títulos de los botones de comando de tu formulario como la hora a la que se hizo clic por última vez sobre ellos:
Haz clic en Sí en el cuadro de diálogo. Ahora abre la ventana de código haciendo doble clic en cualquiera de los dos botones de comando. Verás que se ha añadido un parámetro Index (índice) a cada procedimiento de evento, como en el ejemplo que se muestra aquí: Sub btnTest_Click (Index As Integer) End Sub
Este procedimiento de evento es llamado independientemente del botón sobre el que se haga clic; la propiedad Index del botón es pasada, como un parámetro entero, para indicar el botón sobre el que se hizo clic. Cuando se crea una matriz de control, Visual Basic le asignará un valor índice a cada objeto. Usa la ventana Properties para examinar la propiedad Index de los dos botones de comando que has creado: 18 6
Sub btnTest_Click (Index As Integer) btnText(Index).Caption = Format(Now, "hh:mm:ss") End Sub
Las matrices de control son especialmente útiles con botones de opción. Puedes definir todos los botones dentro de un solo marco como matriz de control y usar la propiedad Index o la propiedad Caption en una declaración de asignación, por ejemplo, podrías usar el procedimiento Click con la matriz de control de botones de opción que se muestra en la figura 6.12: Sub btnTest_Click (Index As Integer) MiComadreja.Color = optColor(Index).Caption End Sub
Un atajo muy útil para crear una matriz de control consiste en crear el primer ob jeto de control y establecer sus propiedades. Luego puedes copiarlo y pegarlo tantas veces como sea necesario para crear controles adicionales que tengan el mismo tamaño y propiedades. 18 7
EL LIBRO DEL VISUAL BASIC
7 Figura 6.12.
Una matriz de control de botones de opción
El uso de procedimientos y funciones La mayoría de los procedimientos que has escrito en los capítulos anteriores han sido procedimientos de eventos —o sea, fueron diseñados, especialmente, para responder a eventos concretos producidos por el usuario o por el sistema. Sin embargo, como podrás recordar, no todos los procedimientos son procedimientos de eventos. Este capítulo te enseñará a escribir y a usar procedimientos generales (incluyendo tanto a los procedimientos sub como a los procedimientos de función) que llevan a cabo una tarea particular cuando son explícitamente llamados por el código del programa (en lugar de ser provocados por un evento). También estudia el uso de los parámetros, los cuales permiten a un programa pasar valores específicos a los procedimientos y funciones a los que llama. Como verás, se pueden pasar como parámetros incluso los objetos de Visual Basic. Finalmente, este capítulo trata algunos procedimientos de evento avanzados, como aquellos que permiten seguir el movimiento del ratón e implementar posibilidades de arrastrar y soltar.
Procedimientos generales Las primeras aplicaciones que escribiste tenían un control de flujo lineal: cuando se haya ejecutado una instrucción, se ejecutará la que venga secuencialmente detrás. En el capítulo anterior, comenzaste a trabajar con ramificaciones condicionales (declaraciones If ) y bucles que modifican el orden en que se ejecutan las declaraciones. La figura 7.1 muestra un diagrama de estas tres clases de flujo. Al igual que los bucles, los procedimientos permiten que un programa ejecute un conjunto de instrucciones más de una vez. Sin embargo, en lugar de ejecutar re 188
189
EL LIBRO DEL VISUAL BASIC
7 El uso de procedimientos y funciones
MsgBox "Me aburro" End If End Sub
Dado el procedimiento que acabas de escribir, los dos fragmentos siguientes de programas son equivalentes: Lloriquear MsgBox "Odio esto" Lloriquear
Respuesta = InputBox("¿Hemos llegado ya?") If Respuesta = "No" Then MsgBox "Me aburro" End If MsgBox "Odio esto" Respuesta = InputBox("¿Hemos llegado ya?") If Respuesta = "No" Then MsgBox "Me aburro" End If
Figura 7.1.
El control del flujo en los programas
petidamente un conjunto de declaraciones, los procedimientos permiten incluir las declaraciones en un grupo que se pueden ejecutar cada vez que se desee. Por ejemplo, un procedimiento de evento de Visual Basic se ejecutará cuando el usuario realice una acción; un procedimiento general se ejecutará cuando sea llamado por el código de la aplicación. Piensa en un programa que imite las acciones de un niño pequeño que viaja en coche. Este código ilustra el comportamiento conocido como lloriqueo: Respuesta = InputBox("¿Hemos llegado ya?") If Respuesta = "No” Then MsgBox "Me aburro" End If
En un programa que simula el comportamiento de un niño sería previsible tener que duplicar esas líneas varias veces. En lugar de crear varias copias de las declaraciones, podrías reunirlas todas en un procedimiento y ejecutarlo, simplemente, usando el nombre del procedimiento. Añade una declaración de procedimiento y dale un nombre descriptivo: Sub LLoriqueo ( ) Dim Respuesta As String Respuesta = InputBox("¿Hemos llegado ya?") If Respuesta = "No" Then
190
Flujo de control
Los procedimientos afectan, obviamente, al flujo de control. Cuando Visual Basic encuentra un nombre de procedimiento, "memoriza" la posición actual del programa y significa que se va a ejecutar el procedimiento. Cuando termina el procedimiento vuelve a la posición original en el programa y continúa la ejecución desde allí. A este proceso se le denomina llamada a un procedimiento porque el programa llama al nombre del procedimiento. Como Visual Basic puede seguirle la pista a cientos de niveles de llamadas, un procedimiento llamado por un programa puede él mismo contener una llamada a otro procedimiento, y así sucesivamente, como se ilustra en la figura 7.2. Parámetros
Supongamos que estás escribiendo un programa que necesita, en algún momento, imprimir los números enteros del 1 al 10. En otro punto, el mismo programa necesita imprimir los números del 1 al 17. El código de las dos rutinas se compara aquí: Primera rutina
Segunda rutina
For Contador = 1 To 10 Print Contador Next Contador
For Contador = 1 To 17 Print Contador Next Contador
Como las rutinas son muy similares, sería bastante fácil generalizarlas —es decir, hacer que el mismo código sirva para ambos propósitos. La única diferencia entre 191
EL LIBRO DEL VISUAL BASIC
7 El uso de procedimientos y funciones
inicializadas por el código que llama al procedimiento. Las rutinas que llaman al procedimiento inicializan esas variables especificando un conjunto de valores detrás del nombre del procedimiento. Aquí tienes la sintaxis de una llamada a un procedimiento de ese tipo: nombre [ v a l o r
[
,
v a l o r ] . . . ]
Date cuenta de las comas que separan a los argumentos. Las rutinas de llamada no necesitan conocer los nombres de los parámetros porque los argumentos se asignan, en orden, a los parámetros declarados en el procedimiento. En la declaración del procedimiento, los parámetros se declaran dentro de los paréntesis que van detrás del nombre del procedimiento. Visual Basic permite que los procedimientos tengan más de un parámetro. Aquí tienes la sintaxis de una declaración de un procedimiento que incluye parámetros:
Figura 7.2.
Llamadas a procedimientos
las dos es el valor final del bucle For, el cual puedes sustituir por una variable. Entonces podrías usar un solo procedimiento y llamarlo después de ajustar la variable con el valor apropiado, como se muestra a continuación. (Suponemos que la declaración Dim FinalContador As Integer aparece en la sección de declaraciones generales del programa.) Primera llamada
Segunda llamada
Procedimiento
FinalContador = 10 FinalContador = 17 Sub Impr imirBucle ( ) ImprimirBucle ( ) ImprimirBucle ( ) Dim Contador As Integer For Contador = 1 To FinalContador Print Contador Next Contador End Sub
Como puedes ver, la combinación de variables y llamadas a procedimientos permite solucionar problemas de índole general y proporciona unas herramientas de programación excelentes. Sin embargo, con la implementación mostrada aquí surgen algunos problemas prácticos. En concreto, debes declarar variables globales o de nivel de módulo para la comunicación entre el programa principal y el procedimiento al que llama; y debes recordar los nombres, utilizando nombres de variables diferentes para cada procedimiento con el fin de evitar que un procedimiento llame al otro y reescriba su propia variable. Visual Basic soluciona estos problemas permitiendo que todos los procedimientos tengan parámetros, variables que son locales a un procedimiento pero que son 192
Sub nombre ([parámetro [As tipo[, parámetro [As tipo]...] End Sub Mira el ejemplo anterior reconstruido con parámetros: Primera
Segunda
llamada
llamada
Procedimiento
ImprimirBucle 10 ImprimírBucle 17 Sub ImprimirBucle (FinalContador AsInteger) Dim Contador As Integer For Contador = 1 To FinalContador Print Contador Next Contador End Sub
Para ilustrar el uso de varios parámetros, podrías cambiar el procedimiento ImprimirBucle para que acepte tanto un valor de comienzo como un valor de finalización, como se muestra aquí: Primera llamada
Segunda llamada
Procedimiento
ImprimirBucle 1, 10 ImprimirBucle 1, 17 Sub ImprimirBucle (InicioContador As Integer, FinalContador As Integer) Dim Contador As Integer For Contador = InicioContador To Final Contador Print Contador Next Contador End Sub
193
EL LIBRO DEL VISUAL BASIC
Procedimientos de función En los ejemplos anteriores puedes haber notado que las líneas de comunicación discurren en una sola dirección cuando se trata de una llamada normal a un procedimiento —es decir, la rutina que llama pasa valores al procedimiento, el cual lleva a cabo algunas acciones, pero no devuelve ninguna información a la rutina que lo llamó. Sin embargo, se puede usar un tipo especial de procedimientos denominados procedimientos de funci ón (o, simplemente, función) que devuelva un valor al que llama, de manera muy similar a lo que hacen las funciones internas de Visual Basic. Cuando se declara una función se debe declarar el tipo de valor que devolverá, así como los parámetros que requiera, como muestra la sintaxis que viene a continuación: Function nombre ([parámetro [As tipo] [, parámetro [As tipo]...) [As tipo] [ declaraciones] nombre = expresión [ declaraciones] End Function Puedes ver dos diferencias que distinguen a un procedimiento de función de un procedimiento sub. Un procedimiento de función aparece entre las declaraciones Function y End Function , mientras que un procedimiento sub requiere Sub y End Sub. Y, como muestra la definición de la sintaxis, en algún lugar del cuerpo de la función debes asignar un valor (expresión) al nombre de la función. Ese es el valor que será devuelto a la rutina que llamó a la función. Por ejemplo, esta función devuelve el mayor de dos números enteros: Function MaxEntero (X As Integer, Y As Integer) As Integer If X > Y Then MaxEntero = X Else MaxEntero = Y End If End Function
La sintaxis para llamar a una función es ligeramente diferente de la que se usa para llamar a un procedimiento. Como una función devuelve un valor, puede ser llamada desde cualquier posición en que pueda ir una expresión. Los parámetros de la función aparecen entre paréntesis para separarlos de otras partes de la expresión. Aquí tienes algunas declaraciones que llaman a la función M axEntero: 194
7 El uso de procedimientos y funciones
Print MaxEntero(7, 14) ElDobleDeGrande = MaxEntero(3, 4) * 2 If MaxEntero(Primer Intento, SegundoIntento) > 20 Then
Cuando se llama a una función que no necesita parámetros, simplemente se usa el nombre de la función, como si fuera una variable. La función interna Now de Visual Basic (que devuelve la fecha y hora actuales) es un ejemplo de una función que no requiere parámetros.
Escribir procedimientos La explicación que viene a continuación utiliza el término procedimiento para hacer referencia a la idea general de una rutina que puede ser llamada. Cuando sea necesario, se especificarán los términos procedimiento de funci ón (o simplemente funci ón) o procedimiento sub para lograr una mayor claridad.
A unque Visual Basi c permite procedimientos y funciones defini dos por el usuario, no permite métodos definidos por el usuario; sólo es tán disponibles los métodos construidos internamente.
Nota:
Para crear en Visual Basic un procedimiento que pueda ser llamado debes abrir una ventana de código. Selecciona el menú New Procedure (procedimiento nuevo) del menú View. En el cuadro de diálogo New Procedure escribe el nombre del nuevo procedimiento, elige Sub o Function haciendo clic en uno de los botones de opciones, y haz clic en el botón OK. Entonces Visual Basic creará un nuevo elemento en el cuadro Procedure de la ventana de código y suministrará la declaración End apropiada para el procedimiento. Vamos a escribir un programa sencillo llamado Conversión de temperaturas que realizará una simple conversión entre temperaturas Celsius y Fahrenheit. Abre un proyecto nuevo y pon una barra de desplazamiento vertical, seis etiquetas y dos cuadros de texto en el formulario, organizando los elementos como se muestra en la figura 7.3. Establece las propiedades de los objetos con los ajustes que se muestran en la figura 7.4. El programa permitirá que el usuario ajuste la barra de desplazamiento a cualquier temperatura entre los puntos 40 y 212 de la escala Fahrenheit o las correspondientes temperaturas (40 y 100) de la escala Celsius. La aplicación mostrará entonces el valor de la temperatura elegida tanto en las escalas Fahrenheit como Celsius. Oberva que el ajuste la propiedad Min de la barra de desplazamiento es mayor que el ajuste Max. Al establecer las propiedades de esta forma se obliga a que la barra de desplazamiento use los números más grandes en la parte de arri 195
EL LIBRO DEL VISUAL BASIC
7 El uso de procedimientos y funciones
Figura 7.4. continuación
Objeto
Figura 7.3.
El diseño inicial del formulario para la aplicación Conversión de temperaturas
ba de su rango, en lugar de mostrar los más pequeños arriba, que es lo que nor malmente hace cuando el ajuste de Min es menor que el de Max.
Objeto
Form1
Propiedad
Ajuste
BorderStyle Caption Name
3 - Fixed Double Conversión de temperaturas Temp
LargeChange Max Min Name SmallChange
10 - 40 100 vscTermometro 1
Label1
Alignment Caption
2 - Center Fahrenheit
Label2
Alignment Caption
2 - Center Celsius
Label3
Alignment Caption
1 - Right Justify 212
Label4
Alignment Caption
1 - Right Justify -40
VScroll1
Figura 7.4.
El ajuste de las propiedades para la aplicación Conversión de temperaturas
196
Propiedad
Ajuste
Label5
Alignment Caption
0 - Left Justify 100
Labe16
Alignment Caption
0 - Left Justify - 40
Text1
Name Text
txtGradosF [ninguno]
Text2
Name Text
txtGradosC [ninguno]
Para mayor simplicidad, el programa siempre "piensa" en grados Celsius y efectúa una conversión para obtener la temperatura Fahrenheit. Primero debes escribir la función que devuelva una temperatura Fahrenheit cuando el programa suministre una temperatura Celsius. Abre la ventana de código del formulario. Selecciona el comando New Procedure del menú View. En el cuadro de diálogo escribe CaF, elige el botón de opción Function y haz clic en OK. Luego edita la nueva función como sigue (asegúrate de añadir el parámetro y el tipo a la primera l ínea): Function CaF (TempC As Integer) As Integer C aF = C In t( Te mp C * 9 / 5 + 3 2) End Function
La función CaF utiliza la fórmula de conversión estándar. Acepta una temperatura Celsius como parámetro y devuelve la temperatura equivalente medida en la es cala Fahrenheit. Para simplificar la salida y el uso de las barras de desplazamien to, los valores se restringen a valores enteros. (La función CInt convierte un valor en coma flotante en un entero redondeándolo.) Ahora puedes escribir el código que lee el valor de la barra de desplazamiento y muestra los valores de la temperatura. Introduce el siguiente procedimiento sub debajo de la función: Sub MostrarTemps () Dim TempC As Integer
(continúa)
TempC = CInt(vscTermometro.Value) txtGradosC.Text = Str$(TempC) txtGradosF.Text = Str$(CaF(TempC)) End Sub
197
EL LIBRO DEL VISUAL BASIC
Después de que introduzcas la primera línea (la declaración Sub), observa que Visual Basic añade el nombre del procedimiento al cuadro Procedure y que añade la declaración End Sub al código que estás escribiendo. Como puedes ver, es posible crear un procedimiento nuevo seleccionando el comando New Procedure del menú View o introduciendo la declaración Sub o Function del nuevo procedimiento en cualquier parte de la ventana de código. El código del procedimiento MostrarTemps lee el valor de la barra de desplazamiento, vscTermometro. Value , y lo almacena en la variable TempC. Este valor se muestra en el cuadro de texto txtGradosC. Luego se establece el valor del cuadro de texto txtGradosF con el resultado generado por la función CaF.
7 El uso d e proc edimientos y funcione s
Pensar por delante
Pudiera parecer como si hubiéramos realizado cierto trabajo innecesario al escri bir el código de la aplicación Conversión de temperaturas. Después de todo, como cada procedimiento se usa sólo una vez, ¿por qué no hacer todos los cálculos en línea y centralizar todo el código en el procedimiento del evento Change de la barra de desplazamiento? El código del programa resultante sería algo así: Sub vscTermometro_Change ( ) Dim TempC As Integer TempC = CInt(vscTermometro.Value) txtGradosC.Text = Str$(TempC) txtGradosF.Text = Str$(CaF(TempC)) End Sub
Finalmente, selecciona vscTermometro (la barra de desplazamiento) del cuadro Object de la ventana de código y edita los procedimientos Change y Scroll como se muestra aquí: Sub vscTermometro_Change ( ) MostrarTemps End Sub Sub vscTermometro_Scroll ( ) MostrarTemps End Sub
Ahora, cada vez que el usuario cambie la barra de desplazamiento, el procedimiento MostrarTemps llevará a cabo su trabajo. Ejecuta la aplicación para ver si funciona de la manera que esperabas. El resultado debe asemejarse al que se muestra en la figura 7.5.
De hecho, este programa es perfectamente aceptable y funcionaría igual de bien que la primera versión. Pero el programa Conversión de temperaturas original es preferible por las siguientes razones: ■
Sustituye en el programa las fórmulas por funciones con nombre. Los nom bres añaden claridad y ayudan a explicar lo que está sucediendo en el programa.
■
Contiene rutinas generales que se pueden usar de nuevo. Copiar la función CaF a otro programa sería trivial.
■
Los procedimientos son partes que pueden ser manipuladas fácilmente si se decide alterar el programa.
A modo de ilustración piensa en una mejora del programa. En la versión actual debes usar la barra de desplazamiento para ajustar una temperatura concreta. Pero podría ser útil permitir al usuario que introdujese el valor de la temperatura directamente, y a continuación hacer que el programa calcule la conversión requerida. Mediante los bloques que ya has creado puedes conseguir que esta tarea sea relativamente simple. Si hubieras escrito el programa como un sólo bloque, un cambio de este tipo requeriría duplicar o reescribir el código. Generalizar
Figura 7.5.
Ejecución de la aplicación Conversión de temperaturas
198
Las mejores herramientas son las que se pueden utilizar para más de un trabajo. A menudo se pueden convertir en una rutina general unas pocas líneas de código específico que sea útil en un solo contexto. Piensa en el programa que escribiste en el capítulo 6 para buscar una comadreja en particular por su nombre; en la fi 199
7 El uso d e proc edimientos y funcione s EL LIBRO DEL VISUAL BASIC
gura 7.6 aparece una versión completa. La figura 7.7 muestra una versión que usa un procedimiento general derivado del código original. Esta segunda versión proporciona una rutina que buscará cualquier comadreja por su nombre y que, seguramente, será útil muchas veces en el programa.
Cómo funcionan los p arámetros Hasta ahora has utilizado los parámetros simplemente para pasar argumentos a los procedimientos. Pero los parámetros son en realidad mucho más flexibles que eso. Veamos los dos mecanismos que están disponibles en Visual Basic para pasar parámetros. Pasar por referencia
Cuando presentamos los parámetros por primera vez los describimos como varia bles locales. En realidad, ese no es siempre el caso. Piensa en el procedimiento I ncremento , el cual suma 1 al valor del parámetro X: Sub Incremento (X As Integer) X = X + 1 End Sub
F u n c t i o n BuscarComadreja (SuNombre A s S t r i n g ) A s I n t e g e r Dim W A s Integer, Encontrado A s I n t e g e r Encontrado = -1 For W = 0 To PoblacionComadrejas - 1 If Comadrejas(W).Nombre = "Siegmund" Then Encontrado = W Exit For End If Next W BuscarComadreja = Encontrado End Function W = BuscarComadreja("Siegmund") If W = -1 Then MsgBox "No se ha encontrado" El se Print Comadreja(W).Peso End If
Figura 7.7.
Código con un procedimiento general que puede encontrar cualquier comadreja
Dim W As Integer, Encontrado As Integer Encontrado = -1 For W = 0 To PoblacionComadrejas - 1 If Comadrejas(W).Nombre = "Siegmund" Then Encontrado = W Exit For End If Next W If Encontrado = -1 Then MsgBox "No se ha encontrado" Else Print Comadreja(Encontrado).Peso End If
Figura 7.6.
El código de un programa que busca a una comadreja por su nombre
200
Si X fuera una variable local, este procedimiento no tendría ninguna utilidad. El valor del parámetro de la rutina que llama sería asignado a X , y el procedimiento incrementaría el valor y luego terminaría, destruyendo, efectivamente, la variable local. En realidad, X es una referencia del valor original. En el código que se muestra aquí, tras llamar al procedimiento Incremento se imprimiría el valor 4: Dim A As Integer A = 3 Incremento A Print A
Como el parámetro X es una referencia, no se asignará memoria para almacenar el valor. En lugar de ello, Visual Basic simplemente almacena la información de que X es una referencia. La utilización de la referencia permite a Visual Basic operar de manera muy eficiente. Esta eficiencia no es evidente en el caso de las variables integer, pero mira el procedimiento A l_lado que imprime su parámetro de cadena encerrado entre paréntesis: 201
7 El uso de procedimientos y funciones
EL LIBRO DEL VISUAL BASIC
Sub Al_lado (Str As String) Print "("; Print Str; Print ")" End Sub
Si los parámetros fueran realmente variables locales, Visual Basic tendría que asignar espacio para cada una de las cadenas pasadas y copiar la cadena en cada llamada. Como las cadenas pueden ser de miles de caracteres de largo, implica mucho menos trabajo crear una referencia al valor original. Pasar por valor
También puedes hacer que los parámetros funcionen de la otra manera —es decir, exactamente igual que las variables locales. Si comienzas la declaración de parámetros con la palabra clave ByVal (por valor), Visual Basic asignará espacio local para el parámetro y copiará el valor del argumento en el parámetro. Aqui tienes un ejemplo de una declaración de ese tipo: Sub Incremento (By Val X As Integer) X = X + 1 End Sub
Reciclar el código
Hoy estás escribiendo programas que almacenan datos de comadrejas copetudas alemanas. Mañana pueden ser mugwumps. Y cuando estés escri biendo tu programa para los mugwumps sería práctico poder decir, "oh, yo escribí algo igual que esto hace dos semanas". Si escribes rutinas de propósito general siempre podrás recuperar el código de la programación anterior y usarlo en la nueva. El código ya está depurado, tienes que hacer menos trabajo y el proyecto se termina antes. ¿Qué más puedes pedir? Aunque es bueno reutilizar el código que tú mismo has desarrollado, normalmente, es poco ético (y a menudo ilegal) copiar directamente el código que haya escrito otro. Sin embargo, eres libre de copiar el código de los programas que vienen de ejemplo con Visual Basic; Microsoft ha dado permiso para copiar el código. (La autorización aparece en la parte superior del módulo principal de cada aplicación.)
202
Pasar por referencia es, generalmente, más eficiente, pero pasar por valor te proporciona una variable local, que necesitarás algunas veces en tus programas. Por ejemplo, veamos una función que calcula x elevado a y, o x y . Este cálculo usa la multiplicación repetidamente —x 3 ,por ejemplo, es igual a x * x * x). Para una mayor simplicidad, la función ignorará los exponentes negativos. El parámetro Y especifica el número de multiplicaciones que hay que realizar. El valor de Y es "decrementado" después de cada multiplicación, y el cálculo se completa cuando Y llega a 0. Function ElevadoA (X As Single, ByVal Y As Integer) As Single Dim Resultado As Single Resultado = 1 Do While Y > 0 Resultado = Resultado * X Y = Y - 1 Loop ElevadoA = Resultado End Function
Como quieres modificar Y localmente pero no quieres cambiar el valor de la variable que se pasó, debes declarar Y con la palabra clave ByVal. Examina el siguiente fragmento de código, el cual llama a la función ElevadoA: 'Aproximar e^n usando la serie de Taylor Resultado = 1 For Aproximación = 1 To 10 Resultado = Resultado + ElevadoA(N, Aproximación) / Factorial(Aproximacion) Next Aproximacion
El programador espera que esta rutina haga 10 bucles mientras realiza el cálculo. Sin embargo, si la función ElevadoA que está llamando no utilizase la palabra clave ByVal , esta rutina haría un bucle infinito. Después de que la rutina llamase a ElevadoA por primera vez, Aproximacion sería puesta a 0 (porque la variable local Y sería una referencia de Aproximacion). La función Factorial sería llamada con un valor incorrecto, y luego la declaración For incrementaría Aproximacion en 1 y se repetiría el bucle de nuevo. Como ElevadoA continuaría poniendo Apro ximacion a 0, el bucle For no se detendría nunca. Una buena regla de seguridad consiste en que cualquier declaración de parámetros de los tipos integer, long o single debe ser una declaración ByVal (es decir, el parámetro debe pasarse como un valor) a no ser que la rutina que llama espe 203
EL LIBRO DEL VISUAL BASIC
re explícitamente que el procedimiento modifique el valor que se pasa. Por el contrario, las cadenas y las matrices deben pasarse por referencia para obtener una mayor eficiencia. Los tipos definidos por el usuario (como BTFComadreja) y los controles sólo pueden pasarse por referencia en Visual Basic. En el caso de los otros tipos de datos (double, currency y variant), la decisión no es tan fácil. La práctica de la buena programación dicta que estos parámetros se pasen por valor porque será menos probable que se modifique su valor inadvertidamente. Pero es más eficiente pasar estos parámetros por referencia. Mi consejo es asegurar primero los buenos principios de la ingeniería: pasar todas las variables (excepto cadenas, matrices y tipos definidos por el usuario) inicialmente por valor. Después de que hayas terminado el programa y lo hayas ejecutado correctamente, puedes investigar las maneras de lograr que sea más rápido. Entonces, si el programa opera incorrectamente después de quitar algunas de las palabras clave ByVal, también sabrás dónde buscar los problemas. Pasar matrices como p arámetros
Se puede declarar un parámetro matriz igual que cualquier otro, excepto que se omite el tamaño de la matriz en la declaración. Por ejemplo, esta función calcula la media de una matriz de valores con precisión doble: Function MediaD (Dmatriz( ) As Double, ByVal Delementos As Integer) As Double Dim Total As Double, Ix As Integer Total = 0 For Ix = 0 To Delementos - 1 Total = Total + Dmatriz(Ix) Next Ix If Delementos = 0 Then MediaD = 0 Else MediaD = Total / Delementos End If End Function
El parámetro Dmatriz se declara como una matriz del tipo doble, pero su tamaño no se declara. Este código es otro ejemplo de una solución generalizada. Como el tamaño de la matriz no se declara, la misma función puede ser llamada con argumentos que sean matrices de cualquier tamaño (en la medida en que los elementos de las matrices sea del tipo doble). 204
7 El uso de procedimientos y funciones
Para pasar una matriz como argumento a un procedimiento, simplemente se usa el nombre de la matriz seguido por unos paréntesis vacíos. Este fragmento de código muestra cómo se puede usar el procedimiento MediaD: Dim MisDatos(100) As Double, ElementosLeidos As Integer ElementosLeidos = CargarDatos(MisDatos( ), 100) Print "Valor medio de los datos:"; MediaD(MisDatos( ), ElementosLeidos)
MisDatos se declara como una matriz de dimensión 100. Se llama al procedimiento CargarDatos (que no se muestra aquí), y MisDatos se pasa como parámetro, junto con el tamaño máximo de la matriz. Presumiblemente, la rutina CargarDatos rellena tantos datos de la matriz como sea posible. Luego el programa imprime la media. La llamada a MediaD pasa la matriz y el número de elementos que se leyeron con CargarDatos. Desde luego, cuando sea necesario, también se pueden pasar elementos individuales de una matriz. Simplemente, indica el índice en la matriz del elemento específico que quieres pasar, como en esta línea de código: Print "La raíz cuadrada del elemento tres es"; sqr(MisDatos(3))
Puedes modificar la aplicación Calcular del capítulo 6 para que use una función, como se muestra en la figura 7.8. Cada vez que hagas clic en el botón Media el programa redimensiona la matriz dinámica ListaDeValores para que se adapte al número de elementos del cuadro de lista. Como el cuadro de lista contiene una matriz de cadenas en lugar de números, cada elemento debe ser convertido a medida que se copia en ListaDeValores. El programa pasa luego la matriz entera a la función MediaD. Este programa modificado es un poco más largo que la aplicación original. Pero has creado una nueva herramienta —la función MediaD— que podrás utilizar una y otra vez. Por ejemplo, si quieres ampliar el programa Calcular para que gestione más de una cuenta, puedes llamar a la función MediaD para cada cuenta, en lugar de tener que escribir un bucle separado para cada una de ellas. Si necesitas escribir un programa que calcule el volumen medio de las precipitaciones de lluvia, puedes cargar el programa Calcular, copiar la función MediaD y pegarla en tu nuevo programa.
As ig nac ió n l oc al Estás familiarizado con las variables locales desde que hablamos sobre el ámbito en el capítulo 3. Ahora que estás trabajando con parámetros, que son similares a 205
7 El uso de proc edimientos y funcione s
EL LIBRO DEL VISUAL BASIC
las variables locales, sería interesante echar una mirada a la manera en que Visual Basic gestiona la memoria usada por las variables locales.
a procedimientos distintos. Los ordenadores modernos ejecutan esta asignación y liberación temporal de memoria de manera muy eficiente.
Cuando se arranca un programa, Visual Basic sabe cuántas variables globales existen y asigna memoria para ellas. Pero no sabe cuántas variables locales existen e, incluso, no sabe si todos los procedimientos del programa serán llamados. Las variables locales y los parámetros se crean cuando se llama al procedimiento en el que están contenidos, y luego serán destruidos cuando el procedimiento finalice. Si se llama de nuevo al procedimiento, las variables se vuelven a crear. Este procedimiento no sólo retrasa la asignación de memoria hasta que se necesita sino que permite que la memoria sea reutilizada por variables que pertenecen
Sin embargo, algunas veces puede que no quieras perder el valor almacenado en una variable local una vez que el procedimiento que contiene a la variable finaliza. Podrías declarar una variable de nivel de módulo o una variable global, pero esta solución no es deseable si la variable la usa un solo procedimiento.
Function MediaD (Dmatriz( ) As Double, ByVal Delementos As Integer) As Double Dim Total As Double, Ix As Integer Total = 0 'Suma de todos los elementos For Ix = 0 To Delementos - 1 Total = Total + Dmatriz(Ix) 'Calcular la suma Next Ix If Delementos = 0 Then MediaD = 0 Else MediaD = Total / Delementos 'Calcular y devolver la media End If End Function Sub btnMedia_Click ( ) Dim I As Integer ReDim ListaDeValores(cboEntradas.ListCount - 1) For I = 0 To cboEntradas.ListCount - 1 ListaDeValores(I) = Val(cboEntradas.List(I)) Next I lblMedia.Caption = Str$(MediaD(ListaDeValores( ), cboEntradas.ListCount)) End Sub
Figura 7.8. Una modificación de la aplicación Calcular 206
Visual Basic dispone de la palabra clave Static (estática) para solucionar el pro blema. Si utilizas Static en lugar de D im en el interior de un procedimiento, las variables así declaradas tendrán un ámbito local, y serán visibles sólo para ese procedimiento; pero serán permanentes, como si estuviesen declaradas a nivel de módulo. Visual Basic inicializa todas las variables Static a 0, lo que las hace muy útiles para situaciones como la siguiente: Sub Command1_Click ( ) Static Contador As Integer Contador = Contador + 1 MsgBox "Este botón se ha pulsado" + Str$(Contador) + "veces." End Sub
Abre un formulario nuevo, añade un solo botón de comando y prueba este programa. Después, sustituye la palabra clave Static por D im para que veas que el programa no trabaja con una variable puramente local.
Objetos como p arámetros Los procedimientos que has escrito hasta ahora han pasado valores numéricos, matrices y cadenas como parámetros. Visual Basic también permite pasar controles y formularios. La sintaxis es similar: simplemente, hay que utilizar las palabras clave Control o Form en lugar de Str ing, I nteger ; etc., en la declaración del procedimiento. Esta posibilidad aumenta la capacidad para escribir código de propósito general. Por ejemplo, supon que estás escribiendo una aplicación que tiene varios botones en la pantalla. En diversos puntos de la aplicación quieres dirigir la atención a un botón concreto mediante la técnica de poner en cursiva su título y de poner el color del fondo en rojo. El siguiente procedimiento hace justamente eso: Sub Atencion (Btn As Control) Btn.FontItalic = True Btn.BackColor = RED 'RED (rojo) está definido en CONSTANT.TXT End Sub
207
EL LIBRO DEL VISUAL BASIC
Los objetos se pasan como parámetros usando sus nombres. Podrías pasar un bo tón que se llamase btnSiguiente a este procedimiento mediante la declaración
Atencion btnSigniente.
De manera similar, puedes declarar que un formulario sea un parámetro. Puedes establecer o examinar las propiedades del formulario y llamar a sus métodos. El formulario se pasa usando su nombre, o también puedes utilizar la variable inter na Me( yo), que es el formulario activo en ese momento.
La aplicación Escapar Construyamos un programa llamado Escapar que le gaste una broma al usuario. Emitirá un mensaje de error, como si hubiera fallado al arrancar. El usuario verá un cuadro de diálogo con dos botones de comando, Cancelar y Reintentar. Sin embargo, lo que sucederá cuando el usuario pulse uno de estos botones será bastante inusual. El botón se "escapará" rápidamente a algún punto aleatorio del formulario y el usuario nunca será capaz de cancelar el programa simplemente haciendo clic en los botones. La aplicación muestra la manera de pasar objetos como parámetros y el modo de usar el método Move (mover) —un método que se puede implementar para la mayoría de los controles de Visual Basic. Todos los botones de comando deben tener el mismo comportamiento. En cierta medida, te puedes asegurar de que esto sea así llamando a un procedimiento co mún. Pero una de las acciones del procedimiento moverá al botón a una nueva ubicación. Esta acción significa que hay que llamar al método Move del botón, lo cual requiere que se pase el botón como parámetro. Crea un proyecto nuevo y organiza en el formulario dos etiquetas, dos botones de comando y un control imagen, como se muestra en la figura 7.9. La figura 7.10 muestra los ajustes adecuados de las propiedades.
7 El uso de procedimientos y funciones
Objeto
Propiedad
Ajuste
Form1
Caption Name
Error Escapar
Label1
Caption FontSize
Fallo de inicialización: 12
Label 2
Caption
Error de memoria en un chip de RAM - el tercero por la izquierda
Image1
Picture
TRFFC14.ICO
Command1
Caption
Cancelar
Command2
Caption
Reintentar
Figura 7.10.
El ajuste de las propiedades para la aplicación Escapar
La figura 7.11 contiene el código del programa para la aplicación Escapar, mien tras que la figura 7.12 muestra el aspecto que tendrá la aplicación cuando el usuario la ejecute. El procedimiento Saltar usado en esta aplicación puede ajustar la posición no sólo de los botones de comando sino de casi cualquier tipo de control que sea pasado como parámetro, ya que la mayoría de los controles poseen un método Move. Sin embargo, algunas veces puede que quieras ejecutar ciertas clases de procesos que sean propios de ciertas clases de objetos. Visual Basic dispone de la declaración If TypeOf (si el tipo de) para determinar el tipo del parámetro control. Funciona de la misma manera que una declaración If convencional; sólo es dife rente la sintaxis de la primera línea: If TypeOf objeto Is tipoDeObjeto Then Si quisieras que el procedimiento Saltar distinguiese los botones de opciones de los otros tipos de controles, la primera línea de la declaración If TypeOf sería como ésta: If TypeOf Ctl Is OptionButton Then
Procedimientos de evento avanzados Figura 7.9.
El diseño inicial del formulario para la aplicación Escapar 208
Este apartado estudia algunos procedimientos de eventos de Visual Basic que son más complicados que los simples Click y DblClick. Estas técnicas te permitirán
209
EL LIBRO DEL VISUAL BASIC
7 El uso d e proc edimientos y funcione s
construir aplicaciones que tengan una gestión del teclado y del ratón más sofisticada e implementar una técnica gráfica denominada arrastrar y soltar. Eventos del ratón
Nuestros ejemplos anteriores sólo le prestaban atención al ratón cuando era utilizado para hacer clic sobre un objeto. Todo lo que tenías que hacer entonces era crear el código para un procedimiento Click o DblClick. Pero ciertos tipos de aplicaciones necesitan vigilar las actividades del ratón mucho más de cerca. Por ejemplo, un programa de dibujo necesita saber la posición del ratón cuando se está arrastrando un gráfico o creando una imagen nueva. Un juego puede utilizar la posición del ratón para controlar algún aspecto de la partida. Sin embargo, Visual Basic no contiene un objeto ratón. En lugar de ello, se emite un evento MouseMove cada vez que cambia la posición del ratón. La mayoría de las veces,
Figura 7.12. Ejecución de la aplicación Escapar
los eventos del ratón están asociados con formularios y con cuadros de dibujo, pero también se pueden usar con otros objetos. Por motivos pedagógicos, este apartado se concentra en el trabajo con formularios. Todos los formularios tienen estas tres plantillas de procedimientos:
Function EnteroAleatorio (EntMin As Integer, EntMax As Integer) As Integer EnteroAleatorio = Int(EntMax - EntMin + 1) * Rnd + EntMin End Function Sub Saltar (Ctl As Control) Dim Horiz As Integer, Vert As Integer Horiz = EnteroAleatorio(0, Width - Ctl.Width) Vert = EnteroAleatorio(0, Height - Ctl.Height - 375 ) Ctl.Move Horiz, Vert End Sub Sub Command1_Click ( ) Saltar Command1 End Sub Sub Command2_Click ( ) Saltar Command2 End Sub
Figura 7.11.
El código del programa de la aplicación Escapar
21 0
Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single) Sub Form_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single) Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single)
Visual Basic llama a estos tres procedimientos cuando el usuario interactúa con el ratón. El evento MouseDown tiene lugar cada vez que se pulsa un botón del ratón. El evento MouseUp ocurre cuando se suelta un botón del ratón. El evento MouseMove sucede cuando la posición del ratón cambia. La figura 7.13 describe los parámetros que se pasan a estos tres procedimientos de evento. Parámetro
Descripción
Button
Este parámetro contiene un valor que indica el botón del ratón pulsado. Se crea combinando las constantes apropiadas con una operación Or: LEFT_BUTTON (botón izquierdo), RIGHT_BU TTON (botón derecho), MIDDLE_BUTTON (botón central).
Figura 7.13.
(continúa)
Los parametros de los procedimientos de evento del ratón
211
7 El uso de procedimientos y funciones
EL LIBRO DEL VISUAL BASIC
Figura 7.14. continuación
Figura 7.13. continuación
Parámetro
Descripción
Shift
Este parámetro representa el estado de las teclas Mayús, Ctrl y Alt usando las constantes SHIFT_MASK, CTRL_MASK y ALT_MASK. Se pone un bit a 1 si la tecla está siendo pulsada. Estos valores corresponden a la posición actual del ratón, usando las coordenadas del sistema especificadas por las propiedades de escala.
X, Y
La mejor manera de ilustrar estos eventos es escribir una aplicación sencilla. El código para la aplicación Dibujo de líneas, que se muestra en la figura 7.14, está basado en el programa Scribble de la documentación de Visual Basic. Esta aplicación usa el método Line (línea), un método gráfico para dibujar en un formulario. (Trataremos con más detalle el método Line en el capítulo 10.)
Sub Form_MouseMove (Button As Integer, Shift As Integer, X As Single, Y As Single) If Dibujando Then If (Shift And SHIFT_MASK)) = SHIFT_MASK Then Line -(X, Y), RED 'Dibujar lineas rojas El se Line -(X, Y) 'Dibujar lineas negras End If End If End Sub
Cuando ejecutes esta aplicación, la variable Dibujando estará inicialmente esta blecida como False. Sin embargo, cuando pulses el botón izquierdo del ratón la variable será puesta a True. Cuando sueltes el botón del ratón, Dibujando será puesta a False otra vez. A medida que mueves el ratón con el botón pulsado, el programa dibuja una línea desde la última coordenada conocida ( CurrentX , Cu rrent Y ) hasta la posición actual del ratón. Si pulsas la tecla Mayéis mientras estás dibujando, el color de la línea cambiará a rojo hasta que sueltes la tecla.
'De CONSTANT.TXT Const LEFT_BUTTON = 1, SHIFT_MASK =1, RED = &HFF& Dim Dibujando As Integer Sub Form_Load ( ) Dibujando = False End Sub
Sub Form_MouseUp (Button As Integer, Shift As Integer, X As Single, Y As Single) If (Button And LEFT_BUTTON) <> 0 Then Dibujando = False 'Parar de dibujar End If End Sub
'No dibujar al empezar
Sub Form_MouseDown (Button As Integer, Shift As Integer, X As Single, Y As Single) If (Button And LEFT_BUTTON) <> 0 Then Dibujando = True 'Dibujar mientras que el botón esté pulsado CurrentX = X CurrentY = Y End If End Sub
Nota: En los ratones que tienen solamente un botón, dicho botón está definido como el botón izquierdo. Si tienes un ratón de dos botones y has usado el Panel de Control de Windows para intercambiar el sentido de los botones del ratón, Visual Basic pasará el valor LEFT_BUTTON cuan do pulses el botón derecho, y el valor RIGHT_BUTTON cuando pulses el izquierdo.
Eventos del teclado Figura 7.14.
El código del programa para la aplicación Dibujar línea
212
(continúa)
En el capítulo 6 se introdujo el evento KeyPress, el cual es emitido hacia ciertos objetos cuando el usuario está escribiendo. Visual Basic también dispone de un 21 3
EL LIBRO DEL VISUAL BASIC
7 El uso de procedimientos y funciones
grado de control todavía más preciso con los eventos KeyUp y KeyDown (tecla arriba y tecla abajo), los cuales son emitidos cuando el usuario pulsa y suelta teclas en el teclado. Sin embargo, sólo aplicaciones muy especializadas requieren el uso de estos eventos; la información completa está contenida en el manual de referencia de Visual Basic.
arrastrado se denomina objeto fuente, y el ítem que recibe el evento DragDrop (arrastrar/soltar) se denomina destino. Cuando el usuario suelta el objeto fuente (soltando el botón del ratón), Visual Basic emite un evento DragDrop al destino. Además, se emiten eventos DragOver (arrastrar sobre) a todos los objetos por encima de los cuales haya pasado el objeto fuente.
Los formularios tienen otra posibilidad interesante relacionada con las pulsaciones de teclas del usuario. Normalmente, las pulsaciones de teclas (y sus eventos asociados) son enviados directamente al objeto (un cuadro de texto, por ejemplo) que es el foco de atención actual. Sin embargo, estableciendo la propiedad Key Preview (revisión previa de la tecla) de un formulario como True, se obliga a que los procedimientos de los eventos KeyPress, KeyUp y KeyDown del formulario sean ejecutados primero. Estos procedimientos pueden, por tanto, filtrar la información que se está pasando a los procedimientos KeyPress, KeyUp y KeyDown del objeto.
La característica arrastrar y soltar te permiten diseñar un interface de usuario simple, en el cual las tareas se puedan llevar a cabo sin comandos, menús o botones. Este método es muy intuitivo en muchas situaciones y, a menudo, es mucho más rápido que otros métodos. Ejemplos obvios son los de arrastrar iconos de archivos a una carpeta de directorio en el Administrador de archivos de Windows e imprimir un archivo arrastrándolo al Administrador de impresoras de Windows.
Por ejemplo, para registrar todas las teclas que pulse el usuario, podrías definir la siguiente función (asumiendo que GuardarTodo está declarada como una varia ble de cadena de nivel del formulario): Sub Form_KeyPress (KeyAscii As Integer) GuardarTodo = GuardarTodo + Chr$(KeyAscii) End Sub
Si la propiedad KeyPreview del formulario está establecida como True y si el procedimiento de gestión del teclado de nivel del formulario modifica la variable KeyAscii, el procedimiento del evento KeyPress del objeto seleccionado actualmente verá la tecla modificada. Si el procedimiento de nivel del formulario esta blece KeyAscii en 0, no se llamará al procedimiento KeyPress del objeto.
Para mostrar las posibilidades de la técnica de arrastrar y soltar vamos a escribir una aplicación llamada Correo electrónico, la cual simulará un entorno de escritorio para correo electrónico. Te permitirá crear mensajes nuevos y arrastrarlos hasta un buzón de correo desde el que serán enviados a través de la red. (Aquí se muestra sólo la característica de arrastrar y soltar; el código fuente de un sistema de correo electrónico podría llenar un libro entero.) Comienza por crear un formulario nuevo. Añade dos botones de comando y siete pequeños controles imagen, como se muestra en la figura 7.15. Los tres controles imagen de la parte de abajo de la pantalla contendrán las copias principales de los iconos, como hacían los controles imagen de la aplicación Tragaperras del capítulo 6. Después de que inicialices estos controles puedes reducir el tamaño del formulario para ocultarlos de la vista.
Ar ras tr ar y s ol ta r
Visual Basic también proporciona un soporte especial para otra forma de interacción del usuario, denominada arrastrar y soltar. El término arrastrar y soltar se refiere al uso del ratón para arrastrar un objeto que aparece en la pantalla a algún otro lugar. Has visto este proceso en el Administrador de archivos de Windows, el cual permite mover archivos de un directorio a otro arrastrando sus iconos. La "arrastrabilidad" de un objeto se activa estableciendo su propiedad DragMode (modo de arrastre) en 1. Cuando DragMode se establece en 1, el control no reci be más los eventos Click y MouseDown. En su lugar, el objeto se mueve cuando el usuario hace clic sobre él y comienza a arrastrarlo. El ítem que está siendo 214
Figura 7.15.
El diseño inicial del formulario de la aplicación Correo electrónico 215
EL LIBRO DEL VISUAL BASIC
7 El uso de procedimientos y funciones
Establece las propiedades de los tres controles imagen (Image5, Image6 e Ima ge7) como se muestra en la figura 7.16. La propiedad Tag es ignorada por Visual Basic; la puedes utilizar para mantener e identificar el texto que quieras. Esta aplicación utiliza la propiedad Tag para distinguir el icono de una carta de los otros iconos. Objeto
Propiedad
Ajuste
Image5
Name Picture Name Picture DragMode Index Name Picture Tag
imgBuzonVacio MAIL16A.ICÔ imgBuzonLleno MAIL16B.ICO 1 Automatic
Image6 Image7
0
imgCarta MAIL01A.ICO Carta
Figura 7.16.
El ajuste de las propiedades de los tres controles imagen de la parte inferior de la aplicación Correo electrónico
Estableciendo la propiedad DragMode de Image7 (el icono carta) permites al usuario arrastrar cartas por la pantalla. El ajuste en 0 de la propiedad Index hace que el icono de la carta sea una matriz de control, aunque la matriz contenga un solo elemento en este momento. (Dentro de un momento verás cómo usa esto el programa.) La figura 7.17 te muestra el aspecto que debe tener la fila inferior de controles imagen del formulario después de establecer las propiedades. Ahora establece las propiedades de los demás objetos como se indica en la tabla de la figura 7.18. Después de que cambies el tamaño del formulario, de manera que no sean visibles las tres imágenes inferiores, el formulario debe parecerse al mostrado en la figura 7.19. El control imagen que aparece en la parte superior izquierda servirá como buzón en el que se pueden echar los iconos carta. Los iconos que ves en el escritorio (el lápiz, el teléfono y el clip) no pueden ser echados al correo. El buzón mostrará el icono de buzón vacío (de Image5) cuando esté vacío, y el icono de buzón lleno cuando el usuario arrastre cartas a él. Los botones de comando permitirán al usuario crear cartas nuevas (con el icono carta) y vaciar el buzón. 216
Figura 7.17.
Los tres iconos inferiores utilizados en la aplicación Correo electrónico
Objeto
Form1 Image1 Image2
Image3
Image4
Command1 Command2
Propiedad
BorderStyle Caption BorderStyle Name DragMode Name Picture DragMode Name Picture DragMode Name Picture Caption Name Caption Name
Ajuste
3 Fixed Double Correo electrónico 1 Fixed Single imgBuzon 1 Automatic imgLapiz PENCIL09.ICO 1 Automatic imgTeléfono PHONE01.ICO 1 Automatic imgClip CLIP1.ICO Mensaje nuevo btnNuevo Vaciar buzón btn Vaciar
Figura 7.18.
El ajuste de las propiedades restantes para la aplicación Coreo electrónico
217
EL LIBRO DEL VISUAL BASIC
7 El uso d e proc edimientos y funcione s
Si gui enteCarta. Después de que Visual Basic cree el nuevo miembro de la matriz de controles (imgCarta), se le da una posición en la ventana a este nuevo miem bro y se hace que sea visible. Luego se incrementará la variable Si gui enteCar ta de manera que el siguiente evento Clic cree una carta nueva. El botón Vaciar buzón simplemente devuelve el icono (la propiedad Picture) del buzón a su valor por omisión:
Figura 7.19.
El diseño del formulario terminado para la aplicación Correo electrónico
El código para esta aplicación requiere la siguiente declaración: Dim SiguienteCarta As Integer
Se necesitan, además, dos procedimientos de nivel de formulario. El procedimiento Form_Load inicializa el icono buzón y la variable Si gui enteCarta; el procedimiento Form_DragDrop mueve el control al punto que el usuario especifique: Sub Form_Load ( ) imgBuzon.Picture = imgBuzonVacio.Picture SiguienteCarta = 1 End Sub Sub Form_DragDrop (Source As Control, X As Single, Y As Single) Source.Move X, Y End Sub
La ventana básica sólo muestra tres iconos. Para permitir que el usuario cree nuevos objetos carta debes escribir el código para el botón Mensaje nuevo: Sub btnNuevo_Click ( ) Load imgCarta(SiguienteCarta ) imgCarta(SiguienteCarta).Left = btnNuevo.Left - 2000 + SiguienteCarta * 100 imgCarta(SiguienteCarta).Top = btnNuevo.Top imgCarta(SiguienteCarta).Visible = True SiguienteCarta = SiguienteCarta + 1 End Sub
El programa llama primero al procedimiento Load. Como imgCarta es una matriz de controles, Load crea un control nuevo y le asigna el índice especificado por 218
Sub btnVaciar_Click imgBuzon.Picture = imgBuzonVacio.Picture End Sub
El buzón necesita su propio procedimiento de arrastrar y soltar. Cuando se suelta un control sobre el buzón, el programa comprueba la propiedad Tag del objeto fuente. Si el objeto fuente no es una carta, el procedimiento termina, y no se mueve el objeto fuente. En caso contrario, la declaración Unload eliminará la carta, y la propiedad Picture del buzón cambiará al icono imgBuzonLleno. Sub imgBuzon_DragDrop (Source As Control, X As Single, Y As Single) If Source.Tag <> "Carta" Then Beep Exit Sub End If Unload Source imgBuzon.Picture = imgBuzonLleno.Picture End Sub
Ejecuta esta aplicación y prueba a hacer clic en el botón Mensaje nuevo varias veces para crear cartas nuevas. Excepto el buzón, se pueden arrastrar el resto de las imágenes del escritorio. Arrastrar una carta al buzón hace que cambie el icono del buzón, y hacer clic en el botón Vaciar buzón devuelve el icono original del buzón. Observa que el programa no te permite arrastrar el teléfono, ni el lápiz ni el clip al buzón. Este sencillo programa usa la variable Si gui enteCarta para especificar un índice que se incrementa continuamente para los elementos siguientes de la matriz de controles Carta. En una versión del programa que funcionase en el mundo real querrías mantener muy controlada la cuenta de los valores del índice. Visual Basic permite un máximo de 255 elementos en una matriz de controles, lo que significa que el programa fallaría si el usuario tratase de crear 256 cartas o más. En condiciones ideales, el programa controlaría la eliminación de elementos de la matriz de controles y volvería a usar los valores índice de los elementos que se hubieran descargados. 219
8 Depuración y gestión de errores Este capítulo se centra en los errores y en qué hacer al respecto. Independientemente de la experiencia que tengas como programador, tus programas rara vez funcionarán perfectamente al primer intento. Es más, también de forma independiente a la habilidad que tengan los usuarios que trabajen con tus programas, están casi obligados a producir o a encontrarse con cierto número de errores durante la ejecución. Primero veremos el proceso de buscar y eliminar bugs (errores) y luego el proceso de gestionar los errores que se produzcan durante la ejecución del programa. Los bugs (bichos en inglés) son esos insidiosos gremlins que llenan los programas que tú "sabes" que son correctos, incluso aunque no estés obteniendo los resultados correctos. Anecdóticamente, uno de los primeros bugs de ordenador que están registrados realmente era un bicho. El ordenador Mark II fue un ordenador electromecánico construido en 1945. Un día el ordenador dejó de funcionar misteriosamente. Una ardua búsqueda reveló que una polilla había sido atrapada entre los contactos de un relé. Grace Murray Hopper, una de las creadoras del lenguaje COBOL y una de las pioneras de la industria de los ordenadores, recuperó el infortunado lepidóptero y escribió en el libro de registro del proyecto "Primer bicho real que se ha encontrado". Sin embargo, los bugs que se tratan en este capítulo son errores en la lógica de los programas. Desde luego puedes cometer todo tipo de errores que evitarán que tu programa funcione —por ejemplo, tratando de asignar un valor de cadena a una variable de tipo double. Pero Visual Basic avisa de esos errores bastante evidentes en cuanto se los encuentra, lo que hace que sean fáciles de localizar y 221
8 Depurac ión y gestión de errores
EL LIBRO DEL VISUAL BASIC
de eliminar. Los bugs realmente interesantes son lo que debes encontrar y solucionar por ti mismo.
Debbuging (o depuración) es, simplemente, el proceso de buscar y eliminar bugs. Al contrario que los sistemas tradicionales de eliminación de pestes, la depuración de programas de ordenador no tiene efectos laterales tóxicos, a no ser que cuentes las horas sin dormir y las innumerables tazas de café que puede conllevar la búsqueda de un bug casi ilocalizable. Depurar un programa puede ser interesante e incluso excitante. Perseguir y eliminar un bug del programa, generalmente produce una sensación de satisfacción real, ya se derive del hecho de recuperar o reparar el programa, del objetivo logrado o de la emoción de la caza. El ejercicio intelectual puede ser también en riquecedor, permitiéndote examinar y analizar tus propios procesos de pensamiento.
Herramientas de depuración Aunque no queramos admitirlo, los bugs son realmente errores del programador. Sin embargo, algunas veces aparecen de manera tan infrecuente o bajo condiciones tan inusuales que parecen exhibir algún tipo de inteligencia maligna que se divierte burlándose de nosotros. Yo he tenido la experiencia de un bug que sólo aparecía en semanas alternas y con un programa que funcionaba perfectamente bien, excepto cuando una aplicación concreta se ejecutaba inmediatamente delante de él. Mucho más habitual es la rutina que, simplemente, no funciona. Cuanto te encuentres con un problema como ese, posiblemente querrás usar algunas de las herramientas que Visual Basic ofrece para llevar a cabo la depuración del programa. A medida que trabajes con las distintas herramientas de depuración verás que algunos de los botones de la barra de herramientas ofrecen prácticos atajos. La figura 8.1 identifica los botones de la barra de herramientas que son más útiles en la depuración de programas. La ventana Debug
Como ya sabes, se puede pulsar Ctrl+Pausa en cualquier momento en que un programa esté funcionando para interrumpir la aplicación y activar la ventana De bug. Si se estaba ejecutando un procedimiento concreto cuando se interrumpa el programa, también se verá la ventana de código de ese procedimiento. En ese momento se puede introducir código y ejecutar declaraciones de Visual Basic en 222
Figura 8.1.
Los botones de la barra de herramientas que se usan en la depuración de programas
la ventana Debug. Cada declaración sólo puede ocupar una línea. Las declaraciones se ejecutan dentro de la ventana Debug cuando se pulsa la tecla Intro. El código de la ventana de código no se modifica. Normalmente, lo que se hace es imprimir los valores de variables y de expresiones que interesan, pero se pueden hacer muchas cosas más. De hecho se puede ejecutar prácticamente cualquier instrucción de programación de Visual Basic; se puede, por ejemplo, modificar una variable o ejecutar un procedimiento desde la ventana Debug. Sin embargo, debes darte cuenta de que sólo se pueden modificar las variables locales y los parámetros del procedimiento actual y las variables globales y de nivel de módulo; no se pueden examinar ni cambiar variables locales de ningún procedimiento que no sea el actual. También se pueden cambiar los valores de todas las propiedades que se puedan modificar durante la ejecución del programa. A modo de demostración, crea un proyecto nuevo que contenga un solo botón de comando. Añade el procedimiento general PierdeElTiempo y el procedimiento Click para el botón de comando, como se muestra en la figura 8.2. Pulsa E5 para ejecutar la aplicación. Haz clic en el botón de comando, y a continuación pulsa Ctrl+Pausa para que Visual Basic detenga la aplicación y muestre la ventana de código, la cual se parecerá a la de la figura 8.3. (Lo más probable es que la aplicación se detenga en la rutina PierdeElTiempo; si no es así, pulsa F5 para reiniciar el programa y prueba a pararlo otra vez.) En la ventana de código que se muestra en la figura 8.3, aparece un recuadro alrededor de la línea Next B, que es la declaración que Visual Basic ejecutará a 223
EL LIBRO DEL VISUAL BASIC
Sub PierdeElTiempo Dim A As Single, B As Integer A = .5 For B = 1 To 10000 A = A + B Next B End Sub Sub Command1_Click ( ) Dim C As String, D As Integer C = "Hola marinero” For D = 1 To 100 PierdeElTiempo Next D C = "Buenas noches, Gracia" End Sub
Figura 8.2.
El código del programa para la aplicación Girar la ruleta
8 Depuración y g estión de errores
biendo que tienen valores asignados, debido a que la ventana Debug está limitada al ámbito del procedimiento que se está ejecutando. Si introdujeses la instrucción Print C o Print D, Visual Basic supondría que estas utilizando simplemente variables no declaradas en el procedimiento actual e imprimiría una línea en blanco. Tienes acceso a todas las variables y propiedades cuyo ámbito sea de nivel de módulo o global, lo cual te permite ejecutar instrucciones como Print
Command1.Caption y Print Form1.Height. Nota: Si has incluido la declaración Option Explicit en la sección de de claraciones generales del programa, Visual Basic ni siquiera imprimirá una línea en blanco cuando intentes ver en la ventana Debug el valor de una variable no declarada. En su lugar verás el mensaje Variable not delined (vari able no defi nida).
Si quieres probar a modificar una propiedad o una variable dentro de la ventana Debug, puedes utilizar para ello las mismas declaraciones y expresiones que usarías en un programa. Por ejemplo, podrías reducir el tamaño de la ventana del formulario ejecutando la declaración Form1.Height = Form1 .Height / 2. O podrías ejecutar cualquier procedimiento o método introduciendo su nombre. Por ejemplo, cuando escribes la declaración Print estás llamando al método Print del ob jeto que representa a la ventana Debug (un objeto llamado Debug). No estás limitado a los procedimiento internos de Visual Basic; también puedes ejecutar cualquiera de los procedimientos que tú hayas escrito. Expresiones Watch
Cuando simplemente quieras comprobar el valor de una variable, Visual Basic ofrece una técnica rápida que no necesita de la instrucción Print. Haz doble clic sobre el nombre de la variable en la ventana de código —prueba a hacer doble clic sobre la variable B del procedimiento PierdeElTiempo — y luego selecciona el comando Instant Watch (comprobación instantánea) del menú Debug o haz clic en el botón Instant Watch de la barra de herramientas. Aparecerá el cuadro de diálogo Instant Watch que se muestra en la figura 8.4, y mostrará el valor de la variable que hayas seleccionado. Figura 8.3.
La ventana de código de un programa interrumpido
continuación. En la ventana Debug podrías introducir la declaración Print B (o simplemente ? B ) para ver cuántas veces se ha ejecutado el bucle For. Podrías introducir Print A para ver el valor actual de A . Sin embargo, no podrías escribir Print C o Print D para examinar las otras variables de la aplicación, incluso sa224
A la variable seleccionada se le denomina una expresión watch (de comprobación). Como su nombre implica, una expresión watch puede contener más de una variable. Si seleccionas A + B en el procedimiento PierdeElTiempo, el cuadro de diálogo Instant Watch mostrará el valor de la expresión completa. También puedes añadir una expresión watch a la ventana Debug para que puedas conocer el valor de la expresión en todo momento sin que tengas que abrir 225
EL LIBRO DEL VISUAL BASIC
8 Depuración y g estión de errores
La figura 8.6 muestra la ventana Debug después de haber añadido dos expresiones de comprobación. Las expresiones muestran la variable D del procedimiento Commandl_Click y la variable B del procedimiento PierdeElTiempo.
Figura 8.4.
Si quieres modificar o eliminar una expresión watch que haya sido añadida a la ventana Debug, elige el comando Edit Watch del menú Debug y haz los cambios necesarios en el cuadro de diálogo Edit Watch en el que aparece.
El cuadro de diálogo Instant Watch
el cuadro de diálogo Instant Watch. Para añadir la expresión seleccionada, haz clic en el botón Add Watch del cuadro de diálogo Instant Watch o selecciona el comando Add Watch del menú Debug. En el cuadro de diálogo Add Watch, que se muestra en la figura 8.5, haz clic en el botón OK para hacer que la expresión watch aparezca en la parte superior de la ventana Debug. Figura 8.6.
La ventana Debug con expresiones watch
El árbol de llamadas (¿dónde estoy?)
Figura 8.5.
El cuadro de diálogo Add Watch
Se puede, incluso, añadir una expresión watch a la ventana Debug sin seleccionarla previamente en el código del programa. El modo de hacerlo es escribir, simplemente, la expresión directamente en el cuadro de texto Expression del cuadro de diálogo Add Watch. La parte Context (contexto) del cuadro de diálogo permite especificar el procedimiento o el módulo en el que están definidas las variables de la expresión —lo cual puede ser muy útil, por ejemplo, en el caso de que tengas una variable de nivel de formulario y una variable local con el mismo nombre. (Trataremos la parte Watch Type del cuadro de diálogo en un apartado posterior.) 226
En el sencillo ejemplo del apartado anterior (la aplicación Girar la ruleta), era bastante evidente lo que estaba sucediendo cuando el programa se interrumpió. Sin embargo, en un aplicación más compleja la secuencia de eventos puede no ser tan clara. En tales casos puedes seleccionar el comando Calis (llamadas) del menú Debug o hacer clic en el botón Calis de la barra de herramientas para que aparezca un cuadro de diálogo que muestre la lista de llamadas del programa a procedimientos que estén activos. La figura 8.7 muestra el cuadro de diálogo Calis de nuestra aplicación Girar la ruleta. La primera línea del cuadro de diálogo muestra el procedimiento actual —en este caso, el procedimiento PierdeElTiempo , el cual está en el módulo Form1. Este procedimiento ha sido llamado por el procedimiento del evento Command1_Click, también del módulo Form1. La secuencia de llamadas acaba aquí porque el procedimiento Click fue iniciado por un evento del usuario. En el caso de un programa más complejo, el cuadro de diálogo Calis podría contener muchas entradas indicando el anidamiento de las llamadas a los procedimientos. Puedes hacer doble clic sobre cualquiera de estas entradas (o seleccionar una de ellas y hacer clic en el botón Show) para que aparezca el código de un procedimiento en particular. 227
EL LIBRO DEL VISUAL BASIC
8 Depurac ión y gestión de errores
Static BreakContador As Integer BreakContador = BreakContador + 1 If BreakContador > 10 And A < 0 Then Stop End If
Figura 8.7.
El árbol de llamadas de un programa interrumpido
Breakpoints y d eclaraciones Stop
Cuando pulsaste Ctrl+Pausa para interrumpir el programa Girar la ruleta no tenías mucho control sobre dónde se detendría el programa. Sin embargo, Visual Basic permite marcar explícitamente una o más declaraciones como breakpoints (puntos de interrupción en inglés), puntos en los que se detendrá la ejecución del programa, dándote la oportunidad de estudiarlo e investigarlo para diagnosticar sus problemas. Si quieres establecer un breakpoint abre la ventana de código del procedimiento apropiado y haz clic sobre la declaración en la que el programa se debe detener. Pulsa F9, selecciona el comando Toggle Breakpoint (activar/de activar breakpoint) del menú Debug o haz clic en el botón Toggle Breakpoint de la barra de herramientas. Visual Basic resaltará la línea para indicar la presencia de un breakpoint. Para eliminar un breakpoint simplemente hay que hacer clic en la línea resaltada del programa para seleccionarlo y pulsar la tecla F9, seleccionar el comando Toggle Breakpoint de nuevo o hacer clic en el botón Toggle Breakpoint. Si tienes establecidos varios breakpoints puedes elegir el comando Clear All Breakpoints (eliminar todos los breakpoints) del menú Debug para quitarlos todos en un único paso. Puedes lograr el mismo efecto que al establecer un breakpoint añadiendo una declaración Stop al programa. Esta técnica no es tan satisfactoria como usar un breakpoint porque ello significa tener que modificar el código. Sin embargo, con un breakpoint Visual Basic interrumpe el programa cada vez que llega a él. Si utilizas una declaración Stop puedes ser mucho más específico, asegurándote de que tu programa sólo se detendrá bajo determinadas condiciones. Por ejemplo, el siguiente fragmento de código contiene una declaración Stop que sólo detendrá el programa después de ejecutarse 10 veces y sólo si el valor de la variable A es menor de 0. 228
Después de que el programa se haya interrumpido ya sea por un breakpoint o por una declaración Stop, puedes continuar la ejecución pulsando F5 o seleccionando el comando Continue (continuar) del menú Run de Visual Basic. Si has utilizado una declaración Stop, debes acordarte de quitarla de tu programa. Los breakpoints permanecen activos sólo durante una sesión de Visual Basic. Usar una declaración Stop puede describirse como técnica invasora —o sea, de bes ir y modificar físicamente el código del programa. Puedes recordar otra técnica invasora de un capítulo anterior: escribir en la ventana Debug desde el interior del programa. La declaración Debug.Print seguida por una expresión produce que la expresión sea escrita en la ventana Debug sin que el programa se interrumpa de ninguna manera. Repartiendo algunas instrucciones de este tipo por un programa defectuoso se puede descubrir a menudo en qué punto comienzan los problemas. Los usos habituales suelen ser imprimir el nombre del procedimiento en cuanto comience a ejecutarse o imprimir el nombre de ciertas variables clave. Aunque las técnicas invasoras permiten llevar a cabo operaciones más sofisticadas, las técnicas no invasoras, como establecer breakpoints, son preferibles en la mayoría de los casos, ya que evitan el equivalente en programación de dejarse una esponja o un escalpelo dentro del paciente. Si se te olvida quitar una declaración Stop de un procedimiento que no se ejecute con frecuencia antes de compilar el programa tú, o lo que sería peor, un cliente que esté utilizando el programa, os podríais llevar una desagradable sorpresa cuando el mensaje Stop statement encountered (se ha encontrado una declaración Stop) aparezca en medio de una aplicación que finalice abruptamente, enviando todos tus datos al país de nunca jamás. Watchpoints
También se puede usar una herramienta no invasora denominada watchpoint (punto de vigía), la cual instruirá a Visual Basic para que detenga el programa cuando se encuentre con unas condiciones especiales (al contrario que un breakpoint, el cual determina una interrupción cuando se alcanza una línea de código concreta) o cuando el valor de una expresión cambie. 229
EL LIBRO DEL VISUAL BASIC
Para establecer un watchpoint debes resaltar la expresión específica en el código y seleccionar el comando Add Watch (añadir vigía) del menú Debug, o elegir el comando Add Watch primero y luego escribir la expresión en el cuadro de texto del cuadro de diálogo Add Watch. En este cuadro de diálogo (que ya se vió en la figura 8.5), ve a la sección Watch Type (tipo de vigía), selecciona el botón de opción marcado como Break When Expression Is True (suspender cuando la expresión sea verdadera) y luego, haz clic en el botón OK. Visual Basic añadirá la expresión a la ventana Debug. Si quieres que el programa se pare cuando la expresión vigilada cambie, entonces deberás seleccionar el botón Break When Expression Has Changed (suspender cuando la expresión haya cambiado) en el cuadro de diálogo Add Watch. En cualquier caso, cuando reinicies la ejecución del programa, Visual Basic evaluará la expresión vigilada después de cada instrucción y detendrá la ejecución cuando concurran las condiciones especificadas. Los watchpoints son herramientas potentes, pero tienen un lado negativo. Aunque son herramientas no invasoras y ello hace que no tengas que cambiar el código del programa, ralentizan la ejecución del programa porque las expresiones vigiladas se deben comprobar continuamente. La mejor técnica consiste en utilizar breakpoints y watchpoints juntos: establece un breakpoint en el lugar del programa donde sospeches que algo funciona mal. El programa funcionará a su velocidad normal hasta ese punto. Entonces puedes activar uno o más watchpoints y continuar la ejecución más despacio. Paso a paso
Otra útil técnica no invasora de depuración es avanzar paso a paso, que permite ejecutar el programa de instrucción en instrucción. Esto es prácticamente equivalente a establecer un breakpoint en la declaración siguiente a la posición actual, ejecutar la declaración actual y eliminar el breakpoint. Cuando se avanza paso a paso por el código se puede examinar el efecto que produce cada una de las instrucciones en el programa. La ejecución la controla la tecla E8 o el botón Single Step (un solo paso) de la barra de herramientas (o el comando Single Step del menú Debug, aunque la tecla de función o el botón de la barra de herramientas son mucho más prácticos). Puedes iniciar la ejecución paso a paso siempre que el programa no esté funcionando. Cada vez que pulses F8, Visual Basic ejecutará una instrucción, y el recuadro que marca la siguiente línea en la ventana de código avanzará. Si la declaración que se ha ejecutado contiene un procedimiento escrito por el usuario, 230
8 Depuración y g estión d e errores
la ventana de código cambiará, y el recuadro aparecerá en la primera línea ejecutable del nuevo procedimiento. Si ejecutas una instrucción que contenga más de una llamada, irás pasando de un procedimiento a otro en orden. Por ejemplo, piensa en el programa que se muestra en la figura 8.8. (Los números de referencia que aparecen a la izquierda se han añadido simplemente para identificar varias líneas del programa.) Si ejecutas este programa con un breakpoint establecido en la línea 3 ( A = 4 ) , inicialmente aparecerá un recuadro alrededor de la línea 3. Cuando pulses F8 para iniciar la ejecución paso a paso, el recuadro avanzará a las líneas 4, 8, 9, 12, 15 y 5. (Como las líneas 7 y 11 se consideran declaraciones no ejecutables, la herramienta de depuración se las salta. Si estableces un breakpoint en una declaración no ejecutable, el recuadro aparecerá en la siguiente línea ejecutable cuando el programa se interrumpa.) Si estás avanzando paso a paso por un programa y llegas a un procedimiento que ya hayas depurado, puedes evitar el pasar por cada una de las instrucciones de ese procedimiento. Si mantienes pulsada la tecla Mayús mientras pulsas F8 o si haces clic en el botón Step Procedure (saltar procedimiento) de la barra de herramientas, Visual Basic restringirá el ir paso a paso al procedimiento actual y, simplemente, ejecutará las llamadas a procedimientos de ese procedimiento como si cada llamada fuera una sola instrucción. Si usas Mayús+F8 para ir paso a paso
1 2 3 4 5
Sub Command1_Click ( ) Dim A As Integer A = 4 'Breakpoint inicial debug.Print UnoMas(A) + UnoMenos(A) 'Paso a los procedimientos End Sub
6 7
8 9
Function UnoMas (X As Integer) As Integer UnoMas = X + 1 End Function
10
11 12 13
Function UnoMenos (X As Integer) As Integer Uno Men os = X - 1 End Function
Figura 8.8.
El código de un programa para mostrar la ejecución paso a paso
231
EL LIBRO DEL VISUAL BASIC
por el programa de la figura 8.8 te moverás de la línea 3 a la 4 y luego a la 5. Visual Basic ejecuta las líneas 7 a 9 y 11 a 13, pero puedes ahorrarte ir paso a paso por dos procedimientos que sabes que son correctos. Puedes alternar entre paso a paso y paso de procedimiento en cualquier momento durante la sesión de depuración. Ten en cuenta que un breakpoint que haya dentro de un procedimiento interrumpirá el programa, incluso si estás usando la ejecución paso a paso. Prueba a experimentar estas técnicas en el programa Girar la ruleta que se muestra en la figura 8.2. Primero utiliza F9 para establecer un breakpoint en la declaración Next D del procedimiento Command1_Click. Pulsa F5 para ejecutar el programa y haz clic en el botón de comando para llegar al breakpoint. Pulsa la tecla F9 de nuevo para eliminar el breakpoint. Luego manten pulsada la tecla Mayéis y pulsa F8 un par de veces. Permanecerás en el procedimiento Cotnmandl_Click (aunque te puedes percatar de una pausa que se produce mientras se ejecuta el procedimiento PierdeElTiempo.) Cuando vuelvas a Next D, pulsa F8 dos veces sin usar la tecla Mayus. Este paso a paso te llevará al interior del procedimiento PierdeElTiempo, donde puedes continuar el paso a paso.
Estrategias de depuración Normalmente es fácil localizar el origen de un problema; a menudo es razonablemente obvio que todo esté funcionando excepto un botón o un cierto cálculo. Entonces puedes utilizar la clásica técnica de la disminución granular. El término granular se refiere al tamaño de las estructuras de programa que se tienen que ejecutar. Puedes comenzar usando breakpoints, los cuales te permiten ejecutar ampliar porciones del programa sin interrupción. A medida que te acerques al punto donde las cosas van mal puedes cambiar al paso de procedimiento y luego al paso a paso para identificar la instrucción donde se produce el error. Evidentemente, el párrafo anterior presume de forma optimista que el origen de todos tus problemas es una sola instrucción. Esto a menudo no es así. Puedes encontrarte con que has realizado unas presunciones sobre valores de variables o sobre entradas del usuario que, simplemente, no se corresponden con la realidad, y que te obligarán a reescribir partes del programa. Como posiblemente llevarás tus presunciones contigo a la sesión de depuración, algunas veces puede ser difícil saber qué es lo que va mal exactamente. En momentos así puede ser ventajoso que codifiques tus presunciones en el programa directamente. Por ejemplo, si supones que un cierto parámetro nunca tendrá un valor que sea menor de 10 ni 232
8 Depurac ión y gestión d e errores
mayor de 50 puedes incluir el siguiente código al comienzo del procedimiento que contiene al parámetro: If Param < 10 Or Param > 50 Then Debug.Print "La presunción sobre 'Param' ha sido violada.") Stop End If
Aunque es una técnica invasora, el codificar estas presunciones en un programa puede ayudar algunas veces a localizar los bugs más rápidamente que usando breakpoints o la ejecución paso a paso, especialmente si el programa es largo o complejo. Sin embargo tienes otra alternativa: puedes usar una búsqueda binaria, que es una variante de la técnica de la disminución granular. La estrategia de la búsqueda binaria es la misma que la del juego infantil de la adivinación. Si tu oponente elige un numero entre el 1 y el 100 siempre puedes determinar qué número es con no más de ocho intentos de adivinación. El primer intento siempre debe ser la mitad, 50. Tu oponente debe decirte entonces si es demasiado alto o demasiado bajo. Si es demasiado alto debes intentar el 25; si es demasiado bajo, el 75. Con cada intento eliminarás la mitad de las posibilidades restantes. De la misma manera, cuando trabajes con un programa complejo y no tengas una idea clara de dónde buscar, establece un breakpoint por la mitad de la aplicación. Cuando llegues a la interrupción examina las variables importantes. Si todo parece estar bien establece el siguiente breakpoint . a mitad de camino entre la posición actual y el final del programa. Si no, establécelo entre el comienzo del programa y el breakpoint actual, y vuelve a ejecutar el programa. Esta técnica debe conducirte rápidamente a las proximidades del error, y luego puedes pasar fácilmente al paso a paso o a otra técnica apropiada. No vaciles en utilizar las posibilidades que Visual Basic ofrece para la depuración con el fin de comprobar tus teorías sobre lo que va mal en el programa. Por ejemplo, si descubres que se te ha olvidado incrementar una variable, no te limites a detener el proceso de depuración y a modificar el programa. Utiliza la ventana Debug para establecer la variable con el valor que crees que es correcto y deja que el programa siga funcionando. Algunas veces descubrirás que lo que parecía ser la causa del problema en realidad sólo es un efecto lateral o un síntoma del problema real. Puedes usar las herramientas de depuración incluso para experimentar con el flu jo de control del programa. Digamos que interrumpes el programa en mitad de 233
8 Depurac ión y gestión d e errores
EL LIBRO DEL VISUAL BASIC
un procedimiento y que te das cuenta de que deberías haber puesto una declaración If para saltarte las siguientes líneas. Puedes determinar la siguiente instrucción que se va a ejecutar haciendo clic sobre ella o usando el comando Set Next Statement (establecer siguiente instrucción) del menú Debug. Puedes seleccionar cualquier instrucción del procedimiento actual, incluso una que esté delante de la instrucción actual, pero no puedes especificar una instrucción que esté en algún otro procedimiento.
Un grito de ayuda El sistema de Ayuda en línea de Visual Basic, que introdujimos en el capítulo 1, puede proporcionarte una asistencia de un valor incalculable durante la programación y la depuración. Para acceder rápidamente a la Ayuda, pulsa la tecla F1 en cualquier momento durante el diseño o la depuración de una aplicación, o selecciona una opción del menú Help (ayuda) de Visual Basic. Visual Basic dispone de ayuda sensible al contexto —es decir, trata de ofrecer la ayuda más útil para la situación actual. Por ejemplo, si quieres usar la función Format en un programa pero no recuerdas los parámetros que hay que suministrarle, comienza a escribir la instrucción en el programa. Tan pronto como hayas escrito la palabra Format , pulsa F1 Visual Basic abrirá una ventana que mostrará el texto de Ayuda sobre la función Format. De la misma manera, si tu programa genera un error durante la ejecución con un mensaje como Subscri pt out of ran ge, puedes pulsar El cuando aparezca el cuadro de diálogo con el mensaje y, así, el sistema de Ayuda de Visual Basic te dirá más cosas sobre el error.
Figura 8.9. La pantalla de contenidos de la Ayuda de Visual Basic
Si necesitas buscar información, puedes elegir varios caminos. Cuando selecciones el comando Contents (índice) del menú Help o hagas clic en el botón Indice de la zona superior izquierda de una ventana de Ayuda que esté abierta, Ayuda mostrará una lista completa de sus categorías de información, como se muestra en la figura 8.9. Cada frase subrayada representa un enlace de hipertexto con otra pantalla de Ayuda. Por ejemplo, si haces clic en la frase Programming Language (o pulsas Tab hasta llegar a ella y luego pulsas Intro), la pantalla de Ayuda mostrará un índice de todas las características del lenguaje Visual Basic, como se muestra en la figura 8.10. Entonces podrás hacer clic sobre cualquiera de los términos de este índice para buscar información específica sobre ese tema. Por ejemplo, Ayuda podría proporcionar la sintaxis de una declaración, una descripción del funcionamiento de la declaración y, algunas veces, incluso un ejemplo de código. Si te re 234
Figura 8.10. Parte del índice de Ayuda de Programming Language
235
8 Depuración y gestión de errores
EL LIBRO DEL VISUAL BASIC
sulta útil, incluso puedes marcar y copiar el código de ejemplo desde el sistema de Ayuda y pegarlo en tu programa. Cuando estés reuniendo y comprobando información, también te puede ser útil la opción Buscar. Al hacer clic en el botón Buscar de la ventana de Ayuda se abre el cuadro de diálogo Buscar que se muestra en la figura 8.11. Comienza a escribir en el cuadro de texto que hay en la paite superior de la ventana la palabra clave o el concepto que quieras investigar. Con cada letra que escribas, el sistema de Ayuda estrechará la búsqueda a los elementos que aparecen en el cuadro de lista que hay justo debajo del cuadro de texto. Luego, puedes seleccionar un elemento del cuadro de lista y hacer clic en el botón Mostrar temas o, simplemente, hacer clic en el elemento. Cuando lo hagas, el cuadro de lista que hay en la parte inferior del cuadro de diálogo mostrará una lista de todos los temas de Ayuda relacionados. Puedes ver cualquiera de estas pantallas de Ayuda haciendo doble clic en el tema o seleccionándolo y haciendo clic en el botón Ir a. Muchos de los temas de Ayuda incluyen ejemplos de código que muestran los elementos del lenguaje tratados. Para ver el ejemplo, solamente tienes que hacer clic en el hipervínculo Example (ejemplo) que hay en la parte superior de la pantalla. Si quieres probar a ejecutar el código, haz clic en el botón Copy (copiar) de la parte superior de la ventana del código de ejemplo. En la ventana Copy, selecciona el código en el que estás interesado y haz clic en el botón Copy. Cuando vuelvas a Visual Basic podrás pegar el código seleccionado directamente en la ventana de código de tu programa.
Algunas veces resulta de utilidad tener la ventana de Ayuda disponible en la pantalla mientras se está editando el código. Para evitar que otras ventanas puedan ocultar la ventana de Ayuda, selecciona el comando Siempre visible del menú Ayuda de la ventana de Ayuda. Aparecerá una marca de control al lado de esta opción en el menú cuando esté activa. Para desactivarla, simplemente selecciónala otra vez. Y si quieres imprimir el tema de Ayuda para estudiarlo más tarde, selecciona el comando Imprimir tema del menú Archivo de la Ayuda.
Gestión de errores Este capítulo se ha concentrado hasta ahora en los errores del programador que producen que una aplicación falle o devuelva unos resultados no válidos. Otro tipo de problemas, denominados errores en tiempo de ejecución, también pueden provocar que un programa falle. Los errores en tiempo de ejecución surgen a menudo debido a condiciones que tú no puedes controlar, como una insuficiencia de memoria o de espacio de almacenamiento en disco, un error del usuario, un intento de abrir un archivo que ya ha sido abierto por otro programa, etc. Otros errores en tiempo de ejecución son bugs, indicadores de errores lógicos en tu programa, como intentar utilizar un elemento de una matriz cuyo índice sea superior a la dimensión de ésta. Cuando se produce un error en tiempo de ejecución, Visual Basic normalmente muestra un cuadro de diálogo con un mensaje y finaliza la aplicación. Sin embargo, es posible mediante la programación hacerse cargo de la gestión de errores. Esta técnica, denominada cazar errores , permite que tu programa detecte y, posi blemente, solucione el problema, o al menos, termine el programa de una forma agradable al usuario. El control sobre el sistema se adquiere estableciendo la caza de errores. Cuando se escribe un procedimiento que caza errores, su estructura general debe parecerse a esto: Sub declaración
[ instrucciones] On Error GoTo etiqueta Exit Sub
etiqueta: código de gesti ón de errores End Sub Figura 8.11.
El cuadro de diálogo Buscar de la Ayuda
236
La instrucción On Error GoTo etiqueta , en la que etiqueta identifica el código de gestión de errores, activa la caza de errores. Si ocurre un error en tiempo de eje 237
8 Depurac ión y gestión gestión de errores errores
EL LIBRO DEL D EL VISUAL BASIC
cución en las instrucciones que siguen a la declaración On Error GoTo etiqueta , el control es transferido inmediatamente al código de gestión de errores designado por etiqueta. Etiqueta puede ser cualquier identificador que tú elijas y, cuando se utiliza para señalar una posición particular en el código, debe terminar en dos puntos (:). Para desactivar la caza de errores más adelante en el mismo procedimiento, puedes usar la declaración On Error GoTo (). Cualquier error en tiempo de ejecución que ocurra detrás de esa declaración será gestionado directamente por Visual Basic, no por el código de gestión de errores del procedimiento. Esta posibilidad de activar y desactivar la caza de errores es útil sólo cuando es una pequeña parte del código la que es susceptible de producir errores en tiempo de ejecución. La caza de errores está activa sólo dentro del procedimiento que contenga la declaración On Error GoTo etiqueta. Cuando el procedimiento finaliza, la caza de errores vuelve a la rutina que originalmente llamó al procedimiento. Si esa rutina no tiene un gestor de errores, se desactivará la caza de errores. Una vez que el programa pasa al código de gestión de errores de un procedimiento, puedes comprobar el valor de la función Er r para conocer la causa del error. Er r devuelve un número entero que indica el tipo de error —por ejemplo, el error 7 indica que te has quedado sin memoria, el error 53 indica que el programa no puede encontrar el archivo designado, y así sucesivamente. La lista completa de códigos de error está incluida en la Ayuda en línea de Visual Basic y en su manual de referencia. Evidentemente, tu gestor de errores no tiene que comprobar todos los errores posibles. El error 53, por ejemplo, solamente se puede producir si tratas de acceder a un archivo. Si el procedimiento no utiliza archivos, no tienes que comprobar el error 53. Después de que hayas determinado qué error ha ocurrido, tienes cuatro opciones para seguir. La alternativa más simple es devolverle el error a Visual Basic.. Puedes hacer esto usando la declaración Error. La declaración Error tiene un solo parámetro (el número del error) y fuerza inmediatamente un error en tiempo de ejecución. Añadiendo la línea Error Err al final de tu código de gestión de errores podrás negociar limpiamente cualquier error que no quieras gestionar. Las otras tres opciones conllevan la continuación de la ejecución del programa. Incluyendo la instrucción Resume en el código de gestión de errores rearranca el programa una vez que el error haya sido corregido. Puedes usar cualquiera de estas tres variaciones: 238 238
Instrucción
Acción
Resume
Continúa el programa ejecutando la instrucción que produjo el error. Resume Next Continúa el programa ejecutando la instrucción que está situada inmediatamente detrás de la que produjo el error. Resume etiqueta Continúa la ejecución del programa ejecutando en un punto especificado por etiqueta. Considera el código de programa que se muestra en la figura 8.12, el cual genera un error cuando se trata de dividir por cero.
1 2 3 4 5
6 7 8 9 10 11 12 13
Sub Test ( ) Dim XX As Integer, YY As Integer XX = 0 Y Y = 10 On Error GoTo Resuelvelo Y Y = Y Y / XX Debug.Print YY Y o F i n a l izo: End Resuelvelo: XX = 2 Resume End Function
Figura 8.12. El código de un programa programa que incluye gestión gestión de errores
Cuando ejecutes este procedimiento, las instrucciones se ejecutarán secuencial mente hasta que el programa llegue a la línea 6. En ese punto se produce un error 11 (división por cero), y el control del programa pasa a la línea 10. El códi X X , y la instrucgo de gestión de errores establece como 2 el valor de la variable XX ción Resume hace que se ejecute de nuevo la línea 6. Esta vez, la expresión no generará un error. La declaración de la línea 7 imprimirá el valor 5 y el procedimiento terminará. 239 239
8 Depuración y gestión de errores
EL LIBRO DEL VISUAL BASIC
Si se hubiera utilizado la instrucción Resume Next en la línea 12, el programa hu biese continuado en la línea 7, que habría impreso el valor 10 (el valor no modificado de YY ) ya que la línea 6 no se ejecutó con éxito. Finalmente, si la declaración de la línea 12 hubiese sido Resume YoFinalizo, la ejecución se hubiese reiniciado en la línea 8, que habría finalizado el programa sin imprimir ningún valor. Es importante observar que la declaración Resume se aplica sólo al procedimiento en el que aparece. Tomemos el ejemplo de la figura 8.12 y modifiquemos el código para que incluya dos procedimientos, como se ve en la figura 8.13, para mostrar la posibilidad de gestión de errores a través de diversos procedimientos.
Cuando ejecutes este código verás la siguiente salida: Inicio Entrando Entrando 5 Saliendo Fi n
Si modificas la instrucción Resume del código de gestión de errores para que esume Next, la salida cambiará a esto: ponga R esume Inicio Entrando Fi n
Dim XX As Integer Sub ConError ( ) Dim YY As Integer Debug.Print "Entrando" YY = 10 YY = YY / XX Debug.Print YY Debug.Print "Saliendo" End Sub
En ambos casos, el gestor de errores hace que la ejecución continúe dentro del procedimiento que contiene el gestor de errores, no en la declaración que realmente produjo el error en el procedimiento ConError. Si quisieras que el programa pudiese continuar la ejecución normal dentro del procedimiento ConError tendrías que añadir un gestor de errores a ese procedimiento.
Sub Test ( ) On Error GoTo Resuelvelo Debug.Print "Inicio" XX = 0 ConError Debug.Print "Fin" En d Resuelvelo: XX = 2 Resume End Sub
Figura 8.13.
El código de un programa programa que muestra muestra la gestión de errores errores a través de varios procedimientos
240
241
9 Arch Ar chiv ivos os Los archivos (o ficheros) proporcionan un sistema para almacenar la información a largo plazo. Los valores que están almacenados en las variables son transitorios: desaparecen cuando se cierra la aplicación y son recalculados otra vez cuando se ejecutan. Para que los datos se almacenen permanentemente, y se pueda acceder a ellos y recuperarlos, se deben guardar en un archivo. Este capítulo ilustra cómo gestiona Visual Basic algunas operaciones estándar de archivos, incluyendo buscarlos, abrirlos, guardarlos y cerrarlos. Te permite crear una aplicación de ejemplo que muestra las herramientas del sistema de archivos de Visual Basic. Con estas herramientas se pueden crear cuadros de diálogo que funcionen como los cuadros de diálogo Archivo Abrir y Archivo Guardar como creados por el control Common Dialog. También veremos dos maneras de almacenar y acceder a los datos en los archivos: un método línea por línea, que, esencialmente, trata a la información como texto; y un método orientado a los registros. Además aprenderás a almacenar la información de configuración en archivos INI de forma para guardar la información de arranque y de configuración de tus aplicaciones Windows.
Visión general del sistema de archivos Como se vió) en el capítulo 2, el microprocesador del ordenador usa los bits de información almacenados en la memoria como instrucciones y datos. El diseño del hardware del microprocesador le permite un acceso inmediato a la RAM (memoria de acceso aleatorio) del ordenador. Pero incluso los modernos microordenadores con decenas de megabytes de RAM no pueden mantener en ella toda la información que necesitan. El sistema necesita otro lugar de almacenamiento para los datos que no caben en la RAM. 243
9 Archivos
EL LIBRO DEL VISUAL BA SIC
Los ordenadores han utilizado varios mecanismos para conseguir lugares externos de almacenamiento, desde tarjetas perforadas y discos duros hasta disquetes y CDROM. Estos medios externos pueden almacenar cientos de megabytes, e incluso gigabytes, a un coste mucho menor que el de la RAM. El coste y la capacidad hacen que el almacenamiento externo de la información sea muy atractivo, incluso, aunque sea más lento e incómodo. Las grandes cantidades de datos manipuladas por los sistemas de almacenamiento externo también conlleva el problema de la organización. Se necesita alguna manera de decir "bueno, aquí está mi carta a la abuela", o "por allí está mi programa procesador de textos". Los pioneros en el mundo de la Informática, afrontaron este problema de la organización mediante una analogía empresarial, estableciendo un sistema de archivadores y llamando archivo a cada grupo independiente de datos. Los interfaces gráficos de usuario continúan basándose en esta analogía mediante el uso de iconos de carpetas de archivos y archivadores. Como el almacenamiento en disco se produce fuera del procesador principal, el ordenador tiene que establecer un conjunto de actividades para obtener o incluir información en un archivo. Visual Basic clasifica los archivos según la manera que tiene el ordenador de acceder a ellos: secuenciales, de acceso aleatorio o binarios. ■
Un archivo secuencial es un archivo de texto plano. Visual Basic lee y escribe en un archivo secuencial solamente una línea cada vez. Cada línea puede ser tan larga o tan corta como sea necesario.
■
Un archivo de acceso aleatorio es un archivo cuyo contenido puede leer y escribir Visual Basic en el orden que necesite. Todas las líneas (o registros) deben tener la misma longitud.
■
Un archivo binario es meramente una colección de bytes —Visual Basic no realiza presunciones de cómo están organizados los datos, lo cual permite que un programa organice y acceda a los datos de cualquier manera que requiera. Este tipo de archivos proporciona una gran flexibilidad, pero ello significa un mayor trabajo para el programa. (Debido a estas mayores demandas no trataremos los archivos binarios en este libro.)
Operaciones Operaciones con archivos Cuando se abre un archivo o se guarda el trabajo en un archivo, la mayoría de las aplicaciones para Windows presentan un cuadro de diálogo que permite especifi 244
car el nombre del archivo, el directorio y la unidad de disco. En Visual Basic, normalmente, usarás el control Common Dialog para presentar los cuadros de diálogo Archivo Abrir o Archivo Guardar como. Sin embargo, es posible que necesites crear un cuadro de diálogo que sea similar pero que tenga opciones adicionales. Se puede crear un cuadro de diálogo de ese tipo utilizando tres de las herramientas de la caja de herramientas de Visual Basic: la herramienta File List Box (cuadro de lista de archivos), la herramienta Directory List Box (cuadro de lista de directorios) y la herramienta Drive List Box (cuadro de lista de unidades de disco), que se muestran en la figura 9.1. Estas herramientas permiten crear tres clases de objetos que están diseñados para interactuar unos con otros; casi ninguna aplicación usa estos objetos por separado.
Figura 9.1.
Las herramientas herramientas File List Box (cuadro (cuadro de lista de archivos), archivos), Directory List Box Box (cuadro de lista de directorios) y Drive List Box (cuadro de li sta de unidades de disco)
Crear la aplicación TestDeArchivos
La aplicación TestDeArchivos muestra cómo crear un cuadro de diálogo utilizando los formularios de Visual Basic y las tres herramientas del sistema de archivos. El código de TestDeArchivos y el cuadro de diálogo son reutilizables, lo que significa que podrás copiarlo en otras aplicaciones que requieran las mismas características de acceso a archivos. El cuadro de diálogo se llamará Archivo Abrir, para distinguirlo del cuadro de diálogo Abrir Archivo producido por el control Common Dialog. Comienza abriendo un proyecto nuevo. Establece la propiedad Caption del formulario como Principal y la propiedad Name como frmPrincipal. Incluye un botón de comando en el medio del formulario y establece su propiedad Name como btnTest y su propiedad Caption como Test. Haz doble clic en el botón de comando para abrir una ventana de código y define el procedimiento Click del botón como se muestra muestra a continuación: continuación: 245
9 Archivos
EL LIBRO DEL VISUAL BASIC
Sub btnTest_Click ( ) Dim Seleccionado As String
Figura 9.2. continuación
Objeto
Seleccionado = AbrirDlgArchivos("*.TXT") I f Seleccionado = " " Then MsgBox "Cancelado" Else MsgBox "Se ha seleccionado el archivo" + Seleccionado End If End Sub
Este procedimiento llama a la función AbrirD lgArcbivos (que todavía no está defi nida), la cual mostrará un cuadro de diálogo que permitirá al usuario seleccionar un archivo basándose en la especificación de archivo *.TXT. Si el usuario no se lecciona un archivo y simplemente cierra el cuadro de diálogo, la función devol verá una cadena vacía; en caso contrario, el procedimiento btnTest_Click mostrará el nombre del archivo seleccionado.
Añ adir un s egu ndo for mul ario
Propiedad
Ajuste
Button1
Caption Default Name
Abrir True btnAbrir
Button2
Cancel Caption Name
True Cancelar btnCancelar
Cuando se cree una aplicación de Visual Basic que tenga más de un formulario, Visual Basic cargará sólo uno de ellos cuando el programa arranque. Para desig nar a frmPrincipal como el formulario inicial elige Project (proyecto) del menú Options (opciones). En el cuadro de diálogo Project Options, que se muestra en la figura 9.4, selecciona la opción Start Up Form (formulario inicial). La lista des-
El siguiente paso consiste en crear el cuadro de diálogo que va a mostrar la fun ción AbrirDlgArcbivos. Selecciona el comando New Form (nuevo formulario) del menú File o haz clic en el botón New Form de la barra de herramientas para po ner en la pantalla un segundo formulario de Visual Basic. Añádele a este nuevo formulario un cuadro de lista de archivos, un cuadro de lista de directorios, un cuadro de lista de unidades de disco y dos botones de comando. Establece las propiedades de estos objetos como se indica en la figura 9.2, y a continuación or ganiza los objetos en el formulario de manera similar a la que se muestra en la fi gura 9.3 de la página siguiente. Figura 9.3.
El diseño del formulario para el cuadro de diálogo Archivo Abrir de la aplicación Objeto
Propiedad
Ajuste
Form2
BorderStyle Caption Name
File1
Name
filLista
Dir1
Name
dirLista
Drive1
Name
drvLista
3 - Fixed Double Archivo Abrir frmAbrir
Figura 9.2.
Los ajustes adecuados gara el segundo formulario de la aplicación TestDeArchivos
246
(continúa)
Figura 9.4. El cuadro de diálogo Project Options (opciones del
proyecto) TestDeArchivos 247
LIBRO DEL VISUAL BASIC
plegable Setting (ajuste) que está en la parte superior del cuadro de diálogo contiene una lista con todos los formularios de la aplicación. Selecciona frmPrincipal en ella y luego haz clic en OK.
Cuando selecciones la opción Start Up Form en el cuadro de diá logo Project Options, date cuenta de que el cuadro de lista Settings in cluye la opción Sub Main además de una lista con los formularios de tu aplicación. Si eliges Sub Main le estás diciendo a Visual Basic que no cargue ningún formulario cuando el programa arranque , si no que ini cie la aplicación ejecutando el procedimiento llamado Main (el cual debes proporcionar). Esta opción se puede usar ; por ejemplo, s i el formu lario que muestra tu programa depende del día de la semana o de cier tos parámetros de inici alizaci ón.
Nota:
Añ adir un m ódu lo d e cód igo
A continuación, tendrás que escribir los procedimientos que controlen el cuadro de diálogo Archivo Abrir, incluyendo la función A bri rD lgA rcbivos. Podrías esperar que todo este código estuviese en el formulario frmAbrir, pero hay una consideración previa para que no sea así: el ámbito de todos los procedimientos de un módulo de formulario está restringido a ese módulo —es decir, sólo un procedimiento de frmAbrir puede acceder a otro procedimiento que esté en frmAbrir. Como la llamada a A bri rD lgA rcbivos está en frmPrincipal, la función no puede estar situada en frmAbrir. Una solución posible consiste en poner A bri rD lgA rcbi vos en frmPrincipal. Pero nosotros estamos interesados en hacer que el cuadro de diálogo sea reutilizable, y el botón Test de frmPrincipal está claro que no será necesario para todas las aplicaciones. Una solución mejor consiste en crear un módulo de código separado que contenga el código que controle el cuadro de diálogo. Como todos los procedimientos de un módulo de código tienen un ámbito global, hemos resuelto el problema de la accesibilidad. El módulo de código será una entidad separada que puede ser cargada en cualquier otra aplicación de Visual Basic. Añade el módulo de código seleccionando el comando New Module (nuevo módulo) del menú File de Visual Basic o haciendo clic en el botón New Module de la barra de herramientas. Visual Basic añadirá un archivo llamado MODULE1.BAS a la lista de la ventana Project y abrirá la ventana de código de este nuevo módulo. En la parte de declaraciones generales del módulo incluye la siguiente declaración: Global ArchivoSeleccionado As String 248
9 Archivos
Esta instrucción declara una variable global de cadena que contendrá el nombre del archivo seleccionado por el usuario. La variable debe ser global porque a ella accederán tanto la función A bri rD lgA rcbivos del módulo de código como los procedimientos de eventos de frmAbrir. Ahora añade el siguiente procedimiento al módulo de código: Function AbrirDlgArchivos (Mascara As String) As String Load frmAbrir frmAbrir.filLista.Pattern = Mascara ArchivoSeleccionado = " " frmAbrir.Show 1 AbrirDlgArchivos = ArchivoSeleccionado End Function
A esta función se la llama con una especificación de archivos en forma de máscara (como *.TXT) a modo de argumento. Primero carga en memoria el formulario frmAbrir mediante la instrucción Load (cargar). La instrucción Load se asegura de que el formulario esté disponible, pero no hace que sea visible. La siguiente línea de código establece la propiedad Pattern del objeto filList (el cuadro de lista de archivos) como la máscara que se ha pasado como argumento. La propiedad Pattern (patrón) de un cuadro de lista de archivos determina qué archivos aparecerán en la lista —por ejemplo, el patrón *.* permite que se muestren todos los archivos. Observa que el código está escrito como formulari o. objeto.propi edad en lugar de con la designación típica objeto.propiedad. Como la función A bri rD lgA r cbivos no están en el formulario frmAbrir, la función debe nombrar explícitamente al formulario si necesita acceder a un objeto de frmAbrir. A continuación, la variable ArchivoSeleccionado se establecerá como una cadena vacía, lo que indicará que todavía no se ha realizado ninguna selección. La siguiente declaración llama al método Show (mostrar) de frmAbrir, el cual hace que el formulario sea Visible. Show se puede llamar con un argumento de 0 ó de 1. Cuando se usa Show 0, el formulario se hace visible, pero se continúa procesando el procedimiento que llamó) al método Show : Cuando se usa Show 1, como en este caso, el formulario especificado no sólo se hace visible, sino que se muestra de manera modal —o sea, ningún otro formulario de la aplicación puede usarse mientras que éste esté en pantalla. El proceso en el procedimiento que llama se suspende hasta que se cierre el formulario modal. Cuando el usuario cierra el cuadro de diálogo, ocultando frmAbrir, la función
A bri rD lgA rchi vos continúa con su declaración final, que se encarga de establecer el valor que la función va a devolver como la cadena A rchi voSeleccionado. El 249
9 Archivos
LIBRO DEL VISUAL BASIC
control del programa vuelve entonces al procedimiento que llamó a la función
AbrirD lgArchivos.
Codificar los procedimientos de eventos
Todo lo que queda consiste en codificar los procedimientos de eventos en frm Abrir. Esos procedimientos están definidos en la figura 9.5. Los comentarios en el código describen lo que sucede a medida que el programa se ejecuta. Como puedes ver, el funcionamiento del sistema de archivos es relativamente simple, aunque se debe programar cuidadosamente la interacción entre ellos. (Puedes utilizar una técnica similar para crear el cuadro de diálogo Guardar como, aunque debes
Sub filLista_DblCIick ( ) ’Hacer doble clic en un nombre de archivo es lo mismo que ’hacer clic en el botón Abrir btnAbrir_Click End Sub Sub dirLista_Change ( ) ’Cuando el cuadro de lista de directorios cambie, establece una ’nueva ruta en el cuadro de lista de archivos filLista.Path = dirLista.Path End Sub Sub drvLista_Change ( ) ’Cuando el cuadro de lista de unidades de disco cambie, ’establece una nueva ruta en el cuadro de lista de directorios. ’También se produce un evento Change para dirLista dirLista.Path = drvLista.Drive End Sub Sub btnCancel_Click ( ) 'No se ha seleccionado ningún archivo; borra la cadena ’de caracteres y oculta el formulario ArchivoSeleccionado = " " Hide End Sub
Figura 9.5.
Código del programa para los procedimientos de eventos en la aplicación TestDeArchivos
25 0
(continúa)
Figura 9.5. continuación
Sub btnAbrir_Click ( ) ’Asegurarse de que se ha resaltado un nombre de archivo ’en el cuadro de lista de archivos If filLista.ListIndex >= 0 Then ’Obtener la ruta del archivo seleccionado ArchivoSeleccionado = filLista.Path ’Asegurarse de que la ruta acaba en una barra inversa If Right$(ArchivoSeleccionado, 1) <> "\" Then ArchivoSeleccionado = ArchivoSeleccionado + "\" End If ’Añadir el nombre del archivo seleccionado a la ruta ArchivoSeleccionado = ArchivoSeleccionado + filLista.List(filLista.ListIndex) End If ’Ocultar el formulario (cerrar el cuadro de diálogo) Hide End Sub
realizar una pequeña programación adicional para comprobar que la entrada del usuario sea válida; la documentación de Visual Basic proporciona una información más amplia.) Ejecutar y guardar la aplicación TestDeArchivos
Cuando ejecutes la aplicación TestDeArchivos verás solamente el formulario inicial que hemos designado (con el título Principal), el cual contiene el botón Test. Haz clic en el botón Test para que aparezca el cuadro de diálogo Archivo Abrir. Elige diferentes directorios y unidades de disco para ver cómo reaccionan los controles. Cuando selecciones un archivo, un cuadro de mensaje te informará de tu elección. Si no seleccionas ningún archivo o si haces clic en el botón Cancelar, un mensaje te avisará de que has cancelado el cuadro de diálogo. Puedes hacer clic otra vez en el botón Test y abrir de nuevo el cuadro de diálogo, tantas veces como quieras. Como puedes ver, se requiere muy poco esfuerzo para copiar las posibilidades del control Common Dialog (que se trató en el capítulo 5). La aplicación TestDeArchivos podría programarse con un solo formulario y alrededor de 10 líneas 25 1
El LIBRO DEL VISUAL BASIC
9 Archivos
de código en el procedimiento btnTest_Click si estuvieras usando el control Com mon Dialog. Asegúrate de guardar la aplicación TestDeArchivos porque puedes utilizar la función AbrirD lgArchivos en otros proyectos. Cuando finalices la aplicación, elige el comando Save Project (guardar proyecto) del menú File. Utiliza los nombres FRMPPAL.FRM, FRMABRIR.FRM y FRMABRIR.BAS para el formulario principal, el formulario del cuadro de diálogo y el módulo de código. Guardar el archivo del proyecto como TESTARCH.MAK.
Ar ch iv os sec uen ci ales Como ya se ha mencionado antes, el método más simple para procesar archivos de datos implica leer o escribir líneas de datos como si fueran líneas secuenciales del texto de un libro. Un editor de textos como la aplicación Bloc de notas de Windows, por ejemplo, trata los documentos de manera secuencial: lee la primera línea en la memoria y la muestra en pantalla, luego lee y muestra la segunda línea, y así sucesivamente. Cuando se le dice al programa que guarde el documento ocurre un proceso similar a medida que el documento se va escribiendo en el archivo línea por línea. La figura 9.6 ilustra este proceso. Date cuenta de los símbolos y de la ilustración. Estos dos caracteres son reminiscencias históricas de los días de las comunicaciones por teletipo, y se
Bytes en un archivo almacenado en disco
utilizan para separar una línea de otra en un archivo secuencial. Los teletipos imprimían en rollos de papel una línea cada vez. Además de imprimir texto también respondían a ciertos códigos de control no imprimibles como Ctrl+G, el cual hacía sonar un timbre en la máquina. Comenzar una línea nueva de texto requería dos códigos de control: el retorno de carro (ASCII 13), que movía la cabeza de impresión al comienzo de la línea; y el avance de línea (ASCII 10), que avanzaba el papel una línea. Estos códigos estaban contenidos en los archivos de texto junto con el propio texto. A medida que se desarrollaron nuevos dispositivos como los terminales y las impresoras de margarita, sus fabricantes adoptaron algunas de estas convenciones de caracteres de control. El mundo MSDOS/Windows también ha heredado el legado retorno de carro/avance de línea. Por tanto, a menudo verás esté par de caracteres abreviados como CR y LF. Ab ri r y ce rr ar arc hi vo s s ec ue nc ia les
La instrucción Open (abrir) le dice a Visual Basic a qué archivo debe acceder. Normalmente, usarás un cuadro de diálogo estándar como el que has diseñado anteriormente en este mismo capítulo para obtener el nombre de un archivo. Luego, especificarás ese nombre de archivo en la instrucción Open utilizando esta sintaxis: Open nombreDeArchivo For {Input | Output} As #numeroDeArcbivo Además de proporcionar el nombre del archivo, debes decirle a Visual Basic si quieres leer del archivo (input) o escribir en él (output), y debes darle un número de archivo. El número del archivo debe estar entre el 1 y el 255. Aquí tienes algunas instrucciones que abren archivos: Open "C:\CONFIG.SYS" For Input As #1
Datos mostrad os en p antalla
Doc$ = "C:\WWATCH1\BANZAI.DOC" Open Doc$ For Input As #2 Open "RESULTAD.TXT" For Output As #15
Figura 9.6.
Un archivo secuencial en disco y en la pantalla 252
Si tratas de abrir un archivo para lectura (input) cuando el archivo todavía no existe, Visual Basic producirá un error. Si estás abriendo el archivo para escritura (output), Visual Basic siempre creará un archivo nuevo, reemplazando cualquiera que ya exista con el mismo nombre. Si quieres comprobar la existencia de un archivo antes de abrirlo para escritura, utiliza la función Dir$. Si llamas a la función Dir$ con un nombre de archivo como parámetro, la función devolverá una copia 253
EL LIBRO DEL VISUAL BASIC
del nombre del archivo (lo que significa que el nombre existe) o una cadena vacía (lo que significa que no existe ningún archivo que tenga el nombre especificado). Este fragmento de programa ilustra la función Dir$: If Dir$("EDIP0.TXT") <> " " Then If InputBox("EDIP0.TXT" ya existe. ¿Lo borro?”) <> "Si" Then Exit Sub End If End If Open "EDIP0.TXT" For Output As #15
Después de que hayas terminado de trabajar con un archivo debes cerrarlo. La declaración Close (cerrar) de Visual Basic tiene la siguiente sintaxis: Glose #numeroDeArchivo El número de archivo de la instrucción Close corresponde con el número que le asignaste al archivo en la instrucción Open. Cuando cierres un archivo, todos los datos escritos en él (si hay alguno) se guardarán, y entonces otros programas tendrán acceso al archivo.
9 Archivos
y el código utiliza la variable VariableDeLinea para almacenar cada línea de texto que va leyendo. Escribir en archivos secuenciales
Escribir en un archivo secuencial es tan fácil como leer en uno de ellos. La ins trucción Print # escribe en un archivo secuencial de manera muy parecida a como el método Print escribe en un formulario. Aquí tienes la sintaxis de la instrucción Print #■: Print #numeroDeArchivo [, expresión [{ , | } expresión]... ]{ , | ; }] Los valores de expresiones separadas por punto y coma se escriben sin espacios entre ellas, mientras que los valores de las expresiones separadas por comas se escriben en campos de impresión separados (cada campo de impresión tiene 14 caracteres de largo). Al texto escrito se le añade un retorno de carro y un avance de línea a no ser que el último carácter de la instrucción Print # sea una coma o un punto y coma. La aplicación Configurador
Leer de archivos secuenciales
Leer de un archivo secuencial es notablemente fácil. Una sola instrucción, Line Input #, lee cada línea de texto. Como puedes ver en la sintaxis de la instrucción, se debe identificar el archivo (por el número) y proporcionar una variable de cadena en la que almacenar el texto leído: L i n e I n p u t # n ú m e r o D e A r c h i v o , v a r i a b l e D e C a d e n a
Construyamos un pequeño programa de ejemplo usando lectura y escritura secuencial. Lo llamaremos Configurador, ya que te permitirá editar tu archivo CONFIG.SYS. Crea un proyecto nuevo y sitúa un cuadro de texto grande y tres botones de comando en el formulario como se muestra en la figura 9.7. Establece las propiedades de los objetos según puedes ver en la figura 9.8.
La función EOF (que son las iniciales de fin de archivo en inglés) te permite saber cuándo se acaban Tiene un solo argumento (un número de archivo) y devuelve un valor de True, si toda la información ha sido leída. Aquí tienes un ejemplo de código que abre, lee, procesa y cierra un archivo secuencial: Open VariableDeArchivo For Input As #1 Do While Not EOF(1) Line Input #1, VariableDeLinea Procesar VariableDeLinea ’Procedimiento del usuario para ’gestionar una linea de texto Loop Close #1
Este código presupone la existencia de las variables de cadena VariableDeArchi vo y VariableDeLinea. VariableDeArchivo se inicializa con el nombre del archivo,
Figura 9.7.
El diseño inicial del formulario para la aplicación Configurador 254
255
L LIBRO DEL VISUAL BASIC
Objeto
Form1
Text1
Command1 Command2 Command3
9 Archivos
Propiedad
BorderStyle Caption Name Multiline Name ScrollBars Text Caption Name Caption Name Caption Name
Ajuste
3 Fixed Double Configurador CEdit True txtContenido 3 Both [ninguno] Abrir btnAbrir Guardar btnGuardar Salir bntSalir
Figura 9.8. El ajuste de las propiedades para la aplicación Configurador
En la sección de declaraciones generales del código, añade las siguientes declaraciones: Dim TextoModificado As Integer, ConfigEncontrado As Integer, CRLF As String
A continuación introduce los procedimientos que se muestran en la figura 9.9 correspondientes a sus objetos respectivos. Observa que la variable de cadena CRLF aparece en el código del programa Configurador. Normalmente, la implementación del fin de línea está oculta. La instrucción Line Input # lee hasta el final una línea y luego pasa una cadena que contiene todos los caracteres de la línea, excepto los terminadores. La instrucción Print #1 escribe lo que especifiques y añade, automáticamente, los caracteres de final de línea. Sin embargo, en el programa de ejemplo, el retorno de carro/avan ce de línea que había sido eliminado por la instrucción Line Input # es insertado de nuevo, de manera que el cuadro de texto sepa dónde está situado el final de la línea y pueda darle un formato adecuado a la presentación en pantalla. La figura 9.10 muestra el aspecto que puede tener la aplicación Configurador cuando ejecutes el programa y lo utilices para editar el archivo CONFIG.SYS.
Sub Form_Load ( ) TextoModificado = False ConfigEncontrado = False CRLF = Chr$(13) + Chr$(10) End Sub Sub btnAbrir_Click ( ) Dim CLinea As String If ConfigEncontrado Then Beep Exit Sub End If Open "C:\CONFIG.SYS" For Input As #1 Do While Not EOF(1) Line Input #1, CLinea txtContenido.Text = txtContenido.Text + CLinea + CRLF Loop CIose #1 ConfigEncontrado = True End Sub Sub btnGuardar_Click ( ) If Not (ConfigEncontrado And TextoModificado) Then Beep Exit Sub End If Open "C:\CONFIG.SYS" For Output As #1 Print #1, txtContenido.Text CIose #1 End Sub Sub bntSalir_Click ( ) En d End Sub Sub txtContenido_Change ( ) TextoModificado = True End Sub
Figura 9.9. El código del programa de la aplicación Configurador
256
257
9 Archivos
EL LIBRO DEL VISUAL BASIC
Ignorar los límites de la línea
Aunque la instrucción Print # normalmente se emplea para escribir solamente una línea (o parte de una línea), también es posible utilizarla para escribir varias líneas de texto a la vez, como hemos hecho en la aplicación Configurador. La instrucción Line Input #, por el contrario, está limitada a procesar la lectura de una línea cada vez. Sin embargo, se puede usar la función Input$ de Visual Basic para leer caracteres de un archivo. La función Input$ devuelve una cadena de caracteres leídos del archivo, incluyendo los caracteres de retorno de carro y avance de línea. Esta es la sintaxis:
Figura 9.10.
Editando) el archivo CONFIG.SYS con la aplicación Configurador
Input$( númeroD eCaracteres, #númeroD eArchi vo ) Se puede especificar la cantidad de caracteres que se van a leer cada vez, entre 1 y 32767 ( númeroDeCaracteres). Si el archivo contiene menos caracteres que el número que indiques, Visual Basic generará un mensaje de error Input past end of file (la lectura sobrepasó el final del archivo). El programa Configurador podría haberse escrito fácilmente utilizando la función
Input$. Aquí tienes el procedimiento btnAbrir_Click ( ) reescrito con I nput$■. Sub btnAbrir_Click ( ) Dim CLinea As String If ConfigEncontrado Then Beep Exit Sub End If Open "C:\CONFIG.SYS" For Input As #1 txtContenido.Text = Input$(LOF(1), #1) ’Supone que el archivo tiene ’me nos de 32767 caracte r es Close #1 ConfigEncontrado = True End Sub
Este procedimiento lee el archivo CONFIG.SYS completo de una vez, lo cual es aceptable porque CONFIG.SYS, normalmente, es un archivo muy pequeño. Con un archivo más grande necesitarás un bucle que compruebe si se ha llegado al final del archivo (EOF). Observa que el nuevo procedimiento también utiliza la función LO F (que es la abreviatura de longitud del archivo en inglés). Esta función toma como parámetro un número de archivo, y devuelve el número de bytes que contiene. 258
Ar ch iv os de ac ces o al eato ri o La mayoría de los programadores se encuentran alguna vez con dos problemas referentes a las lecturas secuenciales tal y como se han descrito. Un problema consiste en que no siempre resulta eficiente representar datos en forma de texto. For ejemplo, se puede almacenar el número 42,1596 en una variable de precisión simple de 4 bytes, pero se necesitaría utilizar 7 bytes para almacenar el número como texto en un archivo secuencial. El otro problema consiste en que algunas veces es necesario procesar la información de manera no secuencial. Volvamos una vez más a nuestras amigas las comadrejas copetudas alemanas. Cuando las dejamos la última vez, estábamos construyendo una base de datos para mantener su información. La presunción en ese momento consistía en suponer que toda la información sobre las comadrejas podía mantenerse en variables del programa (una matriz). Sin embargo, con este enfoque los cambios en los datos requieren cambios en el programa, un problema que es equivalente, en líneas generales, a tener que modificar físicamente el procesador de textos cada vez. que escribas un documento. Desde luego, la solución estriba en almacenar los datos en un archivo. Sin embargo, no querrás almacenar los datos como texto; es preferible almacenarlos exactamente como están almacenados en el programa: enteros como enteros, números de precisión doble como números de precisión doble, etc. Además, debes poder acceder a las estadísticas vitales de cualquier comadreja en cualquier momento, sin tener que procesar el archivo entero linealmente hasta encontrar lo que necesitas. En las páginas siguientes construiremos la base de datos Comadrejas para que sirva de ejemplo de un programa que usa archivos de acceso aleatorio. 259
EL LIBRO DEL VISUAL BASIC
Ab ri r y ce rr ar arc hi vo s d e a cc es o ale at or io
La sintaxis de la instrucción Open para los archivos de acceso aleatorio es la siguiente: Open nombreDeArchivo For Random As númeroDeArchivo Len = longitudDelRegistro En esta versión de la instrucción Open no se especifica el modo de lectura o de escritura, porque se puede leer y escribir en archivos de acceso aleatorio sin tener que abrirlos y cerrarlos cada vez. Adicionalmente, debes suministrar una longitud del registro, que es el número de bytes que se deben leer o escribir con cada instrucción Get o Pul (las instrucciones para leer y escribir en el archivo). Por ejemplo, si tienes pensado usar un archivo que contenga números enteros, la longitud del registro debe ser 2. Si en lugar de ser enteros, todos los valores fueran monetarios, la longitud del registro sería 8. Si no especificas una longitud para el registro, Visual Basic asumirá una longitud de 128. (Muy raro sería que este valor por omisión no sea apropiado para tu archivo.) Para determinar la longitud del registro de la base de datos Comadrejas es necesario ver qué datos deseamos leer y escribir. En el capítulo 6 definimos el tipo de datos BTFComadreja como sigue: Type BTFComadreja Nombre As String Color As String Peso As Integer Longitud As Integer FechaNacimiento As Double ColorCopete As String LongitudCopete As Integer End Type
Suponiendo que todos los registros sean como éste, podemos sumar todos los campos componentes para obtener el tamaño del registro. Por desgracia, tres de los campos son cadenas de caracteres (strings), y no tenemos manera de conocer sus tamaños. Para solucionar este problema, Visual Basic permite declarar tamaños fijos para las cadenas. Si te decides por esta posibilidad e impones algunas restricciones a los datos, podrás calcular la longitud del registro. Por ejemplo, si restringes los nombres de las comadrejas a un máximo de 32 caracteres y los nombres de los colores a 12 caracteres, podrás redefinir el tipo BTFComadreja como sigue: 260
9 Archivos
Type BTFComadreja Nombre As String * 32 Color As String * 12 Peso As Integer Longitud As Integer FechaNacimiento As Double ColorCopete As String * 12 LongitudCopete As Integer End Type
La expresión String * 32 adjudica el tamaño fijo de 32 bytes a todos los nombres de comadreja. Si un nombre tiene menos de 32 caracteres, Visual Basic lo rellenará con espacios. Los nombres con más de 32 caracteres se truncarán. Así, la longitud de un registro BTFComadreja es ahora de 70 bytes (32+12+2+2+8+12+2). Cerrar un archivo de acceso aleatorio es simple: usa la instrucción Close exactamente como si fuese un archivo secuencial. Por ejemplo, si abres un archivo de acceso aleatorio como archivo #1, usa la instrucción Close #1 para cerrarlo. Leer y escribir en un archivo de acceso aleatorio
Para leer y escribir en un archivo de acceso aleatorio se utilizan las instrucciones
Get y Put. La sintaxis de las dos instrucciones es simple: Get #númeroDeArchivo, [númeroDeRegistro], variable P u t # n ú m e r o D e A r c h i v o , [ n ú m e r o D e R e g i s t r o ] , v a r i a b l e
La instrucción Get lee del archivo y almacena los datos en la variable, mientras que la instrucción Put escribe el contenido de la variable en el archivo. En ambos casos se puede especificar opcionalmente el número del registro. Si no se especifica el número del registro, se utilizará la siguiente posición secuencial. Un archivo de acceso aleatorio se parece mucho a una matriz de un tipo definido por el usuario. La diferencia principal radica en que los datos se almacenan en un disco, en lugar de hacerlo en la memoria y, de esta manera, los datos no se desvanecerán cuando el programa finalice. (Ten en cuenta también que el índice de los registros en un disco comienza en el 1 —registro 1—, mientras que los índices de una matriz comienzan a partir del 0.) La figura 9.11 muestra la manera en que se almacenan los registros en un disco. La aplicación de la base de datos Com adrejas
Ahora comencemos a construir la aplicación de la base de datos Comadreja, la cual mantendrá los datos de nuestras comadrejas copetudas alemanas. Evidente 261
9 Archivos
EL LIBRO DEL VISUAL BASIC
más, habrá botones de comandos que permitirán añadir una comadreja nueva al archivo o eliminar una de ellas. Para comenzar, crea un proyecto nuevo. Dispon un cuadro combinado sobre el formulario, así como seis cuadros de texto, siete etiquetas y dos botones de co mando. El diseño inicial se muestra en la figura 9.12 de la página anterior. Establece las propiedades de los objetos de pantalla como se especifica en la fi gura 9.13. Cuando lo hayas hecho, el formulario debe parecerse al que se mues tra en la figura 9.14.
Figura 9.11.
Los registros en un archivo de acceso aleatorio
mente, si resulta que no tienes ninguna comadreja, recuerda que puedes modifi car fácilmente el programa para que gestione otros tipos de datos. El plan básico para la base de datos Comadrejas implicará la utilización de un ar chivo de acceso aleatorio para almacenar la información sobre las comadrejas. Cuando se ejecute la aplicación, ésta examinará el archivo, obtendrá los nombres de todas las comadrejas y mostrará la lista de los nombres en un cuadro de lista. Cuando el usuario elija un nombre del cuadro de lista, el programa buscará el registro de esa comadreja en el archivo y mostrará la información relevante. Ade-
Objeto
Propiedad
Ajuste
Form1
BorderStyle Caption Name
3 - Fixed Double Comadrejas Comadrejas
Label1
Alignment Caption
1 - Right Justify Nombre:
Combol
Name Style
cboNombre 2 - Dropdown list
Label 2
Alignment Caption
1 - Right Justify Color:
Text1
Name Text
txtColor [Ninguno]
Label 3
Alignment Caption
1 - Right Justify Peso:
Text2
Name Text
txtPeso [Ninguno]
Label4
Alignment Caption
1 - Right Justify Longitud:
Text3
Name Text
txtLongitud [Ninguno]
Label5
Alignment Caption
1 - Right Justify Fecha de nacimiento:
Text4
Name Text
txtFechaNacimiento [Ninguno]
Figura 9.12.
El diseño inicial del formulario para la aplicación de la hase de datos Comadrejas
262
Figura 9.13.
(continúa)
El ajuste de las propiedades para la aplicación de la hase de datos Comadrejas
263
EL LIBRO DEL VISUAL BASIC
9 Archivos
Figura 9.13. continuación Objeto
Propiedad
Ajuste
Label6
Alignment Caption
1 - Right Justify Color del copete:
Text 5
Name Text
txtColorCopete [Ninguno]
Label 7
Alignment Caption
1 - Right Justify Longitud del copete:
Text6
Name Text
txtLongitudCopete [Ninguno]
Command1
Caption Name
Añadir btnAñadir
Command2
Caption Name
Eliminar btnEliminar
Type BTFComadreja Nombre As String * 32 Color As String * 12 Peso As Integer Longitud As Integer FechaNacimiento As Double ColorCopete As String * 12 LongitudCopete As Integer End Type Global Const COMADREJA_LONGITUD = 70
Al definir la constante COMADREJA_LONGITUD hacemos que el programa sea más fácil de leer; ver el nombre de la constante en lugar del número 70 es un re cordatorio de lo que realmente significa ese valor. Sin embargo, una razón más importante para definir la constante es la posibilidad de modificar el programa. Supón que en el futuro necesitas redefinir el tipo BTFComadreja; quizás tengas que añadir un campo nuevo, o quizás decidas que 32 caracteres son insuficientes para los nombres. Si no hubieses utilizado un nombre de constante para la longi tud del registro, tendrías que examinar todas las líneas del programa, buscando el número 70, y cambiándolo por el nuevo valor. Además, tendrías que asegurarte de que el 70 era realmente una referencia al tamaño del registro y no algún otro valor. Usando el nombre de una constante no tienes más que cambiar el valor de la constante y el resto del programa será actualizado instantáneamente para traba jar con el tamaño del registro recién definido. El resto de las declaraciones son locales del formulario. Cierra la ventana de códi go del módulo de código y abre la del formulario. Añade las siguientes líneas a la sección de declaraciones generales:
Figura 9.14.
El diseño del formulario de la aplicación de la base de datos Comadrejas completado
Esta aplicación necesita algunas declaraciones globales. Como las variables globa les y las declaraciones de tipo no se pueden declarar en un módulo de formu lario, es necesario crear un módulo de código. Elige el comando New Module del menú File. Añade las siguientes declaraciones a la sección de declaraciones gene rales de la ventana de código: 264
Dim ComadrejaActual As Integer Dim NumeroDeComadrejas As Integer Dim RegistroModificado As Integer
'Número de la comadreja actual 'Número total de comadrejas 'Bandera booleana
Estas variables contendrán un número de índice que indicará, respectivamente, qué registros se están mostrando en pantalla, el número total de comadrejas al macenadas en el archivo y si el usuario ha modificado o no cualquiera de los da tos de la pantalla. Para inicializar el sistema, el programa debe leer todos los registros del archivo y poner los nombres de todas las comadrejas en el cuadro de lista. El usuario podrá entonces elegir un nombre. El programa responderá leyendo todo el registro de 265
9 Archivos
EL LIBRO DEL VISUAL BASIC
esa comadreja y mostrándolo en pantalla. Si el usuario modifica el registro, esos cambios se escribirán en el archivo. Para ilustrar un estilo de programación que funcione bien con grandes cantidades de datos, el programa no leerá todos los registros en una matriz sino que trabajará únicamente con variables de memoria. Como recordarás, una matriz no puede tener un índice mayor de 32767. Esas son muchas comadrejas y, a 70 bytes por registro, necesitarías más de 2 megabytes de RAM. Manteniendo en memoria sólo un registro cada vez podrías reducir considerablemente los requerimientos de memoria. Para que sea más sencillo, el programa requiere que todos los nombres estén a la vez en la memoria, pero si el nombre medio tiene 8 ó 9 caracteres, esto no debería ser un problema. Suponiendo que el archivo de datos existe en una posición predeterminada en el disco, entonces podemos escribir la siguiente rutina de inicialización. (En esta aplicación no utilizaremos la función AbrirD lgArchivos. En su lugar supondremos que el archivo de datos tiene un nombre y una ruta fijos. En mi ordenador, Visual Basic están en el directorio C:\VB; asegúrate de usar una ruta de acceso que sea válida para el tuyo.) Sub ComadrejaInicio ( ) Dim Comadreja As BTFComadreja, C As Integer Open "C:\VB\COMADREJ.DAT" For Random As #1 Len = COMADREJA_LONGITUD NumeroDeComadrejas = LOF(1) / COMADREJA_LONGITUD For C = 1 To NumeroDeComadrejas Get #1, C, Comadreja cboNombre.AddItem Comadreja.Nombre Next C End Sub
La instrucción Open abre o crea un archivo. La función LOF devuelve el número total de bytes del archivo, que es dividido por el tamaño de un registro para obtener el número total de registros. Luego se leen todos los registros existentes, y se insertan todos los nombres de comadrejas en el cuadro de lista. Cuando la inicialización esté completa, el usuario podrá elegir un nombre de comadreja para ver sus datos y editarlos. Los procedimientos que se muestran en la figura 9.15 responden a estos requerimientos. El procedimiento MostrarComadreja toma un número de índice como parámetro. Establece ComadrejaActual a ese número y obtiene los datos de esa comadreja, actualizando todos los campos de pantalla. A continuación establece una bandera 266
que indica que el registro todavía no ha sido modificado. El procedimiento ActualizarComadrejaActual comprueba si el registro ha sido modificado. Si no lo ha sido, simplemente termina. En caso de que el usuario haya modificado el registro, se leerá el valor actual de cada campo y el registro resultante se escribirá de vuelta en el disco. Sub MostrarComadreja (ByVal Ix As Integer) Dim Comadreja As BTFComadreja Get #1, Ix + 1, Comadreja ComadrejaActual = Ix cboNombre.ListIndex = Ix txtColor.Text = Comadreja.Color txtPeso.Text = Str$(Comadreja.Peso) txtLongitud.Text = Str$(Comadreja.Longitud) txtFechaNacimiento.Text = Format(Comadreja.FechaNacimiento, "dd/mm/yy") txtColorCopete.Text = Comadreja.ColorCopete txtLongitudCopete.Text = Str$(Comadreja.LongitudCopete) RegistroModificado = False End Sub Sub ActualizarComadrejaActual Dim Comadreja As BTFComadreja If Not RegistroModificado Then Exit Sub End If Comadreja.Nombre = cboNombre.Text Comadreja.Color = txtColor.Text Comadreja.Peso = Val(txtPeso.Text) Comadreja.Longitud = Val(txtLongitud.Text) Comadreja.FechaNacimiento = DateValue(txtFechaNacimiento.Text) Comadreja.ColorCopete = txtColorCopete.Text Comadreja.LongitudCopete = Val(txtLongitudCopete.Text) Put #1, ComadrejaActual + 1, Comadreja RegistroModificado = False End Sub
Figura 9.15.
Los procedimientos MostrarComadreja y ActualizarComadrejaActual
267
EL LIBRO DEL VISUAL BASIC
Las otras tareas principales del programa consisten en crear nuevos registros y en eliminar los antiguos. Puedes crear registros nuevos con la función que se muestra en la figura 9.16. (Trataremos los procedimientos de eliminación después.) La función ComadrejaNneva rellena un registro de comadreja con el nombre pasado a la función y con valores por omisión para los otros campos. Incrementa NumeroDeComadrejas para que tenga en cuenta a la nueva comadreja, escribe el nuevo registro en el archivo de datos y luego añade el nombre al cuadro de lista. Como el nuevo registro siempre se añade al final del archivo, su índice en el cuadro de lista es el mismo que el valor antiguo de NumeroDeComadrejas, el cual es devuelto al procedimiento de llamada como valor de la función. Los procedimientos de este programa que has escrito hasta ahora, se han definido en la sección general del formulario porque cada rutina lleva a cabo una tarea específica. Estos procedimientos pueden ser llamados por cualesquiera otros procedimientos, incluyendo a los procedimientos de eventos, de manera que es mejor definirlos como unidades independientes en lugar de codificarlos como parte de
9 Archivos
un procedimiento de evento de un objeto específico. Es mejor crear el trabajo específico de la aplicación en procedimientos generales y hacer que el código de los procedimientos de eventos sirva de vínculo entre el interface de usuario y la parte funcional del programa. El primer vínculo importante consiste en conectar el arranque del programa con la inicialización de la base de datos. Cuando se arranca una aplicación, el primer procedimiento que es llamado es el procedimiento Load. Sub Form_Load ( ) ComadrejaInicio End Sub
También debes enlazar la elección por parte del usuario de un nombre en el cuadro de lista con la presentación en pantalla del registro por parte del programa, y debes enlazar la creación de un nuevo registro con el botón Añadir. Estas dos ru tinas realizan esas conexiones: Sub cboNombre_Click ( ) MostrarComadreja cboNombre.ListIndex End Sub
Function ComadrejaNueva (NuevoNombre As String) As Integer Dim Comadreja As BTFComadreja Comadreja.Nombre = NuevoNombre 'Asignar la información por omisión Comadreja.Color = "Marrón" Comadreja.Peso = 0 Comadreja.Longitud = 0 Comadreja.FechaNacimiento = Now Comadreja.ColorCopete = "Marrón" Comadreja.LongitudCopete = 0 'Asignar un número de indice para devolver NumeroDeComadrejas = NumeroDeComadrejas + 1 'Escribir el nuevo registro en el disco Put #1, NumeroDeComadrejas, Comadreja 'Añadir el nombre a la lista de comadrejas cboNombre.Addltem Comadreja.Nombre RegistroModificado = False End Function
Figura 9.16.
La función ComadrejaNueva
268
Sub btnAñadir_Click ( ) Dim NuevoNombre As String NuevoNombre = InputBox("¿Cuál es el nombre de la nueva comadreja?”) If NuevoNombre = " " Then Exit Sub End If MostrarComadreja ComadrejaNueva(NuevoNombre) End Sub
Configurar la presentación del registro es fácil porque simplemente añadiendo 1 al índice del nombre del cuadro de lista se obtiene la posición índice del registro en el archivo. Con la segunda rutina, al hacer clic en el botón Añadir, se le pregunta al usuario un nombre para la nueva comadreja. Si el usuario no proporciona un nombre no se añade el registro. Si el usuario proporciona un nombre, el procedimiento llama a ComadrejaNueva para crear un registro y pasar directamente a MostrarComadreja el valor del índice que aquella devuelve, de manera que se pueda mostrar el nuevo registro. Para completar la aplicación debemos implementar soporte para la edición de los registros de las comadrejas. Se requieren dos simples rutinas para cada cuadro de texto: el procedimiento Change ejecutará la declaración RegistroModificado = 269
EL LIBRO DEL VISUAL BASIC
9 Archivos
True , y el procedimiento LostFocus actualizará el registro llamando a ActualizarComadrejaActual. El código de cada cuadro de texto aparece en la figura 9.17.
Sub txtColorCopete_LostFocus ( ) ActualizarComadrejaActual End Sub
Sub txtColor_Change ( ) RegistroModificado = True End Sub
Sub txtLongitudCopete_Change ( ) RegistroModificado = True End Sub
Sub txtColor_LostFocus ( ) ActualizarComadrejaActual End Sub
Sub txtLongitudCopete_LostFocus ( ) ActualizarComadrejaActual End Sub
Sub txtPeso_Change ( ) RegistroModificado = True End Sub Sub txtPeso_LostFocus ( ) ActualizarComadrejaActual End Sub
Es mejor establecer una bandera en el procedimiento Change que llamar directamente a la rutina ActualizarComadrejaActual , ya que Visual Basic llamará al procedimiento Change cada vez que el contenido del cuadro de texto cambie. Por ejemplo, si escribes el texto Negro en el cuadro de texto Color, el procedimiento Change es llamado cinco veces, una vez por cada letra introducida. Pero el registro no tiene que ser actualizado hasta que el dato del cuadro de texto esté completo, así que el procedimiento llama a la rutina de actualización en el procedimiento del evento LostFocus.
Sub txtLongitud_Change ( ) RegistroModificado = True End Sub Sub txtLongitud_LostFocus ( ) ActualizarComadrejaActual End Sub
¿Qué es el evento LostFocus? Cualquier control de la pantalla puede ser el "foco de atención" en algún momento durante la ejecución de una aplicación. Windows controla la situación mediante los eventos GotFocus y LostFocus. Cuando se hace clic en un cuadro de texto, por ejemplo, se emite el evento GotFocus. El foco se queda en el cuadro de texto mientras estás escribiendo. Cuando pulsas la tecla Tab o haces clic en otro control, el cuadro de texto recibe un evento LostFocus, y el nuevo control recibe GotFocus. Por tanto, cuando se ejecute el procedimiento LostFocus de un cuadro de texto sabrás que el usuario ha terminado de escribir y que el programa puede llamar con total seguridad a la rutina de actualización.
Sub txtFechaNacimiento_Change ( ) RegistroModificado = True End Sub Sub txtFechaNacimiento_LostFocus ( ) ActualizarComadrejaActual End Sub Sub txtColorCopete_Change ( ) RegistroModificado = True End Sub
Figura 9.17. Los procedimientos de los eventos para los cuadros de texto de la aplicación
270
Figura 9.17. continuación
(continúa)
La aplicación de la base de datos Comadrejas está ahora preparada para funcionar. Pulsa F5 para arrancarla. Como es la primera vez que ejecutas el programa no aparecerán entradas en el cuadro de lista. Haz clic en el botón Añadir e introduce los datos de tres o cuadro comadrejas. A continuación pulsa la combinación de teclas Alt+F4 para salir del programa e, inmediatamente, ejecútalo otra vez. 271
EL LIBRO DEL VISUAL BASIC
Como se puede ver en la figura 9.18, debes poder elegir de entre los nombres que introdujiste en la sesión anterior.
9 Archivos
CO MADREJ .DAT
Figura 9.19.
Un archivo de datos de cuatro registros de la base de datos Comadrejas
CO MADREJ .DAT
CO MADREJ .TMP A
Figura 9.18.
1.
Ejecución de la aplicación de la base de datos Comadrejas
Copiar los
A, C y
registros
D al nuevo
B
archivo
D
Eliminar registros
El modelo lógico de esta aplicación es eficiente y relativamente fácil de comprender. Pero la simplicidad tiene un precio: no hay una manera sencilla de borrar registros. Imagina que el archivo de la base de datos COMADREJ.DAT contiene cuatro registros para las comadrejas que, de forma poco imaginativa, denominaremos A, B, C y D, como se muestra en la figura 9.19. Crear estos registro ha producido un archivo que contiene 280 bytes (4 x 70).
3. Asignarle el nombre original al archivo nuevo
2. Borrar el archivo original
CO MADREJ .DAT
CO MADREJ .DAT
No se pueden quitar simplemente bytes del medio del archivo y "tirarlos". Si quisieras borrar el registro de la comadreja B, por ejemplo, solamente tendrías dos posibilidades: copiar todos los registros excepto el de B a un archivo nuevo, o sobrescribir el registro B con datos nuevos. Si haces la copia, luego podrías borrar el archivo original y ponerle a la copia el nombre del archivo original. Esta solución se ilustra en la figura 9.20. Si sobrescribes el registro de B con otros datos —por ejemplo, con los de un registro que contenga todos los datos en blanco—, el cuadro de lista podría llegar a estar lleno de entradas en blanco. Podrías pensar que la rutina de inicialización 272
Figura 9.20.
Copiar registros y cambiar el nombre del archivo
273
9 Archivos
EL LIBRO DEL VISUAL BASIC
no tendría más que omitir cualquier registro que tuviese el campo nombre en blanco. Por desgracia, si omites registros, la aplicación no será capaz de encontrar el registro que corresponde a cada entrada en la lista. La figura 9.21 ilustra este problema. La aplicación, tal y como está escrita actualmente, requiere un mapa de uno a uno entre los nombres del cuadro de lista y los registros del archivo. (Este requerimiento también significa que no se puede establecer como True la propiedad Sorted del cuadro de lista, ya que desordenaría la relación entre los valores índice del cuadro de lista y la posición de los registros en el archivo.) Sin embargo, se puede sortear este problema manteniendo un mapa separado entre el índice del cuadro de lista y las posiciones del archivo. La figura 9.22 muestra un ejemplo. ¿Qué solución es la preferible? Si sabes que los datos de la aplicación van a ser siempre pocos, el método de copiar y cambiar el nombre podría ser el mejor. Puede implementarse sin afectar al código que ya está escrito y la aplicación sigue siendo fácil de comprender. Sin embargo, en un programa que maneje grandes cantidades de datos, copiar grandes archivos conllevaría un gran gasto de tiempo y requeriría suficiente espacio libre en el disco, para que tanto el archivo original como la copia coexistan a la vez; si el espacio en el disco es reducido, el programa podría fallar. Crear un mapa permite al programa funcionar más deprisa, algo que los usuarios finales aprecian. Pero esta solución implicará añadir complejidad (y posiblemente bugs) y reescribir parte del código existente. Como programador, a menudo tendrás que tomar decisiones como ésta. Es muy importante comprender con claridad las tareas del programa y la naturaleza de los datos antes de tomar una decisión. No importa que el código no tenga bugs,
A (En blanco ) C D Registros Figura 9.21.
Sobrescribir un registro con blancos
274
A (En blanco ) C D Registros Figura 9.22.
Hacer mapas de las posiciones del cuadro de lista
ya que no tendrá ninguna utilidad si los usuarios no pueden aceptar las decisiones que hayas tomado con respecto al diseño. Echemos una mirada más de cerca a las dos alternativas para borrar registros de la base de datos Comadrejas. La solución de copiar y cambiar el nombre no requiere cambios en el código existente. Simplemente, añade al programa el procedimiento que se muestra en la figura 9.23. El procedimiento btnEliminar_Click abre un archivo nuevo y copia todos los registros, excepto el actual en él. Luego se cierran ambos archivos. La instrucción Kill (eliminar) toma como parámetro el nombre del archivo original y borra ese archivo. Después, la instrucción Name (nombre) cambiará de nombre al archivo copiado. Cuando se haya terminado con el archivo de datos, se borrará el contenido del cuadro de lista y el programa llamará de nuevo al procedimiento Comadrejalnicio para volver a cargar el cuadro de lista. La segunda alternativa, usando una matriz como mapa, es algo más compleja porque requiere realizar modificaciones en el código ya existente. La figura 9.24 contiene sólo las rutinas que deben modificarse para producir la versión que utiliza el mapa; las líneas que se han añadido o modificado aparecerán resaltadas. El programa modificado utiliza una propiedad llamada ItemData, que es una característica interna del cuadro de lista. ItemData es una matriz que contiene un entero largo por cada elemento del cuadro de lista. Esta matriz se utiliza para almacenar el mapa —es decir, contiene el índice real del archivo de disco de cada entrada. En la versión original, la variable ComaclrejaActual podía referirse tanto a la posición en el archivo como al índice del cuadro de lista. En la nueva ver 275
EL LIBRO DEL VISUAL BASIC
Sub btnEliminar_Click ( ) Dim Comadreja As BTFComadreja, C As Integer ’Copiar todos los registros excepto el actual en el archivo ’temporal Open "C:\VB\COMADREJ.TMP" For Random As #2 Len = COMADREJA_L0NGITUD For C = 1 To NumeroDeComadrejas If C <> ComadrejaActual + 1 Then Get #1, C, Comadreja Put #2, , Comadreja End If Next W ’Cerrar y cambiar el nombre Close #1 Close #2 Kill "C:\VB\COMADREJ.DAT" Name "C:\VB\COMADREJ.TMP" As "C:\VB\COMADREJ.DAT“ ’Borrar el cuadro de lista y volver a cargar la base de datos cboNombre.Clear ComadrejaInicio End Sub
Function ComadrejaNueva (NuevoNombre As String) As Integer Dim comadreja As BTFComadreja Comadreja.Nombre = NuevoNombre ’Asignar la información por omisión Comadreja.Color = "Marrón" Comadreja.Peso = 0 Comadreja.Longitud = 0 Comadreja.FechaNacimiento = Now Comadreja.ColorCopete = "Marrón" Comadreja.LongitudCopete = 0 'Asignar un número de indice para devolver
C o m a d r e j a N u e v a = c b o N o m b r e . Li s t C o u n t ’Incrementar el número de comadrejas ComadrejaNueva = NumeroDeComadrejas + 1 ’Escribir el nuevo registro en el disco Put #1, NumeroDeComadrejas, Comadreja ’Añadir el nombre a la lista de comadrejas cboNombre.AddItem Comadreja.Nombre
cboNombre.ItemData(cboNombre.Newlndex) = NumeroDeComadrejas
R e g i stroModificado = False End Function Sub MostrarComadreja (ByVal Ix As Integer) Dim Comadreja As BTFComadreja
Figura 9.23.
El procedimiento btnEliminar_Click para la aplicación de la base de datos Comadrejas
sión, ComadrejaActual se refiere sólo al índice en el cuadro de lista; la posición en el archivo debe obtenerse con la expresión cboNombre.ItemData(Comadreja-
Actual).
Los cambios de los procedimientos ComadrejaNueva, MostrarComadreja y ActualizarComadrejaActual son triviales, y simplemente sirven para asegurarse de que el mapa se usa y se mantiene correctamente. Los cambios en ComadrejaInicio son relativamente evidentes: a medida que se lee un registro del archivo, se comprueba si el primer carácter del campo nombre es un blanco (un espacio); en caso de que así sea, ese registro se ignora. A medida que el programa lee los registros escribe los valores apropiados en la matriz mapa ItemData. La propiedad NewIndex (nuevo índice) contiene el valor ListIndex del elemento que se haya añadido más recientemente. Como no necesitarás tener más la relación de uno a 276
Get #1, cboNombre.ItemData(Ix), Comadreja ComadrejaActual = Ix cboNombre.ListIndex = Ix txtColor.Text = Comadreja.Color txtPeso.Text = Str$(Comadreja.Peso) txtLongitud.Text = Str$(Comadreja.Longitud) txtFechaNacimiento.Text = FormatComadreja.FechaNacimiento, "dd/mm/yy”) txtColorCopete.Uext = Comadreja.ColorCopete txtLongitudCopete.Text = Str$(Comadreja.LongitudCopete) RegistroModificado = False End Sub
Figura 9.24.
El código revisado del programa, implementando un mapa mediante una matriz
(cont.)
9 Archivos
EL LIBRO DEL VISUAL BASIC
Figura 9.24. continuación
Figura 9.24. continuación
Comadreja.Nombre = " "
Sub ActualizarComadrejaActual Dim Comadreja As BTFComadreja If Not RegistroModificado Then Exit Sub End If Comadreja.Nombre = cboNombre.Text Comadreja.Color = txtColor.Text Comadreja.Peso = Val(txtPeso.Text) Comadreja.Longitud = Val(txtLongitud.Text) Comadreja.FechaNacimiento = DateValue(txtFechaNacimiento.Text) Comadreja.ColorCopete = txtColorCopete.Text Comadreja.LongitudCopete = Val(txtLongitudCopete.Text) Put #1, cboNombre.ItemData(ComadrejaActual), Comadreja RegistroModificado = False End Sub Sub Comadreja Inicio ( ) Dim Comadreja As BTFComadreja, C As Integer Open "C:\VB\COMADREJ.DAT" For Random As #1 Len = COMADREJA_LONGITUD NumeroDeComadrejas = L0F(1) / COMADREJA_LONGITUD For C = 1 To NumeroDeComadrejas Get #1, C, Comadreja ’Saltar los registros borrados If Mid$(Comadreja.Nombre, 1, 1) <> " " Then cboNombre.AddItem Comadreja.Nombre cboNombre.ItemData(cboNombre.NewIndex) = C
End Sub
uno entre el disco y el cuadro de lista, puedes establecer la propiedad Sorted del cuadro de lista como True en esta versión del programa. Finalmente, el procedimiento btnEliminar_Click es completamente distinto en el código revisado. Para eliminar el registro actual, el programador lo sobrescribe con un registro en blanco. Una vez se haya sobrescrito el registro, se eliminara el nombre correspondiente del cuadro de lista. Queda un problema menor con la versión que utiliza el mapa: cada registro borrado requiere espacio, y los registros nuevos se añaden al f inal del archivo. Sería magnífico si el procedimiento ComadrejaNueva usase los registros borrados, en caso de que haya alguno, en lugar de ampliar el archivo automáticamente. Este cambio evitaría que el archivo de datos se hiciese innecesariamente grande. Im plementar esta modificación queda como ejercicio para el lector. (Siempre he querido decir eso.)
Configuración A menudo querrás guardar uno o dos datos importantes de una sesión de trabajo de un programa a otro —quizás la configuración de una opción, como el modo analógico o digital de tu programa reloj. Las variables normales no sirven porque desaparecen cuando el programa finaliza. Podrías crear un archivo de datos, pero eso sería mucho trabajo para tan pocos datos.
End If Next C End Sub Sub btnEliminar_Click ( ) Dim Comadreja As BTFComadreja ’Sobrescribir el registro actual (continúa)
278
Put #1, cboNombre.ItemData(ComadrejaActual), Comadreja ’Actualizar la lista de nombres y el mapa eliminando un elemento cboNombre.RemoveItem ComadrejaActual
La solución estándar para este problema en el caso de las aplicaciones para Windows consiste en almacenar los valores en el archivo WIN.INI, que es el archivo de inicialización de Windows. Cada aplicación tiene su propia sección en este archivo, indicada por un nombre entre corchetes. A continuación del nombre están los nombres de las variables y sus valores. Aquí tienes algunas líneas de mi archivo WIN.INI : 279
EL LIBRO DEL VISUAL BASIC
[Paint Shop] OpenDir=C:\DOCS FileData=65,65,0,0,0,0 SaveDir =C:\DOCS\BOOK [Corel Draw] Dir=C:\WIND0WS\C0REL [Clock] iFormat=0
La manera obvia de proceder consiste en abrir el archivo WIN.INI, leer cada línea buscando la sección correcta, y luego editar las líneas que hay detrás. Esto podría ser un montón de trabajo si tuvieras que escribir todo el código tú mismo. Sin embargo, esta operación se realiza con tanta frecuencia que, afortunadamente, está construida dentro del propio Windows. Aunque ninguna función de Visual Basic puede acceder a ese código, tú puedes escribir tus propias funciones. Librerías de enlace dinámico
Se puede acceder a las funciones que están creadas internamente en Windows o en aplicaciones para Windows si esas funciones forman parte de una librería de enlace dinámico (una DLL). Si miras el directorio SYSTEM de Windows verás muchos archivos que tienen la extensión DLL. Algunos de ellos vienen con Windows; otros (como VBRUN300.DLL) vienen con las aplicaciones que hayas ido incorporando al sistema. Si conoces las definiciones de las funciones de esos archivos puedes llamar prácticamente a todas las funciones desde tus aplicaciones Visual Basic. Para llamar a estas funciones desde Visual Basic es necesario conocer cierta información técnica sobre los tipos de datos, el paso de parámetros, etc. Parte de esta información viene en el análisis de la instrucción Declare del manual de referencia de Visual Basic. Si necesitas información específica sobre una función determinada a la que puedas llamar, debes consultar los manuales de los productos que suministran DLL. Atención: La
instrucción Declare es muy potente. Te da acceso a casi to das las funciones del sistema Windows. Pero debes tener mucho cuida do. Debido a que las llamadas se realizan directamente al sistema no dispones del beneficio del chequeo de errores de Visual Basic. Potencial mente, podrías hacer que el sistema se viniese abajo si te equivocas en una declaración o llamas a una función con valores incorrectos.
280
9 Archivos
Las funciones del perfil de Windows
Las funciones que leen y escriben WIN.INI son parte de KERNEL.DLL, una librería de enlace dinámico estándar de Windows. Las funciones se llaman GetProfile String y WriteProfileString. Para usar estas funciones en un programa dé Visual Basic debes declararlas. La declaración es similar a una declaración de procedimiento, pero le dice a Visual Basic que el procedimiento se encuentra en algún otro sitio que no es la propia aplicación de Visual Basic. A continuación, se muestran las declaraciones de las dos funciones GetProfile String y WriteProfileString. Date cuenta de que cada declaración debe introducirse como una sola línea (sin retornos de carro), aunque aquí no tengamos más remedio que reproducirlas en varias líneas: Declare Function GetProfileString Lib "Kernel" (ByVal lpNombreAp As String, ByVal lpPalabraClave As String, ByVal lpPorOmision As String, ByVal lpCadenaDevuelta As String, ByVal nTamaño As Integer) As Integer Declare Function WriteProfileString Lib "Kernel" (ByVal lpNombreAp As String, ByVal lpPalabraClave As String, ByVal lpCadena As String) As Integer
La declaración de GetProfileString le dice a Visual Basic que la función se encuentra en KERNEL.DLL, que tiene cuatro parámetros de cadena y uno entero, y que devuelve un número entero. El primer parámetro de GetProfileString es una cadena que corresponde al nombre de la aplicación (nombre de la sección) en WIN.INI. El segundo parámetro es la palabra clave (el nombre de la "variable"). El tercer parámetro es el valor por omisión que se devuelve si no se encuentra la palabra clave. El cuarto parámetro es una cadena vacía que será ocupada por el valor de la variable de configuración. El quinto parámetro es un entero que define la longitud de la cadena vacía. El valor devuelto es el tamaño de la cadena de la variable de configuración. La declaración WriteProfileString es similar pero más simple. WriteProfileString también toma como primer parámetro una cadena que identifique la sección en WIN.INI, y utiliza la palabra clave como segundo parámetro. El tercer parámetro es el valor que quieras asignar a la palabra clave en WIN.INI. Empaquetar las fun dones para Visual Basic
Crea un nuevo proyecto en Visual Basic y elige New Module del menú File. Tendrás que crear dos procedimientos, ObtenerIni y EstablecerIni, y ponerlos en el 281
9 Archivos
EL LIBRO DEL VISUAL BASIC
nuevo módulo. Luego puedes incluir este módulo en cualquier aplicación que escribas, y acceder así a las variables de WIN.INI. En la sección de declaraciones generales de la ventana de código, introduce las declaraciones de las funciones GetProfileString y WriteProfileString como se muestran en el apartado anterior. A continuación introduce el código de y de EstablecerIni como se muestra en la figura 9.25. Los procedimientos ObtenerIni y EstablecerIni te permiten ahora leer y escribir en el archivo WIN.INI con un simple interface de Visual Basic. Por ejemplo, la línea de código EstablecerIni "Godzilla”, "Color", "Verde" producirá que se añadan estas líneas a tu archivo WIN.INI: [Godzilla] Color=Verde
ción. Si el usuario mueve la ventana a una posición en la pantalla, la ventana aparecerá en esa misma posición la próxima vez que se ejecute la aplicación. De la misma manera, si el usuario le cambia el tamaño a la ventana, ésta aparecerá con el nuevo tamaño la siguiente vez que el usuario ejecute la aplicación. La aplicación Memoria realiza exactamente esta tarea (y nada más). Cierra la ventana del módulo del código en el que has creado las funciones Esta blecerIni y ObtenerIni. Establece las propiedades Nombre y Caption del formulario como Memoria. Luego, añade el código que se muestra en la figura 9.26. El procedimiento Form_Load lee las variables de configuración; si contienen valores, utiliza esos valores para establecer las propiedades de la posición del formulario. El procedimiento Form_Unload , que es llamado cuando la aplicación finaliza, escribe la posición actual en el archivo WIN.INI.
La aplicación Memoria
Puedes probar estas funciones con un pequeño programa de demostración. Una utilización clásica que se le da a las variables de configuración consiste en usarlas para almacenar la última posición y tamaño conocidos de la ventana de la aplica
Function ObtenerIni (NombreAp As String, PalabraClave As String) As String Dim CadenaObtenida As String * 128, Temp As Integer Temp = GetProfileString(NombreAp, PalabraClave, " " , CadenaObtenida, Len(CadenaObteni da)) ’Obtener la cadena devuelta pero sin incluir el código ASCII 0 ObtenerIni = Left$(CadenaObtenida, Temp) End Function Sub EstablecerIni (NombreAp As String, PalabraClave As String, ValorClave As String) Dim Temp As Integer Temp = WriteProfileString(NombreAp, PalabraClave, ValorClave) End Sub
Figura 9.25.
Los procedimientos ObtenerIni y EstablecerIni
282
Sub Form_Load ( ) Dim Coger As String Coger = ObtenerIni("Memoria", "Arriba") If Coger <> " " Then Memoria.Top = Val(Coger) End if Coger = ObtenerIni("Memoria", "Izquierda") If Coger <> " " Then Memoria.Left = Val(Coger) End if Coger = ObtenerIni("Memoria", "Alto") If Coger <> " " Then Memoria.Height = Val(Coger) End if Coger = ObtenerIni("Memoria", "Ancho") If Coger <> " " Then Memoria.Width = Val(Coger) End if End Sub
Figura 9.26.
(continúa)
El código del programa de la aplicación Memoria
283
EL LIBRO DEL VISUAL BASIC
10
Figura 9.26. continuación
Sub Form_Unload ( ) EstablecerIni "Memoria", EstabiecerIni "Memoria", EstablecerIni "Memoria", EstablecerIni "Memoria", End Sub
"Arriba", Str$(Memoria.Top) "Izquierda”, Str$(Memoria.Left) "Alto", Str$(Memoria.Height) "Ancho", Str$(Memoria.Width)
N o se considera "correcto” que una aplicaci ón escri ba más de nueve o diez valores en el archivo WIN.INI. Si tu programa requiere una gran cantidad de información de configuración, debes pensar en crear un archi vo de datos pri vado que sea procesado en tu códig o. Consejo:
Pulsa F5 para ejecutar la aplicación. Cuando aparezca el formulario vacío, utiliza el ratón para moverlo o cambiar su tamaño. Ahora termina la aplicación haciendo doble clic en el cuadro del menú control del extremo superior izquierdo de la ventana o seleccionando el comando Cerrar del menú control del formulario. (Debes usar el menú control; seleccionar End del menú Run de Visual Basic termina la aplicación sin descargar —unload— el formulario.) Cuando hayas vuelto al modo de diseño verás el formulario tal y como se diseñó originalmente. Pero si vuelves a pulsar F5 para ejecutar de nuevo la aplicación, las propiedades posicio nales se cargarán desde el archivo WIN.INI y la ventana aparecerá con el mismo tamaño y en la misma posición que cuando saliste de la aplicación por última vez. Asegúrate de guardar el programa para que tengas disponible el módulo que contiene los procedimientos ObtenerIni y EstablecerIni cuando los necesites.
Programación gráfica Este capítulo es una introducción a los gráficos de Visual Basic. Trabajar con gráficos puede ser divertido, aunque no necesariamente fácil. Windows es en su interior un entorno gráfico; recuerda que los mejores programas escritos para Windows hacen uso de esa fuerza.
Formularios y cuadros de dibujo Hasta este punto, la mayor parte de los "dibujos" que has hecho en Visual Basic los has realizado durante la fase de diseño. Visual Basic también dispone de varios métodos gráficos que permiten escribir en la pantalla durante la fase de eje cución, realizando tareas como imprimir texto, dibujar líneas, dibujar círculos, etc. Estos métodos está asociados con formularios, cuadros de dibujo y con un objeto especial denominado Printer (impresora). El estudio que sigue se centra en los formularios, pero las propiedades y los métodos que se describen se aplican tam bién a los cuadros de dibujo. Imprimir y el objeto Printer se tratarán en la última parte de este capítulo. Gestión de la pantalla
Las imágenes que aparecen en un monitor son el reflejo directo de la memoria de vídeo, un banco de RAM que pertenece a la tarjeta controladora del vídeo. Las imágenes de la pantalla están compuestas por muchos puntos individuales llamados pix els (que es una abreviatura de pict ure elements, elementos del dibujo). El número de pixels que componen la pantalla determinan la cantidad de memoria de vídeo que se necesita. Una pantalla monocroma requiere un sólo bit por pixel. Si el bit correspondiente de la memoria de vídeo vale 1, el pixel se enciende en la pantalla. Cuando el bit vale 0, el punto es negro. Si la resolución de la pantalla 284
285
i LIBRO DEL VISUAL BASIC
es de 640 por 320 pixels, por ejemplo, se usan 204800 (640 x 320) bits, ó 25600 bytes, para controlar la pantalla. En un monitor de color se necesitan más de un bit para controlar cada pixel, ya que el color se crea mezclando varias intensidades de rojo, verde y azul. Dependiendo del tipo de controlador puede llevar de 4 a 32 bits por pixel controlar un monitor de color. (Cuantos más bits, más colores se podrán mostrar simultáneamente en la pantalla.) En ordenadores de alto precio con grandes pantallas en color, la RAM de vídeo puede ser a veces de hasta 4 megabytes. Mostrar gráficos en pantalla
Todas las imágenes de la pantalla, desde las líneas de varios colores hasta el simple texto, se crean estableciendo los valores de los bits adecuados en la memoria de vídeo. Los métodos gráficos de Visual Basic se encargan de realizar todo ese proceso por ti. Esos métodos gráficos —que se llaman Print, Line, Circle y Pset — dibujan en la pantalla texto, líneas, arcos y puntos individuales. Además, un método llamado Point determina el color de un punto concreto, y el método Cl s borra el formulario para que quede vacío. En un entorno en el que un sé)lo programa controle la pantalla, una imagen que se dibuje en esa pantalla se quedará allí. Windows, sin embargo, es un entorno multitarea. Después de que se haya dibujado una imagen en un formulario, el usuario puede cambiar a otra aplicación que, a su vez, dibujará algo en la pantalla. La "diversión" comienza cuando el usuario cambia de la segunda aplicación y espera ver la imagen creada por tu programa, cuando en realidad ésta ha sido borrada por la segunda aplicación. Windows resuelve este problema con el evento Paint (pintar), el cual es gestionado por un procedimiento de evento de Visual Basic. Si la presentación en pantalla de una aplicación ha sido tapada por alguna otra ventana, Windows envía un evento Paint a la aplicación cuando recupera el control de la pantalla, permitiéndole "redibujar" la presentación en pantalla. El mismo proceso ocurre (sin una aplicación que interfiera) cuando se minimiza una ventana que contiene dibujos o controles y luego se restaura. Una aplicación sencilla puede demostrar lo que ocurre. Crea un proyecto nuevo. Añade el siguiente código como procedimiento para el evento Click del formulario, y luego ejecuta la aplicación: Sub Form_Click ( ) Print "Hola" End Sub
286
10 Programación gráfica
Ejecuta la aplicación y haz clic en el formulario varias veces para poner algo de texto en la pantalla. Ahora minimiza la ventana o pon la ventana de otra aplicación delante de la tuya. Cuando restaures el formulario para que la suya sea la ventana que esté delante de todas las demás, verás que el texto ha desaparecido. En este caso, cuando se restauró el formulario, Visual Basic llamó al procedimiento Form_Paint. Como tú no lo habías escrito, no sucedió nada. Evidentemente, si tienes la intención de escribir aplicaciones gráficas, debes escribir un procedimiento que pueda reconstruir la pantalla para el evento Paint. Esto supone cierta planificación cuidadosa. El mejor enfoque consiste en poner todo el código de los gráficos en el propio procedimiento Paint. Cuando estés preparado para dibu jar una imagen por primera vez, llama al procedimiento Paint directamente. Luego, todo estará ya en su lugar, de manera que si es necesario refrescar la pantalla, Visual Basic puede llamar automáticamente a tu procedimiento Paint. Prueba a modificar el programa Hola que acabas de escribir usando esta técnica. Primero introduce este código en la sección de declaraciones generales: Dim NumeroDeClicks As Integer
'Visual Basic la inicializa a 0
A continuación añade estos dos procedimientos de evento: Sub Form_Click ( ) NumeroDeClicks = NumeroDeClicks + 1 Form_Paint End Sub Sub Form_Paint ( ) Dim I As Integer Cls
'Borrar la pantalla; comenzar a escribir 'desde la parte superior del formulario
For I = 1 To NumeroDeClicks Print "Hola” Next I End Sub
Cuando ejecutes esta versión del programa, prueba a minimizar o a ocultar la ventana del formulario. Verás que lo que hay en pantalla siempre vuelve a aparecer cuando se restaura el formulario. La propiedad Auto Redraw
Visual Basic también ofrece una técnica más simple para redibujar la pantalla. Cada formulario tiene una propiedad AutoRedraw (autoredibujado) que está es 287
10 Programación gráfica
EL LIBRO DEL VISUAL BASIC
tableada como False por omisión. Si estableces esta propiedad como True, el propio Visual Basic gestionará todo el redibujado. Para probar esto utiliza el código original del programa de ejemplo Hola (sin incluir el procedimiento Form_Paint ):
pantalla, con valores que se incrementan a medida que nos movemos hacia la derecha a lo largo del eje horizontal y hacia abajo a lo largo del eje vertical del formulario. Las propiedades Top y Left de un objeto específico determinan su desplazamiento desde el punto origen (0, 0, el extremo superior izquierdo).
Sub Form_Click ( ) Print "Hola" End Sub
Ahora establece la propiedad AutoRedraw como True y pulsa F5 para ejecutar la aplicación. Esta vez, el contenido del formulario no se perderá si el formulario es ocultado o minimizado, incluso, aunque el programa no tenga un procedimiento
Form_Paint.
Esto es, desde luego, un atajo. Cuando se establece la propiedad AutoRedraw como True, simplemente delegas la responsabilidad de la gestión de la pantalla a Visual Basic. Visual Basic realiza esta tarea asignando cierta cantidad de memoria (el número de bits que se requieran para duplicar la imagen de tu formulario). Cuando se dibuja en el formulario, Visual Basic realiza una copia en esta memoria de seguridad. Cuando necesita restaurar el contenido del formulario, sólo tiene que escribir la copia que tiene en la memoria de seguridad en la memoria de vídeo del ordenador.
Figura 10.1.
El sistema de coordenadas por omisión de Visual Basic
El problema está, pues, en elegir entre un programa más simple que requiere más memoria y un programa complejo que requiere menos memoria. Mientras que escribas aplicaciones sencillas, de un solo formulario, probablemente será adecuado establecer como True la propiedad AutoRedraw. Sin embargo, cuando las aplicaciones que crees adopten un tamaño mayor, no querrás desperdiciar memoria en mantener copias de seguridad del contenido de los formularios y, por tanto, tendrás que escribir procedimientos Form_Paint.
Las propiedades Top, Left, Width y Height se miden en twips. Como recordarás del capítulo 5, un twip es una unidad de medida equivalente a 1/1440 pulgadas, o 1/ puntos. (Un punto, que aproximadamente es 1/ pulgadas, es una medida tipográfica estándar que se utiliza en la medida de las fuentes.) De esta manera, un objeto que tenga 1/ pulgada de alto y 2 de ancho tendrá sus propiedades Height y Width establecidas a 720 y 2880, respectivamente (una pulgada equivale a 2,54 centímetros).
En aplicaciones que no utilicen métodos gráficos, la propiedad AutoRedraw siempre debe establecerse como False. Los cuadros de texto, etiquetas, cuadros de lista, cuadros combinados y otros controles simila res no se ven afectados por los eventos Paint y, por tanto, no es necesario mantener copias de seguridad del formulari o.
Si te sientes más a gusto trabajando con otras unidades de medida puedes cam biar el ajuste de la propiedad ScaleMode (modo de la escala) para que Visual Basic informe de las coordenadas de pantalla utilizando otras escalas. La figura 10.2 describe las unidades de medida que corresponden a los diversos ajustes de la propiedad ScaleMode.
Nota:
Las coordenadas de la pantalla
Visual Basic proporciona un sistema de coordenadas por omisión que determina la posición de los objetos en un formulario. Este sistema, que se ilustra en la figura 10.1, asigna las coordenadas iniciales (0, 0) al extremo superior izquierdo de la 288
20
72
2
Se puede ver, fácilmente, el efecto de cambiar el ajuste de ScaleMode. Incluye en el formulario un objeto de la caja de herramientas y examina sus propiedades Top, Left, Width y Height. Ahora modifica el ajuste de la propiedad ScaleMode del formulario (no la del objeto), y vuelve a examinar las propiedades del objeto. Si cambias el ajuste de la propiedad ScaleMode a 5, un control cuya propiedad Height fuese originalmente 720 (twips) tendrá ahora un ajuste de 0,5 (pulgadas). 289
EL LIBRO DEL VISUAL BASIC
10 Programación gráfica
Si estableces la propiedad ScaleMode en 6, el ajuste de Height cambiará a 12,7 (milímetros). Ajuste de
Unidad de
ScaleMode
medida
0 1 2 3 4 5 6 7
Definida por el usuario Twips (20 por punto, 1440 por pulgada) (actúa por omisión) Puntos (72 por pulgada) Pixels (depende del monitor) Caracteres (6 por pulgadas verticalmente, 12 por pulgada horizontalmente) Pulgadas Milímetros Centímetros
Figura 10.2.
Los ajustes de la propiedad ScaleMode
El ajuste 4 de ScaleMode, que mide en caracteres, es un poco extraño porque utiliza una escala diferente para medidas verticales y horizontales. Con las demás unidades de medida, un objeto que tenga n de ancho y n de alto sería cuadrado. Cuando se utilizan caracteres como unidad de medida, un objeto con una altura de 6 y una anchura de 12 es un cuadrado de 1 pulgada.
Figura 10.3.
Trabajar con una unidad de medida definida por el usuario
define mediante las propiedades ScaleLeft y ScaleTop, las cuales están establecidas por omisión en 0. Estableciendo nuevos valores para estas propiedades, se puede definir un nuevo sistema de coordenadas. Por ejemplo, estableciendo ScaleLeft como 3 y ScaleTop como 4 se cambia el punto de origen de las coordenadas (la esquina superior izquierda) de (0, 0) a (3, 4). Las coordenadas de la esquina inferior derecha se definen como (ScaleLeft + ScaleWidth, ScaleTop + ScaleHeight). De esta manera, si establecieses ScaleHeight a 17 y ScaleWidth a 10, las coordenadas de la esquina inferior derecha serían (13, 13) en el nuevo sistema de medidas, como se muestra en la figura 10.4. Si quisieras ver el formulario como un sistema de coordenadas cartesianas estándar con el punto (0, 0) como el centro del formulario, (figura 10.5), tendrías que
ScaleMode 0
Si estableces la propiedad ScaleMode a 0, puedes utilizar tu propia escala de medida. Para definir el sistema particular de medidas se deben establecer las propiedades ScaleHeight y ScaleWidth. Por ejemplo, si estableces ScaleWidth a 500, le estás diciendo a Visual Basic que use una escala que contenga 500 unidades entre los extremos horizontales del formulario. Si entonces estableces la propiedad Width de una etiqueta a 250, por ejemplo, la etiqueta estará exactamente en el medio de la anchura del formulario, como se muestra en la figura 10.3. La propiedad ScaleHeight se establece de manera similar. No es necesario que las unidades de altura tengan absolutamente nada que ver con las de anchura. Además de establecer las escalas vertical y horizontal, también se puede definir un punto de origen alternativo para la esquina superior izquierda. Esta esquina se 290
291
EL LIBRO DEL VISUAL BASIC
10 Programación gráfica
que calcular cuántos twips a la derecha y hacia abajo tienes que dibujar los ejes, convertir todos los valores de x y de y en twips y añadirles el desplazamiento desde el origen. Pero si defines un sistema de coordenadas apropiado al problema, sólo tendrás que calcular x e y; Visual Basic hará el resto. La figura 10.6 contiene el programa que dibuja este gráfico. Dado un valor de X , la función FdeX calcula Y de acuerdo con la fórmula. Observa que el resto del programa funciona independientemente de la fórmula de FdeX. El código principal es el procedimiento Form_Paint , el cual es llamado por Visual Basic cada vez que necesita actualizar la pantalla. Figura 10.5.
Un sistema de coordenadas cartesianas definido por el usuario
establecer la propiedad ScaleTop en un valor positivo y la propiedad ScaleLeft al correspondiente valor negativo. Después, tendrías que definir ScaleWidth como un valor positivo y ScaleHeight como el correspondiente valor negativo. En la figura 10.5 se ilustra un sistema de coordenadas en el que el extremo superior izquierdo se define como (40, 40), la propiedad ScaleWidth como 80 y la propiedad ScaleHeight como 80. Desde un programa se puede establecer la escala de un formulario ajustando las propiedades individualmente o usando el método Scale. La sintaxis de este método es la siguiente:
[objeto.]Scale [( izquierda , arri ba)-( derecha, abajo)] Observa que esta sintaxis incluye sólo las coordenadas de la esquina superior izquierda y de la esquina inferior derecha. Visual Basic calcula ScaleHeight y ScaleWidth a partir de estos dos puntos. De esta manera, la instrucción que establece el formulario de la figura 10.5 sería Scale (-40, 40)-( 40, -40). Si se usa el método Scale sin parámetros se vuelve a la escala de medida en twips y el origen de la esquina superior izquierda vuelve a ser (0, 0). Ecuaciones y cuadrículas
Si estas pensando que esta información no tiene mucho valor, te equivocas. En realidad, un sistema de medidas definido por el usuario puede hacerte la vida mucho más fácil. Supongamos que estás escribiendo un programa que represente gráficamente funciones matemáticas y que quieres representar la función y = x 2 3x + 12 en el dominio -10 <=x<=10. Si usas la escala y origen estándar tendrás 292
El programa establece primero la escala a un sistema de coordenadas cartesianas estándar mediante la instrucción Scale. Luego, dibuja los ejes usando el método Line. En su forma más simple, el método Line tiene la siguiente sintaxis: [objeto. ]Line [(x1, y1)](x2, y2)
Function FdeX (ByVal X As Single) As Single FdeX = X ^ 2 - X * 3 + 12 End Function Sub Form_Paint ( ) Dim X As Single 'Configurar la pantalla Cl s Scale (-150, 150)-(150, -150) 'Dibujar los ejes Line (-150, 0)-(150, 0) Line(0, -150)-(0, 150) 'Dibujar el gráfico CurrentX = -10 CurrentY = FdeX(-10) For X = -10 To 10 Line -(X, FdeX(X)) Next X End Sub
Figura 10.6.
El código del programa para representar gráficamente una ecuación
293
10 Programación gráfica
EL LIBRO DEL VISUAL BASIC
Dibuja una línea que comience en ( x1 , y1) y termine en (x2, y2). Finalmente, el programa dibujará el gráfico utilizando una variante del método Line que no especifica punto de comienzo. En este caso, Visual Basic empezará desde la última posición conocida, cuyas coordenadas están almacenadas en las propiedades CurrentX y CurrentY del formulario. CurrentX y CurrentY sólo es necesario que se establezcan una vez en el programa; después de la ejecución de cada instrucción Line , Visual Basic actualiza el valor de las propiedades. Puedes abrir un formulario nuevo, introducir este código y ejecutarlo sin más controles o rutinas. Un ejemplo de la salida se muestra en la figura 10.7.
Sub Form_Paint ( ) Dim I As Integer 'Configurar la pantalla Cl s Scale (0, 0) -(8, 8) 'Dibujar la cuadricula For I = 1 To 7 Line (0, I) -(8, I) Line (I, 0) -(I, 8) Next I End Sub
'Horizontal 'Vertical
Figura 10.8.
El código del programa para dibujar una cuadrícula de 8x8
Figura 10.7.
La representación gráfica de la Junción FdeX
Observa que el código de la figura 10.6 usa el valor por omisión (1) para Step. Si quieres que el gráfico sea más fino añade una cláusula Step a la declaración For como se muestra aquí: For X = -10 To 10 Step 0,1
Incluso, aunque no hayas representado gráficamente una función desde el instituto, podrás darte cuenta de que un sistema de medida definido por el usuario es de gran ayuda para tareas como dibujar un tablero de ajedrez o construir una cuadrícula para un juego como el Go. Se puede definir una escala personalizada que sea del tamaño de la cuadrícula —por ejemplo, de 0 a 8 (o de 1 a 9) para un tablero de ajedrez. Luego, en lugar de tener que calcular las posiciones de las líneas, simplemente puedes dibujarlas en las posiciones 0, 1, 2 y así sucesivamente. El código que se muestra en la figura 10.8 dibuja la cuadrícula de 8 por 8 que aparece en la figura 10.9. 294
Figura 10.9.
Una cuadrícula de 8 x 8 dibujada por el código del programa de la figura 10.8
Como se ha mencionado antes, todas las propiedades y métodos que se tratan aquí también se aplican a los cuadros de dibujo, de la misma manera que a los formularios. Cada cuadro de dibujo, por ejemplo, puede tener su propio sistema de coordenadas definido por las propiedades de la escala. Debes incluir el nom bre del control cuadro de dibujo cuando uses estas propiedades y métodos; en caso contrario, se aplicarán por omisión al formulario. Por ejemplo, si tienes un objeto en el cuadro de dibujo cuya propiedad Name sea MiDib, puedes dibujar una cuadrícula de 8 por 8 con el código que se muestra en la figura 10.10. 295
10 Programación gráfica
EL LIBRO DEL VISUAL BASIC
Sub Form_Paint ( ) Dim X As Single
Sub DibujarCuadricula ( ) Dim I As Integer 'Configurar el cuadro de dibujo MiDib.Cls MiDib.Scale (0, 0)-(8, 8) 'Dibujar la cuadricula For I = 1 To 7 MiDib.Line (0, I) - (8, I) MiDib.Line (I, 0)-(I, 8) Next I End Sub
'Horizontal 'Vertical
Figura 10.10.
El código del programa para dibujar una cuadrícula de 8 x 8 en un cuadro de dibujo
Colores
Volvamos por un momento al gráfico que se muestra en la figura 10.7. Para distinguir las líneas del gráfico de la de los ejes, sería de utilidad dibujar a estos en otro color. El método Li ne permite usar un parámetro opcional para establecer el color de la línea que estás dibujando. De forma alternativa puedes establecer la propiedad ForeColor, la cual determina el color de cualquier cosa que se dibuje en el formulario (incluyendo el texto impreso en él). Las figuras 10.11 y 10.12 contienen el código que dibuja los ejes del gráfico en verde y la línea que representa a la función en el color por omisión. El código de la figura 10.11 especifica el color con el método Line; el de la figura 10.12 establece la propiedad ForeColor del formulario. Ambas rutinas utilizan la función RG B para crear un valor de color. Esta función (cuyo nombre no es más que un acrónimo de Red, Green, Blue: rojo, verde, azul en inglés) requiere que se le pasen tres argumentos, cada uno de los cuales es un número entero en el rango de 0 a 255. El primer argumento especifica la intensidad del color rojo, el segundo la intensidad del verde y el tercero la intensidad del azul. Un argumento con un valor 0 indica la total ausencia del color; 255 indica la mayor intensidad. La función devuelve un entero largo que representa el valor RGB del color. La figura 10.13 muestra una lista de algunos colores comunes y sus ajustes RGB. 296
'Configurar la pantalla Cl s Scale (-150, 150)-(150, -150) 'Dibujar los ejes Line (-150, 0)-(150, 0), RGB(0, 255, 0) Line (0, -150)-(0, 150), RGB( 0, 255, 0) 'Dibujar el gráfico CurrentX = -10 CurrentY = FdeX(-10) For X = -10 To 10 Line -(X, FdeX(X)) Next X End Sub
Figura 10.11.
El código del programa para emplear colores en el gráfico usando el método Line
Sub Form_Paint ( ) Dim X As Single 'Configurar la pantalla Cl s Scale (-150, 150)-(150, -150) 'Dibujar los ejes GuardarColor = ForeColor ForeColor = RGB(0, 255, 0) Line (-150, 0)-(150, 0) Line(0, -150)-(0, 150) 'Dibujar el gráfico ForeColor = GuardarColor
Figura 10.12.
(continúa)
El código para emplear colores en el gráfico usando la propiedad ForeColor del formulario
297
EL LIBRO DEL VISUAL BASIC
10 Programación gráfica
Figura 10.12 continuación
Line (-150, 0)-(150, 0) Line(0, -150)-(0, 150) 'Dibujar el gráfico ForeColor = GuardarColor CurrentX = -10 CurrentY = FdeX(-10) For X = -10 To 10 Line -(X, FdeX(X)) Next X End Sub
Color
Ajuste RGB
Negro
RGB(0, 0, 0)
Rojo
RGB(255, 0, 0)
Verde
RGB(0, 255, 0)
Azul
RGB(0, 0, 255)
Blanco
RGB(255, 255, 255)
Amarillo
RGB(255, 255, 0)
Violeta
RGB(255, 0, 255)
Cian
RGB(0, 255, 255)
claración ForeColor = AC TIVE_TI TLE_BA R establece que el color de dibujo en el formulario sea el color especificado en el Panel de control para las barras del títu lo de las ventanas. El archivo CONSTANT.TXT define estas constantes globales como se muestra en la figura 10.14. (Observa que las definiciones de las constan tes de la figura 10.14 comienzan por &H, lo que indica que los valores aparecen en notación hexadecimal.) Usar estas constantes, en lugar de colores fijos, te ase gura que tu aplicación se adaptará al mapa de colores definido por el usuario y te ayudará a que tus aplicaciones tengan una apariencia más profesional.
Nombre de la constante
Valor
Descripción
SCROLL_BARS
&H80000000
El color de la zona gris de las barras de desplaz amiento
DESKTOP
&H80000001
El color del escritorio
ACTIVE _TITLE_BAR
&H80000002
El color de la barra del título de la ventana activa
INACTIVE_TITLE_BAR
&H80000003
El color de la barra del título de una ventana inactiva
MENU_BAR WINDOW_BACKGROUND
&H80000004
El color del fondo del menú
&H80000005 & H8 000 000 6
E l c ol or d el m arc o d e l a v en ta na
WIN DOW_FRAME
El color del fondo de una ventana
&H80000007 &H80000008
El color del texto en los menús
WINDOW_TEXT TITLE_BAR_TEXT
&H80000009
EL color del texto en la barra del título
ACTIVE_BORDER
&H8000000A
INACTIVE_BORDER
&H8000000B
El color del borde de la ventana activa El color del borde de una ventana inactiva
APPLICATION_WORKSPACE
&H8000000C
El color del fondo de aplicaciones MDI (interface de múltiples documentos)
Además de ajustar la propiedad ForeColor, también se puede alterar el color del fondo del formulario estableciendo la propiedad BackColor. Si cambias el valor de esta propiedad durante la ejecución, se borrarán todos los gráficos que hubie ra en el formulario.
HIGHLIGHT
&H8000000D
El color del elemento seleccionado de un control
HIGHLIGHT_TEXT
&H8000000E
El color del texto seleccionado de un control
El archivo CONSTANT.TXT también incluye constantes de colores especiales que corresponden a los ajustes del Panel de control de Windows. Por ejemplo, la de
Figura 10.14. Las constantes de colores globales definidas en el archivo CONSTANT.TXT
Figura 10.13. Ajustes RGB para algunos de los colores más habituales
Aunque la función RGB permite un máximo de 16 millones de colores, tu hardware de vídeo impone ciertas restricciones. Una VGA normal, por ejemplo, sólo permite mostrar simultáneamente 16 colores.
Nota:
298
MENU_TEXT
El color del texto en las ventanas
(continúa)
299
EL LIBRO DEL VISUAL BASIC
10 Programación gráfica
Figura 10.14. continuación Nombre de la constante
Otras propiedades y métodos de dibujo
Valor
Descripción
BUTTO N_FACE
&H8000000F
El color del sombreado de la parte delantera de un botón
BUTTON_SHADOW
&H80000010
El color del sombreado del borde de un botón
GRAY_TEXT
&H80000011
El color del texto atenuado (desactivado) (se establece en 0 si el controlador de pantalla actual no admite el gris sólido)
BUTTON_TEXT
&H80000012
El color del texto en los botones de comando
Números hexadecimales
El sistema de numeración hexadecimal (base 16) utiliza 16 símbolos para representar valores numéricos: los dígitos del 0 al 9 y las letras A (equivalente al 10 decimal), B, C, D, E y F (equivalente al 16 decimal). Como se explicó en el capítulo 2 en relación con otros sistemas de numeración, el valor de cada posición en un número hexadecimal (o hex) se incrementa a razón de potencias de 16. Por ejemplo, el número hex 1A3 representa la suma de lx 162(256), 10xl61(l60) y 3xl6 0(3); de esta manera, su equivalente decimal es el 419. La notación hexadecimal se usa habitualmente en programación como una manera compacta de representar los números binarios utilizados por el ordenador. Como cualquiera de los 16 dígitos se puede representar en 4 bits, se pueden representar 2 dígitos hexadecimales (uno para cada 4 bits) en uno de los bytes de 8 bits en los que se basan la memoria y los sistemas de almacenamiento. De esta forma, 1 byte de almacenamiento puede contener uno de 256 números hexadecimales diferentes (del 0 al FF). Puedes utilizar un valor hexadecimal en cualquier lugar donde Visual Basic acepte un número. Simplemente, debes anteponer el prefijo &H para indicar que el valor aparece en notación hexadecimal.
300
La propiedad DrawWidth determina la anchura de las líneas que se dibujen. El ajuste de esta propiedad siempre se mide en pixels. De esta forma, un ajuste de 1 dibuja la línea más estrecha, con una anchura de 1 pixel. Un ajuste de 2 dibujará una línea que sea más ancha en un pixel, y así sucesivamente. Las propiedades DrawStyle y DrawMode afectan a la manera en la que las líneas aparecen en la pantalla. DrawStyle es similar a la propiedad BorderStyle de un objeto. Los ajustes del 0 al 6 especifican si la línea dibujada será sólida, de puntos, de guiones o alguna combinación de esos estilos. La propiedad DrawMode es un poco más compleja. Sus 16 ajustes determinan cómo interactúa la imagen que se está dibujando con lo que ya hay en la pantalla. Por ejemplo, el ajuste por omisión de DrawMode (13 Copy Pen) dibuja la imagen encima de cualquier gráfico existente. Con este ajuste, ejecutar la instrucción Line (O, 0,5)-(2, 0.75) dos veces, una detrás de otra, produce el efecto de que sólo se dibuja una línea, porque la segunda se dibuja directamente sobre la primera tapándola. Sin embargo, si se utiliza el valor 6 Invert en la propiedad DrawMode, la primera instrucción Line dibujaría una línea en el color inverso del fondo, y la segunda lo invertiría otra vez, produciendo, esencialmente, el efecto de que la línea desaparezca. Otros ajustes de la propiedad DrawMode combinan los colores de maneras diferentes y permiten crear efectos especiales; consulta el manual de referencia de Visual Basic, si necesitas más información. Las propiedades FillColor (color de relleno) y FillStyle (estilo de relleno) afectan a la apariencia de los círculos y polígonos rellenos. Estas propiedades son similares a las propiedades del mismo nombre de los controles Shape que vimos en el capítulo 5. Hay tres métodos de Visual Basic que tienen que ver con el dibujo: PSet, que pone un punto (o pixel) de un color especificado; Line , que permite dibujar líneas y rectángulos; y Circle, que permite crear círculos, arcos y elipses. (Trataremos estos métodos con más profundidad dentro de un momento.) Además, el método Cls borra un formulario o un cuadro de dibujo; y el método Point, que trabaja como una función, devuelve el color de un punto determinado. El método Cl s borra el texto y los gráficos del objeto especificado —dicho con más precisión, pone todos los puntos del color del fondo (el color establecido mediante la propiedad BackColor). Como los otros métodos que se tratan en este apartado, Cl s actúa por omisión sobre el formulario actual si no se especifica un objeto. 301
EL LIBRO DEL VISUAL BASIC
El método Point tiene la siguiente sintaxis: [objeto.]Point (x, y)
Devuelve el valor RGB del color del pixel situado en las coordenadas (x, y), donde x es la posición con respecto al eje horizontal e y la posición con respecto al eje vertical. Las coordenadas se miden en las unidades que se especifiquen mediante la propiedad ScaleMode del formulario o del cuadro de dibujo. El método PSet
Para poner un solo punto de un color en particular se usa el método Pset. Este método tiene la siguiente sintaxis: [objeto.] PSet [Step](x, y)[, color]
Las coordenadas (x, y) se refieren a una posición absoluta, medida en las unidades especificadas por la propiedad ScaleMode del objeto en el que se está dibu jando. Sin embargo, si estas coordenadas están precedidas por la palabra clave Step , representan el desplazamiento relativo con respecto a la posición actual (dada por las propiedades CurrentX y CurrentY). Por ejemplo, Step(2, 10) se refiere a una posición desplazada de la posición actual en dos unidades, horizontalmente y en diez, verticalmente —en otras palabras, la posición ( CurrentX + 2,
Cur rentY + 10).
Puedes poner el punto de cualquier color. Si no especificas ningún color, el método PSet asignará al punto en el color establecido por la propiedad ForeColor. Este método puede ser especialmente útil para borrar un solo pixel: simplemente, haz que el pixel tenga el color del fondo (el ajuste de la propiedad BackColor).
10 Programación gráfica
corresponden al punto de finalización. También puedes especificar el color de la línea con este método. Cuando se incluye la letra B (de box , cuadrado) en la instrucción Line, se dibuja un rectángulo en lugar de una línea, en el que los dos conjuntos de coordenadas representan las esquinas opuestas del rectángulo. El rectángulo se rellenará con el color establecido por la propiedad FillColor y con el estilo establecido por la propiedad FillStyle. Si también se incluye la letra F en la instrucción Line , el rectángulo se rellenará con el color utilizado para dibujarlo. No se puede especificar la F, a no ser que también se incluya la B. En las figuras 10.15, 10.16 y 10.17 se muestran algunos ejemplos de dibujos realizados con la instrucción Une. Todos usan la declaración Scale (2, -2)-(-2, 2) y la instrucción Une que se muestra en la figura. (Recuerda que utilizamos el punto como separador decimal.) El método Circle
El método Circle es el más complejo de los métodos de dibujo. Se puede utilizar para dibujar círculos, elipses, arcos y "porciones de tarta". (Una porción de tart a es un arco con líneas que conectan los extremos del arco en el centro.) La sintaxis completa del método Ci rcle es el siguiente: [object.]Circle [Step](x, y), radio[, [color][, [comienzo ][, [final][, aspecto]]]]
Siempre que se utilice el método Circle se deberán especificar las coordenadas del centro (x, y) del círculo; este método no utiliza por omisión la posición actual.
Observa que el tamaño y la apariencia del punto se ven afectados por cómo hayas establecido las propiedades DrawWidth y DrawMode. Por ejemplo, cuando la propiedad DrawWidth está establecida como 1, el método PSet cambia el color de un solo pixel; pero cuando es mayor que 1, el punto es proporcionalmente más grande y está centrado en las coordenadas especificadas. El método Une
El método Line , que dibuja una línea o un rectángulo, usa esta sintaxis: [objeto.]Line[[Step](x1, y1)][Step](x2, y2)[, [color][, B[F]]] El primer conjunto de coordenadas, ( x1, y1), especifica el punto de comienzo de la línea. Si omites las coordenadas de comienzo, la línea empezará en la posición actual. Debes incluir el segundo grupo de coordenadas (x2, y2), que son las que 302
Figura 10.15.
Dibujar una línea con el método Line 303
EL LIBRO DEL VISUAL BASIC 10 Programación gráfica
Figura 10.16.
Dibujar un rectángulo con el método Line
Figura 10.18.
Dibujar una elipse "Laurel" con el método Circle
todas las comas que intervienen en la instrucción pecifiques valores para todos los parámetros.
Círculo,
incluso aunque no es-
Si quieres dibujar un arco en lugar de un círculo o una elipse completa, especifica los parámetros comienzo y final en la instrucción Circle. Estos valores deberán suministrarse en radianes (busca en el armario aquel viejo libro de geometría) y podrán variar de 0 a 2 pi. La figura 10.20 muestra los valores en radianes de ciertos puntos estratégicos que hay a lo largo de un círculo. Si te sientes más a gusto especificando grados en lugar de radianes, define la constante PI y usa la siguiente función: Figura 10.17.
Dibujar un rectángulo relleno con el método Line
Cuando el círculo se ha dibujado, CurrentX y CurrentY se establecen como el punto central. Para dibujar un círculo, simplemente especifica un origen y un radio. Para "aplastar" el círculo y convertirlo en una elipse, debes cambiar el ratio del aspecto. Los círculos tienen un ratio de aspecto de 1.0. Los valores de aspecto que son mayores de 1.0 crean elipses que son altas y estrechas; los valores de aspecto que son menores de 1.0 crean elipses que son bajas y anchas. De esta manera, un valor de aspecto de 4.0 dibujará una elipse "Laurel", y un valor de 0.4 dibujará una elipse "Hardy", como muestran las figuras 10.18 y 10.19. Observa que debes escribir
Figura 10.19.
Dibujar una elipse "Hardy" con el método Circle
304 305
El LIBRO DEL VISUAL BASIC
Figura 10.20. Puntos a lo largo de un círculo especificados en radianes
10 Programación gráfica
Figura 10.21. Dibujar una porción de tarta con el método Circle
Function GradosARadianes (Grado As Single) As Single GradosARadianes = Grado * PI / 180.0 End Function
Ahora, todo lo que tienes que hacer es pasar a GradosARadianes un valor en grados, y la función devolverá el correspondiente valor en radianes. Si quieres dibujar porciones de tarta debes especificar valores negativos para co mienzo y final en la instrucción Circle. Los valores negativos en estos parámetros producen que Visual Basic dibuje un radio con el ángulo especificado por el valor absoluto del parámetro. Tanto comienzo como final deben ser negativos para que se dibujen los dos radios. Visual Basic no rellenará un arco o una porción de tarta que no esté cerrada. En las figuras 10.21 y 10.22 se muestran algunos ejemplos.
El objeto Printer
Figura 10.22. Dibujar un círculo menos una porción de tarta con el método Circle
hay un método Cls , así que no puedes borrar lo que hayas escrito en la impresora. Usa el método NewPage para comenzar una página nueva, y el método EndDoc para finalizar la tarea de impresión. Puedes leer la propiedad Page (página) del objeto Printer para saber el número de la página actual.
Usando muchos de los mismos métodos que se emplean para escribir en un formulario, puedes hacer que tu programa escriba directamente en una impresora. Visual Basic admite métodos para el objeto Printer (impresora), que dibujan tanto texto (el método Print) como gráficos (los métodos Line , Circle y PSet). Puedes imaginarte que escribir en una impresora es como escribir en un formulario especial cuyo tamaño es el del papel de la impresora.
En la figura 10.23 se ha modificado el ejemplo gráfico que se mostró por primera vez en la figura 10.6 para que la función se imprima en la impresora.
Como se puede aplicar el método Scale al objeto Printer, puedes trabajar con cualquier sistema de coordenadas con el que te sientas a gusto. Por supuesto, no
Cuando estés dibujando en un formulario o en la pantalla y termines todos los di bujos necesarios, puedes llamar simplemente al método PrintForm del formulario
306
307
EL LIBRO DEL VISUAL BASIC 10 Programación gráfica
para enviar una copia del mapa de bits del formulario a la impresora. Si haces esto no es necesario que llames a Printer.EndDoc; el método PrintForm es un proceso completo para documentos de una página.
Sub ImprimirGrafico ( ) Dim X As Single Printer.Scale (-150, 150)-(150, -150) 'Dibujar los ejes Printer.Line (-150, 0) -( 150, 0) Printer.Line(0, -150)-(0, 150) 'Dibujar el gráfico Printer.CurrentX = -10 Printer.CurrentY = FdeX(-1O) For X = -10 To 10 Printer.Line -(X, FdeX(X)) Next X Printer.EndDoc End Sub
O quizás podrías desarrollar un programa en un ordenador con una tarjeta de alta resolución. ¿Qué sucedería si el usuario tuviese un sistema de baja resolución? En tu ordenador, el texto de 6 puntos puede quedar bien, pero en un ordenador portátil podría no ser legible. Si tienes pensado escribir programas para distribuirlos, es posible que quieras examinar las propiedades TwipsPerPixelX y TwipsPer PixelX de los objetos Screen y Printer. (El objeto Screen representa a la pantalla entera. Un programa puede examinar las propiedades del objeto Screen para determinar asuntos como qué fuente usar y dónde poner los cuadros de diálogo.)
Figura 10.23.
El código de un programa para representar gráficamente una ecuación en la impresora
Consideraciones sobre el hardware para los pro gramas gráficos Si estás interesado en escribir programas gráficos que sean realmente útiles para otras personas, debes considerar cuidadosamente el diseño de tus programas —y, particularmente, debes tener en cuenta el hardware sobre el que los programas podrán funcionar. Por ejemplo, como ya se trató antes en este capítulo, la decisión de usar la propiedad AutoRedraw o un procedimiento Paint para redibujar la pantalla puede ser importante. Recuerda que la cantidad de memoria requerida por Visual Basic para mantener copias de las imágenes de tus formularios dependen del hardware sobre el que el programa esté funcionando. En un caso extremo, por ejemplo, podrías desarrollar un programa para un sistema monocromo, pero el usuario podría tener una tarjeta gráfica de 1280 por 1024 puntos de 24 bits, cuyos requerimientos de memoria serían substancialmente más grandes que los de tu sistema. Usar AutoRedraw en un caso así podría agotar fácilmente la memoria disponible. 308 309
11 Bases de dato datoss y cuadrí cu adrícul culaas El capítulo 5 te presentó las herramientas Data y Grid, y te describió brevemente cómo se usan para obtener el acceso a bases de datos o para presentar datos. Este capítulo describe ambas herramientas con más detalle y proporciona ejemplos de su uso. El capítulo también cubre conceptos más avanzados y técnicas de programación más complejas que las que has utilizado en los capítulos previos. Si eres nuevo en el ámbito de la programación es posible que prefieras saltarte los dos siguientes capítulos y que quieras ir directamente al capítulo 13, "Una aplicación para Windows completa".
¿Qué es es una base de dato s? Dicho en pocas palabras, una base de datos es cualquier conjunto de información. Sin embargo, en la jerga informática habitual, una base de datos es un con junto de información relacionada, que se almacena de manera estructurada y bien definida. Por ejemplo, la información sobre las comadrejas copetudas alemanas del capítulo 9 es una base de datos. Tiene columnas en las que aparecen distintas clases de información sobre el sujeto, y filas que describen todos los atributos de un único sujeto. Cada fila es un registro , y en este caso, cada fila describe a una comadreja. En la terminología de las bases de datos, una tabla es un conjunto de registros que tienen la misma estructura. Un grupo de tablas relacionadas componen la base de datos. En el capítulo 9, la base de datos estaba compuesta por una sola tabla. La figura 11.1 ilustra la estructura de la base de datos de comadrejas. Mantener controlada información de este tipo es una tarea tan habitual que se sistemas degestión gestión debase basess dedadahan desarrollado aplicaciones conocidas como sistemas 311
11 Bases de datos y cuadrículas :l
libro del visual basic
Publishers
Authors Número
Longitud
registro
Nombre
Color
P es es o
L on on gi gi tu tu d
FechaNacimiento
ColorCopete
Copete
1
Siegmund
Ma rrón
18
11
03/09/93
Marrón
6
2
Sie gl glind e
M ar arró n c la la ro ro
14
10
10/02/94
Negro
6
3
Siegfried
M a rrón
12
8
13/09/94
Marrón
2
Au_ID Author
4
______ ________ __
Titles Tabla
Figura 11.1. La estructura de la base de datos de comadrejas comadrejas
Year Title
Published
Au_ID
ISBN
PublD
tos (SGBD). Estas aplicaciones ayudan a simplificar la creación y el mantenimiento de las bases de datos. Algunas aplicaciones SGBD de las que es posible que hayas oído hablar son: Microsoft Access, Microsoft Fox Pro, Borland Paradox, Borland dBase y Claris FileMaker. Las empresas utilizan a menudo programas SGBD para organizar y actualizar sus registros de empleados, información de nóminas, listas de clientes, etcétera. En este capítulo, trabajarás con una base de datos de ejemplo que viene con Visual Basic —BIBLIO.MDB. Es una base de datos de Microsoft Access que contiene datos bibliográficos sobre libros que tienen que ver con bases de datos y con Visual Basic (son libros editados en Estados Unidos, por lo que están en inglés). La figura 11.2 muestra la estructura de la base de datos. La base de datos BIBLIO está compuesta por tres tablas. La tabla Authors (autores) contiene los nombres de los autores y sus números de identificación. La tabla Publishers (editoriales) es un conjunto de registros que describen a los editores, incluyendo un código de identificación, el nombre de la empresa de la que son filial, el lugar donde radican y el número de teléfono. Las tablas Authors y Pu blishers contienen los datos de fuente reales. La tabla Titles, aunque su estructura no parezca distinta de la estructura de las otras dos, es diferente. Contiene una lista de libros publicados —los datos de servicio— y hace referencia a las tablas Authors y Publishers mediante números de identificación. Contiene algunos datos fuente, pero también hace referencia a las otras tablas a través de campos comunes, como se ilustra en la figura 11.3. 312
Figura 11.2.
La base de datos BIBLIO
La referencia de una tabla a otra mediante un campo común se denomina rela ción. Este término es lo que da origen a la expresión base de datos relacional. Se pueden construir tablas enteras de campos relacionales, todos los cuales se refieren a campos reales. Los campos relacionales también se pueden referir a otros campos relacionales, los cuales, al final, se referirán a los datos reales. En el lenguaje de las bases de datos, una consulta es una solicitud de información que se realiza a las tablas que componen la base de datos. Cuando se consulta a una base de datos (a través del programa SGBD o a través de tu propia aplicación) hay que definir el conjunto de datos del que se desea solicitar infor mación, estrechando de esta manera el ámbito de la solicitud. El resultado de una consulta es siempre algo que tiene el aspecto de otra tabla. Es una tabla virtual o una vista lógica de los datos que se han solicitado. Cuando 313
EL LIBRO DEL VISUAL BASIC
11 Bases de datos y cuadrículas
Company
Year Title
Published
Au_ID
ISBN
Name
Name
Running VB for Windows
1993
33
1556154771
MS PRESS
Microsoft
r
Figura 11.4. Una posible vista lógica de las tablas que componen la base de datos BIBLIO
Ac ced er y mo st rar dat os us and o Vi su al B asi c
Figura 11.3. La tabla Titles hace referencia a las tablas Autbors y Publishers, mediante los números de identificación de los autores y de las editoriales
se define el conjunto de datos, realmente se están estableciendo relaciones entre las tablas de la base de datos. La vista lógica resultante no existe de esa forma en la base de datos, pero se refiere a parte de los datos, algunos de los cuales pueden ser identificados por otras relaciones que haya dentro de la base de datos, que sí existen allí. Por tanto, son las relaciones las que permiten construir vistas lógicas de los datos. La figura 11.4 muestra una posible vista lógica de la base de datos BIBLIO. Acceder a los datos y mostrarlos son dos cosas diferentes. En el siguiente apartado, aprenderás a crear una base de datos en Visual Basic que realizará ambas operaciones. 314
En algún momento puede que te encuentres creando una aplicación que haga uso de información que ya esté contenida en una base de datos. Sería posible duplicar la información de esa base de datos en un archivo de acceso aleatorio de Visual Basic; sin embargo, ello sería ineficiente y potencialmente peligroso. Sería ineficiente, porque significaría que habría varias copias de los datos ocupando espacio en el disco. Sería peligroso, porque tener más de una copia significa que los conjuntos de datos podrían dejar de estar sincronizados unos con otros. Es decir, la información podría ser actualizada en un lugar, pero no en los datos correspondientes rrespondientes a la copia. Una solución mucho mejor es la de mantener una sola copia de los datos de la base de datos y hacer que tu aplicación de Visual Basic acceda a ella. Este acceso se puede configurar creando un control Data (datos) en la aplicación de Visual Basic. La figura 11.5 muestra el botón de la herramienta Data en la caja de herramientas y un control Data como aparece en el formulario. Nota: A ntes
de ut il i zar la herramienta herrami enta D ata en Vi sual B asi c, es necesa necesa rio que actives la posibilidad de compartir archivos, a no ser que estés usando Windows para Trabajo en Grupo. Si esta posibilidad no está ac tivada en tu ordenador , , debes salir de Windows e introducir el comando share en el indicador del MS-DOS. Luego, puedes volver a arrancar Win dows y Visual Basic. Es posible que quieras poner el comando share en el arch archivo ivo A UTOEX EC.BAT. 315
1 1 Bases de datos y cuadrículas
LIBRO DEL VISUAL BASIC
El control Data
El control Data tiene varias propiedades que describen la conexión entre la aplicación Visual Basic y la base de datos a la que quieres acceder. Una aplicación puede tener más de un control Data; de hecho, es necesario un control Data por cada conjunto de datos definido. Cada control Data accede cada vez a un solo registro, al cual se le llama el registro actual. Después de establecer estas propiedades se pueden ligar otros controles de Visual Basic. Cuando se modifica el registro actual (haciendo clic directamente en el control Data o mediante instrucciones en el programa), esos controles muestran los datos que hay en el registro actual. La versión actual de Visual Basic permite intercambiar datos con los siguientes SGBD:
Figura 11.5.
■ Microsoft Access ■ Microsoft FoxPro
Figura 11.6.
El formulario Biblio recién recién creado
■ Borland dBase ■ Borland Paradox Realizar la conexión
Construyamos ahora una aplicación nueva que pueda acceder a la base de datos BIBLIO. La configuraremos de manera que cuando se haga clic en el control Data, se muestren a la vez el numero de identificación del autor y el título del li bro de cada registro de las base de datos. Primero, incluye un control Data en la parte superior del formulario, y luego añade dos etiquetas y dos cuadros de texto. Establece las propiedades como se muestran en la tabla que viene a continuación, y tu formulario deberá parecerse al que se muestra en la figura 11.6. Objeto
Propiedad
Aju ste
Form1
Caption Name Caption Name Caption Caption Name Text Name Text
Base de datos: BIBLIO Biblio Base de datos de libros dtaBiblio Autor Título txtAutor [ninguno] txtTitulo [ninguno]
Data1 Labell Label2 Text1 Text2
316
En esta fase sólo has configurado la apariencia del formulario. Para hacer la conexión con la base de datos, debes establecer una cuantas propiedades adicionales del control Data. Las propiedades que se muestran a continuación se pueden establecer durante la fase de diseño o durante la ejecución del programa. Si tu aplicación siempre va a acceder a la misma base de datos, establécelas durante la fase de diseño; Visual Basic podrá realizar una cierta comprobación de errores adicional si estableces las propiedades en la fase de diseño. Selecciona el control Data (dtaBiblio) en la ventana Properties y establece las propiedades que se definen debajo: (conexión). Esta propiedad le dice a Visual Basic en qué formato están los datos. Para este ejemplo, establece la propiedad como una cadena vacía, lo que indica que la base de datos está en el formato de Microsoft Access. Otros valores legales son "foxpro 2.5;", "paradox;", y "dbase IV;". Consulta en el M anual del P rogr amador de V i sual B asi c todos los formatos de bases de datos aceptados.
Connect
DatabaseName (nombre de la base de datos). Esta propiedad identifica al archivo de base de datos. Haz clic en los puntos suspensivos (...) de la ventana Properties y elige BIBLIO.MDB. Debe estar en el mismo directorio que el programa Visual Basic. RecordSource (fuente del registro). Esta propiedad le dice a Visual Basic de dónde obtener los datos. Puede ser el nombre de una tabla o puede identi
317
EL LIBRO DEL VISUAL BASIC
ficar una vista lógica. Por ahora, establece RecordSource como "Titles" para obtener los datos de la tabla Titles (títulos). Ligar controles de visualización con el control Data
Tu aplicación Visual Basic ya tiene suficiente información para recuperar datos de la base de datos. Con un pequeño añadido, la aplicación también mostrará los datos en la pantalla. Los controles Check Box, Image, Label, Picture Box y Text Box se pueden enlazar directamente con los campos de la tabla a la que accede el control Data. Los controles Image y Picture Box se pueden usar para mostrar las imágenes almacenadas en la base de datos; un control Check Box muestra valores booleanos; y los controles Label y Text Box pueden utilizarse para presentar información numérica o de texto. En todos estos controles, las propiedad Data Source los conecta con un control Data, y la propiedad DataField (campo) identifica el nombre del campo de la tabla al que hay que ligar el control. Haz clic en el cuadro de texto txtAutor y establece su propiedad DataSource como dtaBiblio. Establece la propiedad DataField como Au_ID. Luego, haz clic en el cuadro de texto txtTitulo y establece sus propiedades DataSource como dtaBi blio y DataField como Title. Ejecuta la aplicación. A medida que hagas clic en el control Data, los registros de la base de datos aparecerán en los campos de texto, ¡y tú no has tenido que escribir ni una sola línea de código! También se pueden editar los datos desde la aplicación de Visual Basic, y los resultados se escribirán en la base de datos original.
Es i mportante no modificar datos que no te " pertenecen". Si estás creando una aplicación para acceder a las bases de datos de la empresa, asegúrate de que permites el acceso sólo a aquellos usuarios que tienen permiso para modificar la tabla. Consulta el Manual del Programador de Visual Basic si necesitas información sobre las propiedades Exclusive (exclusivo), Options (opciones)y ReadOnly (sólo lectura). Nota:
Definir el conjunto de registros
El término conjunto de registros se refiere a los registros que están seleccionados para acceder a ellos. Se define por la propiedad RecordSource del control Data. En este ejemplo, el conjunto de registros es la tabla Titles. Sin embargo, con bastante frecuencia desearás que tu aplicación acceda solamente a un subconjunto de los registros de una base de datos o a una vista de la base de datos que se extiende más allá de una sola tabla. 318
11 Bases de d atos y cua drículas
Por ejemplo, la aplicación actual es de alguna manera menos útil de lo que debería, porque muestra el número de identificación del autor del libro en lugar de mostrar su nombre. Podemos solucionar este problema modificando el conjunto de registros para que se apoye en una vista relacional de la base de datos. Detén la aplicación y establece en la ventana Properties la propiedad RecordSource del control Data de esta manera: select Author, Title from Authors, Titles where Authors.Au_ID = Titles.Au_ID
Esto es una instrucción SQL que crea una nueva vista de la base de datos (y define un nuevo conjunto de registros) combinando las tablas Authors y Titles mediante la relación Au_ID y seleccionando dos columnas: Author y Title. Debes modificar la propiedad DataField del cuadro de texto txtAutor a Author, porque la vista recién creada no tiene un campo llamado Au_ID. (Puedes aprender más so bre SQL en el manual de tu SGBD, o puedes recorrer la base de datos para descubrir algunos de los libros que se han publicado sobre el tema.) Ahora ejecuta la aplicación de nuevo. Verás que en este caso obtienes el nombre del autor en lugar de su número de identificación (Au_ID). Cuando accedas a una serie de datos en los que el conjunto de registros esté definido por una consulta en lugar de estarlo por una tabla completa, puede que no se te permita ac tualizar los datos.
Control mediante el programa Además de seleccionar un registro usando el control Data, puedes usar métodos que logran los mismos objetivos desde el programa. De hecho, se puede establecer la propiedad Visible del control Data como False y ejecutar toda la manipulación de los datos bajo el control del programa. Los siguientes métodos tienen efecto sobre el control Data: Refresh (refrescar). La base de datos se abre para ser utilizada, o se cierra y se vuelve a abrir si ya estaba abierta.
(mover al primero). Se establece que el registro actual sea el primero del conjunto de registros.
MoveFirst
(mover al siguiente). El registro actual pasa a ser el siguiente del conjunto de registros. MoveNext
(mover al anterior). El registro actual pasa a ser el anterior del conjunto de registros. NlovePrevious
319
EL LIBRO DEL VISUAL BASIC MoveLast (mover al último). Se establece que el registro actual sea el último del conjunto de registros.
(añadir nuevo). Se añade un registro nuevo al conjunto de registros. (Sólo es válido cuando el conjunto de registros es una tabla o una dynaset : hoja de respuestas dinámica).
Add New
Update (actualizar). Se escriben todos los campos editados en la base de datos. (Sólo es válido cuando el conjunto de registros es una tabla o una dynaset: hoja de respuestas dinámica). Delete (borrar). Se elimina el registro actual. Este método sólo es válido cuando el conjunto de registros es una tabla o una hoja de respuestas dinámica (dynaset ) y debe de estar seguido, inmediatamente, por uno de los métodos Move, ya que el registro actual deja de ser válido después de una operación de borrado.
Cuando te estés moviendo por la base de datos mediante un programa, querrás, comprobar las propiedades BO F (beginning of file: comienzo del archivo) y EOF (end of file: final del archivo) del control Data. La propiedad BOF es True cuando el registro actual está situado delante de todos los datos. Esto ocurre, normalmente, cuando se borra el primer registro. La propiedad EOF es True cuando el registro actual está situado detrás del final de los datos. Si cualquiera de las dos propiedades es True, el registro actual no es válido. Si ambas propiedades son True, entonces no hay ningún dato en el conjunto de registros.
11 Bases de datos y cuadrículas
Do While Not dtaBibli o.Recorset.NoMatch Debug.Print dtaBiblio.Recorset.Fi elds("Title").Value dtaBiblio.Recorset.FindNext Criterio Loop
Este fragmento de programa también te muestra la manera de utilizar la propiedad NoMatch después de una operación Find y cómo acceder mediante el programa a un campo del conjunto de registros. Si la operación Find falla (y la propiedad NoMatch es True), el registro actual no cambiará. Crear una aplicación del tipo agenda de direcciones
Pongamos junto todo lo que hemos tratado en este capítulo y ampliemos la aplicación para que se mueva por la base de datos a partir del nombre del autor. Aprovecharemos el hecho de que la base de datos está ordenada alfabéticamente por autores. Amplía el formulario de la aplicación para poner un pequeño botón de comando en el extremo inferior izquierdo, como muestra la figura 11.7. La propiedad Caption del botón se ha establecido como "A" en la figura, y la propiedad Name es cmdLetra.
Buscar registros específicos
Además de avanzar secuencialmente a través del conjunto de registros, puedes establecer criterios de coincidencia y mostrar sólo los registros que cumplan dichos criterios. Los métodos FindFirst (buscar el primero), FindNext (buscar el siguiente), FindPrevious (buscar el anterior) y FindLast (buscar el último) funcionan de manera muy similar a los métodos Move descritos antes. Las diferencias estri ban en que los métodos Find funcionan sobre el componente del conjunto de registros del control Data, y que toman un parámetro de cadena que expresa el criterio de búsqueda como una expresión booleana. Por ejemplo, para recorrer todos los libros cuyos títulos empiecen por la letra "T" en la aplicación que estamos viendo, puedes escribir un código como éste: Dim Criterio As String Criterio = "Title >= ’T’ And Title < ’U’" dtaBiblio.Recorset.FindFirst Criterio
320
Figura 11.7.
Ampliar la aplicación
Para que tuviera completamente el aspecto de una agenda de direcciones, habría que poner una fila de botones de la A a la Z en lugar de un solo botón. Sin em bargo, dibujarlos todos y hacer que todos sean del mismo tamaño sería verdaderamente pesado, así que dejaremos que Visual Basic haga el trabajo durante la ejecución del programa haciendo que el botón de comando sea una matriz de controles. Haz que el botón sea una matriz de controles estableciendo su propiedad Index en 0. Introduce el código siguiente en el procedimiento Load del formulario: 321
EL LIBRO DEL VISUAL BASIC
Sub Form_Load ( ) Dim I As Integer For I = 1 To 25 Load cmdLetra(I) 'Crear un nuevo control 'Situarlo directamente a la izquierda del anterior cmdLetra (I).Left = cmdLetra(I - 1).Left + CmdLetra(I - 1) .Width 'Calcular su Caption a partir de su posición (A, B, C, D , . . . ) cmdLetra(I).Caption = Chr$(Asc("A") + I) cmdLetra(I).Visible = True Next I End Sub
Cuando este procedimiento se ejecute al arrancar el programa, se crearán 25 nuevos miembros de la matriz de controles de botones de comando, cada uno al lado del otro, y cada uno con la siguiente letra del alfabeto como título. Ahora todo lo que tienes que hacer es ejecutar un método Find cuando se pulse un botón. Usaremos la propiedad Caption del botón como criterio de búsqueda. Es decir, si se elige el botón "N", el criterio será Author >= 'N'. Introduce el siguiente procedimiento como procedimiento Click de la matriz de controles de botones de comando. Sub cmdLetra_Click (Index As Integer) dtaBiblio.RecordSet.FindFirst "Author >= ’" + cmdLetra(Index).Caption + " ' " End Sub
Cada vez que hagas clic en uno de los botones, el registro actual se situará de acuerdo con el criterio de búsqueda. Como la tabla está ordenada alfabéticamente, al pulsar las flechas Siguiente y Anterior del control Data avanzará al siguiente autor. Cuando ejecutes la aplicación, ésta debe parecerse a la de la figura 11.8 (hemos pulsado el botón N).
11 Bases de datos y cuadrículas
Acceder dinámicamente a una base de datos
En los ejemplos anteriores, el conjunto de registros era ya conocido en la fase de diseño. Por tanto, podíamos crear controles enlazados que mostrasen automáticamente los campos de ese conjunto de registros. Es posible que quieras escribir aplicaciones que abran bases de datos desconocidas, que sean seleccionadas por el usuario de la aplicación. En tal caso, tendrás que determinar dinámicamente los campos de la base de datos —esto es, durante la ejecución del programa. Este apartado te muestra cómo crear una aplicación que abra cualquier base de datos, presente al usuario una lista de sus tablas y, cuando se seleccione una tabla, se muestre en un formulario cuadriculado. Además de la propiedad Recorset del control Data, Visual Basic dispone de objetos que describen la base de datos. A estos objetos se accede a través de las propiedades del control Data. Por ejemplo, la propiedad Database del control Data accede al objeto descriptor de la base de datos. Este objeto puede, además, tener propiedades propias. Hasta este momento, la mayoría de los objetos que has usado tenían propiedades de tipos simples; por ejemplo, el objeto Command Button tiene propiedades como Caption y Height, cuyos valores son cadenas o números enteros. No cuesta trabajo imaginar una propiedad que devuelva algo más complejo que una cadena de caracteres o que un número entero, como, por ejemplo, una colección , las cuales se describirán a continuación. Para acceder a una propiedad de un objeto que es en sí mismo la propiedad de otro objeto, simplemente hay que añadir otro punto (.) y el nombre de la propiedad a la expresión original. De esta manera, la expresión X.Y.Z se referiría a la propiedad Z del ob jeto al que se conoce por ser la propiedad Y de X. Colecciones
Una colección es como un cruce entre un cuadro de lista y una matriz. Como matriz es dependiente totalmente de un programa, y no tiene representación gráfica. Sin embargo, como cuadro de lista, una colección es un objeto con sus propias propiedades. Cada colección tiene una propiedad Count que dice cuántos objetos están contenidos en ella. A los objetos contenidos se puede acceder mediante un índice numérico (de 0 a Count-D o por el nombre del objeto contenido. En el bucle de ejemplo de la página 321 accedimos a la colección Fields del objeto Recorset con la instrucción: D e b u g . P r i n t d t a B i b l io . R e c o r s e t . F i e l d s ( " T i t l e " ) . V a l u e
Figura 11.8.
La versión 'agenda de direcciones' de la aplicación Biblia 322
En la instrucción anterior, se utiliza el nombre "Title" para extraer el campo deseado. 323
EL LIBRO DEL VISUAL BASIC
11 Bases de d atos y cua drículas
Expresiones de ejemplo
Aquí tienes algunas expresiones que proporcionan información sobre las bases de datos conectadas a través de un control Data de Visual Basic. Se presupone el uso del control dtaBiblio del ejemplo anterior. Expresión
base de datos u hoja de cálculo. El icono del control Grid en la caja de herramientas se muestra en la figura 11.9. Este control no aparecerá en la caja de herramientas a no ser que se añada el archivo GRID.VBX a la ventana Project.
Valor
El propio control Data El objeto descriptor de la base de datos dtaBiblio.Database.Name El nombre de la base de datos dtaBiblio.Database.TableDefs.Count El número de tablas en la base de datos dtaBiblio.Database.TableDefs(O).Name El nombre de la primera tabla de la base de datos dtaBiblio.Database.TableDefs(0).Fi elds.Count El número de campos en la primera tabla dtaBiblio.Database.TableDefs(0).Fields(0).Name El nombre del primer campo en la base de datos dtaBiblio.Recordset El conjunto de registros al que se está accediendo actualmente mediante el control dtaBiblio.Recordset.Fields.Count El número de campos en el conjunto de registros dtaBiblio.Recordset.Fields(0).Name El nombre del primer campo en el conjunto de registros dtaBiblio.Recordset.Fields(0).Value El valor del primer campo del conjunto de registros dtaBiblio
dtaBiblio.Database
Figura 11.9.
El icono de la herramienta Grid
Se muestran dos controles Grid de ejemplo en la figura 11.10. El Grid de la izquierda muestra celdas grises a lo largo de la fila superior y de la columna izquierda, y tiene barras de desplazamiento verticales y horizontales. El Grid de la derecha no tiene ninguna columna de celdas grises y no tiene barras de desplazamiento. Estas posibilidades de presentación se controlan mediante las siguientes propiedades del control Grid: Rows (filas). El número total de filas del Grid. Si hay más filas de las que caben en el espacio asignado para el Grid en el formulario, aparecerá una barra de desplazamiento vertical. Columns (columnas). El número total de columnas en el Grid. Aparecerá una barra de desplazamiento horizontal si el número de columnas es demasiado grande para el tamaño del Grid.
(filas fijas). El número de filas, empezando desde arriba, que tienen una posición fija. Las filas fijas no se desplazan y tienen el fondo de color gris. Se usan normalmente para los títulos. FixedRows
Una vez que conoces cómo consultar a la base de datos, se puede crear dinámicamente una pantalla para mostrar la información. Sin embargo, en lugar de crear cuadros de texto separados para cada campo, puede ser más interesante utilizar el control Grid. El control Grid
Un grid (rejilla o cuadrícula) es una matriz de dos dimensiones de cuadros de vi sualización, o celdas , especialmente indicada para mostrar información del tipo 324
figura 11.10. Dos controles Grid de ejemplo
325
11 Bases de d atos y cua drículas
EL LIBRO DEL VISUAL BASIC FixedColumns (columnas fijas). El número de columnas, empezando por la izquierda, que tienen una posición fija. Como las filas fijas, son utilizadas normalmente para incluir las cabeceras, no se desplazan con el resto de las columnas y son de color gris. ColWidth (anchura de la columna). La anchura de una columna concreta, medida en mips (1/20 de punto). RowHeight (altura de la fila). La altura de una columna concreta, también medida en twips.
Figura 11.11.
El diseño inicial del formulario
Una aplicación para revisar los datos
Con lo que has aprendido hasta ahora sobre el control de un Grid puedes crear una aplicación que abra cualquier base de datos, presente al usuario una lista de las tablas que contiene y, cuando se seleccione una tabla, ésta se muestre en el Grid. Empieza por crear una aplicación nueva. Si tu ventana Project no contiene GRID.VBX, selecciona el comando Add File del menú File y cárgalo en tu proyecto. GRID.VBX debe estar en el directorio SYSTEM de Windows. Como necesitarás una manera de elegir el archivo de base de datos que quieres examinar, añade CMDIALOG.VBX al proyecto de la misma manera. Inserta un botón de comando, un cuadro combinado, un control Data, un control Common Dialog y un control Grid en el formulario. Después, distribuyelos y cámbiales el tamaño para que aparezcan como se muestra en el figura 11.11. Por último, establece las propiedades de los controles como se detalla en la tabla que aparece a continuación. Objeto
Propiedad
Aju ste
Form1
Caption Name Name Name Visible Caption Name Name Text FixedCols Name
Examinar base de datos Grid1 dlogo dtaTabla False Abrir base de datos cmdAbrir cboTablas [ninguno]
CMDialog1 Data1 Command1 Combo1 Grid1
326
0
grdDatos
El control Data se establece como invisible porque todo el acceso a la base de datos se hará mediante el programa. La propiedad FixedCols del Grid se establece en 0 porque no hay filas de cabecera —solamente cabeceras de columnas en una fila fija en la parte superior del Grid. Añade la primera línea de las que aparecen a continuación a la sección de declaraciones generales del formulario. Luego define el procedimiento Click para el botón de comando como se muestra. (La definición de la constante OFN_FILE MUSTEXIST viene del archivo CONSTANT.TXT.) Const OFN_FILEMUSTEXIST = &H1000& Sub cmdAbrir_Click ( ) cboTablas.Clear diogo.DefaultExt = "MDB"
'Vaciar el cuadro de lista combinado 'Extensión de las bases de datos 'de Microsoft Access
dlogo.Filename = " " dlogo.Filter = "Bases de datos (*.MDB|*.MDB|Todos los archivos (*.* ) | *.* " dlogo.Flags = OFN_FILEMUSTEXIST dlogo.Action = 1 'Abrir el cuadro de diálogo If dlogo.FileName = " " Then Exit Sub abrirArchivoDeDatos dlogo.Filename End Sub
Cuando hagas clic en el botón de comando, el programa presentará el cuadro de diálogo Abrir archivo y permitirá al usuario seleccionar un archivo de base de datos. Este programa está configurado para gestionar archivos del formato de Microsoft Access que tengan la extensión MDB. Cuando se selecciona un archivo, el programa llama a una rutina llamada AbrirArchivoDeDatos, pasándole el nombre 327
11 Bases de d atos y cua drículas EL LIBRO DEL VISUAL BASIC
del archivo de base de datos. El código de esta rutina se muestra en la parte superior de la página siguiente. Sub AbrirArchivoDeDatos (ByVal ArchivoDeDatos As String) Dim I As Integer dtaTabla.Connect = "" 'Formato de Access dtaTabla.DatabaseName = ArchivoDeDatos dtaTabla.ReadOnly = True 'Para un acceso más rápido dtaTabla.Exclusive = True 'Para un acceso más rápido dtaTabla.Refresh 'Cargar la base de datos For I = 0 To dtaTabla.Database.TableDefs.Count - 1 'Poner el nombre de todas las tablas en el cuadro combinado cboTablas.AddItem dtaTabla.Database.TableDefs(I).Name Next I cboTablas.Text = "(ninguna)" 'Nada seleccionado ahora End Sub
La rutina AbrirA rchivoDeDatos inicializa el control Data y luego consulta en el objeto Database el nombre de todas las tablas de la base de datos. Estos nombres son insertados en la lista del cuadro combinado. El código que controla el cuadro combinado es bastante simple; llama a una rutina que rellena el Grid. Establece el procedimiento Click del cuadro combinado como sigue:
For I = 0 To dtaTabla.Database(NombreDeLaTabla).Fields.Count - 1 grdDatos.Col = I grdDatos.Text = dtaTabla.Database(NombreDeLaTabla). Fields(I).Name grdDatos.ColWidth(I) = TextWidth(grdDatos.Text) + 100 Next I dtaTabla.Refresh 'Determinar el número de registros y establecer el tamaño del Grid dtaTabla.Recordset.MoveLast grdDatos.Rows = dtaTabla.Recordset.RecordCount + 1 'Rellenar el Grid comenzando por el primer registro dtaTabla.Recordset.MoveFirst grdDatos.Row = 0 Do While Not dtaTabla.Recordset.EOF grdDatos.Row = grdDatos.Row + 1 For I = 0 To dtaTabla.Database(NombreDeLaTabla).Fields.Count - 1 grdDatos.Col = I 'Almacenar un blanco si el dato del campo es nulo If IsNull(dtaTabla.Recordset(I).Value) Then grdDatos.Text = "" Else grdDatos.Text = dtaTabla.Recordset(I).Value End If
Sub cboTablas_Click ( ) RellenarGrid cboTablas.Text End Sub
Todo lo que queda por hacer es escribir la rutina que rellene el Grid, la cual se muestra a continuación. Esta rutina tomará como parámetro el nombre de la tabla seleccionada, consultará la base de datos para obtener los nombres de los campos, y pondrá esos nombres en la fila fija del Grid. Luego irá recorriendo la tabla, obteniendo los valores de todos los registros y poniéndolos en las filas y columnas adecuadas del Grid. Sub RellenarGrid (ByVal NombreDeLaTabla As String) Dim I As Integer, AnchoDeCelda As Integer 'Inicializar el conjunto de registros dtaTabla.RecordSource = NombreDeLaTabla 'Establecer las cabeceras de las columnas grdDatos.Cols = dtaTabla.Database(NombreDeLaTabla).Fields.Count grdDatos.Row = 0
328
'Asegurarse de que todos los datos s e ven AnchoDeCelda = TextWidth(grdDatos.Text) + 100 If AnchoDeCelda > grdDatos.ColWidth(I) Then grdDatos.ColWidth(I) = AnchoDeCelda End If Next I dtaTabla.Recordset.MoveNext Loop End Sub
Esta aplicación presupone que todos los registros de una tabla concreta cabrán en la memoria. Algunas bases de datos tienen tablas con cientos de miles de registros. Para hacer que esta aplicación fuera realmente general se podría hacer que leyese sólo 100 registros aproxi-
Nota:
329
EL LIBRO DEL VISUAL BASIC
mudamente cada vez y que, una vez que el usuario hubiera pasado los 100 primeros , leyese el siguiente grupo de 100, y así sucesivamente. Si trabajas con grandes bases de datos es posible que quieras mejorar esta aplicación. Hay dos cosas que resaltar en el procedimiento RellenarGrid: para determinar el número de filas que el Grid debe tener, el procedimiento salta al final de la tabla MoveLast) y comprueba la propiedad RecordCount del último registro. (el método MoveLast) Entonces ajusta el tamaño del Grid y comienza a cargar los datos desde el comienzo de la tabla. Cuando se está cargando la base de datos, el procedimiento comprueba los campos que no contienen información llamando a la función I sNull. Si la función IsNull encuentra un campo nulo, se pone un espacio en blanco en el Grid. A medida que el Grid se va rellenando, el procedimiento también establece la anchura de las columnas (ColWidth) que necesitan ser más anchas para mostrar todos los datos. Para determinar lo ancha que debe ser la columna el procedimiento llama al método TextWidtb. Observa que llamar a TextWidth presupone que la información de la fuente es la misma que la del Grid; si no fuera así, el método TextWidth devolvería un valor incorrecto. Después de que la aplicación esté completa puedes ejecutarla. La figura 11.12 muestra la aplicación después de que el usuario haya abierto la base de datos BI BLIO.MBD y haya seleccionado la tabla Publishers.
12 Enlace e incrus inc rustación tación de objetos Este capítulo introduce el concepto de enlace e incrustación de objetos (OLE) y describe los métodos necesarios para usar OLE en las aplicaciones de Visual Basic. Los conceptos y las técnicas de programación presentadas en este capítulo son algo más complejos que los de los capítulos anteriores. Si eres nuevo en el mundo de la programación, quizás prefieras pasar al capítulo 13
OLE en Visual Basic En el capítulo 11 viste cómo Visual Basic puede aprovechar los datos creados, ordenados y mantenidos por una aplicación SGBD. Aunque el control Data es parte de Visual Basic, depende del trabajo del programa de gestión de la base de datos. Mediante OLE, se pueden aprovechar otras aplicaciones de la misma manera.
Figura 11.12.
La aplicación Grid
OLE permite la cooperación entre aplicaciones Windows. Usando OLE, tus aplicaciones Visual Basic pueden mostrar y controlar datos procedentes de otras aplicaciones. La manera de usar OLE en Visual Basic es el control OLE. Este control permite que el usuario muestre en pantalla datos de otra aplicación y que edite los datos en la misma aplicación donde fueron creados. La figura 12.1 muestra la herramienta OLE en la caja de herramientas de Visual Basic.
El control OLE no aparecerá en la caja de herramientas a no ser que hayas cargado el archivo MSOLE2.VBX en la ventana Project. Si mo dificaste tu archivo AUTOLOAD. MAK, tendrás que seleccionar el coman do Add File del menú File de Visual Basic y buscar MSOLE2..VBX. Estará en el subdirecto subdirectorio rio SYSTE S YSTEM M deWi ndows. ndows.
Nota:
331 330
EL LIBRO DEL D EL VISUAL BASIC BA SIC
12 Enlace e incrustación de objetos co nte ned or (container). Una aplicación contenedor contiene el objeto que es creado por otra aplicación. Por ejemplo, una aplicación de Visual Basic que contiene un gráfico incrustado de un programa de dibujo es una aplicación contenedor.
Ap lic aci ón
Figura 12.1.
La herramienta OLE
Antes de que puedas comprender plenamente el control OLE necesitarás familiarizarte con algunos de los términos concretos relacionados con el enlace y la incrustación de objetos.
Una aplicación fuente es la aplicación original que crea un objeto. Por ejemplo, un programa de dibujo que crea un objeto gráfico es una aplicación fuente.
Ap lic ació n fu ent e.
Un ejemplo de OLE: incrustar un objeto en la fase de diseño Al gu no s t ér m in os OL E
Un objeto es una entidad discreta de datos. Los objetos pueden ser texto, hojas de cálculo, algunas celdas de una hoja de cálculo, gráficos, sonido, segmentos de vídeo o cualquier otra cosa que pueda ser mostrada o controlada por una aplicación. Un control OLE puede contener solamente un objeto cada vez.
Objeto OLE.
Los datos de un objeto OLE se pueden enlazar con una aplicación. Cuando se enlaza un objeto, en realidad se inserta un "reflejo", y no los datos reales, del objeto enlazado en el control OLE de la aplicación. Así, cuando se enlaza un gráfico (por ejemplo, un logotipo), en una aplicación Visual Basic, el usuario puede seleccionar el objeto enlazado y la aplicación enlazada arrancará automáticamente. El usuario podrá entonces editar el gráfico usando la aplicación asociada. Se pueden establecer otros enlaces con el mismo objeto, y cuando el gráfico se modifique en la aplicación fuente, también cambiará en todas, las aplicaciones a las cuales esté enlazada.
Objeto enlazado.
incrustado. Los datos de un objeto OLE pueden incrustarse en una aplicación. Cuando se incrusta un objeto, se insertan los datos reales del objeto incrustado en el control OLE de la aplicación. Así, cuando se incrusta un gráfico (por ejemplo, un logotipo), en una aplicación de Visual Basic, todos los datos contenidos con él están asociados en el control OLE. Mientras se use la aplicación de Visual Basic, el usuario podrá seleccionar el objeto incrustado y la aplicación arrancará automáticamente. El usuario podrá entonces editar el gráfico usando la aplicación asociada. Cuando el usuario salga de la aplicación asociada, el objeto se actualizará automáticamente, y los nuevos datos se almacenarán en el control OLE. Al contrario que ocurre con los objetos enlazados, cuando un objeto se incrusta en una aplicación, ninguna otra aplicación tendrá acceso a los datos del objeto incrustado.
Objeto
332
Supon que quisieras que tu base de datos Comadrejas tocase "La cabalgata de las Valkirias" cada vez que la arranques. Como Visual Basic no tiene posibilidades sonoras que vayan más allá del comando Beep, podrías pensar que tienes que aprender las llamadas directas a Windows y crear declaraciones DLL de la misma manera que con las funciones Perfil del capítulo 9. Pero, ¿por qué tendrías que aburrirte aprendiendo todo eso cuando hay una aplicación que puede producir el sonido que tú quieres? La aplicación Grabadora de sonidos de Windows puede interpretar cualquier sonido almacenado como un archivo WAV. Aquí es donde OLE entra en juego, porque tú puedes incrustar el archivo con el sonido en un control OLE. Luego, podrás configurar la aplicación de manera que lo interprete cuando arranque. Haz clic en la herramienta OLE de la caja de herramientas y añade un control a un formulario vacío. Tan pronto como hayas puesto el control en el formulario aparecerá el cuadro de diálogo Insert Object (insertar objeto) que puedes ver representado en la figura 12.2. El contenido del cuadro de diálogo puede variar de un ordenador a otro, dependiendo de las aplicaciones que tengas y de cuántas admitan OLE. Desplázate por la lista hasta que encuentres la entrada Sonido. Selecciónala y haz clic en el botón OK. Aparecerá un icono representativo de la Grabadora de sonido en el área del control OLE, y se ejecutará en primer plano la aplicación Grabadora de sonidos de Windows, como se ilustra en la figura 12.3. En la Grabadora de sonidos selecciona el comando Insertar archivo del menú Edición. Aparecerá el cuadro de diálogo Insertar el archivo que te preguntará por el lugar del cuál seleccionar el archivo de sonido. Como probablemente no tengas una grabación de la "Cabalgata de las Walquirias" en tu ordenador, y como yo no voy a distribuir la mía, tendrá que bastarte, por ahora, con uno de los sonidos del sistema de Windows. Selecciona CHIMES.WAV de tu directorio Windows. 333
EL LIBRO DEL VISUAL BASIC
12 Enlace e incrustación de objetos
Finalmente, haz que el procedimiento Load del formulario contenga la siguiente rutina, de manera que toque el sonido cuando se abra la aplicación: Sub Form_Load ( ) OLE1.Action = OLE_ACTIVATE End Sub
Pulsa la tecla F5 para ejecutar la aplicación. Cuando aparezca el formulario debes oír el sonido de campanas, una atención especial de la aplicación Grabadora de sonidos. Figura 12.2.
El cuadro de diálogo diálogo Insert Object
Enlace frente a incrustación
Acabas de crear un objeto incrustado; es decir, una copia de los datos del sonido se almacenan directamente en tu aplicación. También podrías haber enlazado el archivo de sonido, en cuyo caso se habría almacenado un puntero a los datos (en este caso al archivo CHIMES.WAV), en lugar de los datos reales. La figura 12.4 ilustra la diferencia entre enlazar e incrustar. La principal ventaja del enlace de objetos es que ocupa menos espacio al existir solamente una copia de los datos. Tiene la desventaja de la potencial pérdida del vínculo si se mueve la copia original de los datos o si la aplicación se ejecuta en otro ordenador. Con la incrustación de objetos nunca tendrás que preocuparte de la pérdida de datos, pero algunos objetos pueden ocupar mucho espacio. Sólo 10 segundos de sonido pueden ocupar más de 100 Kb, dependiendo de la calidad deseada.
Figura 12.3.
Un control OLE y la aplicación Grabadora de sonidos
El sonido se cargará en la Grabadora; puedes reproducirlo, si quieres oír primero como suena. Luego, selecciona el comando Salir del menú Archivo. La grabadora de sonido te preguntará si quieres actualizar el objeto incrustado antes de salir, Haz clic en Sí. Selecciona el control OLE en el formulario y a continuación cambia a la ventana Properties y establece la propiedad Visible como False. Como queremos que el sonido se oiga al arrancar, no es necesario que muestres el control OLE. Haz do ble clic en el formulario para que aparezca la ventana de código. Define esta constante en la sección de declaraciones generales como se muestra aquí: Const OLE_ACTIVATE = 7
334
Evidentemente, el enlace es la mejor opción cuando es seguro. Si enlazas objetos con el servidor de una red o ejecutas una aplicación que siempre residirá en tu ordenador, puedes atreverte con el enlace de objetos. Sin embargo, si vas a distri buir la aplicación o si la fuente puede ser modificada y quieres conservar los datos originales, debes incrustar objetos. En nuestro ejemplo, hemos incrustado el sonido CHIMES, lo que significa que podríamos distribuir esta aplicación sin tener que incluir un archivo WAV separado. ¿Qué está disponible para enlazar e incrustar?
Siempre que se instala una aplicación en Microsoft Windows, si esa aplicación admite OLE se añade una entrada al registro OLE. Cuando se crea un control OLE se puede ver una lista de los objetos que se pueden usar en el cuadro de diálogo Insert Object. Dependiento de las aplicaciones de las que dispongas podrás incluir texto con formato, gráficos, hojas de cálculo, vídeo clips y muchas otras cosas en tus aplicaciones de Visual Basic. 335
12 Enlace e incrustación de objetos
LIBRO DEL VISUAL BASIC
ra que el usuario de tu aplicación pueda especificar el objeto que quiere enlazar o incrustar. En este ejemplo uniremos el control OLE con la aplicación Graph sin incrustar ningún dato, y le presentaremos al usuario de la aplicación varias opciones para trabajar con la información.
Aplicac ión fuente fuente
Aplicac Aplicac ión c ontenedor ontenedor Editar
Objetos incrustados Guardar (actualizar)
Aplicación contenedor Aplicación contenedor
Aplicación contenedor
Objetos enlazado enlazado s Aplicac ión fuente fuente Editar
Guardar (actualizar)
El control OLE opera de manera similar al control Common Dialog, en tanto que la asignación de ciertos valores a su propiedad Action produce que se ejecuten las operaciones asociadas. Por ejemplo, establecer la propiedad Action a OLE_IN SERT_OBJ_DLG (que tiene el valor 14) mostraría (durante la ejecución del programa) el cuadro de diálogo Insert Object, que viste cuando creaste el objeto OLE (durante la fase de diseño) del ejemplo anterior. En este ejemplo, sin embargo, no permitiremos que se inserte ningún objeto excepto los creados por la aplicación Graph. Abre un proyecto nuevo de Visual Basic. Selecciona el control OLE y dibuja un cuadro bastante grande en el formulario vacío. Cuando aparezca el cuadro de diálogo Insert Object de OLE, haz clic en el botón Cancel. El control OLE no contendrá ningún dato cuando la aplicación arranque. Añade un botón de comando, un marco con dos botones de opción en su interior, un cuadro combinado y un control Common Dialog, como se muestra en la figura 12.5. Luego, establece las propiedades de los controles como se muestra en la figura 12.6. Lo primero que necesitas es la definición de las constantes que están asociadas con el control OLE. Puedes introducir las definiciones como se muestra en la figura 12.7 o pegarlas desde el archivo CONSTANT.TXT. (Date cuenta de que en el archivo CONSTANT.TXT han sido definidas como globales. Aquí liemos quitado la palabra clave Global.)
Figura 12.4.
Incrustar y enlazar enlazar objetos
La siguiente aplicación de ejemplo utiliza Microsoft Graph, una pequeña utilidad que viene junto con varios programas de la empresa Microsoft, entre los que están Microsoft Word para Windows y Microsoft Access. Si no tienes la utilidad Graph en tu ordenador, trata de adaptar el ejemplo a uno de los objetos que admita tu entorno. Ejemplo de OLE: Manipulación del control OLE durante la ejecución
En el primer ejemplo usamos OLE para incrustar un objeto específico durante la fase de diseño. OLE también se puede controlar mediante el programa, de mane
Figura 12.5.
El formulario OLEGRAPH OLEGRAPH
336
337
EL LIBRO DEL VISUAL BASIC
1 2 Enlace e incrustación de objetos
Figura 12.7. continuación Control
Propiedad
Ajuste
Form1
Caption Name
OLE Graph OLEGraph
OLE1
AutoActivate SizeMode
0 - Manual 1 - Stretch
Command1
Caption Name
Insertar gráfico cmdInsertar
Frame1
Caption
[ninguno]
Option1
Caption Name
Enlazado optEnlazado
Option2
Caption Name Value
Incrustado optIncrustado True
Combo1
Name Text
cboVerbos [ninguno]
CMDialog1
Name
dlogo
Const Const Const Const
'Tipo de OLE Const OLE_LINKED = 0 Const OLE_EMBEDDED = 1 Const OLE_NONE = 3 'Tipo de OLE permitido Const OLE_EITHER = 2 'Opciones de actualización Const OLE_AUTOMATIC = 0 Const OLE_FROZEN = 1 Const OLE_MANUAL = 2 'Modos de auto activación Const OLE_ACTIVATE_MANUAL = 0 Const OLE_ACTIVATE_GETFOCUS = 1 Const OLE_ACTIVATE_DOUBLECLICK = 2
Figura 12.6.
El ajuste de las propiedades de la aplicación OLEGRAPH
'Modos de tamaño C o n s t O L E _ S I Z E _C L I P = 0 Const OLE_SIZE_STRETCH = 1 C o n s t O L E _ S I Z E _A U T O S I Z E = 2
'Control OLE 'Acciones Const OLE_CREATE_EMBED = 0 Const OLE_CREATE_LINK = 1 Const OLE_COPY = 4 Const OLE_PASTE = 5 Const OLE_UPDATE = 6 Const OLE_ACTIVATE = 7 Const OLE_CL0SE = 9 Const OLE_DELETE = 10 Const OLE_SAVE_T0_FILE = 11 Const OLE_READ_FROM_FILE = 12
Figura 12.7.
Definición de las constantes para la aplicación OLEGRAPH 338
OLE_INSERT_OBJ_DLG = 14 OLE_PASTE_SPECIAL_DLG = 15 OLE_FETCH_VERBS = 17 OLE_SAVE_T0_OLE1FILE = 18
'Tipos de presentación en pantalla Const OLE_SIZE_CLIP = 0 C o n s t O L E _S I Z E _ S T R E T C H = 1 Const OLE_SIZE_AUT0SIZE = 2 'Tipos de presentación en pantalla Const OLE_DISPLAY_CONTENT = 0 Const OLE_DISPLAY_ICON = 1
(continúa)
(continúa)
339
LIBRO DEL VISUAL BASIC
12 Enlace e incrustación de objetos
Figura 12.7. continuación
'Constantes de eventos de actualización Const OLE_CHANGED = 0 Const OLE_SAVED = 1 Const OLE_CLOSED = 2 Const OLE_RENAMED = 3 'Valores especiales de Verbos Const VERB_PRIMARY = 0 Const VERB_SHOW = -1 Const VERB_OPEN = -2 Const VERB_HIDE = -3 'Máscaras de bits de banderas Verbo Const VERBFLAG_GRAYED = &H1 Const VERBFLAG_DISABLED = &H2 Const VERBFLAG_CHECKED = &H8 Const VERBFLAG_SEPARATOR = &H800
Cuando la aplicación se ejecute, permitirá al usuario insertar un objeto nuevo en el espacio proporcionado. El objeto puede ser enlazado o incrustado, dependien do de los ajustes de los botones de opciones. El código fuente para la creación del objeto está en el procedimiento Click del control cmdlnsertar (figura 12.8). La última acción que lleva a cabo el procedimiento anterior es llamar al subprograma AñadirVerbos. Esta rutina crea una lista de las opciones aceptadas por el objeto que se acaba de insertar. Los nombres de los verbos se pondrán en el cuadro combinado. El código de AñadirVerbos es el siguiente: Sub AñadirVerbos ( ) D i m I As Integer 'Consultar la matriz ObjectVerbs para buscar las acciones 'aceptadas por este objeto y ponerlas en el cuadro combinado cboVerbos.Clear cboVerbos.AddItem "(ninguno)" For I = 1 To OLE1.ObjectVerbsCount - 1 cboVerbos.AddItem OLE1.ObjectVerbs(I) Next I cboVerbos.ListIndex = 0 End Sub
340
Sub cmdInsertar_Click ( ) OLE1.Class = "MSGraph" 'Aplicación que se va a invocar If optEnlazado.Value Then 'El botón Enlazado está sel eccionado 'Graph usa los archivos de gráficos de Excel; 'buscar uno para enlazar dlogo.Filter = "Gráfico (*.XLC)|*.XLC|Todos los archivos (*.*)|*.*" dlogo.FilterIndex = 1 dlogo.Action = 1 If dlogo.Filename = "" Then MsgBox "No se ha seleccionado ningún archivo" Exit Sub End If 'Crear el enlace OLE OLE1.SourceDoc = dlogo.Filename OLE1.Action = OLE_CREATE_LINK Else 'El botón Incrustado está seleccionado OLE1.Action = OLE_CREATE_EMBED End If 'Realizar el trabajo OLE OLE1.Action = OLE_ACTIVATE 'Crear lista de operaciones AñadirVerbos End Sub
Figura 12.8.
El procedimiento cmdInsertar_Click de la aplicación OLEGRAPH
Después de que se han cargado los nombres de los verbos en el cuadro combinado (además de una entrada especial para que la seleccione el usuario cuando no desee realizar ninguna acción), necesitarás definir la rutina Click del cuadro combinado como viene a continuación para llamar a cualquier acción seleccionada por el usuario. Sub cboVerbos_Click ( ) If cboVerbos.ListIndex > 0 Then OLE1.Verb = cboVerbos.ListIndex OLE1.Action = OLE_ACTIVATE End If End Sub 341
12 Enlace e incrustación de objetos
EL LIBRO DEL VISUAL BASIC
Necesitas crear una rutina más que guarde los datos que el usuario cargue en el objeto OLE. Cuando se crea un objeto durante la fase de diseño, todos los datos OLE se almacenan en el formulario de Visual Basic. Sin embargo, cuando el objeto se crea en la fase de ejecución, los datos se deben guardar en un archivo binario. Al igual que el texto introducido en un cuadro de texto se perdería si no lo almacenases en algún sitio, lo mismo ocurriría con los datos OLE. El control OLE contiene los datos para los dos estilos del control: enlazado o incrustado. Aunque es obvio que el estilo incrustado debe contener los datos, el estilo enlazado tam bién los contiene, aunque esto es menos evidente. El estilo enlazado debe almacenar el nombre del documento enlazado y el tipo de la información. Para guardar los datos almacenados en el control OLE debes crear una variable de nivel de módulo y escribir dos pequeños subprogramas, como viene a continuación: Dim HayQueEscribirlo As Integer Sub OLE1_Updated (Code As Integer) HayQueEscribirlo = True End Sub
OLE1.FileNumber = NumeroDeArchivo OLE1.Action = OLE_READ_FROM_FILE Close #NumeroDeArchivo End Sub
Después de que se han cargado o guardado los datos OLE, se sitúa el archivo inmediatamente detrás de los datos. Sería posible, por tanto, cargar y guardar varios objetos OLE en una fila en tanto se mantenga el mismo orden al guardarlos y cargarlos. La figura 12.9 muestra la aplicación funcionando.
Control directo del objeto En el capítulo 11 pudiste obtener información sobre una base de datos y controlar el acceso a la base de datos mediante unos objetos especiales, como TableDef y Database. La última versión de OLE admite la posibilidad de que cualquier aplicación defina objetos y protocolos que se puedan manipular desde fuera de la aplicación. Por ejemplo, un procesador de textos podría proporcionar el acceso a su corrector ortográfico como objeto, y tú podrías, desde Visual Basic, comprobar la orto
Sub Form_Unload (Cancel As Integer) Dim NumeroDeArchivo As Integer If Not HayQueEscribirlo Then Exit Sub NumeroDeArchivo = FreeFile Open "OLEGRAPH.DAT" For Binary As #NumeroDeArchivo OLE1.FileNumber = NumeroDeArchivo OLE1.Action = OLE_SAVE_T0_FILE Close #NumeroDeArchivo End Sub
Esto nos lleva a otro punto antes de terminar. Si guardas los datos OLE al salir, necesitarás cargarlos de nuevo cuando arranques la aplicación. Aquí tienes la rutina final para cargar los datos OLE. Debe comprobar si el archivo existe antes de tratar de cargar los datos; si el archivo no existe se producirá un error. Sub Form_Load ( ) Dim NumeroDeArchivo As Integer If Dir$("OLEGRAPH.DAT") = "" Then Exit Sub NumeroDeArchivo = FreeFile Open "OLEGRAPH.DAT" For Binary As #NumeroDeArchivo
342
Figura 12.9.
La aplicación OLEGRAPH
343
12 Enlace e incrustación de objetos
EL LIBRO DEL VISUAL BASIC
grafía del texto que el usuario haya introducido en un cuadro de texto. El usuario nunca vería la aplicación procesador de textos porque el acceso a los objetos se hace completamente desde el programa. Esta posibilidad, denominada Automa tización OLE es aceptada por Visual Basic. Sin embargo, en el momento de escri bir esto, esta posibilidad es tan nueva que muy pocas aplicaciones admiten la Automatización OLE. Cada objeto es diferente
La programación de la Automatización OLE es muy similar a la comunicación con los objetos del control Data. Todas las aplicaciones que admitan Automatización OLE expondrán algunas de sus capacidades en la forma de objetos. Para obtener el acceso a los objetos en Visual Basic, se llama a La función CreateObject , pasándole el nombre del tipo de objeto como parámetro de cadena. La documentación de cada una de las aplicaciones que admita Automatización OLE, contendrá una lista de los objetos que se pueden crear.
ilustrará los principios básicos. El primer paso consiste en consultar en la docu mentación los objetos admitidos por DLSPCALC. Nos dice, entre otras cosas, que DISPCALC se debe registrar en el sistema antes de usarlo y que la mites. Cada dimite un objeto denominado dispcalc.ccalc. Este objeto tiene las siguientes propiedades y métodos: Propiedad o método
Explicación
Accum Opnd Op
El acumulador de la calculadora El operando de la calculadora Un código que indica la operación que va a efectuar la calculadora Un método que ejecuta la operación seleccionada por Op Un método que muestra el resultado del cálculo en la pantalla de la calculadora
Eval Display
Una vez creado un objeto, la comunicación con él se realiza a través de los métodos apropiados para dicho objeto. Como cada aplicación incluye características distintas, no hay un conjunto común de métodos, ni una sintaxis estrictamente definida que pueda proporcionarte en este momento. Siento que esto suene algo nebuloso, y de hecho lo es, pero no hay mucho más que te pueda decir en general sobre la Automatización OLE. Es tan abierta porque, esencialmente, no tiene límites. Cada diseñador de aplicaciones puede crear objetos nuevos, desde celdas de hojas de cálculo a correctores ortográficos; desde gráficos hasta diseños CAD. Tú eliges los que mejoran tu programa y haces uso de ellos.
Para registrar la aplicación, abre el Administrador de archivos en el directorio de Visual Basic. Haz doble clic en el archivo DISPCALC.REG. Esto añadirá una entrada en el registro OLE de Windows para la aplicación DISPCALC. La mayoría de las aplicaciones se registran a sí mismas en Windows como parte de su proceso de instalación. Sin embargo, como DISPCALC es sólo una demostración requiere un registro manual.
Un ejemplo d e Automatización OLE: la aplicación Calculadora
Abre una ventana de código e introduce el texto siguiente en la sección de declaraciones generales:
Para ilustrar las posibilidades básicas de la Automatización OLE, el equipo de programación de Visual Basic ha incluido una aplicación especial que la admite. Como no puedo proporcionarte información general sobre la Automatización OLE, haremos uso de esta aplicación especial de demostración en este apartado. La demostración se llama DISPCALC, y cuando se ejecuta por sí misma funciona como una simple calculadora de mano. DLSPCALC también se puede controlar desde un programa a través de la Automatización OLE. Exporta varios objetos y acciones que se pueden manipular desde Visual Basic. La calculadora efectúa las operaciones especificadas por Visual Basic. El programa que escribirás utilizará DISPCALC para multiplicar 19 por 57. Hay que admitirlo: esto es algo que se puede hacer sin el recurso de OLE, pero que 344
Crea un proyecto nuevo y añade un solo botón de comando al formulario. Para una aplicación tan simple, es lo único que tienes que hacer. Observa que no necesitas un control OLE para usar la Automatización OLE. El control OLE es sólo para enlazar e incrustar objetos.
Const Const Const Const
OP_MAS = 1 OP_MENOS = 2 OP_MULT = 3 OP_DIVIDIR= 4
Dim Calc As Object
Las constantes son los códigos específicos de la aplicación que se pueden asignar a la propiedad Op. La variable Calc contendrá el objeto una vez que haya sido creado. Ahora, introduce la siguiente rutina como procedimiento Click para el botón de comando: 345
EL LIBRO DEL VISUAL BASIC
Sub Command1_Click ( ) Set Calc = CreateObject("dispcalc.ccalc") Calc.Accum = 19 Calc.Opnd = 57 Calc.Op = OP_MULT Calc.Eval MsgBox "Los cálculos indican que 19 * 57 son " + Str$(Calc.Accum) Calc.Quit End Sub
1 2 Enlace e incrustación de objetos
Calc.Op = OP_MULT Calc.Eva1 Calc.Display 'Actualizar la salida MsgBox "Los cálculos indican que 19 * 57 son" + Str$(Calc.Accum) Calc.Quit End Sub
Ahora, cuando ejecutes el programa, la salida de la calculadora coincidirá con el resultado que devolvió el acumulador, como se muestra en la figura 12.10.
Observa que en la línea en la que se crea el objeto se usa la instrucción Set para asignar el objeto a la variable Calc. El tipo de asignación Set se debe utilizar con todos los objetos, incluyendo los objetos de Visual Basic como formularios y controles. Las asignaciones normales funcionan copiando; es decir, si tienes una variable A a la cual le asignas la cadena "Beethoven" y luego ejecutas la declaración B = A, ambas variables A y B tendrán copias separadas de la cadena, y si modificas una, la otra se queda sin cambios. Las asignaciones del tipo Set crean meramente una referencia a la cosa que se está asignando, de manera que si ejecutas Set A = Mi Form, A se refiere sólo al objeto Mi Form, y si a continuación ejecutas B = A, la variable B también apuntará al mismo formulario y cualquier cambio hecho en el formulario será visible por todas las variables. Figura 12.10.
En el programa anterior, por tanto, la primera línea le dice a Windows que busque la aplicación que pueda crear un objeto dispcalc.ccalc y que cree el objeto. Entonces se almacena una referencia a ese objeto en la variable Calc de Visual Basic. El programa establece las propiedades Accum, Opnd y Op, llama al método Eval y muestra el valor resultante de la propiedad Accum. El método Quit destruye el objeto. Pulsa F5 para ejecutar tu programa. Cuando hagas clic en el botón de comando, se llamará a la aplicación DISPCALC. Observa que aparece realmente en la pantalla. Esto no es típico de las aplicaciones con Automatización OLE, pero se ha hecho aquí para ilustrar los efectos de la programación OLE. Si miras atentamente a la pantalla de la calculadora, verás que pone 0 antes de cerrar el cuadro de mensajes, aunque el acumulador devuelva el valor correcto. Esto se debe a que la salida de la calculadora es controlada por el método Display, que no ha sido llamado. Sal del programa y modifica el procedimiento Click para que quede así: Sub Command1_Click ( ) Set Calc = CreateObject("dispcalc.ccalc") Calc.Accum =19 Calc.Opnd =57
346
Control de la aplicación DISPCALC con Automatización OLE
Una nota sob re el DDE Si te gusta la idea de hacer que otros programas trabajen para ti y no le temes a una programación algo más complicada, es posible que quieras investigar el in tercambio dinámico de datos (DDE). El DDE permite enviar y recibir mensajes de otras aplicaciones. Por ejemplo, la mayoría de los programas de instalación usan el DDE para decirle al Administrador de programas Windows que cree nuevos grupos de programas e iconos. Microsoft Word y Microsoft Excel pueden crear enlaces DDE con tus programas de Visual Basic, y tú puedes pasar información a través del enlace. La programación de DDE no es simple —normalmente, se deben programar los dos lados de la conversación. Por ejemplo, necesitarás una macro en WordBasic para abrir un vínculo con tu aplicación y para solicitar datos, y también tendrás que programar tu aplicación en Visual Basic para recibir la solicitud y enviar la información pedida. Consulta los manuales de referencia de tus aplicaciones para ver las posibilidades de DDE que admiten. 347
13 Una aplicación para Windows completa Has subido montañas y atravesado mares tormentosos —o, al menos, has aprendido lo suficiente sobre Visual Basic para solucionar algunos de tus problemas de programación. Pero antes de que te puedas relajar y dormirte en los laureles, de berías intentar juntar todo lo que has visto. Este capítulo te ayudará a construir una aplicación que incluya muchas de las posibilidades y capacidades que se han tratado en los capítulos anteriores: varios formularios, controles, archivos, menús e incluso algunos gráficos. También necesitarás los procedimientos ObtenerIni y EstablecerIni que se desarrollaron en el capítulo 9.
Diseño general Para describirla con sencillez, esta aplicación, a la que llamaremos Cronómetro de Proyectos, es un programa que calcula el tiempo dedicado a cada proyecto. Así es como funciona: mientras que estás trabajando con el ordenador le dices al programa con qué proyecto estás trabajando. Cuando cambias a otro proyecto, te vas a comer o terminas el trabajo del día, haces que el programa lo sepa. Al final de la semana (o del mes), el programa puede mostrar un cálculo del empleo que le has dado a tu tiempo. Puedes, también, configurar Windows para que cargue automáticamente el programa cuando lo arranques. Todos los datos de los tiempos de tus proyectos se almacenarán en un archivo y se podrán actualizar acumulativamente. Las estadísticas obtenidas de los datos podrán ser mostradas en la pantalla o imprimirse en papel. El nombre del archivo 349
1 3 Una a plica ción pa ra Windows co mpleta EL LIBRO DEL VISUAL BASIC
del proyecto se almacenará en una variable de iniciación en tu archivo WIN.INI; así, no tendrás que especificar el archivo de proyecto cada vez que ejecutes la aplicación. La figura 13.1 muestra el plan general de acción para el proceso inicial. Después de la inicialización, el programa es controlado por las acciones del usuario: seleccionar una opción de un menú, hacer clic en un botón, salir del programa. En la figura 13.2 se han definido un conjunto de acciones para cada uno de esos posi bles eventos. Te darás cuenta de que trazar diagramas como estos antes de diseñar un programa es extremadamente útil, incluso cuando los recuadros de las tareas son de un nivel muy alto (es decir, no detallados), como los que se usan en las figuras 13.1 y 13.2. Poner un plan sobre el papel ayuda a cristalizar las ideas vagas en pasos concretos. También es más fácil identificar zonas que se han pasado por alto o que están incompletas, y a menudo se pueden encontrar procesos comunes que pueden compartir código. Si el diseño es de un nivel lo suficientemente alto, pue
Figura 13.2.
Un plan de la parte más utilizada de la aplicación Cronómetro de Proyectos
des implementar cada recuadro como procedimientos que no hagan nada, e implementar los detalles una vez que la estructura del programa principal se haya definido, como estás haciendo en este capítulo.
Diseño del menú Figuro 13.1.
Un plan para el proceso inicial del la aplicación Cronómetro de Proyectos 350
Comencemos la implementación programando el sistema de menús. Necesitarás dos menús, a los cuales llamaremos Archivo y Proyecto, para darle al usuario el 351
13 Una aplicación para Windows completa
EL LIBRO DEL VISUAL BASIC
control básico sobre la aplicación. En el menú Archivo, el comando Nuevo permitirá al usuario crear un archivo de proyecto nuevo, y el comando Abrir permitirá que el usuario abra un archivo ya existente para volver a usarlo. El comando Imprimir del menú Archivo escribirá las estadísticas actuales en la impresora, y el comando Salir terminará el programa. El menú Proyecto, por su parte, permitirá al
usuario trabajar con el archivo de proyectos abierto actualmente, con el objetivo de añadir o eliminar proyectos, para poner a cero las estadísticas y para mostrar éstas. La figura 13.3 esquematiza el proceso que llevarán a cabo algunos de estos comandos. Trabajar en la estructura general del programa antes de empezar a escribir el código te permitirá, a menudo, ahorrar tiempo, ya que te darás cuenta de qué procedimientos se utilizan en más de una ocasión a lo largo del programa. Por ejemplo, observa que aparece un recuadro etiquetado como Reinicializar contro les en la figura 13.3 y que también aparece otro recuadro similar denominado Ini cializar controles en el diagrama de la figura 13.1. Como sabes que se va a dar un proceso similar en ambos casos, puedes escribir un solo procedimiento en lugar de dos separados. Comienza un proyecto nuevo en Visual Basic y abre la ventana de diseño de menús. La figura 13.4 muestra el diseño de la jerarquía del menú después de que se han introducido los títulos. Ten en cuenta los guiones que se han introducido en la lista para crear barras separadoras en el menú Archivo. Escribe el nombre de cada menú en el cuadro Name de la ventana Menu Design, de la forma que se indica en la figura 13.5.
Figura 13.3.
Un plan para las opciones del menú de la aplicación Cronómetro de Proyectos
352
Figura 13.4.
El diseño de la jerarquía del menú de la aplicación Cronómetro de Proyectos
353
1 3 Una a plicac ión para Windows completa
C aption
N ame
&Archivo
mnuArchivo
&Nuevo
mnuAchNuevo
&Abrir
mnuAchAbrir
-
mnuAchNULL1
&Imprimir
mnuAchImprimir
&Salir
mnuAchNULL2 mnuAchSalir
&Proyecto
mnuProyecto
&Añadir
mnuProAñadir
&Eliminar
mnuProEliminar
&Poner a cero
mnuProPonerACero
&Mostrar todo
mnuProMostrarTodo
Figura 13.5. Los nombres de los elementos del menú de la aplicación Cronómetro de Proyectos
Diseño del formulario El formulario principal de la aplicación es relativamente simple. Como se muestra en la figura 13.6, contiene 10 etiquetas, un cuadro combinado, un control cuadro de dibujo, un reloj (un control del tipo Timer), un diálogo estándar y un botón de
Figura 13.6. El diseño inicial del formulario principal de la aplicación Cronómetro de Proyectos
354
comando. Cuando hayas terminado de añadir estos controles al formulario (utili zando la figura 13.6 como modelo), establece las propiedades del formulario y de los controles como se muestra en la figura 13.7.
Objeto
Propiedad
Ajuste
Form1
BorderStyle Caption Name
3 - Fixed Double Cronómetro de Proyectos RelojPrincipal
Label1
Caption Name
[ninguna] lblFechaHora
Label2
Alignment Caption
1 - Right Justify Proyecto:
Combo1
Name Style
cboListaProyectos 2 - Dropdown List
Label3
Alignment Caption
1 - Right Justify Inicio:
Label4
BorderStyle Caption Name
1 - Fixed Single [ninguna] lblInicio
Label5
Alignment Caption
1 - Right Justify Fin:
Label6
BorderStyle Caption Name
1 - Fixed Single [ninguna] lblFin
Label7
Alignment Caption
1 - Right Justify Transcurrido:
Label8
BorderStyle Caption Name
1 - Fixed Single [ninguna] lblTranscurrido
Label9
Alignment Caption
1 - Right Justify Total del proyecto:
Label10
BorderStyle Caption Name
1 - Fixed Single [ninguna] lblTiempoTotal
Figura 13.7. El ajuste de las propiedades de la aplicación Cronómetro de Proyectos
(continúa)
355
El l i b r o del visual basic
13 Una a plicación p ara Windows completa Figura 13.7. continuación Objeto
Picture1
Declaraciones globales Propiedad
Ajuste
FillStyle Name ScaleHeight ScaleLeft ScaleMode ScaleTop ScaleWidth
0 - Solid picEstado -2 -1 0 - User 1 2
Caption Name
Inicio btnControl
Timer1
Name
tmrTic
CMDialogl
Name
Dlogo
Command1
Después de que hayas establecido las propiedades, tu formulario debe parecerse al que se muestra en la figura 13.8. El usuario podrá seleccionar un proyecto de la lista desplegable del cuadro com binado Proyectos. Los cálculos de la hora de inicio, de finalización y el tiempo transcurrido serán similares a los que usamos en la aplicación Cronómetro del capítulo 1. Un solo botón de comando iniciará y detendrá la cuenta del tiempo, y el título del botón cambiará según corresponda. Finalmente, el control timer y el cuadro de dibujo ayudarán a mejorar un poco el aspecto de la aplicación.
Selecciona el comando New Module del menú File de Visual Basic y añade el có digo que se muestra en la figura 13 9. Este módulo de código contiene las decla raciones globales y las rutinas compartidas por los distintos formularios que compondrán la aplicación.
Global Const PI = 3.1415926 Global Const WIN_ICONIZED = 1 'Parámetros de MsgBox Global Const MB_OK = 0 ’Sólo el botón Aceptar Global Const MB_OKCANCEL = 1 'Los botones Aceptar y Cancelar Global Const MB_ABORTRETRYIGNORE = 2 'Los botones Abortar, 'Reintentar e Ignorar G l o b a l C o n s t M B _ Y E S N O C A N C E L = 3 ' L o s b o t o n e s S i , N o y C a nc e l a r Global Const MB_YESNO = 4 'Los botones Si y No Global Const MB_RETRYCANCEL =5 'Los botones Reintentar y Cancelar Global Const MB_ICONSTOP = 16 'Mensaje critico 'Banderas del cuadro de diálogo Abrir/Guardar Global Const OFN_0VERWRITEPROMPT = &H2& Global Const OFN_PATHMUSTEXIST = &H800& 'Valores devueltos por MsgBox Global Const ID_OK = 1 Global Const ID_CANCEL = 2 Global Const ID_ABORT = 3 Global Const ID_RETRY = 4 Global Const ID_IGNORE = 5 Global Const ID_YES = 6 Global Const ID_NO = 7
'Se ha pulsado 'Se ha pulsado 'Se ha pulsado 'Se ha pulsado 'Se ha pulsado 'Se ha pulsado 'Se ha pulsado
el el el el el el el
botón botón botón botón botón botón botón
Aceptar Cancelar Abortar Reintentar Ignorar Si No
'Tipos específicos de la aplicación Type RegProy Nombre As String * 30 TiempoTotal As Double End Type Figura 13.8. El diseño completo del formulario principal de la aplicación Cronómetro de Proyectos
Figura 13.9. Las declaraciones globales de la aplicación Cronómetro de Proyectos
(continúa)
356 357
EL libro del visual basic
Figura 13.9. continuación
G l o b a l C o n s t TAMAÑO_REG_PROY = 38 'Variables globales de la aplicación Global ListaProyectos( ) As RegProy
'Matriz con la información 'de los proyectos Global NumProyectos As Integer 'Número de proyectos G l o b a l Nombre Archi v o P r o y e c t o A s S t r i n g ' A r c h i v o d e d a t o s d e 'proyectos Global CRLF As String 'Constante multicarácter
13 Una ap lica ción pa ra Windows co mpleta
grande como para contener una pregunta simple (en una etiqueta) y una respuesta simple (en un cuadro de texto). Crea este formulario seleccionando el comando New Form del menú File de Visual Basic o haciendo clic en el botón New Form de la barra de herramientas. Dibuja la etiqueta, el cuadro de diagramas comunes de comando, y establece las propiedades del formulario y de los objetos como se indica en la figura 13.10. La figura 13.11 muestra el formulario terminado.
Objeto
proyecto. Finalmente, el código declara las variables que usará el programa. ListaProyectos es una matriz dinámica que contendrá los registros de proyecto. NumProyectos contendrá el número de proyectos que la aplicación está controlando en la actua lidad. CRLF se usará como una constante de cadena para almacenar los caracteres de retorno de carro y avance de línea. Reloj Funcionando contendrá un valor booleano que indicará si el programa está actualmente contando tiempo para un proyecto. HoraInicio y HoraFin contendrán los valores actuales del control timer, y la variable SumaTiempoDeproyectos contendrá la suma acumulativa de todo el tiempo cargado a todos los proyectos.
Formularios auxiliares Esta aplicación requiere, además del formulario principal que hemos creado, otros dos formularios adicionales, ambos muy simples. EL primero, llamado Consulta, servirá como alternativa a la función InputBox de Visual Basic, que tiene tenden cia a crear unos cuadros de diálogo bastante desaliñados (impropios de personas detallistas como nosotros). El formulario Consulta debe ser lo suficientemente
Ajuste
Form2
BorderStyle Caption ControlBox Name
1 - Fixed Single Proyecto False Consulta
Label1
Caption Name
[ninguna] lblConsulta
Text1
Name Text
txtConsulta [ninguna]
Command1
Caption Default Name
Aceptar True btnAceptar
Command2
Cancel Caption Name
True Cancelar btnCancelar
Global RelojFuncionando As Integer 'Estado del timer Global HoraInicio As Double, HoraFin As Double G l o b a l SumaTi e m p o D e P r o y e c t o s A s D o u b l e
incluye un nombre y la cantidad de tiempo registrado para cada proyecto. La constante TAMAÑO_REG_PROY define el número de bytes de cada registro de
Propiedad
Figura 13.10. El ajuste de las propiedades del formulario Consulta y de sus controles
Para controlar este formulario debes escribir una función que lo muestre en pan talla y que devuelva cualquier información que el usuario escriba en él. Para que sea accesible para toda la aplicación, esta función debe estar en un módulo; ponla en el módulo que contiene las constantes globales: Function TextoDeConsulta (S As String) As String Consulta.lblConsulta.Caption = S Consulta.txtConsulta.Text = "" Consulta.Show 1 TextoDeConsulta = Consulta.txtConsulta.Text End Function
358 359
13 Una aplicación para Windows completa
EL LIBRO DEL VISUAL BASIC
ben establecerse como muestra la figura 13.12. El formulario terminado aparece en la figura 13.13.
Objeto Figura 13.11. El diseño completo del formulario Consulta
La función acepta un parámetro de cadena, que inserta en la etiqueta del formulario. Entonces, borra el cuadro de texto del formulario y muestra el formulario usando el método Show. El parámetro 1 indica que el método Show debe mostrar el formulario de manera modal —es decir, la función TextoDeConsulta se detendrá hasta que el usuario cierre el formulario Consulta. Cuando se haya cerrado el formulario Consulta, la función devolverá el texto que el usuario haya introducido en el cuadro de texto.
Form3 Text1
Propiedad
Caption Name MultiLine Name ScrollsBars Text
Ajuste
Estadísticas del cronómetro de proyectos ProyStat True txtStats 2 Vertical [ninguno]
Figura 13.12. El ajuste de las propiedades del formulario ProyStat y de su control
Aunque esta función es suficiente para mostrar el formulario y devolver un valor, el propio formulario debe gestionar los botones Aceptar y Cancelar. Haz doble clic en el botón Aceptar y añade este procedimiento: Sub btnAceptar_Click Hide End Sub
Cuando el usuario haga clic en el botón Aceptar, el método Hide cerrará el formulario Consulta, y el control será devuelto a la función TextoDeConsulta. Un procedimiento similar se necesitará para el botón Cancelar: Sub btnCancelar_Click ( ) txtConsulta.Text = "" Hide End Sub
El código del botón Cancelar realiza un paso adicional consistente en borrar el contenido del cuadro de texto. Esto asegura que la función TextoDeConsulta siempre devolverá una cadena vacía cuando se haga clic en el botón Cancelar. (Observa que esta implementación no distingue entre si el usuario no introduce texto pero hace clic en el botón Aceptar o si introduce texto y hace clic en el bo tón Cancelar.) El segundo formulario auxiliar, que hemos llamado ProyStat, proporciona un lugar donde mostrar las estadísticas de todos los proyectos. Su único control es un simple cuadro de texto. Las propiedades del formulario y del cuadro de texto de360
Figura 13.13. El diseño terminado del formulario ProyStat
El formulario ProyStat no es modal —es decir, el usuario puede volver al formulario principal sin cerrar la ventana de estadísticas— y, por tanto, no requiere una rutina especial de control. Sin embargo, puedes definir una rutina que haga más fácil que el programa ponga datos en el cuadro de texto. Este procedimiento, que se debe situar en el módulo de código, permite que el programa envíe las líneas al cuadro de texto de una en una, en lugar de tener que enviar toda la información a la vez: Sub AñadírLineaStat (L As String) ProyStat.txtStats.Text = ProyStat.txtStats.Text + L + CRLF End Sub
361
13 Una aplicación para Windows completa
EL LIBRO DEL VISUAL BASIC
El procedimiento AñadirLineaStat añade una línea al texto ya existente en el cuadro de texto y luego, añade un retorno de carro/avance de línea para pasar a la siguiente línea. Si quieres mejorar el aspecto de este formulario te puedes asegurar de que el cuadro de texto siempre tenga el mismo tamaño que el formulario, sin que haya espacio libre entre uno y el otro. Para ello, haz doble clic en el formulario para que aparezca la ventana de código e introduce el siguiente procedimiento para el evento Resize. Sub Form_Resize ( ) txtStats.Left = ScaleLeft txtStats.Top = ScaleTop txtStats.Width = ScaleWidth txtStats.Height = ScaleHeight End Sub
Siempre que se cambie el tamaño del formulario (incluyendo la primera vez que aparece en pantalla), este procedimiento establecerá el tamaño del cuadro de texto para que se adapte a las dimensiones internas del formulario.
EI procedimiento Main En un proyecto que contenga muchos formularios o en un proyecto en el que se deba producir una inicialización antes de que se muestre un formulario en pantalla, a menudo resulta útil hacer que el programa de Visual Basic comience ejecutando un procedimiento específico, en lugar de mostrar simplemente el primer formulario. Si eliges este camino deberás dar al procedimiento el nombre Main (Principal) y ponerlo en un módulo. Abre la ventana del módulo de código e introduce este procedimiento: Sub Main ( ) CRLF = Chr$(13) + Chr$(10) NombreArchivoProyecto = BuscarArchivoDeProyectos( ) IniciarProyecto End Sub
Es este caso el procedimiento Main inicializa la variable de cadena CRLF , llama a una función para buscar el archivo de datos del proyecto y luego sigue con el procedimiento IniciarProyecto (que todavía no hemos escrito). ¿Recuerdas los diagramas de flujo de las figuras 13.1 y 13.3? Mostraban que esta inicialización debía ser común tanto para los comandos Nuevo y Abrir del menú como para el código de arranque del programa; así que lo mejor será que puedas acceder al código de 362
inicialización desde los tres lugares —y por ello se llama a un procedimiento de inicialización separado. También necesitarás indicar a Visual Basic que comience la aplicación ejecutando el procedimiento Main. Selecciona el comando Proyect del menú Options y esta blece la opción Start Up Form (formulario inicial) a Sub Main.
La estructura de eventos El código de programa que se muestra en la figura 13.14 implementa las funciones básicas de cada uno de los eventos de usuario que pueden ocurrir en el formulario principal. Este código implementa los eventos como llamadas a procedimientos de alto nivel, dejando el trabajo de detalle para más tarde. Observa cómo se utilizan los procedimientos Form_Load y Form_Unload en la figura 13.14. En este programa, el procedimiento Main recibe el control inicialmente y no se carga ningún formulario de manera automática. El procedimiento Form_Load puede, por tanto, servir como procedimiento de inicialización del
Sub btnControl_Click ( ) If RelojFuncionando Then DetenerReloj Else IniciarReloj End If End Sub Sub Form_Load () Dim I As Integer 'Cargar el cuadro de lista con los nombres de los proyectos For I = 0 To NumProyectos - 1 cboListaProyectos.AddItem RTrim$(ListaProyectos(I).Nombre) c b o L i s t a P r o y e c t o s . I t e m D a t a ( c b o L i s t a P r o y e c t os . N e w I n d e x ) = I Next I cboListaProyectos.Enabled = True End Sub
Figura 13.14. Procedimientos de eventos de la aplicación Cronómetro de Proyectos
(continúa)
363
13 Una a plica ción p ara Windows completa
EL LIBRO DEL VISUAL BASIC
Figura 13.14. continuación
Figura 13.14. continuación
Sub mnuProMostrarTodo_Click ( ) MostrarEstadisticas False End Sub
Sub Form_Unload (Cancel As Integer) If RelojFuncionando Then DetenerReloj Unload Consulta Unload ProyStat EscribirArchivoDeProyectos NombreArchivoProyecto End Sub
Sub mnuProPonerACero PonerACeroTotalesProyecto End Sub
Sub mnuAchSalir_Click ( ) Unload RelojPrincipal En d End Sub
Sub cboListaProyecto_Click ( ) lblInicio.Caption = "" lblFin.Caption = "" lblTranscurrido.Caption = "" 'No olvides introducir las lineas siguientes en la misma li nea lblTiempoTotal.Caption = TimeStr(ListaProyectos(cboListaProyectos.ItemData (cboListaProyectos.ListIndex)).TiempoTotal ) End Sub
Sub mnuAchNuevo_Click ( ) Unload RelojPrincipal NombreArchivoProyecto = NuevoArchivoDeProyectos( ) IniciarProyecto End Sub Sub mnuAchAbrir_Click ( ) Unload RelojPrincipal NombreArchivoProyecto = BuscarArchivoDeProyectos( ) IniciarProyecto End Sub
cuadro de lista, y Form_Unload se utiliza para asegurarnos de que todos los datos se escriben en el disco. El trabajo que queda consiste en definir los procedimientos que implementan todos los detalles del programa. Estos procedimientos se pueden dividir en dos grupos: los que tratan fundamentalmente con el formulario principal y los que tratan con la gestión de los datos. Los procedimietos que interactúan con el formulario principal, los cuales se muestran en la figura 13.15, deben introducirse en la sección general del código del formulario.
Sub mnuAchImprimir_Click ( ) MostrarEstadisticas True End Sub Sub mnuProAñadir_Click ( ) Dim NombreNuevo As String
En la figura 13.16 encontrarás las rutinas finales necesarias para hacer que la aplicación funcione. Introdúcelas en el módulo de código del procedimiento Main.
NombreNuevo = TextoDeConsulta("Nombre del proyecto:") If NombreNuevo <> "" Then AñadirProyecto NombreNuevo End Sub
Antes de que puedas ejecutar el programa Cronómetro de Proyectos debes incluir las rutinas ObtenerIni y EstablecerIni que escribiste en el capítulo 9. Selecciona el comando Add File del menú Archivo de Visual Basic y carga el módulo de codigo en el que guardaste estos procedimientos.
S u b m n u P r o E l i m i n a r _C l i c k ( ) If cboLi s t a P r o y e c t o s . T e x t < > " " T h e n E l i m i n a r P r o y e c t o End Sub (continúa)
364
Como puedes ver en el código de la figura 13.16, la función BuscarArcbivoDeProyectos usa la función ObtenerIni para conseguir el nombre de tu archivo de 365
LIBRO DEL VISUAL BASIC
13 Una aplicación para Windows completa
Sub AñadirProyecto (NombreDelProyecto As String) 'Añadir un nombre al cuadro de lista cboListaProyectos.AddItem NombreDelProyecto c b o L i s t a P r o y e c t o s . I t e m D a t a ( c b o L i s t a P r o y e c t o s . N e wI n d e x ) = NumProyectos 'Añadir el registro a los totales del proyecto ListaProyectos(NumProyectos).Nombre = NombreDelProyecto NumProyectos = NumProyectos + 1 'Seleccionar un proyecto nuevo cboListaProyectos.ListIndex = cboListaProyectos.NewIndex End Sub
Figura 13.15. continuación
Sub DetenerReloj ( ) Dim TiempoTranscurrido As Double
Sub EliminarProyecto ( ) Dim Respuesta As Integer Respuesta = MsgBox("¿Eliminar el proyecto " + c b o L i s t a P r o y e c t o s . T e x t + " ? " , M B _ Y E S N 0 , " Pr o y e c t o " ) If Respuesta = ID_YES Then cboListaProyectos.RemoveItem cboListaProyectos.ListIndex End If End Sub Sub IniciarReloj ( ) If cboListaProyectos.Text = "" Then MsgBox "No se ha seleccionado ningún proyecto", MB_ICONSTOP Exit Sub End if HoraInicio = Now RelojFuncionando = True 'Actualizar la información mostrada Caption = "Reloj del proyecto (funcionando)" btnControl.Caption = "Stop" lblInicio.Caption = TimeStr(HoraInicio) lblFin.Caption = " - funcionando - " lblTranscurrido.Caption = "" 'Desactivar objetos del formulario cboListaProyectos.Enabled = False mnuArchivo.Enabled = False mnuProyecto.Enabled = False End Sub
Figura 13.15.
HoraFin = Now RelojFuncionando = False 'Actualizar la información mostrada Caption = "Reloj del proyecto" btnControl.Caption = "Inicio" lblFin.Caption = TimeStr(HoraFin) TiempoTranscurrido = HoraFin - HoraInicio lblTranscurrido.Caption = TimeStr(TiempoTranscurrido) 'Actualizar estructuras de datos L i s t a P r o y e c t o s ( c b o L i s t a P r o y e c t o s . L i s t I n d e x ) . T i e mp o T o t a l = L i s t a P r o y e c t o s ( c b o L i s t a P r o y e c t o s . L i s t I n d e x ) . Ti e m p o T o t a l + TiempoTranscurrido lblTiempoTotal.Caption = T i m e S t r ( L i s t a P r o y e c t o s ( c b o L i s t a P r o y e c t o s . L i s t I n d e x ) . Ti e m p o T o t a l ) SumaTiempoDeProyectos = SumaTiempoDeProyectos + TiempoTranscurrido 'Activar objetos del formulario cboListaProyectos.Enabled = True mnuArchivo.Enabled = True mnuProyecto.Enabled = True End Sub
Sub PonerACeroTotalesProyecto ( ) Dim Respuesta As Integer, I As Integer Respuesta = MsgBox("¿Poner a cero los totales de los proyectos?", MB_OKCANCEL, "Proyecto") If Respuesta = ID_OK Then For I = 0 To NumProyectos - 1 ListaProyecto(I).TiempoTotal = 0 Next I SumaTiempoDeProyectos = 0 cboListaProyectos_Click End If End Sub
(continúa)
Los procedimientos generales del formulario principal de Cronómetro de Proyectos
366 367
EL LIBRO DEL VISUAL BASIC
13 Una aplicación para Windows completa
Figura 13.16. continuación
Function BuscarArchivoDeProyectos ( ) As String Dim F As String, Respuesta As Integer F = ObtenerIni("Cronometro de Proyectos", "Proyectos") If F = "" Then Respuesta = MsgBox("No se ha especificado ningún archivo de proyecto. ¿Crear uno?", MB_OKCANCEL, "Proyectos") 'No se puede continuar sin un archivo de proyecto If Respuesta <> ID_OK Then End F = NuevoArchivoDeProyectos( ) Else If Dir$(F) = " " Then Respuesta = MsgBox("No se puede encontrar " + F, MB_OK, "Proyectos") F = NuevoArchivoDeProyectos( ) End If End If BuscarArchivoDeProyectos = F End Function
Function NuevoArchivoDeProyectos ( ) As String Dim F As String RelojPrincipal.Dlogo.DialogTitle = "Nuevo archivo de proyecto" R e l o j P r incipal.Dlogo.CancelError = True RelojPrincipal.Dlogo.DefaultExt = "DAT" 'Añadir .DAT por omisión RelojPrincipal.Dlogo.FileName = "PROY.DAT" 'Empezar con este nombre RelojPrincipal.Dlogo.Filter = " A r c h i v o s d e d a t o s ( * . D A T ) | * . D A T | T o d os l o s a r c h i v o s ( * . ) | * . * " RelojPrincipal.Dlogo.FilterIndex = 1
368
AtraparError: MsgBox "No se ha seleccionado ningún archivo. Fin el programa." En d End Function Sub LeerArchivoDeProyecto (NombreArchivo As String) Dim Ix As Integer
Sub IniciarProyecto ( ) LeerArchivoDeProyecto NombreArchivoProyecto Reloj Funcionando = False Load RelojPrincipal RelojPrincipal.Show End Sub
Figura 13.16. Los procedimientos generales para la gestión de datos de Cronómetro de Proyectos
'Empezar con el filtro .DAT RelojPrincipal.Dlogo.FIags = OFN_OVERWRITEPROMPT Or OFN_PATHMUSTEXIST On Error Goto AtraparError 'Gestión de Cancelar RelojPrincipal.Dlogo.Action = 2 'Mostrar el cuadro de diálogo On Error Goto 0 'Restaurar el gestor de errores por omisión F = RelojPrincipal.Dlogo.FileName EstablecerIni "Cronometro de Proyectos", "Proyectos", F NuevoArchivoDeProyectos = F Exit Function
Open NombreArchivo For Random As #1 Len = TAMAÑO_REG_PR0Y NumProyectos = LOF(1) / TAMAÑO_REG_PROY ReDim ListaProyectos(NumProyectos + 100) 'Hacer sitio 'para expandirse For Ix = 0 To NumProyectos - 1 Get #1, , ListaProyectos(Ix) SumaTiempoDeProyectos = SumaTiempoDeProyectos + ListaProyectos(Ix).TiempoTotal Next Ix Close #1 End Sub Sub MostrarEstadisticas (EnPapel As Integer) Dim I As Integer, J As Integer, LineaDeSalida As String Load ProyStat ProyStat.txtStats.Text = " "
(continúa) (continúa)
369
EL LIBRO DEL VISUAL BASIC
Figura 13.16. continuación
For I = 0 To RelojPrincipal.cboListaProyectos.ListCount - 1 J = RelojPrincipal.cboListaProyectos.ItemData(I) LineaDeSalida = ListaProyectos(J).Nombre + " " + TimeStr(ListaProyectos(J).TiempoTotal) If EnPapel Then Printer.Print LineaDeSalida Else AñadirLineaStat LineaDeSalida End If Next I LineaDeSalida = "Tiempo total controlado: " + TimeStr(SumaTiempoDeProyectos) If EnPapel Then Printer.Print LineaDeSalida Printer.EndDoc Else Añadir LineaStat LineaDeSalida ProyStat.Show End If End Sub Function TimeStr(ByVal T As Double) As String TimeStr = Format$(T, "hh:mm:ss") End Function Sub EscribirArchivoDeProyectos (NombreDeArchivo As String) Dim I As Integer, J As Integer 'Borrar el archivo antiguo y escribir los datos nuevos para 'evitarnos tener que trabajar con registros en blanco de 'proyectos eliminados Kill NombreDeArchivo Open NombreDeArchivo For Random As #1 Len = TAMAÑO_REG_PROY For I = 0 To RelojPrincipal.cboListaProyectos.ListCount - 1 J = RelojPrincipal.cboListaProyectos.ItemData(I) Put #1, , ListaProyectos(J) Next I Close #1 End Sub
370
13 Una aplicación para Windows completa
proyectos de WIN.INI. Si ObtenerIni no puede encontrar la información, Buscar ArchivoDeProyectos llamará a la función NuevoArchivoDeProyectos, la cual pedirá un nombre para un nuevo archivo de proyectos y luego llamará a EstablecerIni para guardar la respuesta. El procedimiento IniciarProyecto es llamado cuando el programa empieza a funcionar y luego vuelve a ser llamado cada vez que se seleccionan los comandos Nuevo o Abrir del menú Archivo de la aplicación. Llama al procedimiento LeerArchivoDeProyectos, el cual abre el archivo de proyectos y lee la información de todos los proyectos guardados. El procedimiento AñadirProyecto (que aparece en la figura 13.15) inserta el nom bre de un nuevo proyecto en el cuadro combinado e inicializa el tiempo y el nombre del proyecto en la matriz ListaDeProyectos. Usar la propiedad ItemData del cuadro combinado permite al programa enlazar el nombre de un proyecto con la información correspondiente en la matriz ListaDeProyectos. Cuando se termina con un proyecto determinado, el procedimiento EliminarPro yecto (que aparece en la figura 13.15) borra el nombre y el tiempo del proyecto del cuadro combinado. Este procedimiento no se molesta en modificar el contenido de la matriz ListaDeProyectos porque el procedimiento EscribirArchivoDePro yectos ignorará todos los proyectos eliminados cuando guarde en el disco la información sobre los proyectos. Puedes ver el contenido del archivo de proyectos actual en una ventana seleccionando el comando "Mostrar todos" del menú Proyecto de la aplicación, o puedes imprimir la misma información seleccionando Imprimir del menú Archivo. Como los procesos son muy similares, el procedimiento MostrarEstadisticas se ocupa de ambas tareas. Si el parámetro EnPapel es True, MostrarEstadisticas enviará la información al objeto Printer; en caso contrario, el procedimiento enviará la información a la pantalla. Finalmente, el procedimiento EscribirArchivoDeProyectos guarda todos los datos de los proyectos en un archivo vacío, lo que nos evita el problema de tener que trabajar con los registros en blanco que resulten de eliminar proyectos de la lista. EscribirArchivoDeProyectos es llamado por el procedimiento de evento Form_Unload del formulario RelojPrincipal, lo cual te asegura que toda la información se guarde cuando salgas del programa. Además, el procedimiento de los comandos Nuevo y Abrir del menú Archivo descargan el formulario explícitamente, guardando de esta manera el archivo de proyectos actual antes de abrir un archivo nuevo. 371
13 Una aplicación para Windows completa EL LIBRO DEL VISUAL BASIC
La aplicación está ahora lista para funcionar. Sin embargo, antes de ejecutar el programa demos un paso más.
Un pequeño "flash" Finalmente, puedes añadir un par de pequeñas rutinas que son técnicamente innecesarias, pero que le dan al programa un poco de viveza. Mediante estas rutinas el usuario verá una imagen cambiando continuamente cuando el reloj esté funcionando, lo que proporciona una confirmación visual de que el programa se está ejecutando. La imagen será un segmento de un círculo que gira de manera muy similar a la aguja de un cronómetro. Puedes utilizar el objeto timer de Visual Basic y hacer que el gráfico recorra el círculo con cada tic. El gráfico es una "porción de tarta" de un octavo del área del círculo. La variable QuePorcion variará de 0 a 7 (en orden inverso) para determinar qué porción debe pintar a continuación. Como debe retener el dato entre llamadas, QuePorcion debe declararse con la palabra clave Static, como se muestra en la figura 13.17. En este código se llama al método Circle para crear la porción, con parámetros que son siempre nπ/4 y (n+1) π/4 para que la forma de la porción sea siempre la
Figura 13.17. continuación
Sub Form_Resize ( ) 'Asegurar que el titulo es el correcto lblFechaHora.Caption = Format$(Now, ”dd MMMM yyyy") 'Desactivar el timer cuando el proyecto esté iconizado; no es 'necesario gastar tiempo dibujando gráficos que no se pueden ver I f R e l o j P r i n c i p a l . W i n d o w S t a t e = W I N _ _I C O N I Z E D T h e n tmrTic.Interval = 0 Else tmrTic.Interval = 60 End If End Sub
misma. Debido a la manera en que Visual Basic dibuja los radios de la porción, se debe desplazar la porción un valor muy pequeño (como 0,001). Para crear los radios de una porción de tarta se debe llamar al método Circle usando números negativos. Cuando n es 0, nπ/4 también es 0; esto es, un valor no negativo. Añadiendo el pequeño desplazamiento nos aseguramos de que los valores de comienzo y de final siempre serán negativos. La figura 13.18 muestra en acción la aplicación Cronómetro de proyectos una vez finalizada.
Sub tmrTic_Timer ( ) If ReIojFuncionando Then SiguientePorcion End Sub Sub SiguientePorcion ( ) Static QuePorcion As Single picEstado.Fill Col or = picEstado.BackColor picEstado.Circle (0, 0), 1 picEstado.Fill Color = picEstado.ForeColor picEstado.Circle (0, 0), 1, , PI * -(QuePorcion + .0001) / 4, PI * -(((QuePorcion + 1) Mod 8) + .0001) / 4 QuePorcion = QuePorcion - 1 If QuePorcion < 0 Then QuePorcion = 7 End Sub
Figura 13.17.
Los procedimientos "extra"para la aplicación Cronómetro de Proyectos
372
(continúa)
Figura 13.18. ejecución de la aplicación Cronómetro de proyectos terminada
373
EI LIBRO DEL VISUAL BASIC
Una mirada hacia delante Ya sabes todo lo que hay que saber sobre Visual Basic, ¿verdad? Pues me temo que no todo. Aunque ahora puedes tener confianza en tu capacidad para escribir aplicaciones con Visual Basic, este sistema de programación tiene muchas otras características avanzadas que no se han tratado en este libro. Por ejemplo, Visual Basic permite utilizar la potencia del DDE (intercambio dinámico de datos) para llevar a cabo tareas como exportar un dato a una hoja de cálculo de Microsoft Excel, importar el gráfico de tarta resultante y mostrar el gráfico en tu aplicación. O puedes crear una aplicación MDI (interface de múltiples documentos), en la cual un formulario contiene a otros formularios, de manera similar a la del Administrador de programas o a la del Administrador de archivos de Windows. Y puedes añadirle a tus aplicaciones una Ayuda en línea para que sea más fácil de usar y de entender, como cualquier programa comercial. Solamente estás limitado por tu imaginación —bueno, por eso y por el tiempo de que dispongas.
374
Indice alfabético Caracteres especiales
A
! (carácter de declaración de tipo), 47, 57. ? (carácter comodín), 138, 142. ' (carácter de comentario), 49. (especifica la precedencia de los operadores), 66. (especifica la barra separadora en menús), 155. / (operador de división en coma flotante), 67. (operador de resta), 67. $ (carácter de declaración de tipo), 47. + (operador de concatenación), 53, 7173. + (operador de suma), 67. * (carácter comodín), 138, 142. * (operador de multiplicación), 67. `^ (operador de exponenciación), 67. < (operador menor que), 73 <= (operador menor o igual que), 74. <> (operador distinto que), 74. = (operador de asignación), 63, 346. = (operador igual que), 74. > (operador mayor que), 73. >= (operador mayor o igual que), 74. % (carácter de declaración de tipo), 47. # (carácter de declaración de tipo), 47. & (especifica tecla de acceso), 151. &H(notación hexadecimal), 300. @ (carácter de declaración de tipos de datos), 47 | (símbolo de barra vertical), 142.
Abrir, cuadros de diálogo, 142143. abrir archivos cuadros de diálogo Abrir para, 142143 de acceso aleatorio, 260261. secuenciales, 253254. Access, Microsoft, 312, 316. Action, propiedad cuadros de diálogo estándar, 141, 143, 145, 147, 148. OLE, 337. actualizar el acceso a bases de datos, 319. Actualizar, método, 320. Add Watch, botón, 226. Add Watch, comando, 226, 230. AddItem, método, 119, 122. AddNew, método, 320. Alignment, propiedad, 104. Allen, Paul, xvi. Alt, tecla, atajos de menú y, 151. ámbito declaraciones de tipos por omisión y, 5760. determinar, 5254. la ventana Debug y, 224. métodos y propiedades, 97. módulos de código y, 57. variables globales, 5657. variables locales y de nivel de módulo, 5456. And, operador lógico, 75. 375
EL LIBRO DEL VISUAL BASIC
Indice alfabético
aplicaciones arrancar, con procedimientos o con formularios, 248. Ayuda (Windows), 148149. Barra de desplazamiento, 127129. Base de datos tipo agenda, 321322. BIBLIO, base de datos, 312322. Calculadora (DISPCALC), 344347. Calcular, 172176, 178, 205. codificar (Ver codificar) Comadrejas, base de datos, 261279, 312.
compartir objetos entre ( Ver enlace e incrustación de objetos OLE)) Configurador, 255257. contenedor (container ), 333 Conversión de temperaturas, 195198. Correo electrónico, 214219. Cronómetro, (Ver Cronómetro, aplicación) Cronómetro de Proyectos (Ver Cronómetro de Proyectos, aplicación) depurar (Ver depurar) Dibujar líneas, 212213. diseñar (Ver diseñar) EditNota, 109110. ejecutar, 1415, 22. Escapar, 208209. Examinar base de datos, 326330. fuente, 333. Girar la ruleta, 223232. Grabadora de sonidos (Windows), 333335. guardar, 2527, 60. interfaces de usuario, ( Ver interfaces de usuario) Juego, 112114, 115116. Memoria, 282284. Metrónomo, 130132. minimizada, 3 37 6
OLEGRAPH, 336343 Paleta de direcciones, 101103. Proyecto Rejilla, 134136. proyectos (Ver proyectos) Queso, 119120. registro, para OLE, 335336. 345. Sonrisa, 9498. TestDeArchivos, 245252. Tragaperras, 163169. ventanas estándar para, 911. Vuelo,122124. árbol de llamadas, 227228. archivos binarios., 244. de acceso aleatorio abrir y cerrar, 260261. en la aplicación Base d datos Comadrejas, 261279. leer desde y escribir en, 261.. vista general, 244,. 259 de configuración aplicación Memoria, 282284. funciones del perfil de Windows para acceder a, 281. MSDOS (CONFIG.SYS), 255257. Windows (WIN.INI), 279284. de extensión controles Grid, 5, 6, 25, 138, 324326. cuadros de diálogo comunes, 5, 6 , 25, 140. enlace e incrustación de objetos, 5, 6, 25, 139140, 331. secuenciales abrir y cerrar, 253254. en la aplicación Configurador, 255257. escribir en, 255. leer desde, 254255, 258. vista general, 244, 252253. arcos, 303306. argumentos, definidos, 84.
arrancar Visual Basic, 12. arrastrar y soltar, procedimientos de evento, 214219. Ver también ratón, procedimientos de evento ASCII, caracteres, 33, 174. asignación de memoria, 3435. Ver también declaraciones asistente de configuración de aplicaciones, 4161. asistente de instalación de aplicaciones, 40. asterisco (*) como carácter comodín, 134142. como operador de multiplicación, 67. atajos de teclado, 151. atrapar errores, 237241. AUTOEXEC.BAT, archivo, 315. AUTOLOAD.MAK, archivo, 140, 331. AutoRedraw, propiedad, 90, 287288, 308. AutoSize, propiedad, 104. avanzar a paso de procedimiento, 232. paso a paso, 231232. ayuda sensible al contexto, 4, 234241. Ayuda, aplicación (Windows), 148149. Ayuda, sistema en línea, 4, 234241. B
BackColor, propiedad barra de menús, Visual Basic, 4. barra separadora de menús (), 155. barra de herramientas, 3, 4, 5. Add Watch, botón, 226. Break, botón, 72. Calis, botón, 227. End, botón, 15, 22. herramientas de depuración, 222. Instant Watch, botón, 225. Menú Design Window, botón, 150. New Form, botón, 246.
New Module, botón, 248. Open Project, botón, 4, 26. Properties Window, botón, 8. Save Project, botón, 25. Single Step, botón, 230. Start, botón, 15. Step Procedure, botón, 231. Toggle Breakpoint, botón, 228. View Code, botón, 5. View Form, botón, 5. barras de desplazamiento en la aplicación Barra de desplazamiento, 127129. eventos, 127. procedimientos y métodos, 127. propiedades, 126127. vista general, 124125. bases de datos. Ver también entrada y salida en archivos acceder, dinámicamente, 323330. acceder, mediante controles Data, 139, 316319. acceder, mediante el programa, 319322. actualizar acceso a, 319. buscar registros específicos, 320321. colecciones, 323. conectar, a bases de datos, 316318. consultar, por medio de descripciones de, 324. definir vistas de, 319. en la aplicación BIBLIO, 312322. en la aplicación Comadreja, 261279, 312. en la aplicación Examinar base de datos, 326330. mostrar datos desde, 318. relaciónales, 313 tipo agenda, aplicación, 321322. vista general, 311315. BASIC, lenguaje de programación, xvxix. Ver también Visual Basic 37 7
EL LIBRO DEL VISUAL BASIC
BIBLIO, aplicación de base de datos, 312322. bits, 2930, 33 BOF, propiedad, 320. BorderColor, propiedad, 133 BorderStyle, propiedad, 11, 90, 104, 133. BorderWidth, propiedad, 133 Borland dBase, 312, 316. Borland Paradox, 312, 316. botones de comando en la aplicación Cronómetro, 1114. en la aplicación Juego, 112114. eventos, 112. matrices de controles de, 187, 321. procedimientos y métodos, 112. propiedades, 111112. vista general, 110111. botones de opciones en la aplicación Juego, 112114. eventos, 112. matrices de controles de, 186. procedimientos y métodos, 112 propiedades, 111112. vista general, 110111. Break, botón, 72. Break, comando, 72. breakpoints, 228229. Bring To Front, comando, 136. bucles definición, 170. Do, declaración (Ver Do, declaración) For, declaración, 176, 183. infinitos, 170. matrices y, 182184. bugs, definición, 221. Ver también depuración; errores buscar información de ayuda, 4, 234236. bytes, 33. ByVal, palabra clave, 202. 378
Indice alfabético
c cadenas. Ver también caracteres concatenación, 53, 7173 convertir a números, 176. convertir números a, 73, 176. tipo de datos, 4143 caja de herramientas, 3, 67. Check Box, herramienta, 111. Combo Box, herramienta, 120. Command Button, herramienta,
11 -12 , 111 , 322 . Common Dialog, herramienta, 6, 141, 255. Data, herramienta, 139, 315. Directory List Box, herramienta, 136, 137, 245. Drive List Box, herramienta, 136, 137, 245. File List Box, herramienta, 137, 245. Frame, herramienta, 115. Grid, herramienta, 138, 139, 325. Horizontal Scroll Bar, herramienta, 125. Image, herramienta, 99. Label, herramienta, 23, 104. Line, herramienta, 132. List Box, herramienta, 117. OLE, herramienta, 6, 140, 331 Option Button, herramienta, 111. Picture Box, herramienta, 99. Pointer, herramienta, 12. Shape, herramienta, 133. Text Box, herramienta, 141, 107. Timer, herramienta, 129. Vertical Scroll Bar, herramienta, 124126. Calcular, aplicación, 172176, 178, 205. Calculator, aplicación, 343348. Calis, botón, 227. Calis, comando, 227228. cambiar de tamaño a los objetos, 12.
campos, definición, 52. Cancel, propiedad, 112. CancelError, propiedad, 141. Caption, propiedad, 10, 14, 91, 104. caracteres UNICODE, 33. Caracteres especiales caracteres. Ver también cadenas ASCII, 32, 174. color (Ver colores) comodín, 138, 142. contraseña, 107. de comentario ('), 49 de declaración de tipo, 36, 5761, 65. fuentes, 9192, 145147. representación de, 3132. cartesiano, sistema de coordenadas, 292.
Cerrar, comando, 22. cerrar archivos de acceso aleatorio, 260261. secuenciales, 253254. Change, evento barras de desplazamiento, 127. cuadros combinados, 122. cuadros de lista de directorios, cuadros de lista de unidades de disco y cuadros de lista de archivos, 138. cuadros de texto, 108. check boxes (Ver cuadros de control ) Check Box, herramienta, 91111 Checked, propiedad, 155. CInt, función, 197. Circle, método, 286, 303306. Claris FileMaker, 312. Clear All Breakpoints, comando, 228. Clear, método, 119, 122. Click, evento, 16, 93. Close, declaración, 253254, 261. Cls, método, 94, 97, 101, 286, 301. CMDIALOG.VBX, archivo, 5, 6, 25, 141, 140, 326.
code, definición, 6 codificación. Ver también control, programa; depuración; diseñar compiladores frente a intérpretes, 3639 datos ( Ver constantes; datos; bases de datos; tipos de datos; entrada y salida en archivos; variables) declaraciones (Ver declaraciones) definición, 6, 15. expresiones (Ver expresiones) funciones (Ver funciones) generalización, 199200. instrucciones de ordenador, 3540. intérpretes frente a compiladores, 3639. lenguajes ( Ver lenguajes de ordenador) módulos (Ver módulos de código) palabras clave (Ver palabras clave) procedimientos (Ver procedimientos de eventos; procedimientos de función; procedimientos sub) reciclar código, 202. códigos de control, 252253 colecciones, 323. Color, propiedad Color, cuadros de diálogo, 144. Font, cuadros de diálogo, 145 colores borde, 133 constantes globales de, 299300. cuadros de diálogo para la selección de, 145. de elementos del código, 19, 6l. de formas y líneas, 133134. fondo, 90. gráficos y, 296300. primer plano, 92. columnas bases de datos, 311 grids, 325.
:l
l i br o del visual basic
Columns, propiedad controles:grid, 325. cuadros de lista, 117. ColWidth, propiedad, 326. corna fija, tipos de datos, 42. Comadrejas, aplicación, 261279, 312. omandos. Ver también barra de herramientas; caja de herramientas Add Watch, 226, 229230. Break, 72. Bring To Front, 136. Calls, 227. Cerrar, 22. Clear All Breakpoints, 228. Continue, 229. Edit Watch, 227. End, 15. Environment Options, 19, 59 Imprimir tema, 237. Indice, 234. Instant Watch, 225. Load Text, 58. Menu Design, 150. New Form, 246. New Module, 248, 281. Open Project, 26, 39, 140. Project Options, 247248. Remove File, 25. Save Project, 25, 252. Send To Back, 136. Set, 346. share (MSDOS), 315. Siempre visible, 237. Single Step, 230. Start, 15. Toggle Breakpoint, 228. combo box, herramienta, 120. combo boxes. Ver cuadros combinados comentarios, en el código, 49. command buttons. Ver botones de comando 380
Indice alfabético
Command Button, herramienta, 1113, 111, 322. COMMDLG.DLL, archivo, 140. common dialog boxes. Ver cuadros de diálogo estándar) Common Dialog, herramienta, 6, 141. compartir archivos, 139, 315. compiladores frente a intérpretes, 3639. compilar aplicaciones ejecutables, 26, 3940. comprobación automática de la sintáxis, 19, 60. condiciones de desbordamiento, 43. CONFIG.SYS, archivo, 255257. Configurador, aplicación, 255257. conjunto de instrucciones, 25. Connect, propiedad, 317. consideraciones sobre el hardware para los gráficos, 298, 308309. Const, declaración, 4757. CONSTANT.TXT, archivo, 58, 143, 148, 299, 337, 358. constantes ámbito de, 57. color, 299. control OLE, 336340. creación, 4549. cuadros de diálogo estándar, 143, 145, 146, 148. globales, 58. nombres, 4849. tipos de datos (Ver tipos de datos) consultas, base de datos, 313314. container (contenedor), aplicaciones 333 Continue, comando, 229. control de flujo lineal en programas, 189191. control del programa bucles ( Ver Do, declaración; For, declaración) en la aplicación Calcular, 172176.
en la aplicación Tragaperras, 163169. errores comunes, 164. gestión de errores y, 178. ramificación condicional ( Ver If, declaración) ControlBox, propiedad, 91. controles Data buscar registros específicos, 320321. conectar bases de datos a, 316317. definición, 6. Ver también objetos; caja de herramientas definir grupos de registros o vistas, 318319. enlazar controles de visualización a, 318. métodos, 319322. propiedades, 317, 318, 320. SGBD aceptables para, 316. vista general, 139, 315. Conversión de Temperaturas, aplicación, 195198. Copies, propiedad, 147. Correo electrónico, aplicación, 214219 Count, propiedad, 323. CreateObject, función, 344. Cronómetro, aplicación codificar procedimientos de evento, 1522. compilar, 3940. ejecutar, 22. guardar, 2527. interface de usuario, 915. revisar el diseño de, 2325. usar etiquetas, 105106. Cronómetro de Proyectos, aplicación declaraciones globales, 357358. diseño del formulario, 354357. diseño del menú, 351354. diseño general, 349351. estructura de eventos, 363372. formularios auxiliares, 358363.
Main, procedimiento, 363 refinamientos, 372373 cuadrículas, dibujar, 292296. cuadro Ajustes en la ventana Properties, 9, 10. cuadro Object en la ventana Properties, 9 10 cuadro Procedure en la ventana de código, 17. cuadros combinados desplegables, 121. en la aplicación Vuelo, 122124. eventos, 122. procedimientos y métodos, 122. propiedades, 120122. sencillos, 122. vista general, 120. cuadros de control en la aplicación Juego eventos ligar a controles de datos, 318. procedimientos y métodos, 112. propiedades, 111112. visión general, 110111. cuadros de diálogo estándar Abrir, cuadros de diálogo, 142143. Color, cuadros de diálogo, 144. directorio, unidades de disco y archivos, cuadros de diálogo, 136. Fuente, cuadros de diálogo, 145146. Guardar como, cuadros de diálogo, 143 Imprimir, cuadros de diálogo, 147148. llamar a la aplicación Ayuda de Windows, 148149. cuadros de diálogo. Ver cuadros de diálogo estándar; cuadros de lista de directorios; cuadros de lista de unidades de disco; cuadros de lista de archivos -
.
381
Indice alfabético
EL LIBRO DEL VISUAL BASIC
cuadros de dibujo enlazar a controles Data, 318. eventos, 100. procedimientos y métodos, 100101. propiedades, 99100. vista general, 9899 cuadros de lista de archivos en la aplicación TestDeArchivos, 245252. eventos, 138. procedimientos y métodos, 138. propiedades, 137138. vista general, 136137, 244. cuadros de lista de directorio en la aplicación TestDeArchivos, 245252. eventos, 138. procedimientos y métodos, 138. propiedades, 137138. vista general, 136137, 245. cuadros de lista de unidades de disco en la aplicación TestDeArchivos, 245252. eventos, 138. procedimientos y métodos, 138. propiedades, 137138. vista general, 136137, 245. cuadros de lista. Ver también cuadros combinados; cuadros de lista de directorios; cuadros de lista de unidades de disco; cuadros de lista de archivos desplegables, 121. en la aplicación Queso, 119120. eventos, 119 índices, 276. procedimientos y métodos, 119 propiedades, 117119. cuadros de texto en la aplicación Cronómetro, 14, 23. en la aplicación EditNota, 109110. enlazar a controles Data, 318. 382
eventos, 108. procedimientos y métodos, 108. propiedades, 106108. currency, tipo de datos, 4143, 45 D
dar nombres elementos de menú, 151152. objetos, 11, 13, 92. procedimientos de eventos, 18. procedimientos de función, 199 variables y constantes, 4849 Data, herramienta, 139, 315. DatabaseName, propiedad, 317. DataField, propiedad, 318. DataSource, propiedad, 318. datos. Ver también constantes, bases de datos, entrada y salida en archivos; objetos, variables bits, bytes y palabras, 3334. intercambio dinámico de datos (DDE), 347, 374. memoria y, 3435. ordenadores y, 2935. tipos (Ver tipos de datos) valores de caracteres, 33 valores numéricos, 3031. dBase, Borland, 312, 316. DblClick, evento, 93 DDE (intercambio dinámico de datos), 347, 374. Debug, ventana, 73, 222225. declaraciones. Ver también ámbito, control, programa; expresiones; funciones, palabras clave anidadas, 162. asignación, 6364, 80, 346. Glose, 253254, 261. compuestos, 161. Const, 47, 57. constantes, 47. Declare, 21, 280.
Dim, 21, 45, 59, 180. Do ( Ver Do, declaración) ejecutables, 2122. Exit, 184. For, 176177, 183184. funciones de librerías de enlace dinámico, 280. Function, 194. Get, 260261. If (Ver If, declaración) If Type Of, 209 Input$, 258. Line Input #, 254. Load, 249. matrices, 179155. memoria y, 3435. On Error GoTo, 237241. Open, 253260. Option Explicit, 59, 225. parámetros, 193 por omisión, 47, 5761, 65. (Ver también tipos de datos) Print #, 255. procedimiento, 1719. Put, 260261. Randomize, 166. ReDim, 185. Resume, 239. Stop, 228229. Sub, 18, 193, 194. variables, 1921, 4546. Declare, declaración, 21, 280. DefaultExt, propiedad, 112. Delete, método, 320. depuración. Ver también errores árbol de llamadas, 227228. breakpoints, 228229 definición, 221222. estrategias, 232234. expresiones watch, 225227. ir a paso de procedimiento, 232. ir paso a paso, 231232.
Stop, declaraciones, 228229. ventana Debug, 73, 222225. watchpoints, 229230. DialogTitle, propiedad, 142. Dibujar líneas, aplicación, 212213. Dim, declaración, 21, 45, 59, 180. dimensiones, matriz, 180. Dir$, función, 253 Directory List Box, herramienta, 135, 137, 245. discos, instalación, 40 diseñar declaraciones globales en módulos, 357358. formularios, 915, 354357, 358362. general, de aplicaciones, 349351. interfaces de usuario, 915, 2325. menús, 149158, 351354. procedimientos, 199. procedimientos de eventos, 363372. DISPCALC, aplicación, 344347. división en coma flotante, 68, 69. división entera, 6869 DLL. Ver librerías de enlace dinámico (DLL) Do, declaración convertir el bucle For en, 183. en la aplicación Calcular, 172176. proceso repetitivo con, 170172. double, tipo de datos, 42. DragDrop, evento, 215. DragMode, propiedad, 214216. DragOver, evento, 215. DrawMode, propiedad, 301. DrawStyle, propiedad, 301. DrawWidth, propiedad, 301. Drive, propiedad, 137. Drive List Box, herramienta, 136, 245. E
ecuaciones, representación gráfica, 292. Edit Watch, comando, 227. 383
EL LIBRO DEL VISUAL BASIC
EditNota, aplicación, 109110. editor de iconos, 103 ejecutar aplicaciones, 15, 22. elementos, definición, 51, 52. elipses, dibujar, 303306. Enabled, propiedad, 24, 91, 104, 115, 155157. End, botón, 15, 22. End, comando, 15. EndDoc, método, 307. enlace e incrustación de objetos (OLE) control directo del objeto con Automatización OLE, 344347. enlazar frente a incrustar, 335336. incrustar objetos en la fase de diseño, 333335. incrustar objetos en la fase de ejecución, 336342. registrar aplicaciones para, 335, 345. términos, 332. vista general, xvii, 6, 139140, 331332. entrada y salida en archivos. Ver también archivos de configuración, bases de datos; archivos de acceso aleatorio; archivos secuenciales Abrir, cuadros de diálogo, 142143 compartir archivos, 139, 315. cuadros de diálogo estándar, 137, 142143. cuadros de lista de directorio, cuadros de lista de unidades de disco y cuadros de lista de archivos, 136138, 244252. Guardar como, cuadros de diálogo, 143. Imprimir, cuadros de diálogo, 147148. vista general, 243244. Environment Options, comando, 19, 59 EOF, función, 254. 384
Indice alfabético
EOF, propiedad, 320. Eqv, operador lógico, 75. Err, función, 238. Error, declaración, 238. errores. Ver también depuración atrapar, 237, 241. cometidos en expresiones, 7981. cometidos en la declaración If, 164. de sintaxis, 19 desbordamiento, 43. en tiempo de ejecución, 237241. gestión, 178. información sobre, 234. Escapar, aplicación, 208209. escribir código. Ver codificación escribir en archivos de acceso aleatorio, 261. secuenciales, 255. escribir procedimientos. Ver procedimientos estrategias, depuración, 232234. etiquetas en la aplicación Cronómetro, 23, 105108. enlazar a controles de datos, 318. eventos, 105. procedimientos y métodos, 105. propiedades, 104. eventos arrastrar y soltar, 214219. barras de desplazamiento, 127. botones de comando, 112. botones de opción, 112. cuadros combinados, 122. cuadros de control, 112. cuadros de dibujo e imágenes, 100. cuadros de lista, 119. cuadros de lista de directorio, cuadros de lista de unidades de disco y cuadros de lista de archivos, 138. cuadros de texto, 108, 271.
definición, 16.. etiquetas, 105. formularios, 16 , 93. líneas y formas, 134. marcos, 115. ratón, 210213 relojes, 130. teclado, 213214. Examinar base de datos, aplicación, 326330. Excel, Microsoft, 347, 374. Exclusive, propiedad, 318. Exit declaración, 183 exponenciación, 67. expresiones. Ver también declaraciones anidadas, 66. control Data, para información sobre bases de datos, 324. errores comunes en el uso, 7981. operadores aritméticos, 6671. operadores de cadenas, 7173 operadores de comparación, 7374. operadores lógicos, 7577, 81. precedencia de operadores, 7779. tipos de, 6566. vista general, 6465. watch, 225227. extensiones de nombres de archivos, 5, 144, 327. F
False, como constante, 73 Fields, propiedad, 323 filas bases de datos, 311. grids, 325. File List Box, herramienta, 136, 137, 245. FileMaker, Claris, 312. FileName, propiedad cuadros de diálogo Abrir, 142. cuadros de lista de archivos, 137.
FillColor, propiedad, 134, 301. FillStyle, propiedad, 134, 301. Filter, propiedad, 142. FilterIndex, propiedad, 143. FillColor, propiedad, 143. FindFirst, método, 320. FindLast, método, 320. FindNext, método, 320. FindPrevious, método, 320. FixedColumns, propiedad, 326. FixedRows, propiedad, 325. Flags, propiedad cuadros de diálogo Abrir, 143. cuadros de diálogo Color, 145. cuadros de diálogo Fuente, 146. cuadros de diálogo Imprimir, 148. flujo de control. Ver control del programa; procedimientos FontBold, propiedad cuadros de diálogo Fuente, 146. formularios, 91. FontItalic, propiedad cuadros de diálogo Fuente, 146. formularios, 91. FontName, propiedad cuadros de diálogo Fuente, 146. formularios, 91. FontSize, propiedad cuadros de diálogo Fuente, 146. formularios, 91. FontStrikethru cuadros de diálogo Fuente, 146. formularios, 91. FontUnderline, propiedad cuadros de diálogo Fuente, 146. formularios, 91. For, declaración, 176177, 183184. ForeColor, propiedad, 92, 296. Form, ventana, 67. formas eventos, 134. procedimientos y métodos, 134. 385
EL LIBRO DEL VISUAL BASIC
propiedades, 133134. Rejilla, proyecto, 134136. vista general, 132133. Format, función, 21, 169 formato binario para los archivos guardados, 60. formato de texto para archivos guardados, 60. formularios. Ver también interfaces de usuario añadir objetos visualizables, 1115. crear varios, 245248, 358363. definición, 67. diseño, 915, 354357, 358363. en la aplicación Sonrisa, 9498. especificar el de inicio, 248. eventos, 93 inicial, especificar, 247248. Me, variable, 208. modal, 249, 360. nombres de archivo por omisión, 5. procedimientos y métodos, 8485, 9394, 97, 249, 330, 359 propiedades, 911, 8993, 330. rejillas de visualización, 100. FoxPro, Microsoft, 312, 316. Fuente, cuadros de diálogo, 145147. fuentes cuadros de diálogo para la selección de, 145147. formularios, 9192. funciones del perfil (Windows), 281. funciones. Ver también comandos; librerías de enlace dinámico (DLLs) CINT, 197. CreateObject, 344. Dir$, 253 EOF, 254. Err, 238. Format, 22, 169. GetProfileString, 281. 386
Indice alfabético
InputBox, 53, 358. IsNull, 330. LoadPicture, 93, 94, 99, 100. LOF, 258, 266. MsgBox, 53, 358. Now, 19, 84. perfil de Windows, 281. RGB, 298. Rnd, 169. Str$, 73, 176. Val, 176. WriteProfileString, 281. Function, declaración, 194. G
Gates, Bill, xvi. generalizar el código, 199200. gestores, para cambiar el tamaño de los objetos, 12. Get, declaración, 260, 261. GetProfileString, function, 281. gigabyte, definición, 34. Girar la ruleta, aplicación, 223232. Global, 57. nombres reservados, 48. Static, 207. Type, 50. Variant, 20. Global, palabra clave, 57. GotFocus, evento, 271. Grabadora de sonidos, aplicación (Windows), 333335. gráficos círculos, 303306. colores, 296300. consideraciones sobre el hardware para, 308309. coordenadas de pantalla (Ver sistema de coordenadas) elipses, 303306. formularios y cuadros de dibujo, 285306.
gestión de la pantalla, 285288. imprimir, 306308. líneas y rectángulos, 212213, 286, 296, 302303 mostrar en pantalla, 286287. porciones de tarta, 303306. propiedades y métodos de dibujo, 301306. puntos, 302. redibujar pantallas, 287288. granularidad, 232. Graph, Microsoft, 336343 Grid, controles en la aplicación Examinar base de datos, 326330. propiedades, 325326. vista general, 138139, 323 GRID.VBX, archivo, 5, 6, 25, 139, 140, 325, 326. Grig, herramienta, 138, 139, 325. Guardar como, cuadros de diálogo, 143 guardar aplicaciones, 2527, 60. guardar archivos, 143144. guión (), especificación de la barra separadora en menús GWBASIC, xvi H
hardware de vídeo, 285, 298. Height, propiedad, 92, 99, 289 HelpCommand, propiedad, 148. HelpFile, propiedad, 148. HelpKey, propiedad, 148. herramientas, depuración, 222232. Ver también depuración Hide, método, 360. Hopper, Grace Murray, 221. Horizontal Scroll Bar, herramienta, 126.
I Icon, propiedad, 92. iconos, 103
If, declaración en la aplicación Tragaperras,
163169. realizar elecciones con, 159163. If TypeOf, declaración, 209 Image, herramienta, 9899 imágenes en la apliación Paleta de direcciones, 101103 enlazar a controles de datos, 318. eventos, 100. procedimientos y métodos, 100101. propiedades, 99100. vista general, 9899 Imp, operador lógico, 75, 7677. Imprimir, cuadros de diálogo, 147148. Imprimir tema, comando, 237. Index, propiedad, 186. Indice, comando, 234. Input$, declaración, 258. InputBox, función, 53, 358. instalación de Visual Basic, 12, 40. Instant Watch, botón, 225. instrucciones, ordenador compiladores frente a intérpretes, 3639. ejecutables, 2122. vista general, 3536. integer, tipo de datos, 4142. intercambio dinámico de datos (DDE), 347, 374. interface de múltiples documentos (MDI), 374. interfaces de usuario. Ver también comandos cuadros de diálogo ( Ver cuadros de diálogo estándar; cuadro de lista de directorios; cuadro de lista de unidades de disco; cuadro de lista de archivos) diseño, 915, 2327. menús, 149158, 351354. 387
EL LIBRO DEL VISUAL BASIC
objetos de visualización, 1114. propiedades del formulario, 911. Interval, propiedad, 129130. IsNull, función, 330. ItemData, propiedad, 275. J
Juego, aplicación, 112114, 115116. K KERNELL.DLL, 281. KeyAscii, variable, 174. KeyDown, evento, 214. KeyPress, evento, 214. KeyPress, procedimiento de evento, 174.
KeyPreview, propiedad, 214. KeyUp, evento, 214. kilobytes, definición, 34. L
Label, herramienta, 23, 104. LargeChange, propiedad, 126. leer de archivos de acceso aleatorio, 261. secuenciales, 254. Left, propiedad, 93, 289. lenguajes de ordenador ensamblador, 3536. fuente, definición, 36. historia de, xvxvii. máquina, 36. Microsoft Windows y, xviixix. vista general, 3536. librerías de enlace dinámico (DLL) COMMDLG.DLL, 140. cuadros de diálogo estándar, 140. funciones del perfil de Windows y, 281. ligar controles de datos y, 316 , 318. los discos de instalación de Visual Basic y VBRUN300.DLL, 40, 280. 388
Indice alfabético
utilización en la aplicación Memoria, 282284. vista general, 280. Windows 30 y, 140. Line, método, 212213, 286, 296, 302303. Line, herramienta, 132. Line Input #, declaración, 254. líneas en el proyecto Rejilla, 134136. en la aplicación Dibujo líneas, 212213. eventos, 134. procedimientos y métodos, 134; 302303. propiedades, 133134, 301302. vista general, 132133. List, propiedad, 117, 137. List Box, herramienta, 117. ListCount, propiedad, 118. ListIndex, propiedad, 118, 137. LL
llamadas, procedimiento, 8384 , 191193, 227228. Load, declaración, 249. Load, evento, 93 Load, procedimiento de evento, 93 117, 269 Load Texto, comando, 58. LoadPicture, función, 93, 94, 99; 100 LOF, función, 258, 266. long, tipo de datos, 4142. LostFocus, evento, 108, 271.
M Main, procedimiento, 248, 363. Marco, herramienta, 115. marcos en la aplicación Juego, 115116. vista general, 114115. matrices de controles, 186188, 321.
matrices dinámicas, 185. Max, propiedad, 126. MaxButton, propiedad, 92. MaxLength, propiedad, 106. mayor o igual que (>=), operador, 74. mayor que 0, operador, 73. MDB, extensión de nombre de archivo, 327. MDI (interface de múltiples documentos), 374. Me, variable interna, 208. megabyte, definición, 34. memoria, 3435. Ver también declaraciones de acceso aleatorio (RAM), 3435. de vídeo, 285. Memoria, aplicación, 282284. menor o igual que (<=), operador, 74. menor que (<), operador, 73. Menú Design, comando, 150. Menú Design Window, botón, 150. menús. Ver también comandos barra de menús, 149158, 351354. popup, 157158. métodos ámbito, 97. barras de desplazamiento, 127. botones de comando, 112. botones de opciones, 112. controles Data, 319322. cuadros combinados, 120. cuadros de control, 112. cuadros de dibujo e imágenes, 100. cuadros de lista, 119. cuadros de lista de directorios; cuadros de lista de unidades de disco; cuadros de lista de archivos, 138. cuadros de texto, 109. de dibujo. Vet también gráficos etiquetas, 105. formularios, 8485, 93, 97, 249, 360.
gráficos, 212213, 286, 293, 296, 301306. Circle, método, 303306. Cls, método, 286302. Line, método, 176777, 212213, 286, 296, 302303. Point, método, 286, 302. Pset, método, 286, 302. vista general, 286, 301306. impresora, 306308. líneas y formas, 134. marcos, 115. menús popup, 157158. relojes, 130. vista general, 8485. Metrónomo, aplicación, 130132. Microsoft Access, 312315. Microsoft Excel, 347, 374. Microsoft FoxPro, 312315. Microsoft Graph, 336343. Microsoft QuickBasic, xvi. Microsoft Visual Basic. Ver Visual Basic Microsoft Windows arrancar, 1. Ayuda, aplicación, 148149. cuadros de diálogo estándar y la versión 3.0, 140. Grabadora de sonidos, aplicación, 333335. historia de, xvxvii. programar para, xviixix ( Ver también Visual Basic). Microsoft Word, 347. Min, propiedad, 126. MinButton, propiedad, 92. Mod, operador (módulo), 6970. módulo (operador Mod), 6970. módulos de código ámbito de los procedimientos, 5457 declaraciones globales en, 357358. en la aplicación Memoria, 282284. vista general, 57. 389
EL LIBRO DEL VISUAL BASIC
MouseDown, evento, 211. MouseMove, evento, 210. MouseUp, evento, 211. Move, método, 85, 208209. MoveFirst, método, 319. MoveLast, método, 320. MoveNext, método, 319. MovePrevious, método, 319. mover objetos, 12. MsgBox, función, 53, 358. MSOLE3.VBX, archivo, 5, 6, 25, 140. MultiLine, propiedad, 107. múltiples formularios, 246248, 359363. MultiSelect, propiedad, 118. N
Name, propiedad, 11, 14, 92. New Form, botón, 246.
New Module, botón, 248. New Module, comando, 248, 281. NewPage, método, 307. no igual que (<>), operador, 74. NoMatch, propiedad, 321. Not, operador lógico, 75. notación hexadecimal, 300. sintaxis, 45, 8889. Now, función, 19, 84. números binarios, 30. convertir, a cadenas, 73, 176 convertir cadenas a, 176. en coma flotante, 42, 4445. hexadecimales, 300. reales, 42, 4445. sistemas de numeración, 3031 0
objetos. base de datos ( Ver base de datos) caja de herramientas y, 67, 12. cambiar de tamaño, 12. 390
Indice alfabético
colecciones, 323. como parámetros, 207209. ( Ver también parámetros) conjuntos de registros, 318319. creación, 1115. dar nombre, 11 , 13 , 92. definición, 6. enlazados, 332, 335336. Ver también enlace e incrustación de objetos (OLE) incrustados, 332, 335336. Ver también enlace e incrustación de objetos (OLE) matrices de controles, 186188. mover, 12. OLE, 331 ( Ver tambi én enlace e incrustación de objetos (OLE)). Printer, 306308, 309. propiedades, 8 , 9 (Ver t ambién propiedades) Screen (Ver pantallas) seleccionar, 12. vista general, 8789. y eventos ( Ver eventos) y métodos ( Ver métodos) y procedimientos de eventos ( Ver procedimientos de eventos) OLE, herramienta, 6, 140, 331. OLE. Ver enlace e incrustación de objetos (OLE) OLEGRAPH, aplicación, 336343. On Error G0T0 , declaración, 237241. opciones. Ver If, declaración Open, declaración, 253, 260. Open Project, botón, 4, 26. Open Project, comando, 26, 39, 140. operadores aritméticos, 6671. booleanos, 7377. de asignación, 63. de comparación, 7374. de concatenación ( + ), 53, 71.
de división entera (\) y en coma flotante (/), 67, 6869. de exponenciación, 67. definición, 6465. de multiplicación (*), 67. de resta (), 67. de suma (+), 67. errores comunes en el uso de, 7981. lógicos, 7577, 81. Mod (módulo), 67, 69. reglas de precedencia, 66, 7071, 7779. relacionales, 7374. Option Button, herramienta, 111. Option Explicit, declaración, 59, 225. Options, propiedad, 318. Or, operador lógico, 75, 76. orden de precedencia de operadores, 66, 7071, 7779 orden Z de los objetos, 136. ordenadores consideraciones sobre el hardware para los gráficos, 308309. datos y, 2935. instrucciones y, 3540. pantallas, 285. P
Page, propiedad, 307. Paint, procedimiento de evento, 286287, 308. palabras clave ByVal, 202. colores y, 19. definición, 20. palabras y tamaño de palabra, definición, 34. Paleta de direcciones, aplicación, 101103 pantallas. Ver tambi én ventanas coordenadas ( Ver sistemas de coordenadas)
en color, 286. gestión, 285288. monocromas, 285. mostrar gráficos, 286287. (Ver también gráficos) redibujar, 287288. Visual Basic, 39. Paradox, Borland, 312, 316. parámetros objetos como, 207209. pasar por referencia, 200202. pasar por valor, 202204. paso de matrices, 204205. vista general, 174, 191193. paréntesis, 66, 84. PasswordChar, propiedad, 107. Path, propiedad, 137. PathChange, evento, 138. Pattern, propiedad, 138, 249. petabyte, definición, 34. Picture, propiedad, 92. Picture Box, herramienta, 9899. pixels, definición, 285. planificación. Ver diseño Point, método, 286, 301. Pointer, herramienta, 12. PopupMenu, método, 157158. porciones de tarta, 303306. posicionamiento del tabulador, 60. precisión de los números, 4445. Print, método, 8485, 94, 100101, 286, 306. Print #, declaración, 255. Printer, objeto, 306308, 309. PrintForm, método, 307. procedimientos de función. Ver también prcredimiente>s dar nombre a, 199. definición, 1920, 82, 194. internos, 83. librerías de enlace dinámico, 280. parámetros ( Ver parámetros) 3
Indice alfabético
EL LIBRO DEL VISUAL BASIC
procedimientos sub frente a, 195. ( Ver también procedimientos sub) sintaxis, 8284, 194195. vista general, 8182, 194195. procedimientos sub. Ver también procedimientos de evento; métodos; procedimientos de eventos del ratón, 210213 diseñar, 199. escribir, 195200. frente a procedimientos de función, 195. (Vertambién procedimientos de función) Main, 362. parámetros (Ver parámetros) sintaxis, 17, 8284, 193, 194. procedimientos. Ver también métodos de evento frente a generales, 189. ( Ver también procedimientos de evento) de función frente a sub, 195. (Ver también procedimientos de función; procedimientos sub) definición, 16. llamadas, 84, 191193, 227228. parámetros (Ver parámetros) vista general, 8182, 189193 Procedure Step, botón, 231. proceso repetitivo. Ver Do, declaración; For, declaración programa, definición, 35. Ver también aplicaciones; codificación; control del programa programación orientada a eventos, xvii. Ver también procedimientos de eventos; proceclimientos arrastrar y soltar, 214219. declaración de variables, 1921. declaraciones, 1719. definición, 16. diseño, 363372. 392
ratón, 210213. teclado, 213214. ventana, 3, 46, 11. vista general, 1617, 2122. Project Optiones, comando, 247. Properties, lista, 9. Properties, ventana, 3, 5, 89. Properties Window, botón, 8. propiedades acceder, 52. ámbito, 97. Ayuda de Windows, aplicación, 148, 149. barras de desplazamiento, 126127 bases de datos, 323, 330. botones de comando, 111112. botones de opciones, 111112. controles Data, 317, 318. controles Grid, 325. controles OLE, 336. cuadros combinados, 120122. cuadros de control, 111112. cuadros de diálogo Abrir, 142143 cuadros de diálogo Color, 145. cuadros de diálogo estándar, 140148. cuadros de diálogo Fuente, 146. cuadros de diálogo Guardar como, 144. cuadros de diálogo Imprimir, 147148. cuadros de dibujo e imágenes, 99100. cuadros de lista, 117119, 215. cuadros de lista de directorios; cuadros de lista de unidades de disco; cuadros de lista de archivo, 137138. cuadros de texto, 106108. elementos de menús, 155157. etiquetas, 104. formularios, 911, 8993
gráficos, 288292, 296301, 308. líneas y formas, 133134. marcos, 115. objetos, 186, 317. pantalla e impresora, 308309. relojes, 130. proyectos archivos de extensión ( Ver archivos de extensión) creación, 46. guardar, 2527. Rejilla, 134136. Pset, método, 286, 302. Put, declaración, 260261.
Q
Queso, aplicación, 119120. QuickBasic, Microsoft, xvi. R
ramificación condicional, 160, 189191. Ver también If, declaración Randomize, declaración, 166. rango de tipos de datos numéricos, 43. frente a precisión, 44. ratio de aspecto, 304305. Readonly, propiedad, 318. RecordCount, propiedad, 330. Recordset, objetos, 318. RecordSource, propiedad, 317, 318. redibujar pantallas, 90, 287288. ReDim, declaración, 185. redondear frente a truncar, 69. referencia, pasar parámetros por, 200. Refresh, método, 319. registros. Ver también bases de datos; entrada y salida en archivos; tipos de datos definidos por el usuario definición, 50, 52, 244. de aplicaciones para OLE, 335, 345.
reglas de precedencia para operadore 66, 7071, 7779. Rejilla, proyecto, 134136. relaciones, bases de datos, 313 relojes en la aplicación Metrónomo, 130132. eventos, 130. procedimientos y métodos, 130. propiedades, 130. vista general, 129130. Remove File, comando, 25. RemoveItem, método, 119, 122. Resize, evento, 16.
Resume, declaración, 239 RGB, función, 296298. Rnd, función, 169. Row, propiedad, 325. RowHeight, propiedad, 326. Rows, propiedad, 325.
s salida, archivo. Ver entrada y salida de archivos Save Project, botón, 25. Save Project, comando, 25, 252. Scale, método, 292, 306. ScaleHeight, propiedad, 290292. ScaleLeft, propiedad, 290292. ScaleTop, propiedad, 290292. ScaleWidth, propiedad, 290292. Screen, objeto, 309. Scroll, evento, 127. ScrollBars, propiedad, 107. sección del código de declaraciones generales, 20. seleccionar archivos, 142143. seleccionar objetos, 12. Selected, propiedad, 118. SelLength, 107. SelStart, 107. SelText, 108.
EL LIBRO DEL VISUAL BASIC
Send to Back, comando, 136. Set, comando, 346. SetFocus, método, 108. Setup, aplicación, 40, 60. Shape, herramienta, 133. share, comando (MSDOS), 315. Show, método, 249, 360. Siempre visible, comando, 237. signo igual (=) como operador de asignación, 63, 346. como operador igual que, 74. símbolo 1, 142. single, tipo de datos, 42. Single Step, botón, 230. Single Step, comando, 230. sintaxis comprobación automática, 19, 60. notación, 45, 8889. procedimientos y funciones, 8285. sistema de ayuda en línea, 4, 234237. sistema de coordenadas cuadros de dibujo e imágenes,
288296. definidos por el usuario, 288296. líneas y formas, 133 por omisión, 288. representación gráfica de ecuaciones y cuadrículas, 292. vista general, 288290. sistema numérico decimal, 30. sistemas de gestión de bases de datos (SGBD), 311, 316. SmallChange, propiedad, 126. Sonrisa, aplicación, 9498. Sorted, propiedad, 118. Start, botón, 15, 16. Start, comando, 15. Static, palabra clave, 207. Stop, declaración, 228229. Str$, función, 73, 176. Stretch, propiedad, 100. 394
Indice alfabético
Style, propiedad, 120. Sub, declaración, 18, 193, 194. subexpresiones, 66. T
tablas base de datos, 311. virtuales, 313. Tag, propiedad, 216. tamaño de una matriz en tiempo de ejecución, 184186. tamaño en puntos, 92, 289. teclas de acceso, 151. técnica de búsqueda binaria, 232234. técnicas de depuración invasoras, 229. no invasoras, 229. terabyte, definición, 34. TestDeArchivos, aplicación, 245252. Text, propiedad controles Grid, 325. cuadros combinados, 122. cuadros de lista, 119. cuadros de texto, 14, 108. Text Box, herramienta, 14, 107. texto. Ver caracteres; archivos secuenciales; cadenas; cuadros de texto TextWidth, método, 330. Timer, evento, 130. Timer, herramienta, 129. tipos de datos caracteres de declaración de tipos, 47, 5761, 65. coma flotante, 4445. definidos por el usuario, 4952. variables matriz frente a, 179 ventajas de, 51. vista general, 4951. expresiones y, 6466. numéricos coma flotante, 4445.
rango de, 43. vista general, 4143. vista general, 4143. Toggle Breakpoint, botón, 228. Toggle Breakpoint, comando, 228. Top, propiedad, 93, 99, 289. Tragaperras, aplicación, 163169 True, como constante, 73 truncar frente a redondear, 69. tutorial, Visual Basic, 4. twips, definición, 92, 289, 326. TwipsPerPixelX, propiedad, 309 TwipsPerPixelY, propiedad, 309 Type, palabra clave, 50.
u unidad de proceso central (CPU), 35. unidades de disco. Ver cuadros de lista de unidades de disco Val, función, 176. valor pasar como argumento, 84. pasar parámetros por, 202204. Value, propiedad, 112, 127. variables ámbito, 5261. caracteres de declaración de tipo, 47, 5761, 65. creación, 4549. dar nombre, 4849. declaraciones, 1921. Ver tambi én declaraciones) de nivel de módulo, 5456. globales, 5657, 357358. KeyAscii, 174. locales declaración por omisión, 47, 57. preservar sus valores en procedimientos, 205207. vista general, 5456.
matriz bucles y, 182184. determinar el tamaño durante la ejecución, 184186. experimentar con, 180182. matrices de controles, 186188, 321. parámetros, paso, 204205. reservar memoria para, 179180. módulos de código y, 57. tipos de datos ( Ver tipos de datos) variant, tipo de datos, 4143. Variant, palabra clave, 20. VBRUN300.DLL, archivo, 40, 280. VBX extensión de archivos, 5, 6. ventanas. Ver también formularios aplicación estándar, 911. código, 16, 19, 61. Debug, 73, 222225. formulario, 67. minimar, 3. pantalla de Visual Basic, 29. principal, 4. Project, 46. Properties, 8. Vertical Scroll Bar, herramienta, 124126. View Code, botón, 5. View Form, botón, 5. Visible, propiedad, 8, 10, 93, 155, 158, 319. vistas lógicas, 313 Visual Basic. Ver también aplicaciones; codificación; datos; depuración; objetos archivos de extensión ( Ver archivos de extensión) Ayuda, sistema, 4, 234237. características avanzadas, 374. discos de instalación, 40. Edición Profesional, 6. editor de iconos, 103 39