INTRODUCCION A LA PROGRAMACION VISUAL 1.1.- INTRODUCCIÓN HISTÓRICA AL ENTORNO WINDOWS. Las interfaces gráficos de usuario (GUI) han revolucionado el mundo informático. Quizá más importante a largo plazo es el hecho de que las aplicaciones Windows tienen una interfaz de usuario consistente, es decir, los usuarios tienen más tiempo para dominar la aplicación sin tener que preocuparse de las teclas que deben pulsarse dentro de los menús y cuadros de diálogo. Todo esto tiene un precio; antes de la existencia de Visual Basic, el desarrollo de aplicaciones para Windows era mucho más complicado que desarrollar aplicaciones para DOS. Los programadores tenían que preocuparse más de lo que estaba haciendo el ratón, de dónde estaba el usuario dentro de un menú y de si estaba realizando un clic o un doble clic en un punto determinado. Desarrollar aplicaciones para Windows requería expertos programadores en C, e incluso éstos tenían problemas. Visual Basic ha cambiado esta situación. Se pueden desarrollar aplicaciones para Windows más rápidamente. Los errores de programación no se generan tan frecuentemente y, si lo hacen, son más sencillos de depurar. Además incluye dos conceptos importantes: Un método visual de creación de aplicaciones, incluyendo formularios (ventanas), controles y, componentes del formulario. La habilidad de asociar código directamente a cada evento de cada elemento del diseño visual. 1.2.- DESARROLLO DE APLICACIONES EN WINDOWS. Windows 95 ha sido diseñado para tomar las ventajas de las nuevas tecnologías de hardware y software. Entre las innovaciones más importantes de la programación con Windows 95 tenemos: API (Application Programming Interface) de 32 bit, compatible con la API soportada en Windows NT. Un modelo de memoria sin muchas de las restricciones de versiones anteriores de Windows, lo que significa que las cadenas ya no están limitadas a 65.535 caracteres, pudiendo alcanzar casi los 2 billones de caracteres de longitud. La capacidad de incrustar objetos OLE entre la inmensa mayoría de aplicaciones Windows 95 con solo arrastrar y soltar. La adaptación de los controles OLE (OCXs) en lugar de los controles VBX para utilizarlos en programación. Optimización del registro central para almacenar información de las aplicaciones. Ésto sustituye a los ficheros INI utilizados en Windows 3.x para mantener información acerca del sistema y las aplicaciones. Optimización de la implementación de multimedia, incluyendo sonidos, gráficos y animaciones. Introducción de un nuevo modo de presentación de las aplicaciones, incluyendo la barra de tareas, controles de ficha y, ficheros de ayuda. Etc. 1.3.- LA PROGRAMACIÓN VISUAL Y GUIADA POR EVENTOS. Un programa realizado en DOS es un conjunto de sentencias que se ejecutan de arriba a abajo más o menos, en el orden que el programador ha diseñado. Una aplicación en Windows presenta todas las opciones posibles en uno o más formularios para que el usuario elija entre ellas. La secuencia en la que se ejecutarán las sentencias no puede ser prevista por el programador. Ésto da lugar a la Programación Orientada a Eventos. Para programar una aplicación en Windows hay que escribir código separado para cada objeto en general, quedando la aplicación dividida en pequeños procedimientos, conducido cada uno de ellos por un suceso. Un suceso es una acción reconocida por un objeto (formulario o control) el suceso puede ser causado por el usuario o, indirectamente por el código. En Visual Basic cada formulario y cada control tienen predefinidos un conjunto de sucesos. Cuando ocurren estos sucesos, Visual Basic invoca al procedimiento asociado con el objeto para ese suceso. Para desarrollar una aplicación en Visual Basic, los pasos que se seguirán son: 1.Crear la interfaz de usuario. 1.Modificar las propiedades de cada objeto. 1.Escribir el código asociado a los eventos de cada objeto. 1.4.- EL ENTORNO VISUAL BASIC. Los elementos que componen la pantalla de Visual Basic son: Barra de menús. Visualiza las órdenes que se utilizan para desarrollar, probar y archivar una aplicación. Los menús que nos encontramos son: Archivo contiene las órdenes para trabajar con archivos. Edición contiene las herramientas que ayudan a escribir el código. Ver da acceso rápido a todas las partes del programa. Insertar permite incluir nuevos módulos y formularios en la aplicación. Ejecutar permite verificar la aplicación mientras se desarrolla. Herramientas controla el aspecto y propiedades del entorno. Complementos contiene las utilidades para el manejo de bases de datos. Ayuda. Ventana o barra de herramientas. Facilita el uso a las órdenes más comunes. De izquierda a derecha los iconos que aparecen permiten: Formulario crear un nuevo formulario. Modulo crear un nuevo módulo. Se utiliza para crear fragmentos de código independiente del formulario. Abrir Project permite abrir un proyecto. Guardar Proyecto permite guardar un proyecto. Bloquear Controles impide que se muevan los controles del formulario involuntariamente. Editor de Menús visualiza la ventana de diseño de menús. Propiedades visualiza la ventana de propiedades de los distintos objetos. Examinador de Objetos muestra las clases, métodos, propiedades, etc. de los objetos disponibles en la aplicación. Proyecto visualiza la ventana de proyecto. Inicio. Interrumpir. Terminar. Alternar Puntos de Ruptura. Inspección Instantánea visualiza el valor del elemento seleccionado en la ventana de código. Llamadas visualiza la estructura de llamadas activas. Paso a Paso por instrucciones. Paso a Paso por procedimientos. Caja de herramientas. Provee de un conjunto de herramientas que permiten colocar los controles en el formulario durante el diseño del proyecto. Ventana de proyecto. En esta ventana están especificados los ficheros (formularios, módulos, etc.) que forman la aplicación y, dónde se seleccionarán para crearlos o modificarlos. Esto se debe a que hay ficheros que pueden utilizarse en más de una aplicación. Además contiene dos botones: Ver Formulario que visualiza el formulario seleccionado y; Ver Código que visualiza el código del fichero seleccionado. Ventana del formulario. Es la ventana que da lugar a la interfaz de usuario. Es la ventana que se personalizará. Los puntos que aparecen sobre el formulario, forman una rejilla que ayuda a la hora de alinear los controles que se sitúan sobre el mismo. Esta rejilla desaparece en tiempo de ejecución. Para eliminarla en tiempo de diseño se accederá a la opción Herramientas/Opciones/Ficha Entorno/Mostrar Cuadrícula. Ventana de propiedades. Especifica las propiedades de cada uno de los objetos. En cada momento mostrará las propiedades del objeto seleccionado en el formulario. Está formada por dos partes: la lista desplegable de objetos que visualiza el nombre del objeto seleccionado y, la lista de propiedades del objeto seleccionado. ¿QUÉ SUCEDE AL EJECUTAR UNA APLICACIÓN VISUAL BASIC? Los eventos que tendrán lugar a la hora de ejecutar una aplicación son: 1.Form_Initialize 1.Form_Load 1.Form_Resize 1.Form_Activate 1.Form_GotFocus 1.Form_Paint (solo en el caso de que la propiedad AutoRedraw del formulario esté establecida a False) y, antes de descargar un formulario de memoria, los eventos que tienen lugar son: 1.Form_Terminate 1.Form_Unload ¿CÓMO FUNCIONA UNA APLICACIÓN VISUAL BASIC? Normalmente, se escribe código a los eventos a los que se quiera dar respuesta. Si el evento no tiene respuesta o no se produce, Visual Basic no hará nada, es decir no se ejecutará código alguno. Para poder ejecutar código, se tendrá que haber dado respuesta a algún evento de algún control y, que dicho evento tenga lugar. ¿ES VISUAL BASIC 4.0 ORIENTADO A OBJETOS? Visual Basic 4.0 es la primera versión realmente orientada a objetos. Cumple los tres conceptos clave: Encapsulación: La utiliza de manera diferente a C++. Los objetos Visual Basic tienen propiedades como color, tamaño, tipo de letra y, además incorporan unos métodos que responden a mensaje como clics de ratón, pulsación de teclas, etc. En los que se puede integrar código. Polimorfismo: Capacidad de reaccionar de manera distinta ante un mensaje idéntico, dependiendo del objeto que lo reciba, p.e. un clic del ratón recibido por un botón de comando o por una caja de texto. Herencia: Capacidad de derivarse a partir de otro objeto. 2.1.- CONCEPTO DE PROYECTO. Dado que es muy común en aplicaciones Visual Basic compartir código o formularios personalizados, Visual Basic organiza las aplicaciones en lo que denomina proyectos. Cada proyecto puede tener varios formularios y, el código que activa los controles de un formulario es archivado con el formulario en archivos separados. El código general compartido por todos los formularios de una aplicación puede ser dividido en varios módulos, que también se archivan separadamente. En Visual Basic 4.0 un proyecto puede tener, además, módulos de clase y ficheros de recursos. Aunque Visual Basic almacena separadamente los archivos que forman un proyecto, hace un seguimiento de dónde están los archivos. Crea un archivo con la extensión .VBP de Visual Basic Program/Project. Visual Basic permite tener un solo proyecto abierto en un momento determinado. Los formularios se archivan con la extensión .FRM y contienen una imagen del formulario y, de todos los controles que pertenecen a él, incluidas sus propiedades. También pueden contener subrutinas de manejo de eventos, procedimientos generales, declaraciones de variables y de constantes a nivel de formulario y, procedimientos externos. Un módulo estándar contiene código Visual Basic que no está asociado a ningún formulario en particular. Los procedimientos que se encuentran en el módulo, pueden ser accedidos desde cualquier otro procedimiento de la aplicación. Se almacenan con la extensión .BAS. Los módulos de clase tienen la extensión .CLS y contienen código, incluido subrutinas, funciones, métodos y procedimientos para crear descripciones genéricas de objetos. Estos módulos contienen propiedades que describen el comportamiento de una clase, así como el código que define las propiedades y los métodos de la clase. Los archivos de recursos se almacenan con la extensión .RES y contienen bitmaps, cadenas de texto, o cualquier otra información que pueda ser cambiada sin tener que reeditar el código de la aplicación. Un proyecto solo puede contener un archivo de recursos. 2.2.- FORMULARIOS Y CONTROLES. PROPIEDADES COMUNES Después de arrancar Visual Basic, aparece un proyecto y un formulario por defecto. Si se quiere iniciar un nuevo proyecto, se accederá a Archivo/Nuevo Proyecto, o bien se abrirá un proyecto existente. EJEMPLO: Realizaremos el primer programa en Visual Basic. Para ello, una vez arrancado Visual Basic mostraremos la ventana de código, para lo que se hará doble clic en cualquier parte del formulario. En la ventana que aparece se escribirá el código Visual Basic. Esta ventana está formada por las siguientes partes: En la parte superior encontramos a la izquierda una lista desplegable correspondiente a los objetos del formulario (en este caso ninguno) y, precedido por Objeto. A la derecha la lista desplegable que aparece corresponde a la lista de procedimientos y viene precedido por Procedimiento. Esta lista muestra todos los procedimientos que puede reconocer el objeto Visual Basic que se encuentra en la lista Objeto. En la parte inferior y, con fondo blanco, se encuentra la zona de escritura de código donde se escribirá el código. En este momento aparece la plantilla de procedimiento para un suceso. Private Sub Form_Load() End Sub Supongamos que queremos escribir un mensaje cada vez que se haga clic en el formulario. Para ello cambiaremos el procedimiento seleccionando, para el objeto Form, el suceso Clic. Una vez seleccionado, se escribirá: Private Sub Form_Click() Print "Has hecho un clic con el ratón" End Sub Para ejecutar la aplicación pulsaremos F5 y, cuando se haga clic sobre el formulario, aparecerá el mensaje. Para detener la aplicación, pulsaremos el botón de Parada o, Ejecutar/Terminar. Por lo general, los procedimientos de suceso asociados a un formulario empiezan por: Private Sub Form_NombreDelSuceso() Para situar un control en el formulario tenemos dos formas: 1.Se hace clic sobre la caja de herramientas, sobre el control a situar. Se lleva el puntero del ratón al formulario. Se dibuja un rectángulo del tamaño que será el control. 1.Hacer doble clic sobre el control a situar. EJEMPLO: La aplicación que vamos a realizar estará formada por una caja de texto y un botón de comando. Para ello los pasos a seguir son: De la caja de herramientas seleccionamos el control Caja de texto, indicado por ab| y, lo situamos en la esquina superior izquierda del formulario. Ahora seleccionamos el botón de comando (2ª fila, control más a la derecha) y lo situamos a la derecha de la caja de texto. Modificaremos las propiedades de los controles. El botón debe visualizar "Presióname", para lo cual modificaremos las propiedades del botón. Una vez visualizada la ventana de propiedades del botón (con el icono, con F4 o desde Ver/Propiedades) seleccionaremos la propiedad Caption y cambiaremos el texto por "Presióname". Como valor de la propiedad Name asignaremos cmdPrimerBoton. A la caja de texto cambiaremos el valor de la propiedad Name para que muestre txtPrimeraCaja. La propiedad Text la dejaremos vacía. Supongamos que queremos escribir en la caja de texto un mensaje de bienvenida. Para ello cambiaremos el procedimiento seleccionando, para el objeto cmdPrimerBoton, el suceso Clic. Una vez seleccionado, se escribirá: Private Sub cmdPrimerBoton _Click() txtPrimeraCaja.Text = "Bienvenido a Visual Basic" End Sub GUARDAR FORMULARIOS, MÓDULOS Y PROYECTOS En el menú Archivo tenemos 4 opciones para guardar: Guardar Proyecto Guarda todos los archivos asociados con el proyecto actual. Guardar Proyecto Como... Se puede escoger un nuevo nombre para el proyecto actual y guarda todos los archivos asociados con el proyecto actual. Guardar Archivo Guarda el formulario o módulo actual. Guardar Archivo Como... Se puede escoger un nuevo nombre para el formulario/módulo actual. EJEMPLO: Modificaremos la aplicación para que, cuando el usuario escriba en la caja de texto, en el botón aparezca el mensaje "Restaurar mensaje". Para ello mostraremos la ventana de código asociada a la caja de texto haciendo doble clic sobre ella. El evento que se produce cuando el usuario escribe en una caja de texto es Change, por lo que el código a escribir será: Private Sub txtPrimeraCaja _Change() cmdPrimerBoton.Caption = "Restaurar mensaje" End Sub EJERCICIO: Modificaremos la aplicación para que, una vez restaurado el mensaje, en el botón de comando vuelva a aparecer el texto "Presióname". Como se ha podido apreciar, la forma de referirse a una propiedad es Objeto.Propiedad, donde Objeto es el nombre del formulario o del control (valor de la propiedad Name) y Propiedad es el nombre de la propiedad a la que se quiere acceder. PROPIEDADES MÁS COMUNES DE LOS FORMULARIOS AutoRedraw (Redibujado automático) Gestiona la manera de redibujar las imágenes en pantalla. Puede tomar los valores True/False. BackColor (Color de fondo) Determina el color de fondo. BorderStyle (Estilo del borde) Solo se puede determinar en modo de diseño. Modifica el borde del formulario en el momento de ejecución. Puede tomar los siguientes valores: 0 - None La ventana del formulario no tiene borde 1 - Fixed Single Tamaño fijo con borde no dimensionable. Puede incluir menú de control, barra de título, botón de maximizar y botón de minimizar. 2 - Sizeable Valor por defecto. 3 - Fixed Dialog Tamaño fijo del borde, no dimensionable. Puede incluir menú de control, barra de título. No puede incluir botón de maximizar y botón de minimizar. 4.- Fixed ToolWindow Bajo aplicaciones de 16 bits o Windows NT 3.51 o anteriores funciona como Fixed Single, sin visualizar los botones de maximizar y minimizar. Con Windows 95 visualiza el botón de cerrar y, no aparece en la barra de tareas. 5.- Sizeable ToolWindow Bajo aplicaciones de 16 bits o Windows NT 3.51 o anteriores funciona como Sizeable, sin visualizar los botones de maximizar y minimizar. Con Windows 95 visualiza el botón de cerrar y, no aparece en la barra de tareas. Caption (Leyenda) Establece el texto de la barra de título de la ventana del formulario. Esta propiedad indica lo que el usuario visualiza. No confundir con la propiedad Name. Propiedad común a muchos controles. ControlBox (Cuadro de control) Tiene efecto en tiempo de ejecución. Puede tomar los valores True/False. Permite visualizar o no tanto el menú de control como el botón de cerrar en Windows 95. Enabled (Habilitado) El valor False hace que el formulario no responda a eventos. Font (Fuente) Determina el tipo de letra, atributos, etc. para impresión. El texto ya escrito no se verá afectado por un cambio en estas propiedades, pero sí el texto impreso posteriormente. Height, Width (Ancho y Alto) Determinan la anchura y altura del formulario. Se miden en Twips (1/20 punto o lo que es lo mismo, 567 twips en 1 centímetro) Determinan el tamaño del formulario cuando se imprima, no cuando sea visualizado en pantalla. A menos que el usuario modifique el borde cambiando la propiedad BordeStyle, el usuario podrá modificar el tamaño y la forma de los diversos formularios de la aplicación sin tener en cuenta esta propiedad. Icon (Icono) Representa al formulario cuando esté minimizado o cuando se convierta en una aplicación independiente en el escritorio de Windows. Left, Top (Izquierda, Arriba) Determinan la posición del formulario dentro de la pantalla. Funcionan de manera idéntica a las propiedades Height y Width descritas anteriormente. Se miden en twips. MaxButton, MinButton (Botones de maximizar y minimizar respectivamente) El valor de esta propiedad (True/False) será ignorado si se ha establecido la propiedad BorderStyle a 0 - None. Solo es visible en tiempo de ejecución. MousePointer (Puntero del ratón) Determina la forma en que se mostrará el puntero del ratón. Name (Nombre) Propiedad MUY importante y común a todos los objetos de Visual Basic. Define el nombre del objeto en el código del programa. Para poder acceder a un control habrá que hacerlo a partir de su nombre. No disponible en tiempo de ejecución. Picture (Dibujo) Dibuja una imagen en el formulario (bitmap) Visible Determina si un formulario estará visible o no en tiempo de ejecución. WindowState (Estado de la ventana) Determina la forma en la que aparece el formulario durante la ejecución. ScaleMode (Modo de la escala) Permite cambiar las unidades de medida empleadas en el sistema de coordenadas interno del formulario. ScaleHeight, ScaleWidth (Escala de la Altura y la Anchura) Sirven para establecer una escala propia para la altura y anchura del formulario. Tiene efecto colateral sobre la propiedad ScaleMode, que se establece a 0. ScaleLeft, ScaleRight (Escala de Izquierda y Derecha) Sirven para establecer una escala propia para los márgenes izquierdo y superior del formulario. El valor original de estas propiedades es 0. PROPIEDADES COMUNES DE LOS CONTROLES Los controles que se pueden incluir en el formulario aparecen en la caja de herramientas. No es necesario recordar la posición o forma de cada control. En Visual Basic 4.0, cuando el cursor se sitúa sobre un control de la caja de herramientas, aparece una pista recordando el control que permite crear. Todos los controles tienen algunas propiedades comunes como pueden ser: Caption (Leyenda) Establece el texto que el usuario visualizará. No confundir con la propiedad Name. Text (Texto) Actúa igual que la propiedad Caption para aquellos controles que no dispongan de dicha propiedad, p.e. las cajas de texto. Muestra el contenido del control y, por tanto, también contiene los caracteres introducidos por el usuario. No confundir con la propiedad Name. Name (Nombre) Propiedad MUY importante. Define el nombre del control en el código del programa. No confundir con las propiedades Caption o Text que es lo que el usuario visualiza. TabStop (Punto de Tabulación) Si el valor es True, el control será susceptible de recibir el foco durante la ejecución de la aplicación. TabIndex (Índice de tabulación) Indica el número de orden en el que el control recibirá el foco cuando el usuario, en tiempo de ejecución, pulse la tecla Tab para recorrer los controles. A medida que se van situando controles en el formulario, Visual Basic incrementa en una unidad, el valor de esta propiedad para el nuevo control y, lo decrementa en caso de eliminar algún control. El valor para el primer control es 0. PROPIEDADES DE LOS BOTONES DE COMANDO Command Button (2ª fila, icono de la derecha). Se utiliza para ejecutar la acción asociada a la pulsación de dicho botón. Enabled (Habilitado) El valor False hace que el botón aparezca atenuado y, no responda a eventos. Cancel (Cancelar) Establecer el valor de esta propiedad a True, hace que el botón responda a la pulsación de la tecla ESC como si se hubiera hecho clic sobre él. En un formulario solo puede haber un botón con esta propiedad establecida a True. Default (Defecto) Establecer el valor de esta propiedad a True, hace que el botón responda a la pulsación de la tecla INTRO como si se hubiera hecho clic sobre él. Al igual como antes, en un formulario solo puede haber un botón con esta propiedad establecida a True. PROPIEDADES DE LAS CAJAS DE TEXTO Text Box (2ª fila, icono de la izquierda). Es un área dentro del formulario donde el usuario puede escribir texto o visualizarlo. MaxLength (Tamaño máximo) Determina el número máximo de caracteres que puede aceptar la caja de texto. MultiLine (Líneas Múltiples) Permite que la caja de texto admita varias líneas con la pulsación de la tecla INTRO. Normalmente se combina con la propiedad ScrollBars. ScrollBars (Barras de desplazamiento) Controla si en la caja de texto aparecerán las barras de desplazamiento o no. PasswordChar (Carácter clave) Permite mostrar un carácter clave en vez de los introducidos por el usuario. Locked (Bloqueada) Permite bloquear la caja de texto para que el usuario en tiempo de ejecución, no modifique el contenido de la caja. Esta propiedad es nueva en Visual Basic 4.0 SelLength (Longitud del texto seleccionado) Número de caracteres seleccionado actualmente. Accesible durante la ejecución. SelStart (Comienzo de la selección) Indica dónde comienza el texto seleccionado (la posición del cursor). Si el valor es 0, el texto seleccionado empieza delante del primer carácter de la caja de texto. Si es igual a la longitud del texto de la caja, indica la posición detrás del último carácter del texto. Accesible en tiempo de ejecución. SelText (Texto seleccionado) Contiene el texto seleccionado. Accesible en tiempo de ejecución. PROPIEDADES DE LAS ETIQUETAS Label (1ª fila, icono de la derecha). Es un área dentro del formulario donde el usuario puede visualizar texto sin modificarlo. Alignment (Alineación) Determina la situación del texto dentro de la etiqueta. AutoSize, WordWrap (Tamaño automático y enlace de textos) La primera propiedad permite que la etiqueta crezca horizontalmente en función de su contenido. La segunda propiedad permite que el crecimiento sea vertical. EJERCICIOS: 1.Crear una aplicación que traslade el contenido de lo que el usuario escriba en una caja de texto a otra, que será solo de lectura. 1.Crear una aplicación para que al pulsar un botón, muestre en una caja de texto, un mensaje de presentación. Al pulsar otro botón, se debe borrar el contenido de la caja de texto. 1.Crear una aplicación con las siguientes características: en la barra de título del formulario debe aparecer el texto "Modificando las propiedades"; muestre una caja de texto inicialmente vacía; se visualicen tres botones de comando: uno con el texto "Haga clic aquí", otro con el texto "?" y, el tercero con el texto "Salir". Cuando se pulse el botón "Haga clic aquí", se mostrará en la caja de texto, el nombre del programador. Al pulsar el botón "?", se mostrará el mensaje "¿Contento?" y, al pulsar el botón "Salir", finalice la aplicación. Inicialmente, el botón "?" estará desactivado y se activará al pulsar el botón "Haga clic aquí". INTERACCIÓN CON EL USUARIO Para permitir al usuario introducir valores, se utilizan las cajas de texto, pero en un momento determinado, puede interesar la detención momentánea de la ejecución y, mostrar un cuadro de diálogo para que el usuario introduzca algún dato. Del mismo modo, se puede mostrar un cuadro de mensaje al usuario para advertirle de cualquier circunstancia. Para ambos casos tenemos respuesta en Visual Basic. Variable_de_cadena = InputBox("Pregunta_a_realizar" [," Título_Caja", Valor_por_Defecto]) MsgBox("Mensaje_a_mostrar", Tipo_Caja, "Título_Caja") donde el parámetro Tipo_Caja permite controlar el icono y los botones que aparecerán en el cuadro de mensajes. EJERCICIO: Crear una aplicación que pregunte al usuario su nombre y, una vez contestado, le dé la bienvenida. PROPIEDADES DE LOS CUADROS DE IMAGEN Image (1ª fila, icono central). Se utiliza cuando se quiere visualizar una imagen que el programador dibuja con código o que importa de algún fichero. Picture (Imagen) Establece la imagen que el usuario verá en el cuadro de imagen. Stretch (Extensión) Determina si el control de imágenes se ajusta a la imagen o, es la imagen la que se ajusta al tamaño del control. El valor True hace que el cuadro de imágenes se ajuste al tamaño de la imagen, mientras que el valor False, hace que sea la imagen la que se ajuste. PROPIEDADES DEL CONTROL IMAGEN Picture Box (7ª fila, icono de la izquierda). Se utiliza cuando se quiere visualizar una imagen que el programador dibuja con código o que importa de algún fichero. Se diferencia de la caja de imágenes en la forma de presentación. Picture (Imagen) Establece la imagen que el usuario verá en el cuadro de imagen. AutoSize (Extensión) Determina si el control de imágenes se ajusta a la imagen o, es la imagen la que se ajusta al tamaño del control. El valor True hace que el control imagen se ajuste al tamaño de la imagen, mientras que el valor False (valor por defecto), hace que sea la imagen la que se ajuste. PROPIEDADES DEL CONTROL DE FORMAS O FIGURAS Shape (6ª fila, icono central). Se utiliza para añadir rectángulos, cuadrados, elipses o círculos a un formulario. Shape (Forma) Determina el tipo de formas que se dibujará. BackStyle (Color de fondo) Determina si el fondo será transparente o no. BorderColor (Color del borde) Determina el color del contorno del objeto a dibujar. BorderWidth (Ancho del borde) Determina el grosor del contorno del objeto a dibujar. BorderStyle (Estilo del borde) Determina la forma del contorno del objeto a dibujar. Si el valor de la propiedad BorderWidth es mayor que uno, no tendrá efecto el valor de esta propiedad. FillColor, FillStyle (Color de fondo y estilo de relleno) El valor por defecto de la propiedad FillStyle es 1 - Transparent, por lo que si no se cambia, el valor de la propiedad FillColor no tendrá efecto. EJEMPLO: Crearemos una aplicación que encienda y apague una bombilla al mismo tiempo que en un botón de comando el mensaje que aparece cambia a ON y OFF. Se debe añadir un botón con el mensaje Salir. El formulario a diseñar deberá tener los siguientes controles con las propiedades: CONTROL PROPIEDAD VALOR Command Button Caption Salir Name cmdSalir Command Button Caption ON Name cmdOnOff Picture Box BorderStyle 0-None Name picOff Picture vb\icons\misc\Lightoff.ico Picture Box BorderStyle 0-None Name PicOn Picture vb\icons\misc\Lighton.ico El código a escribir será: Private Sub Form_Initialize() 'Centrar el formulario Left = (Screen.Width - F.Width) / 2 Top = (Screen.Height - F.Height) / 2 'Posicionar las linternas en la misma posición picOn.Left = 1200 picOn.Top = 600 picOff.Left = 1200 picOff.Top = 600 'Asegurarse que el programa empieza con la linterna apagada picOff.Zorder 0 End Sub Private Sub cmdClose_Click() 'Finalizar la aplicación Unload cmdClose.Parent End Sub Private Sub cmdOnOff_Click() 'Cambiar la linterna de ON a OFF o viceversa If cmdOnOff.Caption = "ON" Then cmdOnOff.Caption = "OFF" 'Traer la linterna encendida delante picOn.ZOrder 0 Else cmdOnOff.Caption = "ON" 'Traer la linterna apagada delante picOff.ZOrder 0 End If End Sub PROPIEDADES DE LOS CUADROS DE LISTA List Box (4ª fila, icono izquierdo) Permite ofrecer al usuario una serie de opciones para que elija. 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. El contenido de un cuadro de lista no se puede definir durante el diseño. En su lugar se utilizará el método AddItem para introducir elementos en la lista. List (lista) Esta propiedad no se puede modificar en fase de diseño, contiene la matriz de todos los valores almacenados en el cuadro de lista. Para acceder a un elemento de la lista se seguirá la sintaxis: Objeto.List(índice). ListCount (contar lista) No puede modificarse directamente. Contiene el número de elementos del cuadro de lista. ListIndex (índice de la lista) Indica el número de la lista más recientemente seleccionado. El valor del primer elemento es 0, el del segundo, 1, y así sucesivamente. Si no hay ningún elemento seleccionado, la propiedad tendrá un valor de -1. Sorted (ordenada) Para mantener la lista ordenada alfabéticamente. Text (texto) No se puede modificar directamente, contiene el texto del elemento más recientemente seleccionado. Los métodos utilizados con los cuadros de lista son: AddItem (añadir elemento) permite insertar una línea de texto en el cuadro de lista. Su sintaxis es objeto.AddItem texto[, índice] . Clear (borrar) sirve para eliminar todos los elementos del cuadro de lista. Su sintaxis es: objeto.Clear. RemoveItem (eliminar elemento) permite eliminar una línea del cuadro de lista. Su sintaxis es: objeto.RemoveItem índice. PROPIEDADES DE LOS CUADROS COMBINADOS Combo Box (3ª fila, icono derecho) Puede combinar un cuadro de texto y un cuadro de lista en un solo control. Style (estilo) Determina el tipo de cuadro combinado y cómo se comporta. Puede tomar los siguientes valores: 0 - Dropdown Combo; 1 - Simple Combo; 2 - Dropdown List. Text (texto) Contiene el texto del elemento seleccionado o introducido por el usuario en el área de edición. Los procedimientos descritos en el apartado anterior sirven para este tipo de control. Ambos tipos de control permiten asociar a los elementos del listado un número entero. Para ello se debe utilizar la matriz ItemData, que es una propiedad de estos controles. Para añadir los datos numéricos a esta matriz, se debe conocer el índice matriz del elemento, para lo que se utilizará la propiedad NewIndex del control. Es decir, se necesitará escribir código parecido a: Listado1.AddItem Elemento_A_Añadir Listado1.ItemData(Listado1.NewIndex) = Datos_Del_Entero > ¡Transferencia interrumpida! B> 2.3.- PROCEDIMIENTOS DE EVENTO En Visual Basic existen dos clases de procedimientos: procedimientos generales o procedimientos de evento. Un procedimiento de evento es invocado cuando un objeto en la aplicación reconoce que el evento ha tenido lugar. Los procedimientos de eventos para un control combinan el nombre del objeto con un subrayado y, el nombre del evento. P.e. cmdOK_Click. Los procedimientos de eventos para un formulario combinan la palabra reservada Form con un subrayado y, el nombre del evento. P.e. Form_Load. Los procedimientos de eventos para un formulario MDI combinan la palabra reservada MDIForm con un subrayado y, el nombre del evento. P.e. MDIForm_Unload. Un procedimiento general indica cómo realizar una tarea determinada. Se ejecutará solo si es invocado específicamente en la aplicación. 3.1.- VARIABLES Y CONSTANTES: DECLARACIÓN, TIPOS, ÁMBITO Y DURACIÓN. Las variables en Visual Basic no necesitan ser declaradas, en el momento en que son necesitadas pueden aparecer en el código. Sin embargo, puede ser útil el exigir la declaración de todas las variables que aparezcan en el código. Para ello, se utilizará la instrucción: Option Explicit en la sección de declaraciones del formulario. Una vez procesada esta instrucción, no se permitirán variables no declaradas. Para declarar una variable la instrucción adecuada es: Dim Nombre_Variable [As Tipo] donde Tipo puede ser: TIPO DESCRIPCIÓN TAMAÑO OCUPADO IDENTIFICADOR String Carácter 1 Byte por carácter $ Integer Entero 2 Bytes % Long Entero largo 4 Bytes & Single Real simple 4 Bytes ! Double Real doble 8 Bytes # Currency Moneda 8 Bytes @ Byte Byte * 1 Byte (ninguno) Boolean Booleano * 2 Bytes (ninguno) Date Fecha * 8 Bytes (ninguno) Object Objeto * 4 Bytes (ninguno) Variant Variante Cualquiera de los anteriores * Nuevos tipos en Visual Basic 4.0 Para declarar una constante se necesita la instrucción: Const Nombre_Constante = Expresión Hay dos tipos de constantes: Intrínsecas o definidas por el sistema, proporcionadas por Visual Basic o cualquier otra aplicación que provee una librería de objetos. Para ver una lista de estas constantes, se accederá a Ver/Examinador de Objetos. En la lista desplegable superior, se seleccionará VB-Objects and Procedures. De la lista de la izquierda se hará doble clic en cualquier opción acabada en Constants. Simbólicas o definidas por el usuario. Es una buena idea el declarar las constantes simbólicas con el prefijo con, p.e. Const conPi = 3.141592 ÁMBITO DE LAS VARIABLES EN VISUAL BASIC Se entiende por ámbito de una variable el espacio de la aplicación donde la variable es visible y por tanto se puede utilizar. Los distintos alcances que puede tener una variable declarada en Visual Basic son: 1.Las variables declaradas con Dim o utilizadas directamente en un procedimiento, son variables locales, es decir, accesibles solamente desde el procedimiento que las declara. 1.Si las variables se declaran en la sección de declaraciones del formulario o del módulo, son variables a nivel de formulario o de módulo. Una variable declarada a nivel de formulario es accesible desde cualquier procedimiento del formulario y lo mismo para las variables a nivel de módulo: una variable declarada a nivel de módulo es accesible desde cualquier procedimiento de ese módulo, pero no desde otros módulos. Estas variables se declaran con Dim o Private. 1.Las variables públicas son declaradas en la sección de declaraciones de un módulo con la sentencia Public y, podrán ser accesibles desde cualquier módulo. EJEMPLO: Crear un formulario con dos botones de comando (cmdInicio y cmdParada), tres etiquetas (lblHInicio; lblHParada y lblTTranscurrido) y, tres cajas de texto (txtHInicio, txtHParada, txtTTranscurrido). Inicialmente, el botón cmdParada estará desactivado. Se pretende que, cuando el usuario pulse el botón cmdInicio, en la caja de texto asociada a la etiqueta lblHInicio, aparezca la hora actual y, al mismo tiempo, se active el botón cmdParada y se desactive el de cmdInicio. Al pulsar el botón cmdParada, se mostrará la hora de parada, el tiempo transcurrido, se desactivará el botón de cmdParada y, se habilitará el de cmdInicio. El código asociado será: Private Sub cmdInicio_Click() HInicio = Now txtHInicio.Text = Format$(HInicio; "hh:mm:ss") cmdInicio.Enabled = False cmdParada.Enabled = True End Sub Private Sub cmdParada_Click() HParada = Now Tiempo = HParada - HInicio txtHParada.Text = Format$(HParada; "hh:mm:ss") txtTTranscurrido.Text = Format$(Tiempo; "hh:mm:ss") cmdInicio.Enabled = True cmdParada.Enabled = False End Sub En este ejemplo se deben declarar las variables HoraInicio, HoraParada y Tiempo como variables a nivel de formulario (en la sección de declaraciones del formulario) para que sean accedidas desde cualquier procedimiento asociado al formulario. Por tanto, el ámbito de una variable determina qué procedimientos podrán acceder a esa variable. Cualquier sentencia Dim declarada en cualquier procedimiento tiene preferencia con respecto a variables declaradas a nivel de módulo. Siempre que una variable aparece por primera vez, es inicializada al valor por defecto (0 para variables numéricas y cadena vacía para tipo String) Para que una variable mantenga el valor en cada ejecución del procedimiento donde se utiliza, se debe declarar con la instrucción: Static Nombre_Variable [As Tipo] Se mantiene la palabra reservada Global por compatibilidad de la versión 3.0, pero es preferible utilizar la palabra reservada equivalente: Public. EJERCICIOS: 1.Crear un formulario con tres cajas de texto, un botón de comando y una etiqueta. La aplicación debe sumar los dos valores introducidos por el usuario y, mostrarlos en la 3ª caja de texto. La aplicación debe estar preparada para que, la caja de texto que muestre el resultado, no pueda ser accesible al pulsar la tecla TAB. 1.Modificar el ejercicio anterior para que, el usuario pueda escoger la operación aritmética a realizar. TIPOS DEFINIDOS POR EL USUARIO Se pueden definir tipos por parte del usuario para crear registros (structs en C, Record en Pascal). Un registro puede definirse como una colección de datos de diferentes tipos relacionados entre sí. Para crear un registro se necesita la sentencia Type ... End Type. Esta sentencia solo puede aparecer en la sección de declaraciones de un módulo estándar y pueden ser declarados como Private o Public. P.e: Type Ficha Nombre As String Dirección As String * 40 Teléfono As Long DNI As Long End Type Una vez definido un tipo de datos, se pueden declarar variables del mismo tipo. P.e: Dim Alum As Ficha Para refererirse a un determinado campo del registro, se utiliza la notación variable.campo P.e: Alumno.Nombre. Un tipo definido por el usuario no puede contener un array dinámico, pero sí estático. EJERCICIOS: 1.Crear un formulario que permita actuar como un editor de texto haciendo una copia de texto o moviéndolo a otra posición. La aplicación debe tener un botón que permita borrar el contenido de la caja de texto, un botón que permita cortar el texto seleccionado, un botón que permita copiar el texto seleccionado y un botón que permita pegar el texto. La aplicación debe estar preparada para que no se pueda pegar texto si antes no se ha copiado/cortado texto. Pistas: utilizar una caja de texto multilínea y, las propiedades SelStart, SelLength y, SelText para copiar o cortar. La propiedad Enabled para activar/desactivar los botones. 1.Crear una aplicación que permita almacenar la información de 5 empleados, cada uno de ellos con la siguiente información: nombre, sueldo, fecha de ingreso. EJEMPLO: Crear un formulario que actúe como un reloj despertador, de forma que visualice la hora actual y, si el usuario ha activado la alarma, cuando la hora actual sea la misma que la alarma, se debe emitir un pitido. Para ello, añadiremos los siguientes controles al formulario. CONTROL PROPIEDAD VALOR Label Caption (ninguno) Name lblPantalla BorderStyle 1-Fixed Single Label Caption Alarma Text Box Text (ninguno) Name txtAlarma Option Button Caption Alarma On Name optAlarmaOn Option Button Caption Alarma Off Name optAlarmaOff Value True Timer Interval 1000 Name tmrReloj Inicialmente, la alarma debe estar desactivada y no se permitirán valores distintos del carácter ':' o cualquier dígito. El código asociado será: Dim AlarmaOn As Boolean Private Sub txtAlarma_KeyPress(KeyAscii As Integer) Dim Key As String 'Comprobar que se escriben dígitos o el carácter : Key = Chr(KeyAscii) If (Key < "0" Or Key > "9") Then If Key <> ":" Then Beep KeyAscii = 0 End If End If End Sub Private tmrReloj_Timer() 'Comprobar si la alarma > hora actual If (Time >= txtAlarma.Text And AlarmaOn) Then Beep End If lblPantalla.Caption = Time End Sub Private optAlarmaOn_Click() AlarmaOn = True End Sub Private optAlarmaOff_Click() AlarmaOn = False End Sub EJERCICIO: Modificar el ejercicio anterior para que suene la alarma 5 segundos. NOTA: Cada vez que el usuario presiona una tecla, se generan los eventos KeyDown, KeyUp y KeyPress. El evento KeyPress devuelve el código ASCII de la tecla presionada. Los eventos KeyDown y KeyUp se producen cuando el usuario presiona o libera una tecla y reciben dos argumentos: KeyCode que mantiene el código ANSI de la tecla presionada y, Shift que indica el estado de las teclas Shift, Alt y Ctrl. FORMULARIOS MÚLTIPLES Los formularios múltiples añaden flexibilidad a las aplicaciones. Para poder acceder a un control en un formulario distinto del que contiene el foco, es necesario nombrar al control por su nombre completo, es decir, utilizando la sintaxis: Nombre_Formulario!Nombre_del_Control El formulario inicial en cualquier proyecto, se consigue accediendo al menú Herramientas/Opciones/Ficha Proyecto y, de la lista Formulario Inicial, escogeremos el nombre del formulario con el que se quiere iniciar la aplicación. Con cualquier formulario las operaciones posibles serán: Show (Mostrar) Sirve para mostrar en primer plano el formulario. La sintaxis es: Nombre_Formulario.Show Load (Cargar) Lleva a memoria el formulario, pero no lo visualiza. La sintaxis es: Load Nombre_Formulario Hide (Ocultar) Retira el formulario de la pantalla pero no lo descarga de memoria. La sintaxis es: Nombre_Formulario.Hide Unload (Descargar) Descarga de memoria el formulario, perdiéndose toda la información de sus variables. La sintaxis es: Unload Nombre_Formulario EJERCICIO: Crear una aplicación que muestre un formulario inicial preguntando la contraseña. Dicha contraseña no debe visualizarse en la pantalla. Si la contraseña es correcta, se mostrará un nuevo formulario que mostrará la hora y fecha actual y, tras introducir el usuario la fecha de su nacimiento, permita obtener los años vividos por esa persona. En caso que sea el cumpleaños, se debe felicitar al usuario. El número de intentos permitidos para introducir la contraseña es de tres. En caso de superar los intentos, el programa debe dar un mensaje de error al usuario y, tirarlo de la aplicación. 3.2.- SENTENCIAS DE CONTROL: BUCLES Y BIFURCACIONES BUCLES DETERMINADOS For Variable = Valor_Inicial To Ultimo_Valor [Step incremento] [Declaraciones] [Exit For] [Declaraciones] Next [Variable] BUCLES INDETERMINADOS Do [{While | Until} Condición] Do [Declaraciones] [Declaraciones] [Exit Do] [Exit Do] [Declaraciones] [Declaraciones] Loop Loop [{While | Until} Condición] TOMA DE DECISIONES SELECCIÓN SIMPLE SELECCIÓN MÚLTIPLE If Condición_1Then Select Case Condición_de_testeo Declaraciones_1 Case valor1 [ElseIf Condición_2 Then [Declaraciones_1] Declaraciones_2]... [Case valor2 [Else [Declaraciones_2]]... Declaraciones_n] [Case Else End If [Declaraciones_n]] End Select donde valor1,... puede tomar cualquiera de las siguientes formas: expresión1[, expresión2]... expresión1 To expresión2 Is operador_relacional expresión o cualquier combinación de las anteriores separadas por comas. EJEMPLO: Crear una aplicación que permita obtener el código ASCII de una tecla pulsada. Se necesita un botón que permita borrar la tecla anterior. Para ello, añadiremos los siguientes controles al formulario. CONTROL PROPIEDAD VALOR Label Caption Pulsa una tecla Name lblPulsaTecla Text Box Name txtPulsaTecla Text (ninguno) Label Caption Valor ASCII Name lblValor Label Caption (ninguno) Name lblResultado BordeStyle 1-Fixed single Command Button Caption Limpiar Name cmdLimpiar Default True Private Sub cmdLimpiar_Click() txtPulsaTecla.Text = "" lblResultado.Caption = "" txtpulsaTecla.SetFocus End Sub Private Sub Form_Activate() txtpulsaTecla.SetFocus End Sub Private Sub txtPulsaTecla_KeyDown(KeyCode As Integer, Shift As Integer) Const vbKeyDelete = 46 Const vbKeyInsert = 45 Const vbKeyEnd = 35 Select Case Keycode Case vbKeyDelete lblResultado.Caption = "Presionado Suprimir" txtpulsaTecla = "[[Suprimir] " Case vbKeyInsert lblResultado.Caption = "Presionado Insertar" txtpulsaTecla = "[Insertar] " Case vbKeyEnd lblResultado.Caption = "Presionado Fin" txtpulsaTecla = "[Fin] " Case Else End Select End Sub Private Sub txtPulsaTecla_KeyPress(KeyAscii As Integer) If txtPulsaTecla.Text <> "" Then txtPulsaTecla.Text = "" End If Select Case KeyAscii Case 8 txtPulsaTecla.Text = "[Retroceso] " Case 9 txtpulsaTecla = "[Tab] " Case 13 txtpulsaTecla = "[Intro] " Case Else End Select lblResultado.Caption = KeyAscii End Sub 3.3.- FUNCIONES BÁSICAS INCORPORADAS CONVERSIÓN DE TIPO DE DATOS CDbl(expresión) CInt(expresión) Conversión a tipo Doble. Conversión a tipo Integer. CLng(expresión) CDate(expresión) Conversión a tipo Long. Conversión a tipo Date. etc. FUNCIONES DE CALENDARIO DateSerial(expresión) IsDate(expresión) Devuelve el número de serie de la fecha indicada Verifica si un valor es del tipo Fecha/Hora. Date Time Devuelve la fecha actual. Devuelve la hora actual. Now Day(Núm_serie) Devuelve la fecha y hora actuales. Devuelve un entero entre 1 y 31. Month(Núm_serie) Year(Núm_serie) Devuelve un entero entre 1 y 12. Devuelve un entero entre 1753 y 2078. etc. FUNCIONES DE CADENA Space(Num_espacios) String(Número, expr_cadena) Crea una cadena formada por Num_espacios. Crea una cadena de caracteres repetidos. Mid(expr_cadena, Inicio[, Long] ) Left(expr_cadena, Número) Permite extraer subcadenas. Extrae los Número caracteres de la izquierda. Right(expr_cadena, Número) Instr([Inicio,] cadena_1, cadena_2) Extrae los Número caracteres de la derecha. Indica si cadena_2 está contenida en cadena_1 LCase(expr_cadena) UCase(expr_cadena) Convierte a minúsculas. Convierte a mayúsculas. StrComp(cadena_1, cadena_2) Trim(expr_cadena) Compara cadena_1 y cadena_2. Elimina los espacios del principio y final. RTrim(expr_cadena) LTrim(expr_cadena) Elimina los espacios del final. Elimina los espacios del principio. Format(expresión[, formato] ) Permite dar a una cadena o a un número un formato específico. EJEMPLO: Vamos a construir una aplicación que, al desplazarse el usuario con las teclas de cursor, se van iluminando los pixeles por los que pasa. Se necesitará un formulario para el área de dibujo con la propiedad AutoRedraw establecida a True. Finaliza al pulsar la tecla Fin Dim AlturaPixel As Single, AnchuraPixel As Single Dim XPunto As Single, YPunto As Single Private Sub Form_Load() AutoRedraw = True ScaleMode = 3 'Pixels AlturaPixel = ScaleHeight AnchuraPixel = ScaleWidth XPunto = AnchuraPixel / 2 YPunto = AlturaPixel / 2 End Sub Private Sub Form_Resize() AlturaPixel = ScaleHeight AnchuraPixel = ScaleWidth End Sub Private Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Dim sino As Integer Select Case KeyCode Case vbKeyLeft If XPunto <= 0 Then XPunto = 0 Else XPunto = XPunto - 1 End If Case vbKeyRight If XPunto >= AnchuraPixel Then XPunto = AnchuraPixel Else XPunto = XPunto + 1 End If Case vbKeyUp If YPunto <= 0 Then YPunto = 0 Else YPunto = YPunto - 1 End If Case vbKeyDown If YPunto >= AlturaPixel Then YPunto = AlturaPixel Else YPunto = YPunto + 1 End If Case vbKeyEnd sino = MsgBox("¿Estás seguro de que quieres terminar", 4) If sino = 6 Then End 'Clic en el botón Sí Case Else Beep End Select PSet (XPunto, Ypunto) 'Dibujar un punto End Sub EJERCICIOS: 1.Crear una aplicación que permita calcular la posición de los espacios en blanco de una cadena introducida por el usuario. 1.Crear una aplicación que, dada una frase, permita obtener el número de apariciones de cada vocal en la frase. El resultado debe aparecer indicado de forma clara. 1.Diseñar una aplicación que el usuario escoja entre introducir números o letras. Si escoge números, no se debe permitir introducir ninguna letra y, si escoge letras, no se debe permitir introducir ningún dígito. ELEMENTOS DEL LENGUAJE II 4.1.- ARRAYS Y FUNCIONES ASOCIADAS Un array permite referirse a una serie de elementos del mismo tipo por un mismo nombre y referenciar un único elemento de la serie utilizando un índice. Los arrays deben ser declarados explícitamente. ARRAYS ESTÁTICOS Para declarar un array estático, formado por un número fijo de elementos, Visual Basic utiliza una sintaxis parecida a la declaración de variables. Veamos algunos ejemplos: Dim Array_A(19) As String declara un array unidimensional de 20 elementos: Array_A(0), Array_A(1)... Dim Array_B(3, 1 To 6) As Integer declara un array bidimensional de 4x6 elementos: Array_B(0,1), Array_B(1,2)... ARRAYS DINÁMICOS Para declarar un array dinámico, formado por un número variable de elementos, Visual Basic utiliza una sintaxis parecida a la declaración anterior. El espacio necesario para un array dinámico será asignado durante la ejecución del programa. Un array dinámico puede ser redimensionado en cualquier momento durante la ejecución. Para redimensionarlos se utiliza la sentencia ReDim. Esta sentencia puede aparecer solamente en un procedimiento y permite cambiar el número de elementos del array, no el número de dimensiones. Por ejemplo: Dim Array_A() As String declara un array unidimensional dinámico. Más tarde, un procedimiento puede utilizar la sentencia ReDim para asignar el espacio, p.e. ReDim Array_A(4,4) Cada vez que se ejecuta la sentencia ReDim, todos los valores en el array se pierden. Cuando interese conservar los valores del array, se utilizará la sentencia ReDim Preserve. Sólo se puede cambiar el límite superior de la última dimensión. FUNCIONES ASOCIADAS LBound Devuelve el índice más bajo posible de un array. UBound Devuelve el índice más alto posible de un array. En general, la orden LBound(Nombre_Matriz, I) da el límite inferior para la dimensión Y (para un array unidimensional, la I es opcional). Por tanto, en el siguiente ejemplo: Dim Test%(1 To 5, 6 To 10, 7 To 12) Print LBound(Test%, 2) devuelve un 6 y, Print UBound(Test%, 3) devuelve un 12. Las órdenes LBound y UBound permiten copiar arrays de diferentes límites, siempre que el número total de filas y columnas sea el mismo. (Al sustraer LBound de UBound para cada dimensión, se puede comprobar si coinciden) EJERCICIOS: 1.Crear una aplicación que permita crear un cuadrado mágico. Un cuadrado mágico es aquel en el que todas las filas, columnas y diagonales principales suman lo mismo. Para resolver el ejercicio se utilizará el argumento de Loubère, que funciona solo con cuadrados mágicos impares: Colocar 1 en el centro de la primera fila. Los números se colocan en orden moviéndose hacia arriba en diagonal hacia la derecha. Si se sale por la parte superior se sustituye por el lugar correspondiente de la fila inferior. Si se sale por la derecha se sigue en la posición correspondiente de la columna izquierda. Si se llena el cuadrado o se alcanza la esquina superior derecha, desplazarse hacia abajo y continuar con las reglas. 17 24 1 8 15 23 5 7 14 16 4 6 13 20 22 10 12 19 21 3 11 18 25 2 9 2.Crear una aplicación que permita obtener el elemento mayor de una matriz cuadrada de dimensión cualquiera. Los elementos de la matriz serán números entre el 1 y el 1000 introducidos aleatoriamente. 4.2- FUNCIONES Y PROCEDIMIENTOS Para evitar duplicar código en los procedimientos de evento, se deben utilizar los procedimientos generales. Éstos deben escribirse como un procedimiento Sub o como una función Function. Cuando un procedimiento es llamado para su ejecución, Visual Basic lo busca en el formulario o en el módulo donde se encuentre en ese momento. Si no lo encuentra, continúa la búsqueda en el resto de los módulos de la aplicación. Para crear un procedimiento general, desde la ventana de código se accederá a Insertar/Nuevo Procedimiento. Las funciones en Visual Basic son declaradas en los módulos o en la sección de declaraciones de un formulario y devuelven un valor al procedimiento que la invocó. La sintaxis empleada es la siguiente: [Private | Public] [Static] Function nombre [(lista_argumentos) ] [As tipo] [Declaraciones] [nombre = expresión] [Exit Function] [Declaraciones] [nombre = expresión] End Function Los procedimientos generales necesitan ser invocados explícitamente para poder ser ejecutados. No devuelven ningún valor. La sintaxis para declarar procedimientos generales es: [Private | Public] [Static] Sub nombre [(lista_argumentos) ] [Declaraciones] [Exit Sub] [Declaraciones] End Sub donde: Public indica que el procedimiento es accesible desde otros procedimientos en cualquier módulo. Si se utiliza en un módulo privado, no estará disponible fuera del proyecto. Private indica que el procedimiento solo es accesible desde los procedimientos del módulo en que está declarado. Static indica que las variables locales al procedimiento mantendrán el valor entra llamadas al procedimiento. Lista_argumentos es una lista de los argumentos que se pasan al procedimiento. Los argumentos múltiples van separados por comas. Puede tomar la forma siguiente: [[Optional] [ByVal | ByRef] [ParamArray] varnombre [( )] As tipo] donde: Optional indica que el argumento no se necesita. Todos los argumentos opcionales deben ser de tipo Variant. ByVal indica que el argumento es pasado por valor. ByRef indica que el argumento es pasado por referencia. ParamArray utilizado para indicar que el argumento final es una lista opcional de argumentos. Proporciona una forma de pasar un número arbitrario de argumentos. No puede utilizarse con ByVal, ByRef o con Optional. La forma de llamar a una función es var = nombre_función([argumentos] ) La forma de invocar a un procedimiento es utilizando cualquiera de las dos formas siguientes: Call nombre_procedimiento[(argumentos)] nombre_ procedimiento [argumentos] PASO DE PARÁMETROS Por defecto, los argumentos son pasados por referencia.; de este modo cualquier cambio de valor que sufra un parámetro en el cuerpo de la función o del procedimiento también se produce en el argumento correspondiente de la llamada a la función o procedimiento. Cuando se llama a una función o a un procedimiento, se podrá especificar que el valor de un argumento sea pasado por valor, poniendo dicho argumento entre paréntesis en la llamada. Otra forma de especificar que un argumento será siempre pasado por valor es anteponiendo la palabra ByVal a la declaración del parámetro en la cabecera del procedimiento. EJERCICIOS: 1.Crear una aplicación que permita calcular el factorial de un número. Utilizar funciones o procedimientos. 1.Crear un procedimiento que permita separar en palabras una frase dada. 1.Crear un procedimiento que, dada una frase, permita devolver la misma frase invertida. 1.Obtener un procedimiento capaz de determinar si una palabra es palíndroma (capicúa). 1.Diseñar una aplicación que permita al usuario introducir valores en una lista desplegable y, obtenga la suma de dichos valores. 1.Crear una aplicación que permita al usuario escoger entre ordenar valores ascendente o descendentemente. Los valores se introducirán en una lista desplegable y, el resultado se mostrará en otra lista. Sólo se permite la introducción de valores numéricos. 1.Diseñar una aplicación que permita simular un tragaperras de forma que, cuando el usuario pulse el botón de jugar, se descuente de la cantidad introducida el valor de la jugada y, se muestren aleatoriamente las figuras del premio. Transcurrido unos segundos, las imágenes se deben detener y se procederá a comprobar si ha tocado premio, en cuyo caso se incrementará la cantidad ganada. 1.Diseñar una aplicación que utilice procedimientos para hacer el siguiente juego de palabras: Todas las palabras de una letra permanecen iguales. Las palabras que empiezan por vocal, se les añade el sufijo "way". Las palabras que empiezan por una cadena de consonantes se traslada la consonante al final y se les añade el sufijo "ay". Cualquier q movida por la regla anterior se lleva la u con ella. No hay más consonantes. 4.3- MATRICES DE CONTROLES Una Matriz de Controles es un grupo de controles que comparten el mismo nombre y tipo. A su vez, comparten los mismos procedimientos de eventos, pero son controles físicamente separados y cada uno posee su propio conjunto de propiedades. Una matriz de controles tiene al menos un elemento y no puede exceder de 254. Para crear una matriz de controles es suficiente con asignar el mismo nombre a dos o más controles (propiedad Name) durante el diseño de la aplicación, o bien asignar un valor a la propiedad Index de un control. En el último caso se genera una matriz de un solo elemento, lo cual es útil cuando se quieren crear controles en tiempo de ejecución. Cuando Visual Basic crear una matriz de controles, asigna por defecto los índices 0, 1, ..., los cuales pueden modificarse a voluntad del usuario cambiando el valor de la propiedad Index. Esta operación solo puede hacerse durante el diseño. Cuando cualquier control de la matriz reconoce un suceso, Visual Basic pasa el índice como argumento extra y, sirve para determinar que control ha recibido el suceso. Un elemento de la matriz de controles puede referenciarse escribiendo NombreMatriz(Index) AÑADIR Y RETIRAR CONTROLES EN TIEMPO DE EJECUCIÓN Una vez se ha creado una matriz de controles durante el diseño, se pueden añadir controles mientras se ejecuta la aplicación. Cuando Visual Basic crea un nuevo control en una matriz de controles, el objeto es invisible. El resto de propiedades se copian del elemento de la matriz con menor índice. Como lo controles creados se apilan unos sobre otros, deben moverse con el método Move. Para eliminar elementos de una matriz de controles, se utilizará la sentencia Unload Nombre_Matriz(índice) EJEMPLO: Crear un formulario con dos cajas de texto a las que se les haya cambiado la propiedad Name para que ponga, en ambas, "Prueba". De esta forma tenemos creada una matriz de controles. Vamos a escribir un procedimiento de evento asociado a las dos cajas de texto. Private Sub Prueba_Change(Index As Integer) If Index = 0 Then Print "Ha escrito en la caja de texto 0" Else Print "Ha escrito en la caja de texto 1" End If End Sub Ahora modificaremos el ejemplo para que, al cargar el formulario, se añadan cuatro cajas de texto nuevas a la matriz de controles. Private Sub Form_Load(Index As Integer) Dim I As Integer For I = 2 To 5 Load Prueba(I) Prueba(I).Text = "Caja de texto " & Str(I) Prueba(I).Move 0, 495 * (I - 2) Prueba(I).Visible = True Next I End Sub EJERCICIOS: 1.Crear una aplicación que permita simular un tablero de juego tres en raya. Cada vez que el usuario haga clic sobre un cuadrado, la aplicación debe controlar si el cuadrado ya está marcado y, si no lo está, lo marcará con la señal del jugador. En caso de hacer tres en raya, dar un mensaje de felicitación. 1.Diseñar una aplicación que muestre en su formulario tres botones con el texto "+6%", +13%", "+33%" respectivamente. El usuario debe ser capaz de escribir en una caja de texto el valor de una cantidad determinada y, al seleccionar cualquiera de los porcentajes, la aplicación debe mostrar el tanto por ciento correspondiente y, la suma de dicho valor. Si la cantidad introducida por el usuario supera los 100.000.000, debe aparecer otro botón con el texto "+54%" y, si la cantidad es menor, debe desaparecer. 1.Diseñar una calculadora científica utilizando matrices de controles. Se debe poder obtener cualquier operación aritmética básica: sumar, restar, multiplicar y dividir. Llevar un control de la memoria. Obtener la raíz cuadrada y el tanto por ciento de un número. Debe permitir un encendido/apagado de la calculadora (p.e. un botón que inicialmente muestre ON y, una vez pulsado, visualice un cero en la pantalla y, en el botón, el texto OFF) 1.Se pretende realizar una aplicación que permita al usuario llevar la gestión de sus apuestas en la Lotería Primitiva. Para ello, la aplicación debe permitir marcar seis números seleccionados al azar entre el 1 y el 49. Se pretende que el botón correspondiente a "Marcar" seleccione seis números al azar y, los marque en las casillas adecuadas (equivalente al menú Apuesta / Marcar). El botón "Nueva apuesta" debe permitir desactivar las casillas marcadas en la apuesta anterior (Apuesta / Nueva). La aplicación debe tener un formulario inicial con el nombre del alumno, de forma que, transcurridos 5 segundos, muestre el formulario de la Primitiva. VARIABLES DE OBJETO Igual que se tienen variables para manipular enteros, cadenas, etc. se pueden utilizar variables para manipular objetos de Visual Basic. Utilizando variables objeto se podrá crear en tiempo de ejecución múltiples instancias de formularios, escribir procedimientos que modifiquen cualquier formulario o control y construir arrays de formularios. Un ejemplar o instancia de un formulario es una copia que existe con independencia del original. Una variable objeto no contiene una copia de un objeto, sino una referencia a dicho objeto. Para declarar una variable objeto se utiliza la sintaxis: {Dim | ReDim | Static} VarObj As [New] TipoObj donde TipoObj puede ser: un formulario existente o las palabras reservadas Form, Control MDIForm, TextBox, ... EJEMPLO: Crear un formulario con un botón de comando, que tenga asociado el siguiente código: Private Sub Command1_Click() Dim MiForm As New Form1 'Variable objeto; 'se crea un nuevo ejemplar MiForm.Show 'carga y visualiza MiForm 'Mover y colorear el nuevo ejemplar MiForm.Move Left + (Width \ 10), Top + (Height \ 6) MiForm.BackColor = RGB(Rnd * 256, Rnd * 256, Rnd * 256) End Sub Para asignar un objeto específico a una variable objeto, se utiliza la sentencia Set: Set VarObj = RefObj Cuando una variable objeto no se refiere a un determinado objeto, tiene asignado el valor especial, Nothing. Para pasar una variable objeto a un procedimiento se debe definir en la cabecera del procedimiento los parámetros que se necesitan de tipo de objeto genérico (Form, Control y MDIForm) y específico (TextBox, etc.). Un parámetro declarado de tipo Form puede actuar sobre cualquier formulario, un parámetro declarado de tipo Control puede operar sobre cualquier control. Para determinar el tipo de una variable objeto se puede utilizar alguna de las sentencias siguientes: {If | ElseIf} TypeOf VarObj Is TipoObj Then Una colección se define como un grupo de objetos. Visual Basic provee de colecciones que se pueden utilizar para acceder a todos los formularios de una aplicación, o a todos los controles de un formulario particular. Una aplicación tiene una colección de formularios global y cada formulario tiene una colección de controles. La colección de formularios contiene los formularios cargados. La sintaxis para referirse a la colección de formulario es: Foms(índice) donde índice es un valor entre 0 y Forms.Count -1. La propiedad Count devuelve el número de formularios en la colección. La colección de controles permite referirse solamente a los controles cargados en un formulario. Cuando en un formulario hay array de controles, cada elemento de cada array es incluido en la colección. La sintaxis para referirse a la colección de controles es: [formulario.] Controls(índice) donde índice es un valor entre 0 y Controls.Count -1. Visual Basic provee de cinco objetos especiales para obtener información acerca del entorno en el cual se está trabajando. Estos objetos son: App Suministra información específica de la aplicación. Clipboard Permite manipular texto y gráficos a través del portapapeles. Debug Permite enviar información a la ventana de depuración. Printer Permite enviar texto y gráficos a la impresora. Screen Indica el formulario activo, control activo y otros datos. EJEMPLO: Diseñar un formulario que permita obtener una lista de las fuentes de la pantalla: Private Sub Form_Click() Dim I As Integer For I = 1 To Screen.FontCount - 1 Font.Name = Screen.Fonts(I) Print "Escrito en letra "; Screen. Fonts(I) Next I End Sub 4.4- LAS HERRAMIENTAS DE DEPURACIÓN Cuando se realiza una aplicación se pueden presentar tres clases de errores: Los errores de sintaxis son el resultado de escribir incorrectamente una sentencia. Para activarlos tan pronto como se producen se debe tener activada la opción Herramientas/Opciones/Ficha Entorno/Verificación Automática de Sintaxis. Los errores de ejecución ocurren cuando al ejecutar una aplicación una sentencia intenta una operación imposible de realizar. Los errores lógicos se producen cuando siendo la aplicación sintácticamente correcta, se ejecuta sin producirse errores en tiempo de ejecución, pero los resultados obtenidos no son correctos. DEPURACIÓN Durante el diseño y puesta en marcha de una aplicación, hay tres modos en los que se puede estar: diseño, ejecución y pausa. Modo Diseño, caracterizado porque en él se realiza la mayor parte del trabajo de creación de la aplicación. Para pasar al modo ejecución, se ejecutará Ejecutar/Inicio, se pulsará F5 o se hará clic en el icono Ejecutar; para pasar al modo pausa se ejecuta la orden Ejecutar/Paso a paso por instrucciones, Ejecutar/Paso a paso por procedimiento, pulse F8, pulse Mayús + F8, hacer clic en el icono Paso a paso o en el icono Paso procedimiento. Modo Ejecución caracterizado porque la aplicación toma el control. Para pasar al modo de diseño, se accederá a Ejecutar/Terminar o se hará clic en el icono Detener; para pasar al modo pausa, se pulsará el icono pausa. Modo Pausa caracterizado por permitir ejecutar la aplicación paso a paso. Para pasar de este modo al de ejecución, se accederá a Ejecutar/Inicio, pulsar la tecla F5 o se hará clic en el icono Ejecutar. Para pasar al modo de diseño se accederá a Ejecutar/Terminar o se hará clic en el icono Detener. Para depurar una aplicación, se debe entrar en el modo pausa. Para ejecutar el código paso a paso desde un punto determinado, se insertarán puntos de parada, que detienen la ejecución de la aplicación pasando del modo de ejecución al de pausa. VENTANA DE DEPURACIÓN Para poder mostrarla se accede a Ver/Ventana Depuración. Sirve para poder visualizar los valores de las expresiones y poderlas verificar. Para ello, desde la ventana de depuración se podrá utilizar la sentencia Print o ? o utilizar la orden Herramientas/Agragar Inspección. También es posible mediante código, insertar sentencias del tipo: Debug.Print Var_A_Depurar EJEMPLOS 1.Diseñar una aplicación que permita utilizar las herramientas de depuración. Para ello, la aplicación ordenará alfabéticamente 5 nombres. Utilizar las herramientas de depuración para depurarlo. Private Sub Form_Click() Static Nombres(4) As String Nombres(0) = "Juan" Nombres(1) = "Tomás" Nombres(2) = "Eduardo" Nombres(3) = "Samuel" Nombres(4) = "Francisco" For I = 0 To 4 For J = 0 To 4 If Nombres(I) > Nombres(J) Then Temp$ = Nombres(I) Nombres(I) = Nombres(J) Nombres(J) = Tmp$ End If Next J Next I For I = 0 To 4 Print Nombres(I) Next I End Sub 2.Diseñar una aplicación que permita realizar una inversión de 1000 Pts al 7% durante 12 años, lo que debe dar una resultado de: inversión * (1 + Interés/100)Años = 1000 * (1 + 0,07)12 = 2252,19 Pts. El formulario estará formado por 4 cajas de texto y un botón de comando. Añadiremos las etiquetas necesarias para una mejor comprensión. CONTROL PROPIEDAD VALOR Form Appearance 1 - 3D Name frmInversión Label Caption Inversión en Pts Text Box Text (ninguno) Name txtInversión Label Caption Interés Text Box Caption (ninguno) Name txtInterés Label Caption Periodo en años Text Box Caption (ninguno) Name txtAños Label Caption Resultado Text Box Caption (ninguno) Name txtResultado TabStop False Locked True Command Button Caption Rendimiento Name cmdRendimiento Private Sub cmdRendimiento_Click() Inversión = Val(txtInversión.Text) Interés = Val(txtInterés.Text) Años = Val(txtAños.Text) Resultado = Inversión * (1 + Interes / 100) ^ Años txtResultado = Format(Resultado, Currency) End Sub 4.5- CONTROL DE ERRORES EN TIEMPO DE EJECUCIÓN Cuando se produce un error en tiempo de ejecución, Visual Basic detiene la aplicación. Para habilitar la captura de errores en tiempo de ejecución para su uso posterior, se tendrá que utilizar la sentencia: On Error GoTo... donde los tres puntos indican la etiqueta que define la captura del error. El código etiquetado debe estar en el procedimiento actual. Una etiqueta es un identificador que finaliza con dos puntos. Para que no se ejecute la rutina de tratamiento de errores cuando la aplicación funcione bien, es aconsejable tener una salida (Exit Function, Exit sub, etc.) en la línea inmediatamente anterior a la rutina de tratamiento. En caso de que el error pueda corregirse, la sentencia Resume lleva a la instrucción que provocó el error inicialmente. Si no puede resolverse, se puede identificar el error con la función Err, que devuelve el entero asociado al último error producido. La sentencia Resume Next permite saltarse la instrucción que provocó el error y, se comienza a procesar la instrucción inmediatamente posterior a la que ha causado el problema. También se puede restaurar la ejecución a cualquier punto mediante la sentencia Resume Etiqueta. Para conocer el mensaje del error producido, se puede utilizar la función Error$. Para desactivar la captura de errores, se utiliza la sentencia: On Error GoTo 0 EJEMPLO: Diseñar una aplicación que permita ejecutar una aplicación Windows introducida por el usuario. CONTROL PROPIEDAD VALOR Form Caption Ejecutar... Name frmEjecutar MinButton False MaxButton False BorderStyle 1 - Fixed Single Text Box Text (ninguno) Name txtArchivo Command Button Name cmdAceptar Caption Aceptar Default True Command Button Caption Cancelar Name cmdCancelar Default True Private Sub cmdAceptar_Click() Dim Retorno As Long Dim NombreArchivo As String NombreArchivo = txtArchivo.Text If Existe(NombreArchivo) Then Retorno = Shell(NombreArchivo, vbNormalFocus) Else MsgBox "Por favor, inténtalo de nuevo con un fichero existente", vbExclamation, _ "Ejecutar Programa" End If End Sub Private Function Existe(F As String) As Boolean 'Comprueba la existencia de un archivo Dim X As Long On Error Resume Next X = FileLen(F) If X Then Existe = True Else Existe = False End If End Function Private Sub cmdCancelar_Click() End End Sub OTROS CONTROLES VB Y ELTOS DE INTERFACE 5.1.- BOTONES DE OPCIÓN, CUADROS DE VERIFICACIÓN, BARRAS DE DESPLAZAMIENTO Y TEMPORIZADORES. CASILLAS DE VERIFICACIÓN Y CUADROS DE OPCIÓN. Los botones de opción (Option Button, 3ª fila, icono central) y las casillas de verificación (CheckBox, 3ª fila, icono izquierdo), indican un estado y permiten al usuario que cambie el estado. Las casillas de verificación actúan independientemente. Por el contrario, los botones de opción aparecen en conjuntos y permiten escoger un valor del conjunto. Las propiedades importantes de estos controles son, prácticamente las mismas que las de un botón de comando, a excepción de la propiedad Value (valor), que indica el estado del control. Para los botones de opción puede estar establecida a True o False. Si está a True, el botón estará activado. Para las casillas de verificación, se podrá establecer a 0-Unchecked (no está activado), 1-Checked (activado) o 2-Grayed (atenuado). MARCOS Los marcos (Frame, 2ª fila, icono central) sirven para separar grupos de otros objetos en la pantalla. Para los controles anteriores, también afectan al comportamiento de ellos. Para asegurarse que los controles que se añadan al marco pertenecen al marco, se deben crear dentro del marco y no arrastrarlos encima del marco. BARRAS DE DESPLAZAMIENTO (HScrollBar y VScrollBar, 4ª fila, iconos central y derecho) Informan de la posición del cuadro de desplazamiento dentro de la barra. Las propiedades que se suelen utilizar son: Value (valor) contiene el número que representa la posición actual del cuadro de desplazamiento en el interior de la barra. LargeChange (gran cambio) 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. Max (máximo) indica el valor de la propiedad Value cuando el cuadro de desplazamiento está en su posición más a la derecha o abajo posible. Min (mínimo) indica el valor de la propiedad Value cuando el cuadro de desplazamiento está en su posición más a la izquierda o arriba posible. SmallChange (cambio pequeño) representa el valor añadido o sustraído al número contenido en la propiedad Value cuando el usuario hace clic dentro de una de las flechas de desplazamiento. Los eventos asociados a este tipo de control son los eventos Change producido después de que se haya modificado la posición del cuadro de desplazamiento; y el evento Scroll, emitido repetidamente mientras el cuadro de desplazamiento se arrastra por el interior de la barra de desplazamiento (no ocurre si se mueve haciendo clic en las flechas o en la barra). Se utiliza para proporcionar información instantánea. TEMPORIZADORES (Timer, 5ª fila, icono izquierdo) Este tipo de control se programa estableciendo su propiedad Interval al número de milisegundos que deben transcurrir entre los eventos que emita. En la mayoría de los ordenadores, un valor en la propiedad Interval inferior a 56 no es útil. El valor máximo permitido es algo más de un minuto: 66... Antes de generar un evento de reloj, el sistema siempre comprueba si hay algún otro evento de reloj pendiente, si lo hay, no genera un evento nuevo. Invisible en tiempo de ejecución. CONTROL DE REJILLA (CONTROL GRID) Una rejilla tiene la apariencia de una hoja de cálculo, por lo que la información que muestra aparece en las celdas de la rejilla. Durante la ejecución, el usuario podrá seleccionar celdas, pero no modificar su contenido. En una rejilla podemos tener celdas fijas y no fijas. El color por defecto de las celdas fijas es gris y, el de las no fijas, blanco. Si el número de celdas no cabe en la rejilla, aparecerán barras de desplazamiento. En Visual Basic 4.0, este control debe ser añadido al proyecto desde Herramientas/Controles Personalizados/ Activando "Microsoft Grid Control" Las propiedades más importantes de este control son: Row (fila) determina la fila actual. Col (columna) contiene la columna actual. Rows (filas) determina el número total de filas. Cols (columnas) que determina el número total de columnas. FixedRows (filas fijas) determina el número de filas, empezando desde arriba, que permanecen fijas. FixedCols (columnas fijas) determina el número de columnas, empezando desde la izquierda, que permanecen fijas. ColWidth (anchura columna) determina el ancho de la columna. RowHeight (altura fila) determina el alto de la fila. Ambas están medidas en Twips. Text (texto) contiene el contenido de la celda. EJERCICIOS: 1.Crear una aplicación que permita mostrar en una caja de texto la posición actual de una barra de desplazamiento. 1.Diseñar una aplicación que transcurrido un intervalo de tiempo introducido por el usuario, simule un protector de pantalla. 1.Diseñar una aplicación que permita al usuario definir un color escogiendo la cantidad de rojo, verde y azul. Se deben utilizar barras de desplazamiento para cada color y, una caja de texto para mostrar el color resultante. 5.2.- CUADROS DE DIÁLOGO COMUNES. CONTROLES DE UNIDADES, DIRECTORIOS Y ARCHIVOS CUADROS DE DIÁLOGO (Common Dialog, 8ª fila, icono izquierdo) Este control es invisible en tiempo de ejecución. Sin embargo, cuando se pone un control de este tipo en un formulario, se puede llamar a cualquiera de las cinco operaciones estándar de Windows como Abrir, Guardar como, Color, Fuente e Impresora. El cuadro de diálogo no realiza acciones, sólo recoge información. La ejecución de las funciones seleccionadas comienza cuando se establece la propiedad (Personalizado) del control de diálogo estándar. Las instrucciones de Visual Basic se suspenden hasta que el usuario sale del cuadro de diálogo. Entonces se podrán examinar las propiedades del control para ver qué acción se produjo. No hay ni métodos ni eventos asociados a este tipo de control. Todas las funciones del cuadro de diálogo permiten generar un error si el usuario selecciona el botón Cancelar. Para ello, se utiliza la propiedad CancelError (cancelar error), que por defecto está desactivada. Al modificar la propiedad (Personalizado) aparece una serie de fichas para escoger el tipo de cuadro de diálogo que se debe mostrar. Las posibilidades son las siguientes: Abrir / Guardar Como: Permite al usuario seleccionar una unidad de disco, un directorio, una extensión de archivo, un nombre de archivo e indicar si éste va a ser abierto sólo para lectura. Sus propiedades más importantes son: DialogTitle (título del cuadro de diálogo) que puede ser establecida en cualquier cadena de caracteres; FileName (nombre de archivo) utilizada para establecer el nombre inicial que aparecerá en el cuadro Nombre del archivo del cuadro de diálogo. Sirve además para saber el nombre del archivo seleccionado; Filter (filtro) se utiliza para restringir los nombres de los archivos que aparecerán en el cuadro de lista. Debe ser una cadena de texto con una o más parejas de componentes, donde cada componente está formada por una descripción y por un carácter comodín y, separadas por |; FilterIndex (filtro índice) tendrá como valor un número entero que indica la pareja de componentes del filtro que actuará por omisión; Flags (banderas) establecida como una combinación de uno o más valores que controlan características especiales del cuadro de diálogo. Color: Permite al usuario seleccionar un color de una paleta o crear y seleccionar un color personalizado. La propiedad Color determina el color seleccionado. Fuente: Permite al usuario seleccionar un tipo de letra, especificando la fuente, el estilo y el tamaño. Imprimir: Visualiza el tipo de impresora que se está utilizando y permite al usuario especificar una nueva impresora y/o indicar cómo se va a realizar la impresión. Las propiedades Copies (número de copias), FromPage (desde la página nº), ToPage (hasta la página nº), determinan la información relativa a la impresión. Ayuda: Permite ejecutar Winhelp.exe, pero no se visualiza cuadro de diálogo. La propiedad HelpCommand (comando de ayuda) especifica el tipo de ayuda que se quiere obtener; HelpFile (archivo de ayuda) especifica el nombre del archivo de ayuda y HelpKey (clave de ayuda) especifica la palabra clave que se debe usar para la pantalla inicial de ayuda. Una vez en tiempo de ejecución, para visualizar el cuadro de diálogo se deberá utilizar uno de los métodos siguientes: Método Tipo de Caja ShowOpen Caja de diálogo Abrir ShowSave Caja de diálogo Guardar Como ShowColor Caja de diálogo Color ShowFont Caja de diálogo Fuente ShowPrinter Caja de diálogo Imprimir ShowHelp Invoca a Winhelp.exe (no visualiza caja de diálogo) EJEMPLO: Diseñar una aplicación que permita visualizar varios tipos de cuadros de diálogo. CONTROL PROPIEDAD VALOR Form Caption Cuadros de diálogo Name frmCDemo Appearance 1 - 3D Label Caption Elige un tipo de cuadro List Box Font Font: Courier Name lstDiags Command Button Name cmdOK Caption OK Default True Command Button Caption Cancelar Name cmdCancelar Cancel True Common Dialog Name CommonDialog1 Private Sub Form_Load() lstDiags.AddItem "Ningún cuadro de diálogo - Action = 0" lstDiags.AddItem "Cuadro de diálogo Abrir - Action = 1" lstDiags.AddItem "Cuadro de diálogo Guardar Como - Action = 2" lstDiags.AddItem "Cuadro de diálogo Color - Action = 3" lstDiags.AddItem "Cuadro de diálogo Fuentes - Action = 4" lstDiags.AddItem "Cuadro de diálogo Imprimir - Action = 5" lstDiags.AddItem "Cuadro de diálogo Ayuda - Action = 6" End Sub Private Sub cmdOK_Click() MostrarCuadro End Sub Private Sub lstDiags_DblClick() MostrarCuadro End Sub Private Sub cmdCancelar_Click() Unload cmdCancelar.Parent End Sub Public Sub MostrarCuadro() Dim Cual As Integer Const OFNFileMustExists = 4096 'Constantes obtenidas del "Object Browser" Const OFNAllowMultiselect = 512 Const OFNShowHelp = 16 Const OFNOverwritePrompt = 2 Const CCFullOpen = 2 Const CFBoth = 3 Const PPrintSetup = 64 Const HelpContents = 3 If lstDiags.ListIndex = 0 Or lstDiags.ListIndex = -1 Then MsgBox "Lo siento, no hay cuadro de diálogo seleccionado" Else Cual = lstDiags.ListIndex Select Case Cual Case 1 'Abrir archivo, Action = 1 CommonDialog1.Flags = OFNFileMustExist Or OFNAllowMultiselect CommonDialog1.ShowOpen Case 2 'Guardar archivo, Action = 2 CommonDialog1.Flags = OFNShowHelp Or OFNOverwritePrompt CommonDialog1.ShowOpen Case 3 'Color, Action = 3 CommonDialog1.Flags = CCFullOpen CommonDialog1.ShowOpen Case 4 'Fuentes, Action = 4 CommonDialog1.Flags = CFBoth CommonDialog1.ShowOpen Case 5 'Imprimir, Action = 5 CommonDialog1.Flags = PDPrinterSetup CommonDialog1.ShowOpen Case 6 'Ayuda, Action = 6 CommonDialog1.HelpFile = "VB.HLP" CommonDialog1.HelpCommand = HelpContents CommonDialog1.ShowOpen End Select End If End Sub CONTROLES DE UNIDADES DE DISCO (DriveList, 5ª fila, icono central) La propiedad Drive del control de unidades de disco, permite saber cuál es la unidad actual. Sólo el primer carácter es significativo. Disponible en tiempo de ejecución. Un cambio de unidad de disco provoca el suceso Change. Para que cambie la unidad de disco se debe ejecutar la sentencia: ChDrive Drive1.Drive CONTROL DE DIRECTORIOS (DirList, 5ª fila, icono derecho) Muestra la estructura de directorios de la unidad actual. La propiedad Path devuelve el camino completo del directorio actual, incluyendo el nombre de unidad. Disponible en tiempo de ejecución. Un cambio de directorio provoca el suceso Change. Para que cambie el directorio se debe ejecutar la sentencia: ChDir Dir1.Path El directorio especificado por la propiedad Path siempre tiene como índice (propiedad ListIndex) -1. El que está inmediatamente encima de él, tiene como índice -2, y así sucesivamente hasta el directorio raíz. El primer subdirectorio que está inmediatamente a continuación, tiene como índice 0. Si hay varios directorios en el primer nivel de subdirectorios, el siguiente tiene índice 1, y así sucesivamente. El número de directorios correspondientes al primer nivel de subdirectorios del directorio especificado por Path, viene dado por la propiedad ListCount de la lista. CONTROL DE ARCHIVOS (FileList, 6ª fila, icono izquierdo) Muestra los archivos del directorio actual. La propiedad FileName permite especificar el fichero que se quiere utilizar o devuelve el nombre del fichero seleccionado. Disponible en tiempo de ejecución. La propiedad Pattern permite que se visualicen los ficheros que cumplen el patrón especificado por ésta. Admite los comodines * y ?. Los atributos están disponibles a través de las propiedades Archive, Normal, System, Hidden y ReadOnly. Para poner atributos a un fichero se ejecutará la propiedad SetAttr y, para obtenerlos, GetAttr. Las propiedades List y ListIndex son idénticas a las propiedades del mismo nombre de los cuadros combinados. EJEMPLOS: 1.Diseñar una aplicación que permita buscar ficheros a partir de un determinado directorio previamente especificado. Se necesitan dos formularios y un módulo. CONTROL PROPIEDAD VALOR Form Caption Buscar ficheros Name frmBuscarFicheros Label Caption Criterio de búsqueda: Text Box Text (ninguno) Name txtPatrón Command Button Name cmdDirectorio Caption Directorio: Text Box Caption (ninguno) Name txtDirectorio Command Button Caption Buscar Name cmdBuscar Default True Command Button Caption Cancelar Name cmdCancelar Command Button Caption Salir Name cmdSalir List Name lstLista Sorted True Private Sub cmdSalir_Click() End End Sub Private Sub Form_Load() txtDirectorio.Text = CurDir$ 'Directorio actual txtPatrón.Text = "*.*" End Sub Private Sub txtPatrón_Change() FrmSistemaF.fleArchivos.Pattern = txtPatrón.Text End Sub Private Sub cmdBuscar_Click() BuscarFichero End Sub Private Sub cmdCancelar_Click() NoAbandonarBuscar = False End Sub Private Sub cmdDirectorio_Click() frmSistemaF.Show 1 'Formulario modal End Sub En un nuevo módulo: Public NoAbandonarBuscar As Boolean Dim NumFicheros As Integer Public Sub BuscarFichero() 'Inicialización para llamar a RecorrerArbolDirs para ejecutar una búsqueda recursiva Dim Abandono As Boolean, I As Integer, Msj As String 'Si ya existe una lista, borrarla If frmBuscarFicheros.lstLista.ListCount Then FrmBuscarFicheros.lstLista.Clear 'Comenzar la búsqueda recursiva de directorios Abandono = RecorrerArbolDirs(frmBuscarFicheros.txtDirectorio.Text, "") frmSistemaF.fleArchivos.Path = frmSistemaF.dirDirectorio.Path If Not Abadono Then If frmBuscarFicheros.lstLista.ListCount Then NumFicheros = frmBuscar-ficheros.lstLista.ListCount Msj = "Se encontraron " & Str$(NumFicheros) Msj = Msj & " ficheros" Else Msj = "No se encontraron ficheros" End If MsgBox Msj, vbInformation, frmBuscarFicheros.Caption Else Msj = "Error: se abandonó la búsqueda" MsgBox Msj, vbCritical, frmBuscarFicheros.Caption End If End Sub Public Function RecorrerArbolDirs(DirActual As String, DirAnterior As String) _ As Boolean 'Buscar directorios recursivamente desde DirActual hacia abajo Dim vr As Integer, I As Integer, Msj As String 'Permitir al usuario abandonar la búsqueda NoAbandonarBuscar = True 'Si ocurre un error, la función devuelve True RecorrerArbolDirs = False 'Permitir ejecutar otros sucesos vr = DoEvents 'Ahora Cancelar puede poner NoAbandonar a False On Error GoTo ManipularErrorRecorrerArbolDirs 'Directorios debajo del actual DirsDebajo = frmSistemaF.dirDirectorio.ListCount Do While (DirsDebajo > 0) And NoAbandonarBuscar 'DirViejo se guarda en DirAnterior para la próxima recursión DirViejo = DirActual If frmSistemaF.dirDirectorio.ListCount > 0 Then 'otro nodo FrmSistemaF.dirDirectorio.Path = frmSistemaF!dirDirectorio.List(DirsDebajo - 1) NoAbandonarBuscar = RecorrerArbolDirs((frmSistemaF!dirDirectorio.Path), _ DirViejo) End If 'Otra rama del mismo nivel de directorios DirsDebajo = DirsDebajo - 1 If NoAbandonarBuscar = False Then RecorrerArbolDirs = True Exit Function End If Loop 'Completar camino If frmSistemaF.fleArchivos.ListCount Then If Len(DirActual) > 3 Then DirActual = DirActual + "\" 'Añadir ficheros a la lista For I = 0 To frmSistemaF.fleArchivos.ListCount - 1 Entrada = DirActual & frmSistemaF.fleArchivos.List(I) FrmBuscarFicheros.lstLista.AddItem Entrada NumFicheros = NumFicheros + 1 Next I End If If DirAnterior <> "" Then 'Directorio anterior en la lista FrmSistemaF.dirDirectorio.Path = DirAnterior End If Exit Function ManipularErrorRecorrerArbolDirs: Ir Err = 7 Then 'Insuficiente memoria (lista llena) 'Visualizar mensaje de error y retornar True en AbandonarBusqueda Msj = "Lista llena. Se abandona la búsqueda" MsgBox Msj, vbExclamation RecorrerArbolDirs = True Exit Function 'Exit pone Err a 0 Else MsgBox Error, vbCritical End End If End Function En un nuevo formulario: CONTROL PROPIEDAD VALOR Form Caption Sistema de Ficheros Name frmSistemaF Label Caption Ficheros: File Name FleArchivos Label Caption Directorios: Dir Name dirDirectorio Label Caption Unidades: Drive Name drvUnidades Command Button Caption Aceptar Name cmdAceptar Command Button Caption Cancelar Name cmdCancelar Private Sub drvUnidades_Change() On Error GoTo Unidades dirDirectorio.Path = drvUnidades.Drive Exit Sub Unidades: MsgBox "Error: unidad no preparada", vbExclamation, "Sistema Ficheros" Exit Sub End Sub Private Sub dirDirectorio_Change() fleArchivos.Path = dirDirectorio.Path End Sub Private Sub cmdAceptar_Click() 'Actualizar la lista de directorios dirDirectorio.Path = dirDirectorio.List(dirDirecrorio.ListIndex)) frmBuscarFicheros.txtDirectorio.Text = dirDirectorio.Path frmSistemaF.Hide End Sub Private Sub cmdCancelar_Click() frmSistemaF.Hide End Sub 2.Diseñar una aplicación que simule una base de datos de una farmacia. Se debe guardar información sobre el nombre del producto, cantidad en stock y comentarios sobre el producto. Para ello, se utilizará un tipo Registro. El formulario estará formado por un botón para buscar un producto determinado, otro botón para añadir un nuevo producto, así como las cajas de texto necesarias para visualizar el inventario. Cuando se desee buscar un producto, se mostrará un formulario con una lista en la que aparecerán los nombres de los productos. Cuando el usuario seleccione un producto, se visualizará en el formulario inicial toda la información relativa a dicho producto. CONTROL PROPIEDAD VALOR Form Caption Inventario de Farmacia Name frmInventario Text Box Text (ninguno) Name txtNombre Text Box Text (ninguno) Name txtCantidad Text Box Text (ninguno) Name txtComentarios MultiLine True ScrollBars 2-Vertical Command Button Caption Buscar Producto Name cmdBuscar Command Button Caption Añadir Name cmdAñadir Private Sub cmdAñadir_Click() TotalRegistros = TotalRegistros + 1 Articulo(TotalRegistros).Nombre = txtNombre.Text Articulo(TotalRegistros).Cantidad = txtCantidad.Text Articulo(TotalRegistros).Comentario = txtComentarios.Text frmRegistros.lstNombre.AddItem txtNombre.Text txtNombre.Text = "" txtCantidad.Text = "" txtComentarios.Text = "" txtNombre.SetFocus End Sub Private Sub Form_Terminate() End End Sub Private Sub cmdBuscar_Click() frmRegistro.Show End Sub En un nuevo módulo: Type Registro Nombre As String * 50 Cantidad As String * 20 Comentarios As String * 200 End Type Public TotalRegistros As Integer Public Articulo(1 To 100) As Registro Public Sub BuscarRegistro() Dim QueRegistro As Integer For QueRegistro = 1 To 100 If (RTrim(Articulo(QueRegistro).Nombre)) = _ RTrim(frmRegistro.lstNombre.Text Then Exit For Next QueRegistro frmInventario.txtNombre.Text = Articulo(QueRegistro).Nombre frmInventario.txtCantidad.Text = Articulo(QueRegistro).Cantidad frmInventario.txtComentarios.Text = Articulo(QueRegistro).Comentarios frmRegistro.Hide End Sub En un nuevo formulario: CONTROL PROPIEDAD VALOR Form Caption Buscar Producto Name frmRegistro Max Button False Min Button False BorderStyle 1-Fixed Single List Box Sorted True Name lstNombre Command Button Caption Aceptar Name cmdAceptar Command Button Caption Cancelar Name cmdCancelar Private Sub cmdCancelar_Click() frmRegistro.Hide End Sub Private Sub cmdAceptar_Click() BuscarRegistro End Sub Private Sub lstNombre_DblClick() BuscarRegistro End Sub EJERCICIO: Crear una aplicación que permita al usuario escoger un tipo de letra y sus determinados atributos. El formulario debe parecerse lo más posible al mostrado por Visual Basic al cambiar la propiedad Font de cualquier control. 5.3.- CREACIÓN DE MENÚS. DISEÑO DE UN MENÚ Para diseñar un menú se utilizará Herramientas/Editor de Menús. Los elementos de un menú pueden ser órdenes o comandos, que al hacer clic sobre ellos ejecutan acciones; submenús, que despliegan una nueva lista de elementos y; separadores o línea horizontal que agrupa las opciones del menú. Una vez en la ventana de diseño de menús, se introducirán los siguientes datos: Caption Nombre del menú que se desea crear (lo que ve el usuario). Se insertará un ampersand (&) delante de la letra que dará acceso al menú. Para introducir un separador, se escribirá un guión (-) en este apartado. Name Nombre utilizado en el código para referirse al menú. Index Permite que un conjunto de órdenes sean agrupadas en una matriz de controles. ShortCut Permite definir un acelerador, es decir, una combinación de teclas para activar el elemento. Checked Útil para indicar si una orden está activa o no. Si lo está, en la orden aparece una marca Ö a su izquierda. Enabled Útil para desactivar una orden. Si una orden tiene esta propiedad marcada, aparecerá atenuada y no podrá ser ejecutada. Visible Es útil cuando en tiempo de ejecución se quiere ocultar una orden. WindowList Permite especificar si un menú mantiene una lista de las ventanas abiertas, con una marca Ö a la izquierda de la ventana activa. HelpContexID Se utiliza para proveer una ayuda en línea para una aplicación. NegotiatePosition Determina si el menú va a aparecer en el formulario y cómo lo hace. Para introducir sangrías entre los elementos de menú, se pulsará los botones de flecha. El botón Next inserta un nuevo elemento de menú o, se desplaza al siguiente. En tiempo de ejecución se podrán añadir órdenes a un menú. Para ello se utilizará la sentencia Load, tal como se utilizaba en matrices de controles. Para eliminar una orden de un menú, se utilizará Unload. Para poder utilizar estas dos sentencias, las órdenes que componen el menú tienen que pertenecer a una matriz de controles, por lo que durante el diseño se debe haber creado al menos, un elemento (haber puesto a un comando la propiedad Index a 0). MENÚS DESPLEGABLES FLOTANTES O EMERGENTES Para poder crear un menú emergente o contextual, se utilizará el método: [formulario.] PopupMenu NombreMenú donde NombreMenú es el valor de la propiedad Name del menú que se quiere mostrar. Ya se verá cómo hacer que aparezcan al pulsar el botón derecho del ratón. EJEMPLO: Modificar la aplicación que permitía simular un editor de texto. CONTROL PROPIEDAD VALOR Form Caption Editor de Textos Name frmEditor Text Box Text (ninguno) MultiLine True ScrollBars 3- Both Name txtEditor El menú a diseñar tiene el siguiente formato: CAPTION NAME OTRAS &Archivo mnuArchivo &Salir mnuArchivoSalir ShortCut: CTRL+S &Edición mnuEdición &Cortar mnuEdiciónCortar ShortCut: CTRL+X Enabled: False C&opiar mnuEdiciónCopiar ShortCut: CTRL+C Enabled: False &Pegar mnuEdiciónPegar ShortCut: CTRL+V Enabled: False &Configuración mnuConfiguaración &Fuente mnuConfFuente Arial Fuente Checked: True Index: 0 Times New Roman Fuente Index: 1 &Tamaño mnuConfTamaño 10 Tamaño Checked: True Index: 0 20 Tamaño Index: 1 &Color mnuConfColor Negro Color Checked: True Index: 0 Azul Color Index: 1 Rojo Color Index: 2 A&yuda mnuAyuda Acerca de ... mnuAyudaAcerca Dim SeñalColor As Integer Dim SeñalFuente As Integer Dim SeñalTamaño As Integer Private Sub Form_Load() Clipboard.Clear 'Limpiar el portapapeles txtEditor.Font.Name = "Arial" SeñalFuente = 0 txtEditor.Font.Size = 10 SeñalTamaño= 10 txtEditor.ForeColor = RGB(0, 0, 0) SeñalColor = 0 End Sub Private Sub mnuArchivoSalir_Click() End End Sub Private Sub mnuEdición_Click() mnuEdiciónCopiar.Enabled = (txtEditor.SelLength > 0) mnuEdiciónCortar.Enabled = (txtEditor.SelLength > 0) 'Activar la opción Pegar si el portapapeles tiene algo mnuEdiciónPegar.Enabled = (Len(Clipboard.GetText()) > 0) End Sub Private Sub mnuEdiciónCopiar_Click() Clipboard.SetText txtEditor.SelText 'Llevar al portapapeles End Sub Private Sub mnuEdiciónCortar_Click() Clipboard.SetText txtEditor.SelText 'Llevar al portapapeles txtEditor.SelText = "" 'Eliminar el texto End Sub Private Sub mnuEdiciónPegar_Click() txtEditor.SelText = Clipboard.GetText() End Sub Private Sub Fuente_Click() txtEditor.Font.Name = Fuente(Index).Caption Fuente(SeñalFuente).Checked = False 'Desactivar la fuente anterior Fuente(Index).Checked = True 'Activar la nueva fuente SeñalFuente = Index End Sub Private Sub Tamaño_Click() txtEditor.Font.Size = Val(Tamaño(Index).Caption Tamaño(SeñalTamaño).Checked = False 'Desactivar el tamaño anterior Tamaño(Index).Checked = True 'Activar el nuevo tamaño SeñalTamaño = Index End Sub Private Sub Color_Click() Select Case Index Case 0 txtEditor.ForeColor = RGB(0, 0, 0) Case 1 txtEditor.ForeColor = RGB(0, 0, 255) Case 2 txtEditor.ForeColor = RGB(255, 0, 0) End Select Color(SeñalColor).Checked = False Color(Index).Checked = True SeñalColor = Index End Sub EJERCICIOS: 1.Modificar el ejemplo anterior para que no utilice el portapapeles. 1.Modificar la aplicación de la alarma de forma que tenga un menú "Alarma" con una única opción. Inicialmente la opción indicará "Activar alarma" y, una vez la alarma esté activada, la opción del menú indicará "Desactivar alarma". 5.4.- CONTROL DE ACTIVIDAD DEL RATÓN, EVENTOS ASOCIADOS. EVENTOS ASOCIADOS Los formularios y varios tipos de controles reconocen tres sucesos porducidos por el ratón: MouseDown. Reconocido cuando el usuario pulsa cualquier botón. MouseUp. Reconocido cuando el usuario suelta cualquier botón. MouseMove. Reconocido cada vez que el usuario mueve el cursor del ratón a una nueva posición. Los procedimientos asociados a estos sucesos tienen los mismos argumentos: Button, botón pulsado; Shift, tecla/s pulsada/s; X e Y, coordenadas de la posición actual del ratón. Objeto_SucesoRatón(Button As Integer, Shift As Integer, X As Single, Y As Single) Los valores válidos para el argumento Button dependen del suceso. Para los sucesos MouseDown y MouseUp, este argumento puede tomar los siguientes valores: CONSTANTE VALOR vbLeftButton 1 vbRightButton 2 vbMiddleButton 4 Para el suceso MouseMove, este argumento puede tomar los siguientes valores: CONSTANTE VALOR vbLeftButton 1 vbRightButton 2 vbLeftButton + vbRightButton 3 vbMiddleButton 4 vbLeftButton + vbMiddleButton 5 vbMiddleButton + vbRightButton 6 vbLeftButton + vbRightButton + vbRightButton 7 Los valores válidos para el argumento Shift pueden ser: CONSTANTE VALOR vbShiftMask 1 vbCtrlMask 2 vbAltMask 4 EJEMPLOS: 1.Crear una aplicación que indique en tres cajas de texto txtTest1, txtTest2 y txtTest3 respectivamente, que permitan mostrar los valores de los argumentos X, Y y Button para el evento MouseDown. Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, _ Y As Single) txtTest1.Text = Str(X) txtTest2.Text = Str(Y) Select Case Button Case 1 txtTest3.Text = "Botón Izquierdo" Case 2 txtTest3.Text = "Botón Derecho" Case 4 txtTest3.Text = "Botón Central" End Select End Sub 2.Crear una aplicación que permita dibujar líneas en el formulario mientras se presiona el botón izquierdo del ratón. Dim PuntoX As Integer Dim PuntoYAs Integer Private Sub Form_MouseDown(Button As Integer, Shift As Integer, X As Single, _ Y As Single) If Button = 1 Then 'Botón izquierdo PuntoX = X PuntoY = Y CurrentX = X CurrentY = Y End If End Sub Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, _ Y As Single) If Button = 1 Then Line -(X, Y) 'Dibujar una línea End Sub ARRASTRAR Y SOLTAR Para que un control pueda ser arrastrado, su propiedad DragMode debe estar establecida a 1. En este caso, este objeto ya no recibe 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. Al mover un objeto, Visual Basic muestra un cuadro gris en lugar del objeto. Si se quiere sustituir por una imagen, se modificará la propiedad DragIcon del objeto a mover. Cuando un objeto está siendo arrastrado, se denomina objeto fuente y, el objeto sobre el que se suelta, objeto destino. Este último objeto recibe el evento DragDrop. A todos los objetos por los que el objeto fuente haya pasado por encima durante el arrastre, se emitirá el evento DragOver. Un objeto puede ser movido a petición del usuario. Para ello, la propiedad DragMode del objeto estará establecida a 0. Para permitir o no arrastrar el objeto, se utilizará el método: [control.] Drag acción donde acción puede tener el valor 0, 1 ó 2. Un valor 0 cancela la operación de arrastrar, un valor 1 inicia la operación de arrastrar, un valor 2 finaliza la operación de arrastrar y provoca el suceso DragDrop. CREACION DE APLICACIONES MDI 6.1.- ¿QUÉ ES MDI? Visual Basic permite crear aplicaciones empleando una interfaz de múltiples documentos (MDI - Multiple Document Interface), o dicho en términos de Visual Basic, múltiples formularios. En una aplicación MDI, se pueden abrir varias ventanas hijas. Cada una de estas ventanas hijas (formularios) son iguales entre sí. En una aplicación MDI pueden haber varias ventanas hijas, pero solo una ventana padre por aplicación. El formulario padre actúa como contenedor de los formulario hijo. Muchos procesadores de textos bajo Windows son buenos ejemplos de aplicaciones MDI. Para crear una aplicación MDI se empezará a crear un nuevo proyecto y, se accede a Insert/MDI Form. El nuevo formulario será el formulario padre. Para que un formulario sea un formulario hijo, se deberá cambiar su propiedad MDIChild y establecerla a True. Cuando se visualizan varios formulario hijos, todos comparten el mismo código, pero cada uno de ellos guarda sus propios datos y reconoce sus propios sucesos. Según ésto, no se podrá utilizar el identificador del formulario para referirse a los controles o a sus propiedades, aunque sí se podrá utilizar la palabra clave Me. 6.2.- COMPORTAMIENTO DE MENÚS Y BARRAS DE HERRAMIENTAS Los únicos controles que se pueden incluir en un formulario padre son aquellos que tengan la propiedad Align y, dentro de éstos controles se podrán colocar otros controles. De esta forma se crean las barras de herramientas. Los menús de cada formulario hijo, son visualizados en el formulario padre. Cada vez que se activa un formulario hijo, su menú sustituye al menú que se esté visualizando en el formulario padre. Ahora bien, si no hay un formulario hijo cargado, o si dicho formulario no tiene menú, entonces se visualiza el del padre, si lo tiene. Es aconsejable que el formulario padre tenga un menú que permita abrir o crear un nuevo formulario hijo. 6.3.- EVENTO QUERYUNLOAD Cuando el usuario ejecuta la orden Cerrar del menú de control del formulario padre, Visual Basic intenta descargar dicho formulario. Esto hace que se dé el suceso QueryUnload primero para el formulario padre y luego para cada uno de los hijos. Cuando el usuario ejecuta la orden Cerrar del menú de control del formulario hijo también se da el suceso QueryUnload pero solo para este formulario. La sentencia Unload permite descargar un formulario o un control de la memoria, pero antes de que el formulario sea descargado, se da el suceso QueryUnload, seguido del suceso Unload. El suceso QueryUnload para un formulario MDI va seguido del suceso QueryUnload para cada uno de los formularios hijo. EJEMPLO: Vamos a construir una aplicación que permita crear varios formularios hijo. Para ello, se necesitará crear un nuevo proyecto con un formulario MDI y, un formulario hijo, al que se le haya establecido su propiedad Caption a Formulario Hijo y su propiedad Name a frmHijo. Al formulario padre se le añadirá un menú Archivo con los comandos Nuevo y Salir. Se añadirá el menú Ventana con la propiedad Window List activada y, con las opciones Cascada, Mosaico y Organizar iconos. También se le añadirá un control 3D panel, seleccionando Tools/Custom Controls. A dicho control se le modificará las propiedades Align con 2 - Align Bottom, BevelInner con 1 - Inset, BevelWidth con 2 y, BordeWidth con 2. Dentro de este control se añadirán dos etiquetas: lblTexto y lblContador. En un nuevo módulo: Public Contador As Integer En el formulario padre: Private Sub mnuArchivoNuevo_Click() Dim X As New frmHijo Contador = Contador + 1 X.Show End Sub Private Sub mnuArchivoSalir_Click() End End Sub Private Sub mnuVentanaCascada_Click() MDIForm1.Arrange 0 End Sub Private Sub mnuVentanaMosaico_Click() MDIFomr1.Arrange 1 End Sub Private Sub mnuVentanaOrganizar_Click() MDIFomr1.Arrange 3 End Sub Private Sub MDIForm_Initialize() Contador = 0 lblContador = Str(Contador) End Sub En el formulario hijo: Private Sub Form_Initialize() Me.Caption = Me.Caption & " #" & Str(Contador) MDIForm1.lblContador = Str(Contador) End Sub Private Sub Form_Unload(Cancel As Integer) 'Si el valor de Cancel es True, el formulario asociado no se descarga. 'En otro caso, se van cerrando primero cada hijo y, por último el padre. Contador = Contador - 1 MDIForm1.lblContador = Str(Contador) End Sub EJERCICIOS: 1.Modificar la aplicación "Editor de Texto" para permitir trabajar con más de un documento. El formulario padre deberá tener un menú Archivo con las opciones de Nuevo, Cerrar, Abrir, Guardar, Guardar Como, Salir. (Ya se verá cómo Abrir y Guardar archivos). 1.Modificar el ejercicio anterior para que la barra de estado se muestre en la parte superior y aparezcan los iconos de Cortar, Copiar, Pegar del directorio ...\toolbar3\open-up.bmp, ...\toolbar3\save-up.bmp, ...\toolbar3\cut-up.bmp, ...\toolbar3\copy-up.bmp, ...\toolbar3\pste-up.bmp, ...\toolbar3\open-mds.bmp, ...\toolbar3\save-mds.bmp, ...\toolbar3\cut-mds.bmp, ...\toolbar3\copy-mds.bmp, ...\toolbar3\pste-mds.bmp, 7. 1.- TIPOS DE ACCESO A FICHEROS EN VISUAL BASIC. Los archivos proporcionan una manera de almacenar información a largo plazo. Visual Basic ofrece tres formas de acceder a los datos: Archivo secuencial. Archivo de texto plano. Se lee una línea cada vez. Cada línea podrá ser tan larga como quiera. Cuando se empieza a leer un archivo secuencial, se empieza por la primera línea y se continúa con la siguiente hasta llegar al final. Este tipo de datos no suele ser el adecuado para almacenar grandes series de números porque se almacenan en forma de cadena de caracteres. Ejemplos: archivos TXT Archivo aleatorio. Su contenido puede ser leído y escrito en el orden que se necesite. Todas las líneas deben ser del mismo tamaño. Asumiremos que está formado por un conjunto de registros de la misma longitud. Cada registro individual se identifica con un único número y puede ser leído, escrito o actualizado. Ejemplos: archivos que simulen bases de datos. Archivo binario. Es una colección de bytes o secuencia numerada de caracteres, independientemente de la estructura del mismo. Ofrecen la posibilidad de almacenar los datos como se quiera, aunque para poder acceder a ellos, es necesario conocer cómo fueron escritos. Ejemplos: archivos EXE 7.2.- ARCHIVOS DE ACCESO SECUENCIAL. ABRIR ARCHIVOS SECUENCIALES La instrucción Open (abrir) le dice a Visual Basic a qué archivo debe acceder. La sintaxis es: Open NombreDeArchivo For {Input | Output| Append} As #NúmeroDeArchivo donde Input indica si se quiere leer del archivo, Output si se quiere escribir de él, Append si se quiere añadir información al final del fichero y, NumeroDeArchivo es un número entre 1 y 255. Si se trata de abrir para lectura un archivo que no existe, se producirá un error. Si se abre para escritura Visual Basic creará un nuevo archivo, reemplazando cualquier archivo con ese nombre. Si no se sabe qué número de archivo está libre, se utilizará el siguiente código: NumArchivo = FreeFile Open NomArch For {Input | Output} As #NumArchivo CERRAR ARCHIVOS SECUENCIALES Después de trabajar con un archivo, se debe cerrar con la instrucción Close, cuya sintaxis es: Close #NúmeroDeArchivo Si la intrucción Close se utiliza sin poner NumeroDeArchivo, se cerrarán todos los ficheros abiertos. LEER DE ARCHIVOS SECUENCIALES Para leer de un archivo secuencial se utilizará la instrucción Line Input que permite leer una línea cada vez y que tiene la sintaxis: Line Input #NúmeroDeArchivo, VariableDeCadena o bien se utilizarán las órdenes: Input #NúmeroDeArchivo, VariableDeCadena VariableDeCadena = Input(NúmCaracteres, #NúmeroDeArchivo) donde la última instrucción, permite leer un número determinado de caracteres y, está limitado a ficheros de 32.767 bytes máximo. La función EOF (Fin De Fichero) indica cuándo se acaba un archivo. A esta función hay que facilitarle el número de archivo correspondiente y, devolverá True si se ha leído toda la información del archivo. La función LOF (Longitud De Archivo) indica la longitud de un archivo. Por tanto, para leer de un archivo de acceso secuencial se seguirán los pasos: 1.Abrir el fichero para lectura con: Open NombreDeArchivo For Input As #NúmeroDeArchivo 1.Leer los datos del fichero utilizando las sentencias: Line Input #NúmeroDeArchivo, VariableDeCadena; o bien Input #NúmeroDeArchivo, VariableDeCadena; o bien VariableDeCadena = Input$ NúmCaracteres, #NúmeroDeArchivo 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo ESCRIBIR EN ARCHIVOS SECUENCIALES Para escribir en un archivo secuencial, utilizaremos las instrucciones Print o Write con la sintaxis: Print #NúmeroDeArchivo [, expresión [{ , | ; } expresión] ...] [{ , | ; }] Write #NúmeroDeArchivo [, expresión [{ , | ; } expresión] ...] [{ , | ; }] Write y Print son diferentes. Write inserta comas entre los distintos items a escribir en el fichero. Si se desean conservar los valores de un archivo abierto para escritura, se tendrá que abrir en modo Append y no Output. Por tanto, para escribir en un archivo de acceso secuencial se seguirán los pasos: 1.Abrir el fichero para escritura con: Open NombreDeArchivo For Output As #NúmeroDeArchivo 1.Escribir los datos en el fichero utilizando la sentencia: Print #NúmeroDeArchivo, expresiones 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo EJERCICIOS: 1.Modificar el ejercicio del Editor para que se pueda grabar o recuperar el texto de un archivo. debe aparecer un nuevo formulario en el que el usuario introducirá el nombre del fichero a grabar o recuperar, incluida la ruta. Se deben controlar los posiblers errores que aparezcan al intentar acceder a un archivo que no exista. 1.Modificar el ejercicio anterior para que el usuario pueda escoger la unidad, directorio y nombre del fichero a recuperar. 7.3.- ARCHIVOS DE ACCESO ALEATORIO. ABRIR Y CERRAR ARCHIVOS ALEATORIOS Modificaremos la instrucción Open (abrir) con la sintaxis: Open NombreDeArchivo For Random As #NúmeroDeArchivo Len = LongitudDelRegistro En un archivo de acceso aleatorio, se puede leer o escribir sin tener que cerrar cada vez.. Se debe facilitar el número de bytes que se deben leer o escribir. Para cerrar un archivo aleatorio, se utilizará Close como si fuera un archivo secuencial. LEER Y ESCRIBIR DE ARCHIVOS ALEATORIOS Para leer y escribir de un archivo aleatorio, utilizaremos las instrucciones Get y Put respectivamentes, con las sintaxis: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable Put #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable Get lee del archivo y almacena los datos en la variable, mientras que Put escribe el contenido de la variable en el archivo. Por tanto, para leer / escribir en un archivo de acceso aleatorio, se seguirán los pasos: 1.Abrir el fichero para acceso aleatorio con: Open NombreDeArchivo For Random As #NúmeroDeArchivo Len = LongitudRegistro 1.Escribir los datos en el fichero utilizando la sentencia: Put #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable o bien leer los datos del archivo con la sentencia: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo UTILIZAR LA INSTRUCCIÓN SEEK # La intrucción Seek puede ser extremadamente útil porque indica la siguiente posición a leer o escribir de un fichero abierto. La sintaxis es la siguiente: Seek #NúmeroDeArchivo, posicion donde posicion indica el siguiente registro a leer o escribir. Por ejemplo la sentencia: Get #1, QueRegistro, Datos(QueRegistro) es equivalente a las sentencias: Seek #1, QueRegistro Get #1,, Datos(QueRegistro) 7.4.- ARCHIVOS DE ACCESO BINARIO. ABRIR Y CERRAR ARCHIVOS BINARIOS En este tipo de ficheros los datos no siguen ningún orden, por lo que acceder a ellos es complejo. Los pasos que se deberán seguir para escribir en un archivo binario son: 1.Abrir el fichero para acceso binario con: Open NombreDeArchivo For Binary As #NúmeroDeArchivo 1.Escribir los datos en el fichero utilizando la sentencia: Put #NúmeroDeArchivo, [posición] , Variable o bien leer los datos del archivo con la sentencia: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo 7.5.- ACCESO A UNA BASE DE DATOS. EL CONTROL DATOS Utilizando un control Data, podremos comunicarnos con una base de datos para editar, visualizar y actualizar uno o más registros. Visual Basic permite comunicarse con bases de datos creadas con Microsoft Access, Microsoft Fox Pro, Borland Paradox, Borland dBase. Los métodos que se pueden utilizar con un control de datos son: MoveFirst, para posicionarse en el primer registro. MovePrevious, para posicionarse en el registro anterior. MoveLast, para posicionarse en el último registro. MoveNext, para posicionarse en el registro siguiente. Refresh, la base de datos se abre para ser utilizada o, se cierra y se vuelve a abrir si ya estaba abierta. AddNew, añadir un nuevo registro. Update, se escriben todos los campos editados en la base de datos. Delete, elimina el registro actual. Las propiedades importantes de este control son: Connect (conexión). Esta propiedad especifica el formato de la base de datos. Los valores que se pueden utilizar son: cadena vacía para formato Access, "foxpro 2.5;", "paradox;", y "dbase iv;". DatabaseName (nombre de la base de datos) Sirve para identificar al archivo de base de datos. RecordSource (fuente del registro). Indica de dónde se obtienen los datos. Exclusive (exclusiva). Determina el tipo de acceso, monousuario (True) o multiusuario (False). ReadOnly (solo lectura). Determina el modo de acceso. Cada vez que se cambie el valor de una propiedad, debe ejecutarse el método Refresh. Otras propiedades que se podrán consultar son: BOF (comienzo del archivo) esta propiedad es True si el registro actual es el primero. EOF (final del archivo) que estará a True cuando el registro actual sea el último. Un objeto Dynaset es un conjunto dinámico de registros. Cada conjunto de registros tiene asignado una colección Fields por defecto (conjunto de objetos Field, cada uno de los cuales define un campo de la base de datos). La propiedad por defecto para un objeto Field, es Value, que contiene el valor del campo que representa para el registro actual.para acceder a un miembro individual de una colección, puede hacerlo a través de un índice o utilizando el nombre del campo. P.e. la sentencia Print Data1.RecordSet(0) es equivalente, suponiendo que el campo 0 es Título, a las sentencias: Print Data1.RecordSet.Fields(0) Print Data1.RecordSet.Fields("> ¡Transferencia interrumpida! Data1.RecordSet.Fields("Título").Value También tiene asociada una propiedad Count que dice cuántos objetos están contenidos en el objeto Dynaset. Para poder realizar modificaciones en una base de datos, ésta tiene que ser actualizable, es decir, la propiedad ReadOnly tiene que estar establecida a False y la propiedad Updatable a True. Para saber si una base de datos es actualizable, escribiremos el código: Actualizable = True 'Verificar si la base de datos es actualizable If (Data1.ReadOnly = True Or Data1.Recordset.Updatable = False) Then Actualizable = False 'Base de datos no actualizable End If Para verificar si un determinado campo es actualizable, el código necesario es: 'Verificar si el campo(0) es actualizable If (Data1.Recordset.Fields(0).Attributes And DB_UPDATABLEFIELD) = 0 Then Actualizable = False 'Campo de datos no actualizable End If La propiedad Attributes indica los atributos de un campo. Para saber si un campo tiene un determinado atributo, se hará un And con el valor del atributo a verificar. Las constantes DB_... están definidas en el fichero ...\vb\dataconstant.txt Algunos eventos que se producen en un control de datos son: Reposition. Se produce después de que un determinado registro pase a ser el registro actual. Su sintaxis es Sub Data1_Reposition() Validate. Se produce justo antes de que un determinado registro pase a ser el registro actual. Ocurre antes de una operación Update, Delete o Close. Su sintaxis es Sub Data1_Validate(Action As Integer, Save As Integer). Para saber la causa que originó el suceso Validate, habrá que examinar el parámetro Action. Este parámetro se corresponde con el tipo de operación que causó este suceso. Los valores que puede tomar se pueden localizar en el fichero ...\vb\constant.txt y empiezan por DATA_ACTION... El parámetro Save toma el valor True si cualquier control ligado al control de datos cambia. Para saber qué control ha cambiado, habrá que evaluar la propiedad DataChanged de cada uno de ellos. Durante este suceso, no se podrán utilizar los métodos Move.... En su lugar se utilizará el parámetro Action. UTILIZADES ADICIONALES Las utilidades adicionales que se pueden utilizar en aplicaiones complejas son: Control de transacciones. Una transacción es una serie de cambios que se quieren hacer sobre una base de datos con la posibilidad de deshacerlos. Las tres sentencias de Visual Basic para realizar transacciones son: BeginTrans, CommitTrans y RollBack. La forma de utilizarlas lo veremos en un ejemplo. BeginTrans Criterio = "Título Like '*1ª Edición*'" Data1.Recorset.FindFirst Criterio Do While Not Data1.Recordset.NoMatch If Not Data1.Recordset.NoMatch Then Data1.Recordset.Delete 'Borrar registro RegsBorrados = RegsBorrados + 1 End If Data1.Recorset.FindNext Criterio Loop If RegsBorrados = 0 Then RollBack Exit Sub End If Msg = "¿Está seguro que desea borrar " & RegsBorrados & " registros?" If MsgBox(Msg, 17, "¿Borrar registros?") <>1 Then RollBack 'Deshacer los cambios Else CommitTrans 'Borrar Registros End If Métodos UpdateRecord, que guarda valores contenidos en los controles ligados correspondientes al registro actual. Su ejecución no provoca el suceso Update. Y UpdateControls, que actualiza los controles ligados con los valores del registro actual. Ambos métodos ejecutan sus acciones sin cambiar de registro actual. Suceso Error, que se produce si ocurre un error en tiempo de ejecución. Útil para controlar los errores. Su sintaxis es: Sub Data1_Error(DataErr As Integer, Response As Integer), donde DataErr es el nº de error y Response es la respuesta que se desea tomar: 0 continuar, 1 visualizar mensaje (valor por defecto) 7.6.- UTILIZACIÓN DE LOS FICHEROS .INI Muchas veces cuando se escribe una aplicación, se desearía recordar algunas variables de la última vez que se ejecutó la aplicación. Este tipo de información se almacena en los ficheros ini. Afortunadamente, Windows proporciona un editor de texto ASCII para leer y escribir ficheros de este tipo. Existen dos clases de cadenas de perfil: públicas y privadas. Las públicas se almacenan en el archivo Win.ini. las cadenas privadas se incluyen en ficheros con un nombre dado por el programador, con extensión .ini. Nosotros deberíamos introducir cadenas de perfil de tipo privado. Por ejemplo: si escribimos una aplicación MiEjemplo.Exe, podríamos utilizar un archivo privado C:\WINDOWS\MIEJEMPLO.INI. Para leer y escribir en ficheros ini, se necesita conocer tres cosas: 1.El nombre del fichero. 1.El nombre de la sección donde aparece. 1.La palabra de acceso para el valor. Por ejemplo, el fichero MiEjemplo.ini se parecerá a: [Nombre del usuario] 'Esta es la sección UltimoNombre = Lopez 'UltimoNombre es la palabra de acceso Existen tres funciones que se pueden utilizar en ficheros .ini privados: GetPrivateProfileString GetPrivateProfileInt WritePrivateProfileString Estas funciones son parte de la API de Windows. Son fucniones externas a Visual Basic, por lo que deben ser declaradas en la sección general de declaraciones de un formulario del proyecto Visual, o en la sección de declaraciones de un módulo y declaradas como públicos. 7. 1.- TIPOS DE ACCESO A FICHEROS EN VISUAL BASIC. Los archivos proporcionan una manera de almacenar información a largo plazo. Visual Basic ofrece tres formas de acceder a los datos: Archivo secuencial. Archivo de texto plano. Se lee una línea cada vez. Cada línea podrá ser tan larga como quiera. Cuando se empieza a leer un archivo secuencial, se empieza por la primera línea y se continúa con la siguiente hasta llegar al final. Este tipo de datos no suele ser el adecuado para almacenar grandes series de números porque se almacenan en forma de cadena de caracteres. Ejemplos: archivos TXT Archivo aleatorio. Su contenido puede ser leído y escrito en el orden que se necesite. Todas las líneas deben ser del mismo tamaño. Asumiremos que está formado por un conjunto de registros de la misma longitud. Cada registro individual se identifica con un único número y puede ser leído, escrito o actualizado. Ejemplos: archivos que simulen bases de datos. Archivo binario. Es una colección de bytes o secuencia numerada de caracteres, independientemente de la estructura del mismo. Ofrecen la posibilidad de almacenar los datos como se quiera, aunque para poder acceder a ellos, es necesario conocer cómo fueron escritos. Ejemplos: archivos EXE 7.2.- ARCHIVOS DE ACCESO SECUENCIAL. ABRIR ARCHIVOS SECUENCIALES La instrucción Open (abrir) le dice a Visual Basic a qué archivo debe acceder. La sintaxis es: Open NombreDeArchivo For {Input | Output| Append} As #NúmeroDeArchivo donde Input indica si se quiere leer del archivo, Output si se quiere escribir de él, Append si se quiere añadir información al final del fichero y, NumeroDeArchivo es un número entre 1 y 255. Si se trata de abrir para lectura un archivo que no existe, se producirá un error. Si se abre para escritura Visual Basic creará un nuevo archivo, reemplazando cualquier archivo con ese nombre. Si no se sabe qué número de archivo está libre, se utilizará el siguiente código: NumArchivo = FreeFile Open NomArch For {Input | Output} As #NumArchivo CERRAR ARCHIVOS SECUENCIALES Después de trabajar con un archivo, se debe cerrar con la instrucción Close, cuya sintaxis es: Close #NúmeroDeArchivo Si la intrucción Close se utiliza sin poner NumeroDeArchivo, se cerrarán todos los ficheros abiertos. LEER DE ARCHIVOS SECUENCIALES Para leer de un archivo secuencial se utilizará la instrucción Line Input que permite leer una línea cada vez y que tiene la sintaxis: Line Input #NúmeroDeArchivo, VariableDeCadena o bien se utilizarán las órdenes: Input #NúmeroDeArchivo, VariableDeCadena VariableDeCadena = Input(NúmCaracteres, #NúmeroDeArchivo) donde la última instrucción, permite leer un número determinado de caracteres y, está limitado a ficheros de 32.767 bytes máximo. La función EOF (Fin De Fichero) indica cuándo se acaba un archivo. A esta función hay que facilitarle el número de archivo correspondiente y, devolverá True si se ha leído toda la información del archivo. La función LOF (Longitud De Archivo) indica la longitud de un archivo. Por tanto, para leer de un archivo de acceso secuencial se seguirán los pasos: 1.Abrir el fichero para lectura con: Open NombreDeArchivo For Input As #NúmeroDeArchivo 1.Leer los datos del fichero utilizando las sentencias: Line Input #NúmeroDeArchivo, VariableDeCadena; o bien Input #NúmeroDeArchivo, VariableDeCadena; o bien VariableDeCadena = Input$ NúmCaracteres, #NúmeroDeArchivo 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo ESCRIBIR EN ARCHIVOS SECUENCIALES Para escribir en un archivo secuencial, utilizaremos las instrucciones Print o Write con la sintaxis: Print #NúmeroDeArchivo [, expresión [{ , | ; } expresión] ...] [{ , | ; }] Write #NúmeroDeArchivo [, expresión [{ , | ; } expresión] ...] [{ , | ; }] Write y Print son diferentes. Write inserta comas entre los distintos items a escribir en el fichero. Si se desean conservar los valores de un archivo abierto para escritura, se tendrá que abrir en modo Append y no Output. Por tanto, para escribir en un archivo de acceso secuencial se seguirán los pasos: 1.Abrir el fichero para escritura con: Open NombreDeArchivo For Output As #NúmeroDeArchivo 1.Escribir los datos en el fichero utilizando la sentencia: Print #NúmeroDeArchivo, expresiones 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo EJERCICIOS: 1.Modificar el ejercicio del Editor para que se pueda grabar o recuperar el texto de un archivo. debe aparecer un nuevo formulario en el que el usuario introducirá el nombre del fichero a grabar o recuperar, incluida la ruta. Se deben controlar los posiblers errores que aparezcan al intentar acceder a un archivo que no exista. 1.Modificar el ejercicio anterior para que el usuario pueda escoger la unidad, directorio y nombre del fichero a recuperar. 7.3.- ARCHIVOS DE ACCESO ALEATORIO. ABRIR Y CERRAR ARCHIVOS ALEATORIOS Modificaremos la instrucción Open (abrir) con la sintaxis: Open NombreDeArchivo For Random As #NúmeroDeArchivo Len = LongitudDelRegistro En un archivo de acceso aleatorio, se puede leer o escribir sin tener que cerrar cada vez.. Se debe facilitar el número de bytes que se deben leer o escribir. Para cerrar un archivo aleatorio, se utilizará Close como si fuera un archivo secuencial. LEER Y ESCRIBIR DE ARCHIVOS ALEATORIOS Para leer y escribir de un archivo aleatorio, utilizaremos las instrucciones Get y Put respectivamentes, con las sintaxis: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable Put #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable Get lee del archivo y almacena los datos en la variable, mientras que Put escribe el contenido de la variable en el archivo. Por tanto, para leer / escribir en un archivo de acceso aleatorio, se seguirán los pasos: 1.Abrir el fichero para acceso aleatorio con: Open NombreDeArchivo For Random As #NúmeroDeArchivo Len = LongitudRegistro 1.Escribir los datos en el fichero utilizando la sentencia: Put #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable o bien leer los datos del archivo con la sentencia: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo UTILIZAR LA INSTRUCCIÓN SEEK # La intrucción Seek puede ser extremadamente útil porque indica la siguiente posición a leer o escribir de un fichero abierto. La sintaxis es la siguiente: Seek #NúmeroDeArchivo, posicion donde posicion indica el siguiente registro a leer o escribir. Por ejemplo la sentencia: Get #1, QueRegistro, Datos(QueRegistro) es equivalente a las sentencias: Seek #1, QueRegistro Get #1,, Datos(QueRegistro) 7.4.- ARCHIVOS DE ACCESO BINARIO. ABRIR Y CERRAR ARCHIVOS BINARIOS En este tipo de ficheros los datos no siguen ningún orden, por lo que acceder a ellos es complejo. Los pasos que se deberán seguir para escribir en un archivo binario son: 1.Abrir el fichero para acceso binario con: Open NombreDeArchivo For Binary As #NúmeroDeArchivo 1.Escribir los datos en el fichero utilizando la sentencia: Put #NúmeroDeArchivo, [posición] , Variable o bien leer los datos del archivo con la sentencia: Get #NúmeroDeArchivo, [NúmeroDeRegistro] , Variable 1.Cerrar el archivo con la sentencia: Close #NúmeroDeArchivo 7.5.- ACCESO A UNA BASE DE DATOS. EL CONTROL DATOS Utilizando un control Data, podremos comunicarnos con una base de datos para editar, visualizar y actualizar uno o más registros. Visual Basic permite comunicarse con bases de datos creadas con Microsoft Access, Microsoft Fox Pro, Borland Paradox, Borland dBase. Los métodos que se pueden utilizar con un control de datos son: MoveFirst, para posicionarse en el primer registro. MovePrevious, para posicionarse en el registro anterior. MoveLast, para posicionarse en el último registro. MoveNext, para posicionarse en el registro siguiente. Refresh, la base de datos se abre para ser utilizada o, se cierra y se vuelve a abrir si ya estaba abierta. AddNew, añadir un nuevo registro. Update, se escriben todos los campos editados en la base de datos. Delete, elimina el registro actual. Las propiedades importantes de este control son: Connect (conexión). Esta propiedad especifica el formato de la base de datos. Los valores que se pueden utilizar son: cadena vacía para formato Access, "foxpro 2.5;", "paradox;", y "dbase iv;". DatabaseName (nombre de la base de datos) Sirve para identificar al archivo de base de datos. RecordSource (fuente del registro). Indica de dónde se obtienen los datos. Exclusive (exclusiva). Determina el tipo de acceso, monousuario (True) o multiusuario (False). ReadOnly (solo lectura). Determina el modo de acceso. Cada vez que se cambie el valor de una propiedad, debe ejecutarse el método Refresh. Otras propiedades que se podrán consultar son: BOF (comienzo del archivo) esta propiedad es True si el registro actual es el primero. EOF (final del archivo) que estará a True cuando el registro actual sea el último. Un objeto Dynaset es un conjunto dinámico de registros. Cada conjunto de registros tiene asignado una colección Fields por defecto (conjunto de objetos Field, cada uno de los cuales define un campo de la base de datos). La propiedad por defecto para un objeto Field, es Value, que contiene el valor del campo que representa para el registro actual.para acceder a un miembro individual de una colección, puede hacerlo a través de un índice o utilizando el nombre del campo. P.e. la sentencia Print Data1.RecordSet(0) es equivalente, suponiendo que el campo 0 es Título, a las sentencias: Print Data1.RecordSet.Fields(0) Print Data1.RecordSet.Fields("> ¡Transferencia interrumpida! Data1.RecordSet.Fields("Título").Value También tiene asociada una propiedad Count que dice cuántos objetos están contenidos en el objeto Dynaset. Para poder realizar modificaciones en una base de datos, ésta tiene que ser actualizable, es decir, la propiedad ReadOnly tiene que estar establecida a False y la propiedad Updatable a True. Para saber si una base de datos es actualizable, escribiremos el código: Actualizable = True 'Verificar si la base de datos es actualizable If (Data1.ReadOnly = True Or Data1.Recordset.Updatable = False) Then Actualizable = False 'Base de datos no actualizable End If Para verificar si un determinado campo es actualizable, el código necesario es: 'Verificar si el campo(0) es actualizable If (Data1.Recordset.Fields(0).Attributes And DB_UPDATABLEFIELD) = 0 Then Actualizable = False 'Campo de datos no actualizable End If La propiedad Attributes indica los atributos de un campo. Para saber si un campo tiene un determinado atributo, se hará un And con el valor del atributo a verificar. Las constantes DB_... están definidas en el fichero ...\vb\dataconstant.txt Algunos eventos que se producen en un control de datos son: Reposition. Se produce después de que un determinado registro pase a ser el registro actual. Su sintaxis es Sub Data1_Reposition() Validate. Se produce justo antes de que un determinado registro pase a ser el registro actual. Ocurre antes de una operación Update, Delete o Close. Su sintaxis es Sub Data1_Validate(Action As Integer, Save As Integer). Para saber la causa que originó el suceso Validate, habrá que examinar el parámetro Action. Este parámetro se corresponde con el tipo de operación que causó este suceso. Los valores que puede tomar se pueden localizar en el fichero ...\vb\constant.txt y empiezan por DATA_ACTION... El parámetro Save toma el valor True si cualquier control ligado al control de datos cambia. Para saber qué control ha cambiado, habrá que evaluar la propiedad DataChanged de cada uno de ellos. Durante este suceso, no se podrán utilizar los métodos Move.... En su lugar se utilizará el parámetro Action. UTILIZADES ADICIONALES Las utilidades adicionales que se pueden utilizar en aplicaiones complejas son: Control de transacciones. Una transacción es una serie de cambios que se quieren hacer sobre una base de datos con la posibilidad de deshacerlos. Las tres sentencias de Visual Basic para realizar transacciones son: BeginTrans, CommitTrans y RollBack. La forma de utilizarlas lo veremos en un ejemplo. BeginTrans Criterio = "Título Like '*1ª Edición*'" Data1.Recorset.FindFirst Criterio Do While Not Data1.Recordset.NoMatch If Not Data1.Recordset.NoMatch Then Data1.Recordset.Delete 'Borrar registro RegsBorrados = RegsBorrados + 1 End If Data1.Recorset.FindNext Criterio Loop If RegsBorrados = 0 Then RollBack Exit Sub End If Msg = "¿Está seguro que desea borrar " & RegsBorrados & " registros?" If MsgBox(Msg, 17, "¿Borrar registros?") <>1 Then RollBack 'Deshacer los cambios Else CommitTrans 'Borrar Registros End If Métodos UpdateRecord, que guarda valores contenidos en los controles ligados correspondientes al registro actual. Su ejecución no provoca el suceso Update. Y UpdateControls, que actualiza los controles ligados con los valores del registro actual. Ambos métodos ejecutan sus acciones sin cambiar de registro actual. Suceso Error, que se produce si ocurre un error en tiempo de ejecución. Útil para controlar los errores. Su sintaxis es: Sub Data1_Error(DataErr As Integer, Response As Integer), donde DataErr es el nº de error y Response es la respuesta que se desea tomar: 0 continuar, 1 visualizar mensaje (valor por defecto) 7.6.- UTILIZACIÓN DE LOS FICHEROS .INI Muchas veces cuando se escribe una aplicación, se desearía recordar algunas variables de la última vez que se ejecutó la aplicación. Este tipo de información se almacena en los ficheros ini. Afortunadamente, Windows proporciona un editor de texto ASCII para leer y escribir ficheros de este tipo. Existen dos clases de cadenas de perfil: públicas y privadas. Las públicas se almacenan en el archivo Win.ini. las cadenas privadas se incluyen en ficheros con un nombre dado por el programador, con extensión .ini. Nosotros deberíamos introducir cadenas de perfil de tipo privado. Por ejemplo: si escribimos una aplicación MiEjemplo.Exe, podríamos utilizar un archivo privado C:\WINDOWS\MIEJEMPLO.INI. Para leer y escribir en ficheros ini, se necesita conocer tres cosas: 1.El nombre del fichero. 1.El nombre de la sección donde aparece. 1.La palabra de acceso para el valor. Por ejemplo, el fichero MiEjemplo.ini se parecerá a: [Nombre del usuario] 'Esta es la sección UltimoNombre = Lopez 'UltimoNombre es la palabra de acceso Existen tres funciones que se pueden utilizar en ficheros .ini privados: GetPrivateProfileString GetPrivateProfileInt WritePrivateProfileString Estas funciones son parte de la API de Windows. Son fucniones externas a Visual Basic, por lo que deben ser declaradas en la sección general de declaraciones de un formulario del proyecto Visual, o en la sección de declaraciones de un módulo y declaradas como públicos. INTRODUCCION A LOS GRAFICOS 9.1.- FUNDAMENTOS DE LOS GRÁFICOS. ESCALAS DE LA PANTALLA. INTRODUCCIÓN. Lo que se puede hacer con las sentencias gráficas, depende de los controladores que Windows emplee para controlar la pantalla y la impresora. Sin embargo, el uso de estos controladores es automático. A menos que se establezca la propiedad AutoRedraw del formulario a True, será necesario gestionar el volver a dibujar los gráficos. Cuando esta propiedad está a True, se crea una copia del objeto en memoria para poder reproducir automáticamente los dibujos pintados con métodos gráficos cuando la ventana cambia de tamaño o es ocultada total o parcialmente por otra ventana. Esta operación tiene un coste de memoria. Si la propiedad tiene un valor False, los gráficos no serán reproducidos. Visual Basic activa el suceso Paint cada vez que se visualiza un formulario o una parte nueva del mismo. Si la propiedad ClipControls, que determina si los métodos gráficos contenidos en un procedimiento conducido por el suceso Paint perteneciente a un objeto, repintan el objeto entero o solo la parte que se vuelve a visualizar. Si está a False y AutoRedraw a False, Visual Basic vuelve a pintar sólo el área que se muestra nueva. Sólo se llama al procedimiento Paint cuando la propiedad AutoRedraw está a False. EJEMPLOS: 1. Sub Form_Load() Print "Por favor, Haz clic para una demostración de AutoRedraw" Print "Estas dos líneas permanecerán en la pantalla después de hacer doble clic" End Sub Sub Form_Click() AutoRedraw = False Cls Print : Print : Print Print "Pero esta línea desaparecerá después del doble clic" End Sub Sub Form_DblClick() Cls End Sub 2.Crear un nuevo formulario que tenga dos controles picture : uno con la propiedad ClipControls establecida a True y el otro a False. Cuando se ejecute este proyecto, se deberá arrastrar algún formulario hasta tapar parcialmente los círculos que aparecerán en los cuadros de imagen. Al retirarlo de nuevo, el color del círculo de Picture1 se cambia totalmente y, el de Picture2, cambia sólo en la parte que se expone nuevamente. Sub Picture1_Paint() Dim color As Long Picture1.ScaleMode = 3 color = &HFFFFFF * Rnd Picture1.FillStyle = 0 Picture1.FillColor = color Picture1.Circle (43, 41), 30, color End Sub Sub Picture2_Paint() Dim color As Long Picture2.ScaleMode = 3 color = &HFFFFFF * Rnd Picture2.FillStyle = 0 Picture2.FillColor = color Picture2.Circle (43, 41), 30, color End Sub El método Refresh obliga a un refresco inmediato del formulario o del control. Este procedimiento se utiliza normalmente en el procedimiento Form_Resize para volver a presentar cualquier gráfico que se haya calculado en el procedimiento Paint. Para guardar los gráficos que se han dibujado en un formulario o caja de figuras se utiliza la orden : SavePicture [NombreObjeto.] Image, NombreArchivo ESCALAS DE LA PANTALLA. La escala por omisión para los formularios y cajas de figuras viene medida en Twips. El tamaño por omisión de un formulario en una VGA normal es de 7.485 Twips de largo por 4.425 Twips de ancho. Veamos un ejemplo de coordenadas posibles en el formulario. COORDENADAS POSICIÓN (0,0) Esquina superior izquierda (7485,0) Esquina superior derecha (0,4425) Esquina inferior izquierda (7485,4425) Esquina inferior derecha (3742,2212) Aproximadamente en el centro Para cambiar la unidad de medida se utiliza la propiedad ScaleMode. EJEMPLO Simularemos el movimiento de un botón superponiendo diferentes dibujos del mismo. Se necesita un botón de comando con sus valores por omisión (hacer doble clic sobre la herramienta) Sub Command1_Click() 'Movimiento de un cuadrado simulando un paseo aleatorio Dim x As Single, y As Single Dim i As Integer Randomize Form1.ScaleMode = 3 'Unidad de medida Pixels x = Form1.ScaleWidth / 2 y = Form1.ScaleHeight / 2 For i = 0 To 50 xmove = 3 * Rnd ymove = 2 * Rnd If Rnd < 0.5 Then x = x + xmove y = y + ymove Else x = x - xmove y = y - ymove End If If x < 0 Or x > ScaleWidth Or y < 0 Or y > ScaleHeight Then 'No hacer nada Else Command1.Move x, y End If Next i End Sub ESCALAS PERSONALIZADAS. El método Scale establece un nuevo sistema de coordenadas para los formularios y las cajas de figuras que se pueden usar con cualquiera de los métodos gráficos. Su sintaxis es : [objeto.] Scale (x1, y1)-(x2, y2) donde x1 e y1 se corresponden con ScaleLeft y ScaleTop y x2 e y2 con las sumas ScaleWidth + ScaleLeft y ScaleHeight + ScaleTop respectivamente. P.e. Scale (-320,100)-(320,-100) establece el nuevo sistema de coordenadas en el que las coordenadas de la esquina superior izquierda es (-320,100) y las de la esquina inferior derecha es (320,-100). La sintaxis del método Scale es : Scale (Xizquierda, Yarriba)- (Xderecha, Yabajo) Si se establece Scale sin coordenadas, se restablecerán las coordenadas por omisión. Otra forma de establecer coordenadas personalizadas consiste en establecer las coordenadas de la esquina superior izquierda de la forma en la que se deben medir las escalas vertical y horizontal, utilizando las propiedades ScaleLeft, ScaleTop, ScaleWidth, y ScaleHeight. EJEMPLO (0,0) (1,0) ScaleLeft = 0 ScaleHeight = -1 ScaleWidth = 1 ScaleTop = 0 (0,-1) (1,-1) (-40,40) (40,40) ScaleLeft = -40 ScaleHeight = -80 l ScaleWidth = 80 (0,0) ScaleTop = 40 (-40,-40) (40,-40) Scale (-40,40)-(40,-40) Para dibujar líneas se utiliza el método Line, cuya sintaxis es : Line (ColumnaInicial, FilaInicial)-(ColumnaFinal, FilaFinal), CódigoColor Visual Basic recuerda el último punto referenciado y sus coordenadas están guardadas en las variables CurrentX y CurrentY, de forma que, para dibujar a continuación de este punto se utiliza : Line -(ColumnaFinal, FilaFinal), CódigoColor EJEMPLO Programa que dibuja la ecuación y = x2 - 3x + 12 en el dominio -10 <= x <= 10 Function FdeX(ByVal x As Single) As Single FdeX = (x ^ 2) - (x * 3) + 12 End Function Sub Form_Paint() Dim x As Single 'Configura la pantalla Cls Scale (-150, 150)-(150, -150) 'Sistema de coordenadas cartesianas estándar 'Dibujar los ejes Line (-150, 0)-(150, 0) Line (0, -150)-(0, 150) CurrentX = -10 CurrentY = FdeX(-10) For x = -10 To 10 Line -(x, FdeX(x)) 'Dibujar la línea desde la última posición conocida Next x End Sub 9. 2.- COLORES Y PIXELS. COLORES. Se puede utilizar la función RGB cuya sintaxis es: RGB (CantidadRojo, CantidadVerde, CantidadAzul) Siendo cada cantidad un entero entre 0 y 255 aunque también se podrá incluir al proyecto el archivo Constant.Txt y utilizar los códigos allí definidos. Otra función que se puede utilizar es QBColor con la sintaxis : QBColor (CódigoColor) donde CódigoColor es un entero entre 0 y 15 EJEMPLO Para dibujar los ejes del ejemplo anterior de color verde se modificarán las líneas siguientes: Line (-150, 0)-(150, 0) Line (0, -150)-(0, 150) por estas otras Line (-150, 0)-(150, 0), RGB(0,255,0) Line (0, -150)-(0, 150), RGB(0,255,0) CONTROL DE PIXELES. La sintaxis para dibujar un pixel es : PSet (Columna, Fila)[, Códigocolor] Si se exceden los límites de la pantalla, se obtendrá un error de desbordamiento. Si se dibuja un punto fuera del formulario, Visual Basic guarda la posición si la propiedad AutoRedraw está a True. Si luego el formulario se maximiza, se dibujará el punto. EJEMPLOS 1.Trazado de una línea mediante Pset con un pequeño recorte. Sub Form_Click() Dim i As Integer AutoRedraw = True For i = 0 To 5000 PSet (3742, i) 'Dibujar una línea vertical Next i For i = 0 To 7485 PSet (i, 3500) 'Dibujar una línea horizontal Next i End Sub 2.Vamos a construir un pequeño TeleSketch, para lo que necesitaremos utilizar el suceso KeyDown para detectar las teclas del cursor. Cuando el usuario se desplaza con las teclas de cursor, se van iluminando los pixeles por los que pasa. Se necesitarán un formulario para el área de dibujo con la propiedad AutoRedraw a True. Se necesita añadir el archivo Constant.Txt. Dim AlturaPixel As Single, AnchuraPixel As Single Dim XPunto As Single, YPunto As Single Sub Form_Load() AutoRedraw = True ScaleMode = 3 'Pixels AlturaPixel = ScaleHeight AnchuraPixel = ScaleWidth XPunto = AnchuraPixel / 2 YPunto = AlturaPixel / 2 End Sub Sub Form_Resize() AlturaPixel = ScaleHeight AnchuraPixel = ScaleWidth End Sub Sub Form_KeyDown(KeyCode As Integer, Shift As Integer) Dim sino As Integer Select Case KeyCode Case Key_Left If XPunto <= 0 Then XPunto = 0 Else XPunto = XPunto - 1 End If Case Key_Right If XPunto >= AnchuraPixel Then XPunto = AnchuraPixel Else XPunto = XPunto + 1 End If Case Key_Up If YPunto <= 0 Then YPunto = 0 Else YPunto = YPunto - 1 End If Case Key_Down If YPunto >= AlturaPixel Then YPunto = AlturaPixel Else YPunto = YPunto + 1 End If Case Key_End sino = MsgBox("¿Estás seguro de que quieres terminar", 4) If sino = 6 Then End 'Clic en si Case Else Beep End Select PSet (XPunto, YPunto) End Sub 3.Simulación de la explosión de una estrella dibujando líneas aleatorias en colores aleatorios, desde el centro de la pantalla. Se utiliza una escala personalizada donde (0,0) es el centro de la pantalla. Puesto que el número de pixels en el tamaño por omisión de formulario es de 491 de ancho por 268 de alto, (-245,134) es la esquina superior izquierda y (245,134) la esquina inferior derecha. Sub Form_Click() Dim i As Integer, CodColor As Integer Dim Columna As Single, Fila As Single Randomize Cls Scale (-245, 134)-(245, -134) For i = 1 To 100 Columna = 245 * Rnd If Rnd < 0.5 Then Columna = -Columna Fila = 134 * Rnd If Rnd < 0.5 Then Fila = -Fila CodColor = 15 * Rnd Line (0, 0)-(Columna, Fila), QBColor(CodColor) Next i End Sub En ocasiones resulta útil utilizar coordenadas relativas, en las que cada punto viene definido por cuánto de lejos está del último punto referenciado. P.e. PSet (12,100) PSet Step(50,10) el nuevo punto será (62,110) o lo que es lo mismo, (12+50,100+10) EJEMPLO Crear un formulario con una caja de imágenes. Este proyecto dibujará en el formulario y en la caja, las curvas correspondientes a la función sen(x) y cos(x) para valores comprendidos entre 0 y 6.3. El sistema de coordenadas que se define permite mostrar valores de x entre 0 y 6.3 y, valores de y entre -1 y 1. Si se establece la propiedad AutoRedraw a False y, al ejecutar el propyecto, el formulario se minimza, al restauralo, las curvas no serán dibujadas. Sub Curvas() 'Parámetros para el formulario ScaleLeft = 0 ScaleTop = 1 ScaleWidth = 6.3 ScaleHeight = -2 DrawWidth = 2 'Grosor de la línea FontSize = 18 'Tamaño de los caracteres 'Coordenadas del punto central del formulario cx = ScaleWidth / 2 + ScaleLeft cy = ScaleHeight / 2 + ScaleTop Cls msg = "Curvas" 'Coordenadas para escribir msg centrado CurrentX = cx - TextWidth(msg) / 2 CurrentY = cy - TextHeight(msg) / 2 ForeColor = QBColor(2) 'Color verde Print msg ForeColor = QBColor(0) 'Color negro 'Parámetros para la imagen Picture1.Scale (0, 1)-(6.3, -1) Picture1.Cls Picture1.CurrentX = cx - Picture1.TextWidth(msg) / 2 Picture1.CurrentY = cy - Picture1.TextHeight(msg) / 2 Picture1.ForeColor = QBColor(2) Picture1.Print msg Picture1.ForeColor = QBColor(0) 'Dibujar curvas For x = 0 To 6.3 Step 0.05 yc = Cos(x) ys = Sin(x) PSet (x, yc): Picture1.PSet (x, yc) 'Coseno PSet (x, ys): Picture1.PSet (x, ys) 'Seno Next x End Sub Sub Form_Click() Curvas End Sub ANCHURA Y ESTILO DE DIBUJO. Para cambiar el grosor de los puntos o de las líneas, se utiliza la propiedad DrawWidth, cuya forma de empleo es : Objeto.DrawWidth = Tamaño% El ajuste de esta propiedad se mide en pixels. Para cambiar el estilo de la línea, la propiedad a utilizar es DrawStyle, que se verá modificada cuando DrawWidth sea 1. Para rellenar las cajas o círculos, se modificará las propiedades FillStyle y FillColor. EJEMPLOS 1.Demostración de la propiedad DrawWidth Sub Form_Click() WindowState = 2 'Maximizar Dim i As Integer For i = 1 To 10 DrawWidth = i Line (0, i * ScaleHeight / 12)-(ScaleWidth - 15 * TextWidth("D"), i * ScaleHeight / 12) Print "DrawWidth = ", i Next i End Sub 2.Dibujar cajas anidadas. Sub Form_Click() Dim i As Integer Scale (0, 0)-(639, 199) For i = 1 To 65 Step 5 Line (5 * i, i)-(639 - 5 * i, 199 - i), , B 'Dibujar una caja Next i End Sub 3.Demostración que no emplea líneas interiores. Sub Form_Click() WindowState = 2 DrawWidth = 10 Line (100, 100)-(ScaleWidth / 2, ScaleHeight / 2), , B Line (ScaleWidth / 2, ScaleHeight / 2)-(ScaleWidth - 100, ScaleHeight - 100), , B End Sub 4.Demostración empleando líneas interiores para hacer que los límites de la caja queden la mitad dentro y la otra mitad fuera. Sub Form_Click() WindowState = 2 DrawStyle = 6 DrawWidth = 10 Line (100, 100)-(ScaleWidth / 2, ScaleHeight / 2), , B Line (ScaleWidth / 2, ScaleHeight / 2)-(ScaleWidth - 100, ScaleHeight - 100), , B End Sub 5.Modificación del ejemplo 2 para que las cajas se rellenen. Sub Form_Click() Dim i As Integer Scale (0, 0)-(639, 199) For i = 1 To 65 Step 5 CodigoColor = QBColor(i Mod 16) 'Dibujar siguiendo el orden de los colores Line (5 * i, i)-(639 - 5 * i, 199 - i), CodigoColor, BF Next i End Sub 6.Demostración de FillStyle Sub Form_Click() Dim i As Integer Scale (0, 0)-(25, 25) For i = 0 To 7 FillStyle = i Line (0, 3 * i)-(4, 3 * (i + 0.8)), , B CurrentX = 4.1 CurrentY = 3 * i + 0.5 Print "Este está hecho con FillStyle #"; i Next i End Sub 7.Este proyecto crea una tabla de información sobre algunos artículos. Private Sub Form_Load() AutoRedraw = -1 Print: Print: Print Print Tab(12); "Artículo"; Tab(32); "Precio" 'Tab indica la posición donde se desea que comience la impresión de 'una determinada expresión Print Print Tab(12); "Garbanzos"; Tab(32); 500 Print Tab(12); "Lentejas"; Tab(32); 300 Print Tab(12); "Manzanas"; Tab(32); 400 Print Tab(12); "Plátanos"; Tab(32); 200 DrawWidth = 2 Line (700, 350)-(3650, 1950), , B Line (700, 880)-(3650, 880) End Sub 9.3.- CÍRCULOS, ELIPSES Y GRÁFICOS DE SECTORES. CÍRCULOS. Para describir un círculo se dará su centro y su radio y la función que dibuja los círculos es : Circle (Centro), Radio, CódigoColor EJEMPLO Dibujar círculos anidados Sub Form_Click() Static CodColor As Integer Dim i As Single WindowState = 2 Scale (-1, 1)-(1, -1) For i = 0.1 To 0.7 Step 0.5 CodColor = 15 * Rnd Circle (0, 0), i, CodColor Next i End Sub Un sector es una parte de un gráfico y un arco es el límite exterior de un sector. Para dibujar un sector o un arco hay que decirle a Visual Basic dónde tiene que empezar y dónde tiene que terminar, para lo que se tendrá que emplear los radianes como unidad de medida. Para transformar grados en radianes se multiplica por 180/p . Para dibujar un arco de circunferencia comenzando en el punto dado en radianes en AnguloInicial y terminando en AnguloFinal, se utilizará : Circle (Xrad, Yrad), Radio, CódigoColor, AnguloInicial, AnguloFinal Para obtener un sector se usan signos negativos. EJEMPLO Dibujaremos un sector y un arco. Sub Form_Click() Pi = 4 * Atn(1) 'Calcular el valor de Pi Scale (-1, 1)-(1, -1) Circle (-0.4, 0), 0.5, , -Pi / 4, -3 * Pi / 4 'Dibujar el sector Circle (0.4, 0), 0.5, , Pi / 4, 3 * Pi / 4 'Dibujar el arco End Sub ELIPSES. Para dibujar elipses se modificará el método Circle de la siguiente manera : Circle [Paso] (Xcentro, Ycentro), radio,,,, aspecto Si el parámetro aspecto es menor que 1, el radio se toma en la dirección de las columnas y la elipse tendrá su eje menor en dirección vertical. EJEMPLOS 1.- Sub Form_Click() Scale (-2, 2)-(2, -2) Static I As Single Cls Circle (0, 0), 0.5, , , , I + 0.1 CurrentX = -2 CurrentY = 2 Print "Esta es la relación de aspecto "; Format$(I + 0.1, "#.#"); Print ". Haga clic para ver el siguiente tamaño de elipse" I = I + 0.1 End Sub 2.- Dibujaremos un círculo, una elipse y un círculo con un sector desplazado. Sub Form_Load() Pi = 4 * Atn(1) 'Definir el valor de Pi C1 = RGB(0, 0, 255) 'Azul C2 = RGB(0, 255, 0) 'Verde C3 = RGB(255, 0, 0) 'Rojo AutoRedraw = -1 ScaleMode = 3 'Pixels Circle (60, 70), 30, C1 'Círculo Circle (150, 70), 30, C2, , , 5 / 11 'Elipse Circle (240, 70), 30, C3, -Pi / 2, -2 * Pi 'Sector Circle Step(5, -5), 30, C1, -2 * Pi, -Pi / 2 'Sector End Sub 3.- Rellenaremos el círculo, la elipse y el círculo con un sector desplazado del ejemplo anterior. Sub Form_Load() Pi = 4 * Atn(1) 'Definir el valor de Pi C1 = RGB(0, 0, 255) 'Azul C2 = RGB(0, 255, 0) 'Verde C3 = RGB(255, 0, 0) 'Rojo AutoRedraw = -1 ScaleMode = 3 'Pixels FillStyle = 0 FillColor = C1 Circle (60, 70), 30, C1 'Círculo FillColor = C2 Circle (150, 70), 30, C2, , , 5 / 11 'Elipse FillColor = C3: FillStyle = 4 Circle (240, 70), 30, C3, -Pi / 2, -2 * Pi 'Sector FillColor = C1: FillStyle = 5 Circle Step(5, -5), 30, C1, -2 * Pi, -Pi / 2 'Sector End Sub 4.- Simulación de una pelota rodando sobre una línea. Sub Form_Click() D = 100 'Radio de la pelota BackColor = RGB(255, 255, 255) 'Blanco ForeColor = RGB(0, 0, 255) 'Azul CY = ScaleHeight / 2 'Línea sobre la que rueda la pelota Line (0, CY + D)-(ScaleWidth, CY + D), QBColor(2) FillStyle = 0 'Color sólido FillColor = ForeColor 'Color pelota DrawMode = 10 'Animación For I = 0 To ScaleWidth Step 30 Circle (I, CY), D 'Dibujar la pelota For retar = 0 To 1000 Next retar 'Control de velocidad Circle (I, CY), D 'Borrar la pelota Next I End Sub 5.- Simulación de una pelota que rebota al chocar contra una barrera. Sub Form_Click() ScaleMode = 3 'Pixels D = 5 'Radio de la pelota BackColor = QBColor(15) 'Blanco ForeColor = QBColor(1) 'Azul CX = ScaleWidth / 4 * 3 CY = ScaleHeight / 2 'Barrera sobre la que rebota la pelota Line (CX, 10)-(CX + 20, ScaleHeight - 10), QBColor(2), BF FillStyle = 0 'Color sólido FillColor = ForeColor 'Color pelota DrawMode = 10 'Animación. Mover la pelota. Si choca, rebota direccion = 1 '1=derecha, -1=izquierda i = 3 Do While (i > 3 Or direccion = 1) Circle (i, CY), D 'Dibujar la pelota 'Point da el color de la barrera cuando hay contacto. Devuelve el color RGB ' de un punto If Point(i + 6, CY) <> BackColor Then direccion = -1 For retar = 0 To 300 Next retar 'Control velocidad Circle (i, CY), D 'Borrar pelota i = i + direccion Loop End Sub