Programa SCADA - deeea.urv.catdeeea.urv.cat/public/PROPOSTES/pub/pdf/542pub.pdf · Introducción al...

226
Programa SCADA Titulació: Enginyeria Tècnica Industrial en Electrònica AUTOR: Rafael Zafra Doblas. DIRECTOR: Ernest Gil Dolcet . DATA: Gener 2004.

Transcript of Programa SCADA - deeea.urv.catdeeea.urv.cat/public/PROPOSTES/pub/pdf/542pub.pdf · Introducción al...

Programa SCADA

Titulació: Enginyeria Tècnica Industrial en Electrònica

AUTOR: Rafael Zafra Doblas.

DIRECTOR: Ernest Gil Dolcet .

DATA: Gener 2004.

Índice

I

1. El Proyecto Final de Carrera (PFC)....................................................................1 1.1. Objetivo del PFC...........................................................................................................1 1.2. Herramientas para realizar el PFC.............................................................................1 1.3. Condiciones de Instalación del PFC............................................................................2 1.4. Apartados que forman parte del PFC.........................................................................2 2. SCADA, Una breve revisión...................................................................................3 2.1. Introducción a SCADA.................................................................................................4 2.1.1. Definición General....................................................................................................5 2.2. Componentes de un sistema SCADA...........................................................................6 2.2.1. MTU - Master Terminal Unit....................................................................................6 2.2.1.1. Funciones..............................................................................................................6 2.2.1.2. Hardware y software..............................................................................................7 2.2.1.3. Adquisición de datos..............................................................................................8 2.2.1.3.1. Interrogación, informes por excepción..........................................................8 2.2.1.3.2. Manejo de fallas de comunicaciones.............................................................9 2.2.1.3.3. Los protocolos de comunicación..................................................................10 2.2.1.3.4. Las redes de comunicación..........................................................................10 2.2.1.3.5. Procesadores de Comunicaciones Front End.............................................11 2.2.1.3.6. Radio.............................................................................................................11 2.2.1.3.7. Los circuitos telefónicos...............................................................................12 2.2.1.4. Trending - Graficación de tendencias................................................................13 2.2.1.4.1. Características...............................................................................................13 2.2.1.4.2. Particularidades del Almacenaje de datos....................................................14 2.2.1.4.3. Qué especificar..............................................................................................14 2.2.1.4.4. La interrogación, el informe por Excepción................................................15 2.2.1.5. Procesamiento de alarmas..................................................................................15 2.2.1.5.1. Características...............................................................................................16 2.2.1.5.2. La interrogación............................................................................................16 2.2.2. Comunicaciones......................................................................................................16 2.2.2.1. Importancia........................................................................................................16 2.2.3. RTU's Remote Terminal Units...............................................................................16 2.2.3.1. Fundamentos......................................................................................................16 2.2.3.2. Funcionalidad del Hardware de un RTU..........................................................17 2.2.3.3. Funcionalidad del Software de un RTU............................................................18 2.2.3.4. Operación básica................................................................................................18 2.2.3.5. RTU's pequeños contra RTU's grandes............................................................18 2.2.3.5.1. Algunos tipos (medidas) de RTU's................................................................19 2.2.3.6. Estándares...........................................................................................................19 2.2.3.7. PLC's contra RTU's...........................................................................................19 2.2.3.7.1. Qué especificar..............................................................................................20 2.3. Generación de Proyectos.............................................................................................21 2.3.1. Identificación...........................................................................................................21 2.3.2. Lanzamiento............................................................................................................22 2.3.3. Definición................................................................................................................23 2.3.4. Diseño......................................................................................................................24 2.3.5. Adquisición..............................................................................................................24 2.3.6. Liquidación Del Proyecto........................................................................................25

Índice

II

3. Introducción a Visual Basic 6.0...........................................................................26 3.1. Introducción.................................................................................................................26 3.1.1. Entornos de desarrollo visual.................................................................................26 3.1.2. Visual Basic.............................................................................................................26 3.2. Creación de aplicaciones con Visual Basic................................................................27 3.2.1. Proyectos..................................................................................................................27 3.2.2. Archivos de un proyecto..........................................................................................28 3.2.3. Diseñadores y editores.............................................................................................28 3.2.4. Formularios.............................................................................................................29 3.2.5. Controles ActiveX....................................................................................................30 3.2.6. Propiedades..............................................................................................................30 3.2.7. Eventos y métodos....................................................................................................31 3.2.8. Programación estructurada y orientación a objetos..............................................31 3.2.9. Funciones y procedimientos....................................................................................32 3.2.10. Cuestiones de ámbito.............................................................................................33 3.2.11. Clases y objetos......................................................................................................33 3.3. Una primera aproximación........................................................................................34 3.3.1. Menú y barra de botones.........................................................................................35 3.3.2. Uso del botón derecho del ratón.............................................................................37 3.3.3. El formulario...........................................................................................................37 3.3.4. La rejilla...................................................................................................................40 3.3.5. El menú emergente..................................................................................................41 3.3.6. La ventana de propiedades......................................................................................42 3.3.7. La paleta de herramientas.......................................................................................43 3.3.8. Inserción de un control...........................................................................................44 3.3.9. El menú emergente..................................................................................................45 3.3.10. Bloquear controles.................................................................................................46 3.3.11. Añadir y eliminar controles de la paleta...............................................................47 3.3.12. Añadir páginas a la caja de herramientas............................................................48 3.3.13. Asociar código a eventos.......................................................................................48 3.3.14. Codificación de eventos.........................................................................................49 3.3.15. Uso de colores en el código...................................................................................50 3.3.16. Inserción de comentarios......................................................................................50 3.3.17. Continuación de línea...........................................................................................51 3.3.18. La ventana de proyecto..........................................................................................51 3.3.19. El proyecto por defecto..........................................................................................52 3.3.20. Ejecución y parada de un programa.....................................................................53 3.3.21. Generación de un ejecutable.................................................................................53 3.4. Constantes variables y expresiones............................................................................54 3.4.1. Tipos de datos..........................................................................................................54 3.4.2. Definición de variables en Visual Basic.................................................................56 3.4.3. Valores de inicialización.........................................................................................57 3.4.4. La sentencia Dim.....................................................................................................57 3.4.5. Variables globales....................................................................................................58 3.4.6. Variables estáticas...................................................................................................58 3.4.7. Nomenclatura de las variables................................................................................59 3.4.8. Tipo por defecto.......................................................................................................59 3.4.9. Conversiones entre tipos..........................................................................................60 3.4.10. Operadores.............................................................................................................61 3.4.11. Operadores aritméticos..........................................................................................61

Índice

III

3.4.12. Operadores relacionales........................................................................................62 3.4.13. Operadores lógicos................................................................................................63 3.4.14. Trabajo con números............................................................................................64 3.4.15. Funciones generales.............................................................................................64 3.4.16. Funciones trigonométricas..................................................................................65 3.4.17. Número aleatorios.................................................................................................65 3.4.18. Trabajo con cadena...............................................................................................65 3.4.19. Trabajo con fechas................................................................................................66 3.4.20. Trabajo con Variant..............................................................................................68 3.4.21. Matrices..................................................................................................................69 3.4.22. Matrices multidimensionales................................................................................69 3.4.23. Matrices dinámicas................................................................................................70 3.4.24. Asignación e inicialización de matrices................................................................70 3.4.25. Constantes..............................................................................................................71 3.4.26. Definición de tipos.................................................................................................71 3.5. Controles más habituales............................................................................................72 3.5.1. Etiquetas de texto.....................................................................................................73 3.5.2. Entrada de texto.......................................................................................................73 3.5.3. Grupos de controles.................................................................................................73 3.5.4. Botones.....................................................................................................................73 3.5.5. El control CheckBox...............................................................................................73 3.5.6. Uso de listas.............................................................................................................73 3.5.7. Listas combinadas...................................................................................................74 3.5.8. Barras de desplazamiento........................................................................................74 3.5.9. Programación de eventos periódicos......................................................................74 3.5.10. Uso de líneas y polígonos......................................................................................74 3.5.11. Matrices de controles.............................................................................................74 3.5.12. Creación de controles durante la ejecución.........................................................75 3.6. Programación orientada a objetos.............................................................................75 3.6.1. ¿Qué es un objeto?..................................................................................................75 3.6.2. Encapsulación.........................................................................................................76 3.6.3. Herencia...................................................................................................................76 3.6.4. Polimorfismo............................................................................................................76 3.6.5. Fundamentos de creación de controles ActiveX....................................................76 3.6.6. Creación de un control............................................................................................77 3.6.7. La clase UserControl...............................................................................................77 3.6.8. Instalación de un componente................................................................................78 3.6.9. Desarrollo de un control.........................................................................................80 3.6.10. Definición de propiedades.....................................................................................80 3.6.11. Creación de una propiedad...................................................................................80 3.6.12. Métodos de lectura y escritura de propiedades.....................................................81 3.6.13. Almacenar valores de propiedades.......................................................................81 3.6.14. Definición de eventos............................................................................................82 3.6.15. Definición de métodos...........................................................................................82 4. Implementación del PFC........................................................................................83 4.1. Filosofía a seguir........................................................................................................83 4.2. Controles Personalizados (Controles ActiveX).......................................................83 4.3. Ventanas.....................................................................................................................84 4.4. Módulos Estándar.....................................................................................................85

Índice

IV

4.5. Acciones Principales..................................................................................................85 4.5.1. Inserción de Controles..........................................................................................85 4.5.2. Salvar Sinóptico.....................................................................................................86 4.5.3. Cargar Sinóptico....................................................................................................88 4.5.4. Capturar Propiedades............................................................................................88 4.5.5. Creación del archivo ejecutable............................................................................89 4.5.6. Comunicación........................................................................................................89 5. Documentación de Usuario (Manual de Uso).................................................90 5.1. Puesta en Marcha......................................................................................................90 5.2. Editor Sinópticos.......................................................................................................91 5.2.1. Entorno..................................................................................................................91 5.2.2. Rejilla.....................................................................................................................92 5.2.3. Barra de Herramientas..........................................................................................93 5.2.3.4. Nuevo...............................................................................................................93 5.2.3.5. Abrir..................................................................................................................94 5.2.3.6. Guardar.............................................................................................................95 5.2.3.7. Color de Fondo.................................................................................................96 5.2.3.8. Eliminar............................................................................................................97 5.2.3.9. Etiqueta.............................................................................................................97 5.2.3.10. Cuadro Texto..................................................................................................99 5.2.3.11. Pulsador........................................................................................................101 5.2.3.12. Figura...........................................................................................................103 5.2.3.13. Tuberías........................................................................................................105 5.2.3.14. Elemento.......................................................................................................106 5.2.3.15. ImagenFondo...............................................................................................107 5.2.3.16. EliminarImagenFondo................................................................................107 5.2.3.17. Salir...............................................................................................................107 5.3. Editor Código...........................................................................................................108 5.3.1. Entorno................................................................................................................108 5.3.2. Fichas...................................................................................................................108 5.3.2.1. Sinóptico.........................................................................................................108 5.3.2.2. Código Asociado.............................................................................................109 5.2.3.3. Linkador..........................................................................................................110 5.4. Monitorización.........................................................................................................111 5.4.1. Entorno................................................................................................................111 6. Conclusiones.............................................................................................................112 Apéndice A Listado del Código..........................................................................................................113 Apéndice B Bibliografía......................................................................................................................221

Introducción al Proyecto Final de Carrera.

1

1. El Proyecto Final de Carrera (PFC) 1.1. Objetivo del PFC El proyecto tiene como objetivo realizar la implementación de un paquete informático que permita al usuario poder realizar el control de cualquier planta industrial, es decir, se pretende realizar un programa SCADA (Supervisory Control And Data Adquisition) capaz de realizar la monitorización y control de procesos industriales. La aplicación creada deberá ser capaz de crear los sinópticos de proceso, de dotar de funcionalidad a dichos sinópticos y de comunicar mediante puerto serie el estado del proceso en todo momento. Se dotará al software creado de funciones, eventos y propiedades de tal forma que realizar esta actividad suponga un esfuerzo mínimo para el usuario. A la hora de realizar la implementación de la aplicación se ha optado por dotarla de una gran flexibilidad, de manera que el usuario de la aplicación pueda editar sus propios elementos para crear sus pantallas y pueda introducir el código que crea necesario para dotarlas de la funcionalidad que precise para poder así realizar un correcto control del proceso. 1.2. Herramientas para realizar el PFC Para llevar a cabo el objetivo del PFC y poder verificar su funcionamiento sin la necesidad de disponer de una planta en concreto sobre la cual realizar el control, se deberá simular su funcionamiento sobre un PC que actuará como RTU (Remote Terminal Unit). La comunicación entre el MTU (Master Terminal Unit) y la RTU se realizará a través de los puertos serie utilizando la interface RS-232. Sabido esto, se deberá disponer de toda una serie de elementos ya sean de tipo hardware y/o software:

Hardware:

? 2 PC’s (MTU/RTU). ? 1 Cable NULL-MODEM. ? 1 Adaptador USB/SERIE (si es necesario).

Software: ? Microsoft Visual Basic 6.0 (Edición Profesional). 1.3. Condiciones de Instalación del PFC A la hora de instalar el proyecto se deberá tener en cuenta algunas características técnicas y de ubicación, para que el desarrollo del proyecto sea el deseado. Estas características son las siguientes:

Introducción al Proyecto Final de Carrera.

2

? El sistema operativo que deberá tener el equipo donde se ejecutará el proyecto debe ser Windows 2000 o Windows XP (preferiblemente este último). ? El equipo deberá tener instalada la aplicación Microsoft Visual Basic 6.0 ? Los archivos deberán estar recogidos en una carpeta llamada Proyecto, que se ubicará en el directorio raíz del equipo: “C:\Proyecto”, a excepción del archivo ControlDedibujo.ocx que se deberá copiar en el directorio: “C:\Windows\System32” 1.4. Apartados que forman parte del PFC La estructuración del proyecto se ha realizado en fases distintas pero enlazadas entre ellas. Esta estructuración queda recogida a continuación: ? Realización de un estudio para averiguar de lo que se trata una aplicación SCADA y de los elementos que lo conforman. ? Introducción y conocimiento exhaustivo del lenguaje de alto nivel Visual Basic 6.0. ? Realización de un informe donde quedan recogidas todas las incidencias (elementos, rutinas, funciones, etc.) que han hecho posible la implementación del PFC. ? Realización de un manual de uso que haga posible la utilización de la aplicación para el usuario. ? Extracción de las conclusiones obtenidas.

Los Sistemas SCADA.

3

2. SCADA, Una breve revisión SCADA es un acrónimo por Supervisory Control And Data Acquisition (control y adquisición de datos de supervisión). Los sistemas SCADA utilizan la computadora y tecnologías de comunicación para automatizar el monitoreo y control de procesos industriales. Estos sistemas son partes integrales de la mayoría de los ambientes industriales complejos o muy geográficamente dispersos ya que pueden recoger la información de una gran cantidad de fuentes muy rápidamente, y la presentan a un operador en una forma amigable. Los sistemas SCADA mejoran la eficacia del proceso de monitoreo y control proporcionando la información oportuna para poder tomar decisiones operacionales apropiadas. Los primeros SCADA eran simplemente sistemas de telemetría que proporcionaban reportes periódicos de las condiciones de campo vigilando las señales que representaban medidas y/o condiciones de estado en ubicaciones de campo remotas. Estos sistemas ofrecían capacidades muy simples de monitoreo y control, sin proveer funciones de aplicación alguna. La visión del operador en el proceso estaba basada en los contadores y las lámparas detrás de paneles llenos de indicadores. Mientras la tecnología se desarrollaba, los ordenadores asumieron el papel de manejar la recolección de datos, disponiendo comandos de control, y una nueva función - presentación de la información sobre una pantalla de CRT. Los ordenadores agregaron la capacidad de programar el sistema para realizar funciones de control más complejas. Los primeros sistemas automatizados SCADA fueron altamente modificados con programas de aplicación específicos para atender a requisitos de algún proyecto particular. Como ingenieros de varias industrias asistieron al diseño de estos sistemas, su percepción de SCADA adquirió las características de su propia industria. Proveedores de sistemas de software SCADA, deseando reutilizar su trabajo previo sobre los nuevos proyectos, perpetuaron esta imagen de industria-específicos por su propia visión de los ambientes de control con los cuales tenían experiencia. Solamente cuando nuevos proyectos requirieron funciones y aplicaciones adicionales, hizo que los desarrolladores de sistemas SCADA tuvieran la oportunidad de desarrollar experiencia en otras industrias. Hoy, los proveedores de SCADA están diseñando sistemas que son pensados para resolver las necesidades de muchas industrias con módulos de software industria-específicos disponibles para proporcionar las capacidades requeridas comúnmente. No es inusual encontrar software SCADA comercialmente disponible adaptado para procesamiento de papel y celulosa, industrias de aceite y gas, hidroeléctricas, generación y provisión de agua, control de fluidos, etc. Puesto que los proveedores de SCADA aún tienen tendencia en favor de algunas industrias sobre otras, los compradores de estos sistemas a menudo dependen del proveedor para una comprensiva solución a su requisito, y generalmente procurar seleccionar un vendedor que pueda ofrecer una completa solución con un producto estándar que esté apuntado hacia las necesidades específicas del usuario final. Si selecciona a un vendedor con experiencia limitada en la industria del comprador, el comprador debe estar preparado para asistir al esfuerzo de ingeniería necesario para desarrollar el conocimiento adicional de la industria requerido por el vendedor para poner con éxito el sistema en ejecución. La mayoría de los sistemas SCADA que son instalados hoy se está convirtiendo en una parte integral de la estructura de generación de la información corporativa. Estos sistemas

Los Sistemas SCADA.

4

ya no son vistos por la gerencia simplemente como herramientas operacionales, sino como un recurso importante de información. En este papel continúan sirviendo como centro de responsabilidad operacional, pero también proporcionan datos a los sistemas y usuarios fuera del ambiente del centro de control que dependen de la información oportuna en la cual basan sus decisiones económicas cotidianas. La mayoría de los vendedores principales de SCADA han reconocido esta tendencia, y están desarrollando rápidamente métodos eficientes para hacer disponibles los datos, mientras protegen la seguridad y funcionamiento del sistema SCADA. La arquitectura de los sistemas de hoy integra a menudo muchos ambientes de control diferentes, tales como tuberías de gas y aceite, en un solo centro de control. Para alcanzar un nivel aceptable de tolerancia de fallas con estos sistemas, es común tener ordenadores SCADA redundantes operando en paralelo en el centro primario del control, y un sistema de reserva del mismo situado en un área geográficamente distante. Esta arquitectura proporciona la transferencia automática de la responsabilidad del control de cualquier ordenador que pueda llegar a ser inasequible por cualquier razón, a una computadora de reserva en línea, sin interrupción significativa de las operaciones. 2.1. Introducción a SCADA. Supongamos tener un circuito eléctrico simple que consiste en un interruptor y una luz. Similar a este:

Este circuito permite que un operador mire la luz y sepa si el interruptor está abierto o cerrado. El interruptor puede indicar que un motor está trabajando o parado, o si una puerta está abierta o cerrada, o aún si ha habido un incidente o el equipo está trabajando. Hasta ahora no hay nada especial sobre esto. Pero ahora imagínese que el interruptor y la lámpara están separados 100 kilómetros. Obviamente no podríamos tener un circuito eléctrico tan grande, y ahora será un problema que involucrará equipamiento de comunicaciones. Ahora complique un poco más el problema. Imagínese que tengamos 2000 de tales circuitos. No podríamos producir 2000 circuitos de comunicación. Sin embargo alguien encontró que podríamos utilizar un solo circuito de comunicación compartiéndolo. Primero enviamos el estado (abierto | cerrado o 0/1) del primer circuito. Luego enviamos el estado del segundo circuito, etcétera. Necesitamos indicar a qué circuito se aplica el estado cuando enviamos los datos. El operador en el otro extremo todavía tiene un problema: tiene que monitorear los 2000 circuitos. Para simplificar su tarea podríamos utilizar una computadora. La computadora vigilaría todos los circuitos, y le diría al operador cuándo necesita prestarle atención a un circuito determinado. La computadora será informada cuál es el estado normal del circuito

Los Sistemas SCADA.

5

y cuál es un estado de "alarma". Vigila todos los circuitos, e informa al operador cuando cualquier circuito entra en alarma comparando con estos valores. Algunos circuitos pueden contener datos "analógicos", por ejemplo, un número que representa el nivel de agua en un tanque. En estos casos la computadora será informada de los valores de niveles máximo y mínimo que deban ser considerados normales. Cuando el valor cae fuera de este rango, la computadora considerará esto como una alarma, y el operador será informado. Podríamos también utilizar la computadora para presentar la información de una manera gráfica (un cuadro vale mil palabras). Podría mostrar una válvula en color rojo cuando está cerrada, o verde cuando está abierta, etcétera. Un sistema SCADA real es aún más complejo. Hay más de un sitio. Algunos tienen 30.000 a 50.000 "puntos" que normalmente proporcionan tanto información "analógica" como digital o de estado (por ejemplo, números tales como el nivel del líquido en un tanque). Pueden enviar un valor de estado (por ejemplo, encender una bomba) tanto como recibirlo (bomba encendida). Y la potencia de la computadora se puede utilizar para realizar un complejo secuenciamiento de operaciones, por ejemplo: ABRA una válvula, después ENCIENDA una bomba, pero solamente si la presión es mayor de 50. La computadora se puede utilizar para resumir y visualizar los datos que está procesando. Las tendencias (gráficos) de valores analógicos en un cierto plazo son muy comunes. Recoger los datos y resumirlos en informes para los operadores y la gerencia son características normales de un sistema SCADA. 2.1.1. Definición General SCADA (supervisory control and data acquisition): Un sistema industrial de mediciones y control que consiste en una computadora principal o master (generalmente llamada Estación Principal, Master Terminal Unit o MTU); una o más unidades control obteniendo datos de campo (generalmente llamadas estaciones remotas, Remote Terminal Units, o RTU's); y una colección de software estándar y/o a medida usado para monitorear y controlar remotamente dispositivos de campo. Los sistemas SCADA contemporáneos exhiben predominantemente características de control a lazo abierto y utilizan comunicaciones generalmente interurbanas, aunque algunos elementos de control a lazo cerrado y/o de comunicaciones de corta distancia pueden también estar presentes. Sistemas similares a SCADA son vistos rutinariamente en fábricas, plantas de tratamiento, etc. Éstos son llamados a menudo como Sistemas de Control Distribuidos (DCS - Distributed Control Systems). Tienen funciones similares a los sistemas SCADA, pero las unidades de colección o de control de datos de campo se establecen generalmente dentro de un área confinada. Las comunicaciones pueden ser vía una red de área local (LAN), y serán normalmente confiables y de alta velocidad. Un sistema DCS emplea generalmente cantidades significativas de control a lazo cerrado. Un sistema SCADA por otra parte, generalmente cubre áreas geográficas más grandes, y normalmente depende de una variedad de sistemas de comunicación menos confiables que una LAN. El control a lazo cerrado en esta situación será menos deseable.

Los Sistemas SCADA.

6

Entonces, ¿qué es SCADA? Se utiliza para vigilar y para controlar la planta industrial o el equipamiento. El control puede ser automático, o iniciado por comandos de operador. La adquisición de datos es lograda en primer lugar por los RTU's que exploran las entradas de información de campo conectadas con ellos (pueden también ser usados PLC's - Programmable Logic Controllers). Esto se hace generalmente a intervalos muy cortos. La MTU entonces explorará los RTU's generalmente con una frecuencia menor. Los datos se procesarán para detectar condiciones de alarma, y si una alarma estuviera presente, sería catalogada y visualizada en listas especiales de alarmas. Los datos pueden ser de tres tipos principales: ? Datos analógicos (por ejemplo números reales) que quizás sean presentados en gráficos. ? Datos digitales (on/off) que pueden tener alarmas asociadas a un estado o al otro. ? Datos de pulsos (conteo de revoluciones) que serán contabilizados o acumulados. La interfaz primaria al operador es un display que muestra una representación de la planta o del equipamiento en forma gráfica. Los datos vivos (dispositivos) se muestran como dibujos o esquemas en primer plano (foreground) sobre un fondo estático (background). Mientras los datos cambian en campo, el foreground es actualizado (una válvula se puede mostrar como abierta o cerrada, etc.). Los datos analógicos se pueden mostrar como números, o gráficamente (esquema de un tanque con su nivel de líquido almacenado). El sistema puede tener muchos de tales displays, y el operador puede seleccionar los más relevantes en cualquier momento. 2.2. Componentes de un sistema SCADA 2.2.1. MTU - Master Terminal Unit 2.2.1.1. Funciones La parte más visible de un sistema SCADA es la estación central o MTU. Éste es el "centro neurálgico" del sistema, y es el componente del cual el personal de operaciones se valdrá para ver la mayoría de la planta. Una MTU a veces se llama HMI -Human Machine Interface, interfaz ser humano - máquina -. Las funciones principales de una MTU de SCADA son: ? Adquisición de datos. Recolección de datos de los RTU's. ? Trending. Salvar los datos en una base de datos, y ponerlos a disposición de los operadores en forma de gráficos. ? Procesamiento de Alarmas. Analizar los datos recogidos de los RTU's para ver si han ocurrido condiciones anormales, y alertar a personal de operaciones sobre las mismas. ? Control. Control a Lazo Cerrado, e iniciados por operador.

Los Sistemas SCADA.

7

? Visualizaciones. Gráficos del equipamiento actualizado para reflejar datos del campo. ? Informes. La mayoría de los sistemas SCADA tienen un ordenador dedicado a la producción de reportes conectado en red (LAN o similar) con el principal. ? Mantenimiento del Sistema Mirror, es decir, mantener un sistema idéntico con la capacidad segura de asumir el control inmediatamente si el principal falla. ? Interfaces con otros sistemas. Transferencia de datos hacia y desde otros sistemas corporativos para, por ejemplo, el procesamiento de órdenes de trabajo, de compra, la actualización de bases de datos, etc. ? Seguridad. Control de acceso a los distintos componentes del sistema. ? Administración de la red. Monitoreo de la red de comunicaciones. ? Administración de la Base de datos. Agregar nuevas estaciones, puntos, gráficos, puntos de cambio de alarmas, y en general, reconfigurar el sistema. ? Aplicaciones especiales. Casi todos los sistemas SCADA tendrá cierto software de aplicación especial, asociado generalmente al monitoreo y al control de la planta. ? Sistemas expertos, sistemas de modelado. Los más avanzados pueden incluir sistemas expertos incorporados, o capacidad de modelado de datos. 2.2.1.2. Hardware y software La MTU de SCADA se puede correr en la mayoría de las plataformas. Los sistemas tendieron históricamente a ser propietarios y muy especializados, y donde fueron utilizados sistemas operativos de fines generales, tendieron a ser modificados pesadamente. Esto era debido a que los requisitos de SCADA superaban los límites de la tecnología disponible y, por razones de performance, tendieron a proporcionar sistemas gráficos por encargo, a usar bases de datos en tiempo real (con gran parte de la base de datos en memoria), y a menudo el hardware debió ser modificado para estos requisitos particulares.

Figura 2.1. Sinóptico.

Los Sistemas SCADA.

8

La serie Digital Equipment Corporation PDP11 y el sistema operativo RSX11M eran quizás la plataforma más común en los SCADA de los años 70 y principios de los 80. Posteriormente, Unix comenzó a ser el sistema operativo de más frecuente elección. Mientras la potencia de la PC aumentaba, los sistemas Intel llegaron a ser muy comunes, aunque las plataformas DEC Alfa, y otras estaciones de trabajo de fines elevados estén aún en uso. En épocas recientes Windows NT ha alcanzado alta aceptación dentro de la comunidad SCADA, aunque los sistemas muy grandes siguen siendo probablemente estaciones de trabajo Unix (QNX o Solaris) más veloces en sus respuestas. Actualmente la industria se está desarrollando claramente hacia estándares abiertos: ODBC, INTEL PCs, sistemas estándares de gráficos, e interconectividad a sistemas de computación corrientes. En años recientes ha aparecido en el mercado un importante número de sistemas SCADA sobre plataformas INTEL PC, ya que éstas están aumentando rápidamente su capacidad y performance. Ejemplos de ellos son Citect, FIX de Intellution, KEPware y Wonderware. 2.2.1.3. Adquisición de datos La función de adquisición de datos de un sistema SCADA es obviamente una función preponderante. Hay un número de características asociadas a la adquisición de datos. 2.2.1.3.1. Interrogación, informes por excepción, y transmisiones iniciadas por RTU's Los primeros sistemas SCADA tenían RTU's bobos y el sistema central debía utilizar un sistema de interrogación (polling) para tener acceso a sus datos. El Master controlaba todas las comunicaciones, y un RTU nunca hablaba a menos que fuera interrogado. El Master preguntaba así a cada RTU alternadamente, pidiendo que le envíen sus datos. El RTU haría lo necesario para recuperar los últimos datos de sus instrumentos (además de la conversión de señales analógicas a digitales) y después contestaría a la petición del Master. Al ser controladas las comunicaciones por el Master, éste registraba los datos con la hora de recepción, muchas veces muy distinta a la hora en que fueron generados. Algunas variaciones en esto se han introducido para mejorar la eficacia de comunicaciones. El Master podía solicitar solamente algunos de los datos de un RTU en cada encuesta principal, y extraería los datos menos importantes en una segunda encuesta disparada con una frecuencia más baja. Con RTU's más inteligentes, se podían explorar independientemente sus entradas de información, sobre una base continua, e incluso agrupar por hora los datos. El Master entonces preguntaría al RTU si tiene cualquier cosa para informar. Si nada hubiera cambiado desde la vez última, el RTU respondería sin novedad, y el Master se movería al RTU siguiente. Para asegurarse de que un cierto acontecimiento no fue salteado, ocasionalmente el Master haría una encuesta completa como un chequeo de salud. Está claro lo que implica cuando una entrada de información digital ha cambiado, pero el uso del informe por excepción con valores analógicos significa que un cierto cambio del umbral está definido (típicamente 1-2%), y sobre éste se ha producido algún cambio.

Los Sistemas SCADA.

9

El informe por excepción puede reducir dramáticamente el tráfico de comunicaciones, siempre y cuando los datos estén cambiando en forma relativamente lenta. Cuando se están midiendo parámetros altamente volátiles puede aumentar drásticamente el tráfico. En este caso una solución es poner estos parámetros volátiles en una encuesta rutinaria, sacrificando una cierta exactitud en la hora de registro en pos de la reducción del tráfico. El acercamiento más sofisticado es permitir que el RTU reporte por excepción sin la encuesta previa por parte del Master. Esto significa que el sistema de comunicaciones no se está utilizando para las repetidas encuestas con sin novedad siendo la respuesta más frecuente. Esto permite que un sistema típico controle muchos más RTU's con la misma anchura de banda de comunicaciones. Como los asuntos asociados con parámetros altamente volátiles todavía existen, un chequeo de salud en background sigue siendo necesario, de otro modo un RTU podría salir de servicio y el sistema nunca se daría por enterado. Para utilizar esta técnica, el protocolo de comunicación debe tener la capacidad de proporcionar las direcciones de destino del mensaje, y de la fuente del mismo. Este sistema también implica que dos RTU's pueden transmitir simultáneamente, interfiriendo uno con otro. Un sistema SCADA normalmente repetirá la transmisión si no recibe un acuse de recibo dentro de cierto tiempo. Si interfieren dos RTU's transmitiendo simultáneamente, y, luego si ambos poseen el mismo tiempo de reenvío, interferirán otra vez. Por esta razón, el acercamiento típico es repetir el envío después de un período aleatoriamente seleccionado. El uso de timeouts al azar puede no ser suficiente cuando por ejemplo ha habido un apagón extenso. Incluso con recomprobaciones al azar, puede haber tanto tráfico que el RTU todavía no podrá conseguir realizar la transmisión. Por esta razón una mejora que es deseable es que después de 5 intentos, el período de recomprobación se fije en por ejemplo 1 minuto. 2.2.1.3.2. Manejo de fallas de comunicaciones Un sistema SCADA debe ser muy confiable. Los sistemas de comunicación para los sistemas SCADA se han desarrollado para manejar comunicaciones pobres de una manera predecible. Esto es especialmente importante donde está implicado el control - podría ser desastroso si las fallas de comunicaciones causaran que el sistema SCADA haga funcionar inadvertidamente el sector incorrecto de la planta. Los sistemas SCADA hacen uso típicamente de las técnicas tradicionales de la paridad, del chequeo de sumas polinómicas, códigos de Hamming y demás. Sin embargo no confían simplemente en estas técnicas. La operatoria normal para un sistema SCADA es esperar siempre que cada transmisión sea reconocida. El sistema de interrogación que emplea tiene seguridad incorporada, en la que cada estación externa está controlada y debe periódicamente responder. Si no responde, entonces un número predeterminado de recomprobaciones será procurado. Las fallas eventualmente repetidas harán que el RTU en cuestión sea marcado como "fuera de servicio" (en un sistema de interrogación una falla de comunicación bloquea la red por un período de tiempo relativamente largo, y una vez que se haya detectado una falla, no hay motivo para volver a revisar).

Los Sistemas SCADA.

10

La exactitud de la transmisión de un SCADA se ha mirado tradicionalmente como tan importante que la aplicación SCADA toma directamente la responsabilidad sobre ella. Esto se produce en contraste con protocolos de comunicación más generales donde la responsabilidad de transmitir datos confiablemente se deja a los mismos protocolos. A medida que se utilicen protocolos de comunicación más sofisticados, y los proveedores de SCADA comiencen a tomar confianza con ellos, entonces la responsabilidad de manejar errores será transferida al protocolo. 2.2.1.3.3. Los protocolos de comunicación Se han desarrollado técnicas para la transmisión confiable sobre medios pobres, y es así que muchas compañías alcanzaron una ventaja competitiva respecto de sus competidoras simplemente debido al mérito técnico de sus protocolos. Estos protocolos por lo tanto tendieron a ser propietarios, y celosamente guardados. Esto no representaba un problema al instalar el sistema, aunque sí cuando eran requeridas extensiones. Lo obvio y casi absolutamente necesario era acudir de nuevo al proveedor original. No era generalmente factible considerar el uso de un protocolo distinto, pues eran generalmente mutuamente excluyentes. Los progresos recientes han considerado la aparición de un número apreciable de protocolos "abiertos". IEC870/5, DNP3, MMS son algunos de éstos. Los mejores de estos protocolos son los multicapa completamente "encapsulados", y los sistemas SCADA que utilizan éstos pueden confiar en ellos para garantizar la salida de un mensaje y el arribo a destino. Un número de compañías ofrece los códigos fuente de estos protocolos, y otras ofrecen conjuntos de datos de prueba para testear la implementación del mismo. Por medio de estos progresos está llegando a ser factible, por lo menos a este nivel, considerar la interoperabilidad del equipamiento de diversos fabricantes. Como documento adjunto se dará una breve descripción del protocolo DNP 3.0. 2.2.1.3.4. Las redes de comunicación SCADA tiende a utilizar la mayoría de las redes de comunicación disponibles. Los sistemas SCADA basados en transmisión radial son probablemente los más comunes. Éstos evolucionaron con el tiempo, y lo más básico es el uso de FSK (frequency shift keying - codificación por conmutación de frecuencia) sobre canales de radio analógicos. Esto significa que aquellos 0 y 1 son representados por dos diversas frecuencias (1800 y 2100 hertzios son comunes). Estas frecuencias se pueden sintetizar y enviar sobre una radio de audio normal. Velocidades de hasta 1200 baudios son posibles. Una consideración especial necesita ser dada al retardo de RTS (request to send - petición de enviar) que normalmente se presenta. Esto se produce porque una radio se tomará algún tiempo después de ser encendida (on) para que la señal alcance niveles aceptables, y por lo tanto el sistema SCADA debe poder configurar estos retardos. La mayoría de las otras consideraciones con respecto a radio y SCADA se relacionan con el diseño básico de la red de radio.

Los Sistemas SCADA.

11

Servicios basados en satélites. Hay muchos de éstos, pero la mayoría son muy costosos. Hay situaciones donde no hay alternativas. No obstante, existe un servicio basado en satélites que es económico: los sistemas VSAT: Very Small Aperture Terminal. Con VSAT, usted alquila un segmento del espacio (64k o más), y los datos se envían de un sitio remoto a un hub vía satélite. Hay dos tipos de hubs. El primero es un sistema proporcionado típicamente por un proveedor de servicios de VSAT. La ventaja es un costo fijo para los datos aunque su implementación puede costar muy cara. La otra consideración para éstos es la necesidad de un "backlink" del hub al centro de SCADA. Esto puede ser de un costo considerable. El otro tipo de sistema utiliza un hub pequeño (los clásicos de LAN estructuradas) que se puede instalar con el Master. Este es más barato, pero la administración del hub es responsabilidad exclusiva del propietario de SCADA. La interfaz a cualquier tipo de sistema de VSAT implica el uso de protocolos utilizados por el sistema de VSAT - quizás TCP/IP. Modbus es un protocolo de comunicaciones desarrollado para el mundo del PLC, y fue definido para el uso de las conexiones por cable. Aunque los proyectos procuran con frecuencia utilizar Modbus sobre radio, éste está trayendo problemas, fundamentalmente con los temporizadores. En cualquier caso, Modbus es incompleto como un protocolo para SCADA, y existen alternativas mejores tales como DNP3. Modbus tiene su campo de aplicación en comunicaciones con PLC's sobre una conexión por cable. Sistemas Landline. Éstos son comúnmente usados, pero una gran cantidad de sistemas SCADA implican el uso de la radio para sustituir landlines ante una falla. Las termitas y el relámpago son problemas comunes para los landlines. 2.2.1.3.5. Procesadores de Comunicaciones Front End El "centro" de SCADA consiste típicamente en una colección de computadoras conectadas vía LAN (o LAN redundante). Cada máquina realiza una tarea especializada. La responsabilidad de la colección de datos básicamente puede residir en una de ellas (con un sistema mirror), las visualizaciones pueden ser manejadas por una segunda computadora, etcétera. Una función asignada típicamente a una computadora separada es la interfaz a la red de comunicaciones. Ésta manejará toda la interconexión especializada a los canales de comunicaciones, y en muchos casos realizará la conversión del protocolo de modo que el sistema principal pueda contar con datos entrantes en un formato estándar. 2.2.1.3.6. Radio La telemetría de radio es probablemente la tecnología base de SCADA. La velocidad de transmisión de datos sobre radio estaba en su momento limitada al rango 300 baudios a 1200 baudios, pero las radios de datos modernas soportan hasta 9600 baudios (e incluso hasta 64k). Una red de radio que funciona en la banda de 900 Mhz es autorizada normalmente para utilizar 12,5 o 25 kHz de ancho de banda. En 25 kHz, las

Los Sistemas SCADA.

12

velocidades de 9600 baudios pueden ser alcanzadas, pero en 12,5 kHz solamente 4800 baudios son posibles con el equipamiento actual.

Figura 2.2. Esquema comunicación vía Radio. Una red de radio típica consiste en una conversación a través del repetidor situado en algún punto elevado, y un número de RTU's que comparten la red. Todos los RTU's "hablan" sobre una frecuencia (F1) y escuchan en una segunda frecuencia (F2). El repetidor escucha en F1, y retransmite esto en F2, de modo que un RTU que transmite un mensaje en F1, lo tiene retransmitido en F2, tal que el resto de RTU's pueda oírlo. Los mensajes del Master viajan sobre un enlace de comunicación dedicado hacia el repetidor y son difundidos desde el repetidor en F2 a todos los RTU's. Si el protocolo de comunicaciones usado entre el Master y el repetidor es diferente al usado en la red de radio, entonces debe haber un "Gateway" en el sitio del repetidor. Este hecho permitiría utilizar los protocolos apropiados para cada uno de los medios. Se ha utilizado con éxito DNP3 sobre la red de radio y después encapsulado el DNP3 en el TCP/IP para permitir que una red de fines generales lleve los datos al Master. El número de RTU's que puede compartir un repetidor depende de un número de factores. En primer lugar el tipo de equipo de radio puede afectar esto, teniendo en cuenta el retardo en alcanzar una señal estable. La aplicación también es un factor importante, ya que de ella depende el tiempo de respuesta requerido. Las características del protocolo (la interrogación, informe por excepción, las transmisiones iniciadas por el RTU) también pueden ser significativas. La velocidad tiene obviamente un impacto también. 2.2.1.3.7. Los circuitos telefónicos Tienen algunas implicaciones importantes para un sistema SCADA. En primer lugar la administración de módems en campo puede ser molesta. En segundo lugar el RTU debe poder salvar datos mientras el módem está desconectado, para después transmitirlos cuando se establece la conexión.

Los Sistemas SCADA.

13

Preferiblemente el RTU debe poder iniciar la llamada cuando ocurre una alarma, o sus buffers de datos corren el riesgo de desbordar. El Master debe poder manejar la recepción de este cúmulo de datos, y al mismo tiempo "rellenar" su base de datos, generar los gráficos, etcétera. Algunos informes producidos por el Master pueden necesitar ser corregidos cuando llegan los datos. 2.2.1.4. Trending - Graficación de tendencias El recurso de trending es una función base incluida en cada sistema SCADA. La computadora se puede utilizar para resumir y exhibir los datos que está procesando. Las tendencias (gráficos) de valores analógicos sobre el tiempo son muy comunes. Recoger los datos y resumirlos en informes para los operadores y gerencia son características normales de un sistema SCADA.

Figura 2.3. Trendings.

2.2.1.4.1. Características El recurso de trending incluye elementos tales como diagramas X-Y, la capacidad de re-escalar la tendencia mientras es mostrada, la capacidad de visualizar coordenadas para seleccionar una característica en la tendencia y visualizar los valores asociados a ella, histogramas, múltiples valores independientes en una tendencia, y gráficos de información de estado. El sistema de trending trabaja normalmente creando un archivo para cada tendencia con "casilleros" para los valores de datos que se renovarán en una frecuencia especificada (máximo ratio de trending). A medida que se adquieren los datos de campo, se ubican en los archivos de tendencia, quedando disponibles para su posterior análisis. Hay normalmente un límite superior a la cantidad de datos que puedan ser guardados (ejemplo un año de datos).

Los Sistemas SCADA.

14

2.2.1.4.2. Particularidades del Almacenaje de datos El uso de archivos de tendencia con casilleros para los datos, renovados en los intervalos especificados, puede causar dificultades cuando se usa la característica de Reporte por Excepción. Los problemas pueden ser aún mayores cuando se incluyen en el sistema "dial-up" RTU's por las posibles desconexiones. El sistema SCADA debe tener la capacidad de llenar los archivos de tendencia en estas circunstancias. Un set SCADA no está preparado para hacer esto automáticamente, y se debe tener sumo cuidado al configurar y especificar las características de trending para lograrlo. Algunos sistemas no permiten que todas las variables sean afectadas al trending de datos. Cuando se desee ver una tendencia para un valor actualmente no configurado para trending, debe entonces ser afectado al trending de datos, y luego habrá que esperar hasta que se hayan salvado suficientes datos para que el gráfico sea consistente y aporte los datos de tendencia. Esto no es útil si estamos procurando encontrar fallas. 2.2.1.4.3. Qué especificar Lo siguiente es indicativo de una especificación típica para el trending de datos. 1. Se deberán proporcionar la capacidad de trending de variables en tiempo real,

históricas, análogas y de estado, en función del tiempo y diagramas de una variable contra otras variables (por ejemplo, lectura de cabezales contra flujo para analizar la eficiencia de una bomba).

2. Las bases de tiempo para cada tendencia deberán ser configurables a partir de una

muestra por minuto a una muestra por semana (u otros valores que puedan ser deseables especificar).

3. Serán proporcionados histogramas, gráficos de barra y X-Y, gráficos de Y-T, etc. 4. Por lo menos cuatro puntos independientes serán configurables para cada pantalla de

visualización de tendencias para trending simultáneo. 5. Será posible vía un puntero o una línea seleccionar una muestra individual y hacer que

el sistema exhiba el valor para esa muestra. 6. También será posible, o en la configuración o durante la visualización, asignar mayor o

menor magnitud a la escala vertical para cada punto (por ejemplo en vez de 0-100%, hacer un zoom sobre 20-50%).

7. Al ver tendencias, será posible aumentar o disminuir el rango de tiempo de los datos disponibles.

8. La configuración de las tendencias, incluyendo la asignación de los puntos de trending,

y la selección de los períodos que se visualizarán para cada punto, serán opciones de menú.

Los Sistemas SCADA.

15

9. Cuando la recuperación de datos de campo se vea demorada por alguna razón, por ejemplo, debido a fallas de comunicación, o debido al uso de las técnicas de Reportes por Excepción, los datos serán salvados retrospectivamente en los archivos de tendencia.

2.2.1.4.4. La interrogación, el informe por Excepción, y transmisiones iniciadas por RTU's Obviamente los datos no se pueden almacenar en los archivos de tendencia con mayor exactitud o frecuencia de las que son adquiridos de campo. Un sistema de interrogación simple por lo tanto salva los datos condicionado por la frecuencia de interrogación. No obstante es más normal ahora que un sistema de interrogación utilice las técnicas de Reportes por Excepción, en las cuales los valores no se transmiten del campo a menos que haya un cambio significativo. Para un valor analógico esto puede ser un porcentaje especificado del valor a escala completa. Por lo tanto la tendencia mostrará una línea plana, mientras que pudo haber habido un cambio pequeño. En Sistemas donde los RTU's inician la transmisión, ante un cambio significativo, tienen una característica similar. Los sistemas que utilizan "dial-up" RTU's típicamente transmitirán los datos una vez al día. El RTU puede iniciar una transmisión, pero normalmente sólo en una condición de alarma. El sistema debe poder "rellenar" estos datos retrasados. Una situación similar se presenta cuando las comunicaciones se pierden por alguna razón con un RTU enlazado por radio. Cuando se restablecen las comunicaciones, una "reserva" de datos llegará y sucederá lo mismo. 2.2.1.5. Procesamiento de alarmas La característica del procesamiento de alarmas se ha asociado siempre a las funciones de las áreas de control de la planta. La computadora procesa todos los datos como vienen del campo, y considera si la variable ha entrado en alarma. Para los valores digitales, uno de los estados (0 o 1) se puede señalar como estado de alarma. Para valores analógicos es normal que se definan límites de alarmas tal que si el valor cae fuera de estos límites, considerarlo como en alarma. Las alarmas se clasifican normalmente en varios niveles de prioridad, con la prioridad más alta siendo a menudo reservada para las alarmas de seguridad. Esto permite que el operador seleccione una lista de las alarmas más importantes. Cuando un punto entra en alarma, debe ser validada por el operador. Un código es asociado a veces por el operador en ese momento para explicar la razón de la alarma. Esto ayuda en el análisis posterior de los datos. Es común tener cierto anuncio audible de la alarma, alguna señal sonora en la sala de operaciones. Un problema común para los sistemas SCADA es la "inundación" de alarmas. Cuando ocurre un trastorno importante del proceso, a menudo un evento de alarma causa otro y así sucesivamente. A menudo en el entusiasmo inicial, los límites de alarma se especifican firmemente, y aún en valores que no son realmente importantes. La inundación de alarmas

Los Sistemas SCADA.

16

resultante puede abrumar al personal de operaciones, y ocultar la causa inicial del problema. 2.2.1.5.1. Características Los recursos de alarmas incluyen la capacidad de identificar al personal de operaciones por su login, y exhibir solamente las alarmas relevantes a su área de responsabilidad, y de suprimir alarmas, por ejemplo, cuando la planta está bajo mantenimiento. Algunos sistemas sofisticados pueden resolver la inundación de alarmas identificando secuencias de causas y efectos. 2.2.1.5.2. La interrogación, el informe por Excepción, y transmisiones iniciadas por RTU's Cuando los sistemas SCADA no interrogan regularmente todos los sitios, sino que por el contrario confían en la transmisión iniciada por el RTU, si se detectara una condición de error o un cambio significativo en un valor, existe la posibilidad de que el RTU o las comunicaciones puedan fallar, y el evento pase desapercibido. Para solucionar esto, se dispara un "chequeo de salud" en background, en el cual cada RTU es interrogado con una frecuencia determinada por el tiempo que se considere prudente en que una alarma no sea detectada. 2.2.2. Comunicaciones 2.2.2.1. Importancia La característica distintiva de los sistemas SCADA es su capacidad de comunicación. Como ya se ha dicho, comparado a los DCS (Distributed Control Systems - sistemas de control distribuido) considerados a menudo dentro de una planta o de una fábrica, un sistema SCADA cubre generalmente áreas geográficas más grandes, y utiliza muchos medios de comunicaciones diversos (y a menudo relativamente no fiables). Un aspecto importante de la tecnología de SCADA es la capacidad de garantizar confiablemente la salida de datos al usar estos medios. Los sistemas SCADA utilizaron inicialmente enlaces de comunicación lentos. Cálculos cuidadosos debieron ser hechos para evaluar los volúmenes de datos probables esperados, y asegurar que la red de comunicaciones fuera capaz de resolver las demandas. Todo lo relacionado a las redes de comunicación se ha desarrollado más arriba. 2.2.3. RTU's Remote Terminal Units 2.2.3.1. Fundamentos El SCADA RTU es una pequeña y robusta computadora que proporciona inteligencia en el campo para permitir que el Master se comunique con los instrumentos. Es una unidad stand-alone (independiente) de adquisición y control de datos. Su función es controlar el

Los Sistemas SCADA.

17

equipamiento de proceso en el sitio remoto, adquirir datos del mismo, y transferirlos al sistema central SCADA. Hay dos tipos básicos de RTU's- "single boards" (de un solo módulo), compactos, que contienen todas las entradas de datos en una sola tarjeta, y "modulares" que tienen un modulo CPU separado, y pueden tener otros módulos agregados, normalmente enchufándolos en una placa común (similar a una PC con una placa madre donde se montan procesador y periféricos). Un RTU single board tiene normalmente I/O fijas, por ejemplo, 16 entradas de información digitales, 8 salidas digitales, 8 entradas de información analógicas, y 4 salidas analógicas. No es normalmente posible ampliar su capacidad. Un RTU modular se diseña para ser ampliado agregando módulos adicionales. Los módulos típicos pueden ser un módulo de 8 entradas analógicas, un módulo de 8 salidas digitales.

Figura 2.4. Módulo RTU.

2.2.3.2. Funcionalidad del Hardware de un RTU El hardware de un RTU tiene los siguientes componentes principales: ? CPU y memoria volátil (RAM). ? Memoria no volátil para grabar programas y datos. ? Capacidad de comunicaciones a través de puertos series o con módem incorporado. ? Fuente de alimentación segura (con salvaguardia de batería).

Los Sistemas SCADA.

18

? Watchdog timer (que asegure reiniciar el RTU si algo falla). ? Protección eléctrica contra fluctuaciones en la tensión. ? Interfaces de entrada-salida a DI/DO/AI/AO's. ? Reloj de tiempo real. 2.2.3.3. Funcionalidad del Software de un RTU Todos los RTU's requieren la siguiente funcionalidad. En muchos RTU's éstas se pueden mezclar y no necesariamente ser identificables como módulos separados. ? Sistema operativo en tiempo real. ? Driver para el sistema de comunicaciones, es decir la conexión con el Master. ? Drivers de dispositivo para el sistema de entrada-salida a los dispositivos de campo. ? Aplicación SCADA para exploración de entradas de información, procesamiento y el grabado de datos, respondiendo a las peticiones del Master sobre la red de comunicaciones. ? Algún método para permitir que las aplicaciones de usuario sean configuradas en el RTU. Ésta puede ser una simple configuración de parámetros, habilitando o deshabilitando entradas-salidas específicas que invalidan o puede representar un ambiente de programación completo para el usuario. ? Diagnóstico. ? Algunos RTU's pueden tener un sistema de archivos con soporte para descarga de archivo, tanto programas de usuario como archivos de configuración. 2.2.3.4. Operación básica El RTU operará la exploración de sus entradas de información, normalmente con una frecuencia bastante alta. Puede realizar algún procesamiento, por ejemplo cambios de estado, timestamping de cambios, y almacenaje de datos que aguardan el polling del Master. Algunos RTU's tienen la capacidad de iniciar la transmisión de datos al Master, aunque es más común la situación donde el Master encuesta a los RTU's preguntando por cambios. El RTU puede realizar un cierto procesamiento de alarmas. Cuando es interrogado el RTU deber responder a la petición, la que puede ser tan simple como dame todos tus datos, o una compleja función de control para ser ejecutada. 2.2.3.5. RTU's pequeños contra RTU's grandes Los RTU's son dispositivos especiales fabricados a menudo por pequeños proveedores en pequeños lotes de algunos cientos, normalmente para los mercados domésticos. Por lo

Los Sistemas SCADA.

19

tanto no todos los RTU's soportan toda la funcionalidad descripta. Un RTU's más grande puede ser capaz de procesar centenares de entradas de información, y aún controlar el funcionamiento de "sub RTU's" más chicos. Éstos son obviamente más costosos. La potencia de procesamiento de un RTU se extiende desde pequeños procesadores de 8 bits con memoria mínima hasta sofisticados RTU's más grandes capaces de recolectar datos en el orden del milisegundo. 2.2.3.5.1. Algunos tipos (medidas) de RTU's ? Sistemas stand-alone minúsculos que emplean las mismas baterías por un año entero o más. Estos sistemas registran los datos en la EPROM o FLASH ROM y descargan sus datos cuando son accedidos físicamente por un operador. A menudo estos sistemas usan procesadores de chip simple con memoria mínima y pueden no ser capaces de manejar un protocolo de comunicaciones sofisticado. ? Sistemas stand-alone pequeños que pueden accionar periódicamente a los sensores (o radios) para medir y/o reportar. Generalmente las baterías son mantenidas por energía solar con capacidad para mantener la operación por lo menos 4 meses durante la oscuridad completa. Estos sistemas tienen generalmente bastante capacidad para un esquema mucho más complejo de comunicaciones. ? Sistemas medios. Ordenadores industriales single board dedicados, incluyendo IBM-PC o compatibles en configuraciones industriales tales como VME, MultiBus, STD megabus, PC104, etc. ? Sistemas grandes. Completo control de planta con todas las alarmas visuales y sonoras. Éstos están generalmente en DCS en plantas, y se comunican a menudo sobre LAN de alta velocidad. La sincronización puede ser muy crítica. 2.2.3.6. Estándares Como fuera indicado, los RTU's son dispositivos especiales. Ha habido una carencia de estándares, especialmente en el área de comunicaciones, y los RTU's provenientes de un fabricante no se pueden mezclar generalmente con RTU's de otro. Una industria ha crecido desarrollando conversores y emuladores de protocolos. Algunos estándares han comenzado recientemente a emerger para RTU's, como DNPs e IEC870 para comunicaciones IEC1131-3 para programar RTU's. 2.2.3.7. PLC's contra RTU's Un PLC (Programmable Logic Controller) es un ordenador industrial pequeño que substituyó originalmente la lógica de los relés. Tenía entradas de información y salidas similares a las de un RTU. Contenía un programa que ejecutaba un bucle, explorando las entradas de información y tomando las acciones basadas en estas entradas de información. El PLC no tenía originalmente ninguna capacidad de comunicaciones, sino que comenzaron a ser utilizadas en situaciones donde las comunicaciones eran una característica deseable. Los módulos de comunicaciones fueron desarrollados así para

Los Sistemas SCADA.

20

PLC's, utilizando Ethernet (para el uso en DCS) y el protocolo de comunicaciones Modbus para el uso sobre conexiones dedicadas (cables). Con el correr del tiempo los PLC's soportaron protocolos de comunicación más sofisticados. Los RTU's se han utilizado siempre en situaciones donde son más difíciles las comunicaciones, y la potencia de los RTU's residía en su capacidad de manejar comunicaciones difíciles. Los RTU's tenían originalmente programabilidad pobre en comparación con los PLC's. Con el tiempo, la programabilidad del RTU ha ido aumentando. 2.2.3.7.1. Qué especificar

? Rango de temperatura para la aplicación, por ejemplo entre -10 y 65º C. ? Humedad relativa 0 a 95%. ? Protección del polvo, de la vibración, de la lluvia, de la sal y de la niebla. ? Inmunidad al ruido eléctrico. ? Consumo de energía. ? Capacidad de almacenamiento y de entrada-salida. Permita siempre algo de repuesto (alrededor 10-20%). ? Control de exactitud de entradas analógicas, y el tipo de señales digitales esperadas (ej. 0-5v). Programabilidad y flexibilidad de configuración. ? Diagnóstico - local y remoto. ? Capacidad de comunicaciones incluyendo soporte para radio, PSTN, landline, microonda, satélite, X.25. ? Recuerde que el uso del PSTN implica el timestamp y el grabado de los datos mientras no está conectado, y que el Master pueda marcar, validar esta reserva de datos, y llenar su base de datos con estos datos históricos (archivos incluyendo los de tendencia). También considere cómo las alarmas deben ser manejadas con PSTN. Considere los protocolos estándares tales como DNP3, IEC870, MMS en vez de protocolos propietarios. ? Funcionalidad soportada - ej.: timestamping, capacidad de memoria para salvar datos en caso de pérdida de comunicación, capacidad de hacer cálculos. ? Soporte para las comunicaciones punto a punto incluyendo almacenaje y capacidad de redespacho si las comunicaciones son complicadas (especialmente radio). ? Baud Rates utilizado (1200 baudios en FSK, o 9600 baudios en radios de datos).

? Usted puede requerir puertos seriales adicionales especialmente interconectar con PLC's.

Los Sistemas SCADA.

21

? Su Master debe soportar toda la funcionalidad del RTU, especialmente el timestamping de datos analógicos, y los protocolos de comunicaciones. ? Direccionabilidad máxima (Ej. máximo de 255 RTU's). ? Indicación local clara del diagnóstico. ? Chequeos de compatibilidad de la configuración del software contra el hardware actual. ? Capacidad de registro de todos los errores producidos y de acceso remoto a estos registros. ? Filtración por software de los canales de entrada de información analógica. 2.3. Generación de Proyectos Lo que sigue es una descripción muy breve de la generación de proyectos SCADA. Todas las metodologías de la gerencia de proyecto implican descomponerlo en fases, generalmente con entradas de aprobación al final de cada fase. 2.3.1. Identificación ? Identificar la necesidad ? Preparar la estimación preliminar de costes ? Obtener la aprobación para que los fondos o los recursos procedan a la fase próxima. Esta fase es normalmente informal, y no requiere de muchos recursos. La identificación de la necesidad podría haberse presentado como ligada a alguna otra actividad, por ejemplo del desarrollo de estrategias corporativas, revisión de la condición de la planta, o de las consecuencias de hacer frente a un incidente importante. Típicamente un sistema SCADA será requerido por alguna de las razones siguientes: ? Para reducir costos de energía. ? Para reducir costos de personal. ? Para reducir requisitos de capital futuros. ? Para mejorar el nivel del servicio. ? Para evitar incidentes ambientales. ? Para cumplir con requisitos regulatorios. ? Puede no ser posible ejecutar el negocio sin SCADA.

Los Sistemas SCADA.

22

? Para obtener un costo competitivo. ? Para sustituir un sistema existente obsoleto. A menudo SCADA no está rigurosamente justificado sino que es requerido simplemente por la gerencia como parte de la forma que la misma desea llevar el negocio. Ésta puede ser la mejor manera, pues los recursos a menudo substanciales son consumidos intentando dar una justificación para una implementación SCADA, y es extremadamente común que después de que el sistema esté instalado, se presenten beneficios inesperados que abruman las ventajas originalmente predichas. Además, las ventajas pueden presentarse multiplicadas por varias otras iniciativas claves que se estén desarrollando en paralelo, como la reingeniería del negocio, y a veces es imposible separar los beneficios de SCADA de los que se originan en otras iniciativas. Una gerencia progresista creará un clima en el cual el personal busque activamente las vías en las cuales mejorar la productividad de la organización. En otras organizaciones, tal propuesta será tratada con escepticismo. La clave de esto reside en que la gerencia desarrolle una visión de cómo quisiera que la organización se maneje en el futuro. El mundo de los años 90 requiere que las organizaciones lleguen a ser más chicas y más eficientes. Es difícil imaginar que estas tendencias se reviertan en los años próximos. Esta fase es crucial en cualquier proyecto SCADA. El éxito económico del proyecto se encarna en determinar la factibilidad inicial. El alcance del proyecto esencialmente se define en este punto. Por ejemplo si no se consideran los beneficios del uso de los horarios de tarifas eléctricas reducidas para reducir el costo de bombeo, es improbable que usted incluya esto en el proyecto SCADA en una etapa posterior. 2.3.2. Lanzamiento

? Validar la necesidad del proyecto. ? Establecer los conceptos y su alcance. ? Establecer una estructura sumaria de la subdivisión del trabajo. ? Estimación conceptual de costos (-30 a +50%) Generalmente una cierta cantidad de recursos financieros se ha aprobado en esta etapa para emprender las investigaciones preliminares, y preparar un plan preliminar de la administración del proyecto. Será necesario afirmarse en el alcance, identificar las tecnologías principales que se utilizarán, y ganar el acuerdo y la aprobación de los usuarios potenciales del sistema. Es harto necesaria la estimación del costo con una exactitud dentro del rango -30 a +50%, como así también establecer las ventajas del sistema con bastante exactitud para convencer a la gerencia de dar la aprobación para proceder con la siguiente fase. Un error común en este punto es entrar demasiado en detalles técnicos. El trabajo debe concentrarse en esta etapa en los requisitos funcionales (o de usuario), y los requisitos

Los Sistemas SCADA.

23

tecnológicos se deben mirar solamente al punto de permitir las estimaciones de costos con la exactitud señalada. El énfasis debe ponerse en asegurarse de que existe una comprensión común dentro de los usuarios finales de qué funcionalidad proporcionará el sistema. Si el sistema se está introduciendo para mejorar productividad, entonces es importante que la gerencia del usuario entienda cómo puede ser utilizado el sistema SCADA para optimizar prácticas de trabajo. Es importante en esta etapa que el equipo de proyecto incluya a alguien del sector usuario de la organización para comenzar a construir un sentido de la propiedad del sistema. Esta implicación debe continuar a través del proyecto para poder entregar el sistema final a un operador familiarizado en usarlo a su capacidad máxima. Aunque el trabajo debe concentrarse en los requisitos funcionales, es necesario vigilar las capacidades técnicas ofrecidas por los proveedores como "off the shell" en su industria. Restringiendo la cantidad de software de encargo que el sistema requerirá es probablemente la acción más importante que usted puede tomar para reducir costos, riesgos, y reducir al mínimo la duración global del proyecto. Una cierta idea preliminar de la estrategia de contratación deberá haber sido desarrollada. Se podrá por ejemplo utilizar consultores, contratos prediseñados (recomendados), etcétera. Como es evidente, esto puede tener un impacto substancial en costos. La decisión de utilizar consultores se debe tomar con sumo cuidado. Un consultor pudo haber preconcebido ideas en cuanto a cómo el proyecto debe ser manejado. Algunas decisiones tales como el uso de contratos prediseñados pueden no ser del agrado de un consultor, prefiriendo realizar él mismo el diseño por ejemplo. 2.3.3. Definición

? Designar a miembros como líderes de equipo. ? Desarrollar los lineamientos básicos y la agenda para la gerencia del proyecto. ? Evaluar los riesgos. ? Realizar estudios económicos. ? Desarrollar las estrategias contractuales. ? Desarrollar las estrategias de implementación. ? Realizar la estimación definitiva de costo con una máxima exactitud (-15 a +25%). El proyecto está comenzando en esta etapa a volverse serio. Se está concluyendo la vista preliminar (qué sitios, qué funcionalidad, etc.). Decisiones firmes se están tomando sobre estrategias contractuales tales como diseño y construcción, etc.

Los Sistemas SCADA.

24

El trabajo debe todavía concentrarse en esta etapa en los requisitos funcionales (o de usuario), y nuevamente los requisitos tecnológicos deben sólo observarse para permitir las estimaciones de costos. Es importante en esta etapa identificar firmemente las ventajas del sistema, y desarrollar "planes de realización de beneficios". Estos planes identificarán exactamente cómo las ventajas propuestas serán efectivizadas, por ejemplo, observando qué cambios serán realizados a los procesos existentes para alcanzar las ventajas previstas. Esto dará confianza a la gerencia que la inversión va a ser provechosa. 2.3.4. Diseño

? Revisiones de Diseño. ? Revisiones de los reportes de la etapa de definición. ? Justificación de los Fondos. ? Estimación de Diseño (-10%+10%). Esta fase implica normalmente la preparación de la especificación, y el desarrollo de planes de evaluación de licitadores. Es probable que una fase de precalificación pueda proceder en este momento a facilitar la tarea. La Precalificación se utiliza para pre-seleccionar a los licitadores de reputación que tienen una probada trayectoria en este campo. La Precalificación permite la selección de potenciales proveedores antes de que hayan emplazado una cotización, por ejemplo, en base a su capacidad y experiencia. Una decisión clave en esta etapa es exigir la presentación de pruebas específicas. En los años 80 los contratos rutinariamente especificaban pruebas de aceptación de fábrica, pruebas de implementación, pruebas de aceptación, etcétera. Esto era obligatorio en virtud de que la tecnología era nueva, costosa y la separación del diseño y la adquisición implicaban un alto grado de customización. La costumbre moderna es utilizar contratos prediseñados, y pagar por performance. Una prueba funcional es todo lo que se requiere desde la perspectiva del comprador. Si el proveedor desea ejecutar pruebas de aceptación de fábrica, es su decisión. 2.3.5. Adquisición

? Especificación y preparación del trabajo. ? Estimación de costos (después de la recepción de las ofertas) -5%+5%. ? Construcción. ? Fabricación fuera del sitio. ? Comisión.

Los Sistemas SCADA.

25

? Terminación práctica. Bajo contratos prediseñados, todo el trabajo detallado es realizado por un solo proveedor. Los participantes clave en esta etapa son: ? El encargado de proyecto del proveedor. ? El superintendente del contrato. ? El encargado de proyecto. El éxito del proyecto dependerá de la actuación de estos tres. En esta fase el proyecto pasará por un número de etapas: ? Diseño (que culmina en un informe del diseño del proveedor para su aprobación). ? Configuración del software principal de SCADA. ? Desarrollo del software a medida. ? Ensamble de RTU's en fábrica, y prueba. ? Instalación de la instrumentación de campo, de comunicaciones, y de RTU's. ? Comisión. ? Prueba de aceptación en el sitio. ? Entrenamiento del cliente. Subsiguiente a esto, el sistema tiene normalmente un período de detección de problemas, más allá del mantenimiento que debe ser contratado. 2.3.6. Liquidación Del Proyecto

? Reporte final del proyecto. ? Liquidación de defectos y mal funcionamientos. ? Depuración final. ? Revisión pos implementación. La revisión pos implementación es algo que raramente se encara, pero debe ser una parte obligatoria de todos los proyectos. Es importante que una evaluación sea hecha de cuán bien está el sistema resolviendo las necesidades de la organización como son ahora concebidas.

Introducción a Visual Basic 6.0

26

3. Introducción a Visual Basic 6.0 3.1. Conceptos de Visual Basic 6.0 3.1.1. Entornos de desarrollo visual. Desde la aparición de los primeros lenguajes de programación actuales, FORTRAN, COBOL y BASIC, hasta hace unos años, los entornos de programación han evolucionado lentamente. Los compiladores por línea de comandos dejaron paso, no hace mucho, a los llamados “entornos de desarrollo integrados”, desde los que es posible escribir el programan, compilarlo y depurarlo, sustituyendo en gran parte a los editores, compiladores tradicionales y depuradores separados. Sin embargo, ha sido sobre la plataforma Windows donde se ha evolucionado con mayor rapidez, pasando de estos EDI a los llamados entornos de desarrollo visual. Estos entornos se caracterizan, principalmente, porque el programador desarrolla su aplicación básicamente a partir del diseño de una interfaz. Crea una ventana, introduce en ella diversos componentes que simbolizan datos o acciones a llevar a cabo, establece propiedades de esos componentes y, donde es preciso, añade algo de código. El tiempo de desarrollo de cualquier aplicación se ve reducido de meses o semanas a días. Olvídese por completo de cómo se gestiona el ratón, de restablecer la porción de pantalla que había debajo al ocultar una ventana, de permitir al usuario mediante ciertas teclas moverse de un lugar a otro. Todo esto y más queda en manos del sistema y, en parte, del lenguaje. Por lo tanto usted puede centrarse en lo que realmente le interesa, el funcionamiento lógico de su aplicación, y no de la interacción del usuario con ésta. 3.1.2. Visual Basic Visual Basic fue uno de los primeros entornos de desarrollo visual para Windows. Pretendía facilitar el desarrollo de programas Windows a todos los programadores sin necesidad de tener que aprender otro lenguaje. Visual Basic no se parece nada, en apariencia, a aquel GwBasic o QuickBasic que estábamos acostumbrados a utilizar sobre Dos, aunque, por supuesto, sigue siendo BASIC. Eso sí, un BASIC muy evolucionado, que incorpora múltiples tipos de datos, la posibilidad de crear funciones y procedimientos, estructuras de control típicas de Pascal o C, orientación a objetos, capaz de crear nuevos componentes, etc. La mayor parte de los programadores en un momento y otro han utilizado BASIC, es más, la mayoría de ellos aprendieron a programar con este lenguaje. Por ello Visual Basic abre la puerta a la programación sobre Windows a prácticamente todo el mundo y no sólo a aquellos que conocen C y además conocen a fondo el funcionamiento de Windows. Si usted desea desarrollar sus propias aplicaciones para este entorno de una forma simple, desde luego Visual Basic es el lenguaje apropiado. Sin embargo se preguntará a cambio de qué obtenemos esta facilidad, qué perdemos. Desde Visual Basic tendrá al alcance la mayoría de las posibilidades Windows, podrá crear aplicaciones MDI, con soporte OLE, multimedia, acceso a bases de datos, etc. Bastante más de lo que actualmente ofrecen muchos compiladores de C o C++. Si los objetos

Introducción a Visual Basic 6.0

27

facilitados con Visual Basic y el propio lenguaje no cubren una cierta área, siempre tendremos acceso a la API de Windows, por lo que prácticamente tenemos todas las puertas abiertas. A pesar de ello Visual Basic, como se ha dicho antes, sigue siendo BASIC, por lo que siempre existirán operaciones, generalmente de bajo nivel, que son más accesibles a lenguajes como C. Visual Basic 6.0 nos permite, además de lo dicho anteriormente, desarrollar aplicaciones de 32 bits generando verdadero código nativo, lo que redunda en una mayor velocidad de ejecución. Nuestras aplicaciones podrán ejecutarse tanto sobre Windows NT como Windows 95/98. La creación de componentes ActiveX es una tarea fácil con Visual Basic 6.0, abriéndonos las puertas al desarrollo de objetos que podrán ser usados no sólo en nuestras propias aplicaciones, sino por cualquier otro entorno que soporte este tipo de componentes o incluso en páginas Web. Visual Basic 6.0 puede ser ampliado, es posible añadir otras opciones a nuestro menú, a partir de programas externos e incluso escribiendo esas nuevas opciones en el propio Visual Basic. Además de aplicaciones de tipo “estándar” también podemos crear aplicaciones IIS, para trabajar conjuntamente con nuestro servidor Web, e incluso aplicaciones DHTML ( Dynamic HTML). 3.2. Creación de aplicaciones con Visual Basic Antes de comenzar a trabajar con Visual Basic, es fundamental que conozcamos ciertos términos, elementos y estructuras con las que trabajaremos. 3.2.1. Proyectos Toda aplicación Visual Basic parte de la elaboración de un proyecto, nombre con el que se conoce al conjunto de formularios, módulos de clase, módulos de código y cualquier otro archivo necesario para nuestra aplicación. Los formularios contienen controles y métodos, los módulos de código definición de clases, procedimientos y funciones. Archivos adicionales pueden contener recursos, diseños de informes, etc. El proyecto establece, por lo tanto, todos los elementos que forman nuestra aplicación. Aparece como una ventan con una lista jerárquica, en la que podremos ver los archivos que lo forman, cada uno con el nombre de formulario o módulo correspondiente. Aunque lo habitual es que a medida que vamos creando formularios y módulos de código éstos se vayan incluyendo automáticamente en el proyecto, también es posible añadir elementos ya existentes, por ejemplo de otras aplicaciones ya escritas. De igual forma, en cualquier momento es posible eliminar cualquier elemento de un proyecto. Desde la ventana de proyecto podemos seleccionar cualquiera de los componentes de la aplicación haciendo doble clic. S i el elemento es un formulario éste se abrirá para edición, al igual que ocurre en caso de ser un control ActiveX. Si se trata de un módulo de código se abrirá una ventana donde podremos editarlo en forma de texto.

Introducción a Visual Basic 6.0

28

3.2.2. Archivos de un proyecto La definición de un proyecto se almacena en un archivo de texto, que tendrá el nombre que nosotros le demos ya la extensión VBP. En este archivo se almacena información general acerca de la aplicación: referencias a los controles que usa, el nombre del proyecto o su versión, etc. Visual Basic 6.0 nos permite tener abiertos varios proyectos de forma simultánea, pudiendo almacenarse la colección en un archivo que tendrá extensión VBG. Cada uno de los formularios contenidos en el proyecto se almacena separadamente en un archivo que tendrá el nombre del formulario y la extensión FRM. También se trata de un archivo de texto, similar a los archivos de recursos de otros lenguajes, en l que se define la posición y dimensiones del formulario y de cada uno de los controles que éste contiene. Además contiene el código correspondiente a los métodos asociados a los eventos que se hayan definido. En caso de que el formulario cuente con elementos que no sea posible describir mediante texto, como gráficos, existirá un archivo con el mismo nombre que el archivo FRM pero con extensión FRX. En este caso se trata de un archivo binario manipulado indirectamente al editar el formulario. Los módulos de código independientes de los formularios se almacenan en archivos con extensión BAS, como los tradicionales programas BASIC. Estos archivos contienen tan sólo declaraciones y código, en forma de procedimientos o funciones. En caso de que nuestro proyecto defina alguna clase de objeto nueva, esta definición se almacenará en un archivo con extensión CLS. También en este caso se trata de un archivo norma de texto, con la enumeración de las propiedades y los métodos necesarios para poder crear objetos de la clase que se define. Un proyecto puede contener también controles de usuario, diseñados por nosotros mismo, cuya descripción se almacena en archivos con extensión CTL. En caso de que el componente cuente con información binaria se crea también un archivo asociado con extensión CTX, con una estructura similar a los archivos FRX. En caso de que el control cuente con páginas de propiedades, éstas se almacenarán en archivos con extensión PAG. Además de formularios y códigos, es posible añadir a nuestros proyectos archivos conteniendo recursos, tales como mapas de bits o cadenas de texto. Estos archivos de recursos, que tendrán extensión RES, se editan mediante una herramienta específica integrada En Visual Basic. Los elementos mencionados son sólo algunos de los que podríamos encontrar en un proyecto, quizá los más habituales. Habría que añadir otros como los proyectos de datos, archivos con diseños de informes, diseños de HTML dinámico, etc. 3.2.3. Diseñadores y editores. Cada uno de los tipos de archivo anteriores es manipulado en Visual Basic mediante un determinado diseñador o editor, que facilita su edición. Los archivos de proyecto o grupoide proyecto, VBP y VBG respectivamente, se editan mediante el Gestor de proyectos. En esta ventana podemos añadir y eliminar elementos, abrirlos, establecer opciones, etc.

Introducción a Visual Basic 6.0

29

El diseñador más conocido de Visual Basic es el de formularios. Se trata de una ventana en la que los formularios del programa aparecen como se verán finalmente, al ejecutar la aplicación, permitiéndose la inserción y manipulado de componentes. Las interfaces de los programas tradicionales se elaboran mediante el diseñador de formularios. Una interfaz siempre cuenta, por lo general, con un código que la gestiona. Todo código Visual Basic, indistintamente de que esté asociado a un formulario, un módulo de clase o un módulo estándar, se manipula mediante el Editor de código. Se trata de un editor de texto sencillo que nos permite introducir, corregir y eliminar código, pero con capacidades extendidas como la diferenciación sintética por colores o la tecnología IntelliSense que ofrece ayuda inmediata a muchas acciones. Los controles de usuario se manipulan mediante un diseñador muy similar al de formularios, aunque con diferencias lógicas debidas a la distinta naturaleza de formularios y controles. Existen diseñadores más específicos, como los que permiten la edición de módulos de datos o el diseño de informes e interfaces con HTML dinámico. Algunos tipos de módulos, como los que contienen recursos, son editados con una herramienta independiente aunque accesible desde Visual Basic. 3.2.4. Formularios. El formulario es en Visual Basic el punto central de cualquier aplicación estándar, pudiendo ésta contar con uno o más formularios, según las necesidades. Un formulario es una ventana Windows en la que depositaremos los controles necesarios para crear nuestra interfaz con el usuario de la aplicación. El formulario cuenta por defecto con los elementos habituales de cualquier ventana Windows, como el control de menú de sistema, los botones de minimizar y maximizar o el borde por medio del cual es posible redimensionar la ventan. La barra de título del formulario se puede utilizar para desplazarlo de un punto a otro y el título que aparece en él es, por supuesto, establecido por nosotros. Las propiedades que por defecto tiene un formulario pueden ser modificadas durante el diseño de la aplicación, accediendo a la ventana de propiedades. En ella seccionaremos el título que deseamos darle, si debe tener o no botones de minimizar y maximizar, si debe ser o no redimensionable, etc. También es posible asociar código al formulario, abriendo la ventana de código y seleccionando el evento o mensaje que provocará su ejecución. Un formulario por sí solo tiene poca utilidad a no ser que en su interior insertemos controles. Esta es la finalidad principal de un formulario, agrupar una serie de controles por medio de los cuales poder presentar, y solicitar información al usuario. Estos controles pueden ser los estándar de Windows , como botones , listas, etiquetas de texto o botones de radio , otros controles incorporados por Visual Basic, como los controles que nos permiten presentar datos en rejillas o en forma de esquema, o bien ser objetos externos, como una imagen de Paintbrush o un documento de Word. En general podremos usar cualquier componente ActiveX u objeto OLE.

Introducción a Visual Basic 6.0

30

3.2.5. Controles ActiveX. La creación de aplicaciones con Visual Basic se basa principalmente en el uso de distintos controles. Algunos de ellos nos sirven para solicitar o presentar información al usuario, otros para generar un evento cada cierto tiempo, para buscar un archivo en el disco, o para contener una imagen. Estos controles, denominados tradicionalmente controles OLE, se encuentran almacenados en archivos separados ya compilados, conteniendo el código necesario para ser utilizados accediendo a sus propiedades y sus métodos. Actualmente existen infinidad de controles ActiveX, denominación con la que se conoce a este tipo de componentes. Visual Basic facilita un número importante de ellos, en la mayoría de las ocasiones nos serán suficientes para el desarrollo de nuestras aplicaciones. No obstante existen muchos otrosde terceros proveedores, e incluso podemos crear nuestros propios controles ActiveX con Visual Basic. Un control ActiveX no es útil sólo a la hora de crear una aplicación con Visual Basic, sino que puede ser usado con otras herramientas de programación. También es posible usarlos en la composición de páginas Web, haciéndolas más dinámicas y útiles. La facilidad con la cual Visual Basic permite la creación de controles ActiveX pone esta posibilidad al alcance de la mano de cualquier programador. 3.2.6. Propiedades. Todos los objetos con los que trabajamos en Visual Basic, desde el propio formulario hasta cada uno de los controles que podamos utilizar, tienen una serie de propiedades. Estas propiedades permiten personalizar el objeto, indicando su posición, dimensiones, color, aspecto, título, valor, etc. El trabajo de diseño en Visual Basic consiste básicamente en insertar objetos en un formulario y establecer cada una de sus propiedades. Hay propiedades que sólo pueden ser establecidas o modificadas durante el diseño de la aplicación, otras a las que sólo se puede acceder mientras la aplicación se está ejecutando y, por último, hay un tercer grupo que podemos utilizar tanto en tiempo de diseño como de ejecución. Como veremos en el próximo capítulo, el establecimiento y obtención de propiedades es muy simple tanto en el momento en que se está diseñando la aplicación, con la ventana de propiedades, como desde el código, durante la ejecución. Las propiedades pueden ser de distintos tipos, al igual que las variables, pudiendo contener un número entero, una cadena o un valor booleano, por poner un ejemplo. Ala hora de utilizar los valores de una propiedad, o de fijarlos, aplicaremos por lo tanto las mismas reglas que para las variables. Como veremos más adelante, es posible definir nuestros propios objetos con sus propiedades, así como crear procedimientos que se ejecutarán cada vez que se establezca u obtenga una determinada propiedad.

Introducción a Visual Basic 6.0

31

3.2.7. Eventos y métodos. Windows es un entorno gestionado por eventos que son generados por una acción exterior por parte del usuario, como el movimiento del ratón, la pulsación de una tecla o de uno de los botones del ratón, o bien por el propio Windows. Las aplicaciones desarrolladas para funcionar sobre este entorno tienen que trabajar dirigidas por estos eventos y no siguiendo la metodología clásica de programación utilizada en sistemas como DOS. Por ejemplo, un programa no puede estar esperando a que el usuario realice una entrada por teclado cuando se presenta el formulario, porque el usuario en ese momento puede pulsar sobre cualquier otro control del formulario y la aplicación, sin embargo, estaría aún esperando la entrada por teclado. Por ello en Visual Basic sobre DOS, en su lugar el código se encuentra delimitado en procedimientos que son llamados, cuando es necesario, por el propio Windows. Cada uno de los controles que podemos insertar en un formulario, incluido el propio formulario, puede recibir una serie de eventos, en unos casos comunes y en otros específicos de cada control. Por defecto Visual Basic no asocia función alguna a los controles para que respondan a estos eventos. Existen una serie de procedimientos de respuesta, llamados métodos, que en principio están vacíos y a los cuales nosotros podemos asociar el código que necesitemos. Por ejemplo, podríamos insertar un botón en el formulario y asociar unas líneas de código al método CLICK. Este método, y por lo tanto nuestro código, se ejecutará cuando Visual Basic reciba el evento de pulsación sobre el botón. Aunque cada uno de los controles que incorpora Visual Basic es capaz de responder a multitud de eventos, por regla general sólo se definen los métodos de algunos de ellos. Por ejemplo, par un botón estándar es posible definir código para los eventos que se producen cuando se mueve el cursor del ratón encima de él, cuando se aprieta un botón del ratón y cuando se suelta, pero habitualmente sólo se crea el método que responde al evento de pulsación general, tanto si se produce con el ratón como con el teclado. 3.2.8. Programación estructurada y orientación a objetos. Los programadores desde siempre han diferenciado los lenguajes entre estructurados, tipo Pascal o C, y aquellos que no lo eran, como el BASIC. Este último adolecía de las estructuras necesarias para distribuir el código de una forma clara, siendo necesario realizar saltos continuamente, lo peor, sin duda alguna, de este lenguaje. Visual Basic, por el contrario, cuenta con múltiples estructuras de control que nos permiten llevar a cabo la ejecución de una aplicación completa sin necesidad de realizar un solo salto. Ya hemos visto que podemos crear procedimientos y funciones eliminando así la necesidad de utilizar uno de los saltos de BASIC, el de la instrucción GOSUB. Asimismo contamos con varios tipos de bucles y estructuras de decisión múltiple, que desterrarán de una vez por todas el repetitivo GOTO. De esta forma conseguiremos que nuestro código sea mucho más legible y fácil de mantener. El siguiente paso lógico en la evolución de los lenguajes viene determinado por la orientación a objetos. Con esta metodología ya no existen procedimientos o funciones

Introducción a Visual Basic 6.0

32

aisladas, sino objetos que pueden ser usados para realizar determinadas tareas. Visual Basic cuenta con algunas características de orientación a objetos, dejando definitivamente atrás los tiempos de la compleja codificación lineal y monolítica. 3.2.9. Funciones y procedimientos. Además del código contenido en los métodos, que es ejecutado en respuesta a un evento, en ocasiones una aplicación necesita realizar otro tipo de operaciones que, por claridad y facilidad de mantenimiento, no es adecuado incluir en los propios métodos. En estas ocasiones lo que se hace es crear un módulo independiente incluyendo en él el código que necesitemos, debidamente estructurado en procedimientos y funciones. Un procedimiento es un conjunto de líneas de código al que se da un nombre, usado posteriormente para ejecutar ese código. La misma definición es válida para una función, con la única diferencia de que ésta devuelve un valor al finalizar su ejecución, mientras que un procedimiento no. El concepto de procedimiento y función no es nuevo para los programadores de Turbo Basic o Quick Basic, pero sí para aquellos que siempre utilizaron GwBasic y compiladores de BASIC estándar. En éstos la forma de crear trozos de código separados que eran llamados cuando se necesitaban eran las subrutinas, a las cuales se llamaba con GOSUB y de las que volvía con RETURN. Pues bien, un procedimiento no es ni más ni menos que eso, pero con la diferencia de que para ejecutarlo basta con utilizar su nombre. Tanto los procedimientos como las funciones pueden recibir parámetros, lo que facilita el paso de datos sin necesidad de tener que utilizar variables de ámbito global. Estos parámetros pueden ser pasados por valor o por referencia. En el primer caso el procedimiento o función recibe una copia de la variable que se pasa como parámetro, por lo que no puede modificar la variable original. En el segundo se recibe realmente la dirección de la variable, de tal forma que cualquier modificación que se efectúe en ella hará que al volver del procedimiento o función, el código que realizó la llamada encuentre la variable modificada. Dentro de una misma aplicación podemos tener múltiples módulos de código, conteniendo cada uno de ellos declaraciones, funciones y procedimientos. Cuando se da este caso, un procedimiento o función que se encuentre en un módulo no puede llamar a otro de un módulo distinto a no ser que éste último sea público. De forma similar a lo que ocurre con las variables, tanto los procedimientos como las funciones pueden ser públicos, utilizables desde cualquier otro punto de la aplicación, o privados, pudiéndose llamar tan sólo desde el módulo de código en el que están definidos. De lo anterior se puede deducir que si nuestra aplicación va a contar con múltiples procedimientos y funciones, lo más adecuado es crear varios módulos de código, almacenando en cada uno de ellos aquellas funciones o procedimientos que estén relacionadas de alguna forma o sean dependientes unos de otros.

Introducción a Visual Basic 6.0

33

3.2.10. Cuestiones de ámbito. A diferencia de lo que ocurre en los intérpretes y compiladores de BASIC tradicionales, en los cuales una variable declarada en un punto del programa es accesible desde cualquier punto, en Visual Basic las variables pueden ser globales, accesibles desde cualquier punto, públicas en un módulo, accesibles desde los métodos y funciones contenidos en un módulo de código, o privadas, accesibles tan sólo en el ámbito en que se ha declarado. Es una práctica común que todas las variables que se utilizan en métodos, funciones o clases de objetos sean privadas, evitando así que puedan ser manipuladas desde cualquier código externo. Este tipo de variable es creado automáticamente cada vez que se ejecuta el procedimiento o función y destruido cuando éste termina. Este hecho, por otra parte, reduce el consumo global de memoria, ya que la mayor parte de las variables existen tan sólo mientras se está ejecutando la porción de código en la que se declaran u la memoria que ocupan se libera al salir. Los especificadotes de ámbito, que son los que determinan si un identificador es público o privado, no son aplicables sólo a las variables sino que, como veremos posteriormente, pueden aplicarse a definiciones de tipos, declaraciones y otros elementos de una aplicación. 3.2.11. Clases y objetos. Aunque Visual Basic no es completamente un lenguaje orientado a objetos, sí que tiene algunas características de estos lenguajes. Entre estas características está la de poder definir clases de objetos, estableciendo qué propiedades y métodos tendrán. Para definir una clase insertaremos en nuestro proyecto un módulo de clase, en él especificaremos cada una de sus propiedades, escribiendo el código necesario para poder obtenerlas y modificarlas, así como las declaraciones de todos sus métodos. En cada archivo de módulo de clase tan sólo se puede definir una clase, pero es posible incluir varios módulos de este tipo en un mismo proyecto. Una clase es, en cierta forma, como una plantilla del objeto que deseamos crear. En realidad al definir la clase no se está creando el objeto, pero se están poniendo las bases para ello. Cuando en nuestra aplicación necesitamos un objeto de esta clase lo crearemos y en ese momento se tomará la definición efectuada previamente para establecer las propiedades y métodos del nuevo objeto, a los que podremos acceder como si se tratase de cualquier otro control Visual Basic. ¿Qué diferencia hay entre crear una clase y definir un procedimiento o una función? Básicamente una: un procedimiento es un conjunto de líneas de código que podemos ejecutar, no cuenta con propiedades ni métodos, mientras que un objeto encapsula en su interior todo lo necesario para su funcionamiento, no sólo código, también todas aquellas variables e incluso otros objetos que le sean necesarios. El objeto no se ejecuta sin más, como un procedimiento, sino que se crea, se establecen y obtienen propiedades y se utilizan sus métodos. Es una entidad muy superior a un procedimiento o función.

Introducción a Visual Basic 6.0

34

3.3. Una primera aproximación. Inicialmente Visual Basic 6.0 trabaja con una interfaz MDI en la que una ventana principal contiene al resto de las ventanas del entorno. Éstas aparecen adosadas unas a otras, de tal forma que al cambiar el tamaño de una de ellas estaremos afectando indirectamente a la que se encuentra a su lado. Mediante una serie de opciones podemos tanto seleccionar qué ventanas deben estar adosadas como el tipo de interfaz, que en lugar de ser MDI puede ser SDI, caso en el que cada ventana aparece como independiente de las demás. En la figura3.1. puede ver el aspecto típico de la pantalla tras cargar Visual Basic 6.0. En ella podemos distinguir una ventana en la parte superior, distribuida horizontalmente, con el menú y la barra de botones. Ésta es la ventana principal de Visual Basic. Otra ventana contiene una serie de botones representando objetos, es la llamada caja de herramientas. También podemos encontrar un formulario vacío, preparado para que comencemos a trabajar sobre él. La ventana de proyecto estará asimismo a la vista, de igual forma que la lista de propiedades y la ventana de posición en pantalla. Estas ventanas, las de proyecto, propiedades, formulario, etc., no pueden ser minimizadas aunque sí cerradas. Esta es una diferencia debida al hecho comentado de que por defecto las ventanas estén unas adosadas a otras. Sin embargo, si minimizamos la ventana principal de Visual Basic, la que contiene el menú y la barra de botones, automáticamente se cerrarán también todas las demás ventanas y en la barra de tareas tan sólo aparecerá un icono, el que representa a Visual Basic. A lo largo de este capítulo nos familiarizaremos con este entorno de trabajo, aunque no se describirán de forma pormenorizada cada una de las opciones del menú o cada uno de los botones. Tenemos que conocer este entorno para comenzar a trabajar, pero a partir de aquí será el uso continuado de él lo que nos vaya dando a conocer todas sus posibilidades.

Figura 3.1. Aspecto inicial de Visual Basic 6.0

Introducción a Visual Basic 6.0

35

3.3.1. Menú y barra de botones. La ventana principal se distingue de las demás por su título, Microsoft Visual Basic, y por contener el nombre del proyecto sobre el que se está trabajando y el modo actual de trabajo: diseño, ejecución, etc. En esta ventana encontraremos el menú de opciones principal, así como la barra de botones a partir de los cuales podremos efectuar las operaciones más habituales. Veamos brevemente el contenido general de cada una de las persianas de este menú principal. Archivo. Aquí encontraremos las opciones necesarias para crear un muevo proyecto o cargar uno ya existente, añadir un nuevo proyecto, salvar un archivo individual, salvar todo el proyecto, imprimir los formularios o el código de la aplicación y generar un ejecutable. Al final de esta ventana siempre encontraremos una lista con los últimos archivos sobre los que hemos trabajado, permitiéndonos así un acceso rápido a ellos. Edición. En el menú de edición, además de las opciones típicas de deshacer, rehacer, cortar, copiar, pegar, búsqueda y sustitución, encontraremos otras que nos permitirán controlar la identación del código, insertar un archivo, controlar marcar en el texto o abrir distintas ventanas de ayuda con listas de constantes, métodos. Ver. Dentro de este menú encontraremos todas aquellas opciones que nos permiten seleccionar la información que deseamos ver en un momento dado. El código asociado a un control, el formulario, el proyecto, la barra de herramientas o la paleta de colores, la lista de propiedades o la ventana de ejecución inmediata, etc. También encontraremos una opción, Barras de herramientas, con la que podremos eliminar o visualizar las diferentes barras de botones de Visual Basic. Proyecto. Las opciones que encontraremos aquí nos permitirán insertar en nuestro proyecto nuevos formularios, si es que va a tener más de uno módulo de código o definición de clases, nuevas funciones y procedimientos e incluso insertar archivos de texto externos. También tenemos opciones para establecer los componentes que deben aparecer en la paleta de herramientas, las referencias disponibles o las propiedades del proyecto. Formato. La alineación, espaciado, posición en profundidad y, en general, todo lo que afecta al formato de los componentes en el formulario puede ser gestionado mediante las opciones agrupadas en este menú. Depuración. Visual Basic 6.0 dispone de multitud de opciones que facilitan la depuración de los programas, permitiendo la ejecución paso a paso, disposición de puntos de parada, evaluación de expresiones, etc. Ejecutar. Este menú contiene todas las opciones relacionadas con la ejecución del programa desde dentro del entorno Visual Basic. Herramientas. Aquí encontraremos las herramientas que nos permitirán añadir nuevos procedimientos al código, inspeccionar los atributos de los ya existentes, diseñar menús o establecer las opciones generales de trabajo y entorno.

Introducción a Visual Basic 6.0

36

Complementos. Visual Basic 6.0 está abierto a la utilización de otras herramientas no incorporadas en el propio entorno y para ello existe este menú. En él encontraremos opciones externas, tales como el Administrador visual de datos, y una opción mediante la cual es posible añadir otras opciones a este menú. Ventana. Este menú contiene las típicas opciones que permiten disponer las ventanas del entorno en una determinada disposición, según que nos interese en cada momento. Ayuda. Es éste un menú existente en la práctica totalidad de las aplicaciones, cuya finalidad es ayudarnos en cualquier momento en que tengamos una duda. En él encontraremos una referencia de todas las funciones, objetos y propiedades de Visual Basic, así como ejemplos y tutoriales. También disponemos de enlaces a distintas informaciones en la Web. Los botones que encontramos justo debajo del menú de opciones ponen al alcance, de una manera más inmediata, las operaciones más habituales con las que tendremos que trabajar. Aunque la mayoría de estos botones son autoexplicativos, sobre todo una vez que ya conoce el entorno, bastará con situar el cursor del ratón un momento sobre uno de ellos para que aparezca una etiqueta, indicándonos la función del botón. Si por ejemplo situamos el cursor sobre el botón que representa un disco, en un momento aparecerá una etiqueta con la literatura “Guardar proyecto”, indicándonos que si pulsamos ese botón el proyecto actual será guardado. Si estas etiquetas de ayuda no aparecen es porque se ha desactivado esta opción, para volver a activarla abra el menú Herramientas, elija la opción Opciones y en la página General marque la opción Mostrar información sobre herramientas. Algunos de los botones tienen asociada una lista desplegable, que aparecerá sólo si pulsamos sobre la flecha que apunta hacia abajo. El primer botón, a la izquierda, añade directamente un nuevo proyecto EXE al entorno, pero pulsando en la flecha que hay a la derecha podremos elegir el tipo de proyecto que deseamos añadir. En la misma barra de botones, en el extremo derecho, podemos ver dos indicadores que nos servirán para conocer la posición de cada uno de los controles y sus dimensiones. El primero de ellos nos indica el punto de inserción del control dentro del formulario, refiriéndose siempre a la esquina superior izquierda del objeto. El segundo nos indica las dimensiones del control. Estas medidas, tanto la posición como las dimensiones, vienen expresadas en “twips”, una unidad de medida inventada con la finalidad de evitar problemas cuando una aplicación desarrollada bajo una determinada resolución de pantalla es utilizada posteriormente en un equipo con una resolución y el tamaño del monitor. Por ello se toma como referencia una medada más establecida. Aunque por defecto la única barra de herramientas visible es la llamada estándar, pulsando el botón derecho del ratón sobre ella accederemos a un menú emergente con opciones para activar otras barras, con botones asociados a acciones relacionadas con el diseño de formularios, la edición o la depuración. También tenemos una opción que permite personalizar cada una de estas barras de herramientas, eliminado o añadiendo botones, estableciendo la imagen de cada uno de ellos, etc.

Introducción a Visual Basic 6.0

37

3.3.2. Uso del botón derecho del ratón. Cada vez es mayor el número de aplicaciones Windows, sobre todo desde la aparición de Windows 95, que utilizan el botón derecho del ratón, principalmente presentado un menú flotante sensible al contexto. Visual Basic es un de estas aplicaciones. Que un menú sea sensible al contexto significa que sus opciones no son fijas, sino que dependiendo del punto en el que nos encontramos al pulsar el botón derecho las opciones cambiarán, habrá más o menos, unas estarán activadas y otras no. Si pulsamos el botón derecho del ratón sobre un formulario vacío veremos que aparece un menú con opciones para visualizar las propiedades del formulario, el código asociado o para llamar al diseñador de menús. Efectuando la misma operación sobre cualquier control que insertemos en el formulario veremos que el menú es distinto, ahora tenemos opciones para cortar y pegar, alinear el control a la rejilla del formulario y permanecen las opciones de visualizar propiedades y código. En la figura 3.2 puede ver uno de estos menús emergentes o sensibles al contexto. Siempre que esté trabajando y necesite realizar una determinada operación no es mala idea pulsar el botón derecho del ratón, en muchas ocasiones tendremos la opción deseada al alcance de nuestros dedos.

Figura 3.2. Menú emergente con opciones para un control.

3.3.3. El formulario. Como se ha dicho anteriormente, el formulario es el punto a partir del cual se desarrolla cualquier aplicación Visual Basic. Básicamente se trata de una ventana estándar Windows en la que podremos insertar los controles que necesitemos para presentar datos, solicitarlos o definir ciertos procesos. Cuando entramos en Visual Basic seleccionando un proyecto EXE automáticamente aparece un formulario vacío, en el que podemos comenzar a trabajar. Tanto este formulario como cualquier otro que nosotros insertemos posteriormente, tiene unas características definidas por sus propiedades, que podemos ver y modificar en la ventana del mismo nombre. Por defecto el título del formulario es Form1, al igual que su nombre. Estos dos términos, título y nombre, son fáciles de confundir. La mayoría de los controles tienen un título que

Introducción a Visual Basic 6.0

38

no es más que el texto que aparece en el control, no teniendo en realidad ninguna correspondencia ni referencia en el código de la aplicación. Dicho título puede obtenerse y modificarse por medio de la propiedad Caption. El nombre del control o formulario, por el contrario, sí que es referenciado en el código cada vez que se quiere manipular ese objeto. El nombre de un control, que se establece durante el diseño de la aplicación, no será modificado posteriormente y se utilizará tanto para acceder a las propiedades de ese objeto como para realizar cualquier otro tipo de operación con él. La propiedad correspondiente al nombre del objeto es Name. Además del nombre y título del formulario existen otra serie de valores por defecto que se toman con cada formulario nuevo, como son la existencia de un control de menú de sistema, unos botones para cerrar, minimizar y maximizar y un borde que permite que el formulario sea redimensionado. La propiedad ControlBox, que por defecto tiene el valor True, es la responsable de que la ventana cuente con un menú de sistema. Simplemente estableciendo esta propiedad con el valor False eliminaremos dicho menú. Las propiedades equivalentes para los botones de minimizar y maximizar son MinButton y MaxButton, respectivamente, que también por defecto toman el valor True. Para modificar el tipo de borde de la ventana utilizaremos la propiedad BordeStyle, que puede tomar los valores mostrados en la tabla 3.1. El valor tomado por defecto por esta propiedad es vbSizable, por lo que el formulario cuenta con un borde grueso que, además, permite que la ventana sea cambiada de tamaño.

Tabla 3.1. Tipos de borde para un formulario (propiedades BordeSytle).

Constante Tipo de borde vbBNone La ventana no tiene borde alrededor vbFixedSingle Borde simple no redimensionable vbSizable Borde grueso redimensionable vbFixedDouble Borde grueso no redimensionable vbFixedToolWindow Borde no redimensionable con área de título vbSizableToolWindow Borde redimensionable con área de título

Como podrá ver en la ventana de propiedades, un formulario tiene multitud de ellas. Habitualmente sólo se modifican algunas de ellas y las demás permanecerán con los valores asignados por defecto. A continuación vamos a conocer algunas de estas propiedades. Muchas de estas propiedades son idénticas a las que tienen otros controles Visual Basic, por lo que una vez que las conozcamos nos serán útiles en muchos casos y no sólo cuando creemos un formulario. En ocasiones puede parecer sin sentido darle un cierto valor a una propiedad mientras se diseña el formulario, pero debemos tener en cuenta que las propiedades no sólo se establecen en tiempo de diseño de la aplicación, sino también en tiempo de ejecución.

AutoRedraw. La mayor parte de las entidades que aparecen en un formulario: botones, etiquetas de texto, listas, etc., saben cómo dibujarse a sí mismas. Cuando Windows necesita actualizar la visualización de una ventana lo que hace es enviarle un mensaje. Este mensaje, recibido por la ventana, se envía a cada uno de los controles existentes, procediendo cada uno de ellos con el proceso necesario para dibujarse. Sin embargo, hay ocasiones en las que es posible dibujar o escribir en un formulario sin utilizar un control,

Introducción a Visual Basic 6.0

39

por ejemplo utilizando la instrucción Print. El texto que aparece en el formulario puede ser en cualquier momento tapado por otra ventana, o no visible porque el formulario se haya modificado de tamaño, en cualquier caso, cuando sea necesario redibujar el contenido del formulario el texto no volverá a aparecer, porque el texto impreso con Print no está asociado a ningún control que se haga responsable de su actualización. Dando el True a esta propiedad, que por defecto es False, conseguiremos que todas las acciones de impresión y dibujo sobre el formulario no vayan directamente a pantalla, sino a un mapa de puntos mantenido en memoria a partir del cual se dibujarán en pantalla. Esta técnica permite recuperar el contenido completo del formulario aún cuando éste se haya perdido en pantalla y no exista ningún control asociado, porque en realidad el aspecto que debe tener el formulario en pantalla no es generado directamente sobre ésta, sino que se encuentra almacenado en memoria. Ba ckColor. Establece el color de fondo del formulario. Enabled. El valor por defecto de esta propiedad es True, indicando que en principio el formulario está activado y por lo tanto el usuario puede interactuar con él. Dándole el valor False desactivaremos el formulario, impidiendo así que el usuario trabaje con él. ForeColor. Establece el color de primer plano en el formulario. Height. Contiene la altura del formulario. Habitualmente esta propiedad nunca es rellenada manualmente sino que toma su valor automáticamente cuando redimensionamos la ventana. Icon. Podemos asignar a esta propiedad un icono que será visualizado en la esquina superior izquierda de la ventana, así como en la Barra de tareas cuando la aplicación esté ejecutándose. KeyPreview. Cuando en un formulario que contiene varios controles se pulsa una tecla, normalmente es el control que está activo el que recibe esa pulsación y, en caso de no ser procesada, se pasa al formulario. Dando a esta propiedad el valor True, por defecto es False, indicaremos que las pulsaciones se pasen primero al formulario en laugar de al control que está activo. Left. Al igual ocurre con Height, esta propiedad, que contiene la posición horizontal del formulario, se rellena automáticamente cuando desplazamos el formulario, aunque también es posible asignarle directamente un valor. Mouse Pointer. El icono del ratón, como ya sabe, es habitualmente una flecha. En ocasiones este icono cambia cuando se desplaza por ciertas aplicaciones. En un procesador de textos en lugar de la flecha suele aparecer una línea vertical delimitada por dos horizontales, en los programas de dibujo suele aparecer una cruz. Con esta propiedad podemos fijar el tipo de icono para el puntero del ratón cuando éste se encuentre sobre nuestra ventana. Podemos elegir entre una serie de iconos predefinidos o bien la opción Custom, caso en el cual facilitaremos con la propiedad Mouselcon el icono que se utilizará. Picture. Por medio de esta propiedad podemos establecer un gráfico como fondo del formulario. Dicho gráfico puede ser pegado desde otra aplicación o bien leído desde un archivo BMP, WMF, JPG o GIF.

Introducción a Visual Basic 6.0

40

ShowlnTaskBar. Esta propiedad, que por defecto tiene el valor True, determina si en la Barra de tareas de Windows debe aparecer o no un icono representando al formulario, una vez que el programa esté ejecutándose. Tag. Se trata de una propiedad que Visual Basic no utiliza en ningún caso. Su única finalidad es permitirnos asociar al formulario cualquier información que necesitemos. Top. Establece la posición vertical del formulario y junto con Left conforma la coordenada de la esquina superior izquierda de éste. Visible. Normalmente esta propiedad siempre toma el valor True en tiempo de diseño, indicando así que el formulario será visible cuando se ejecute la aplicación. Asignándole el valor False en cualquier momento conseguiremos que el formulario no sea visible. Width. Almacena la anchura del formulario y junto con Height fija las dimensiones del formulario. WindowsState. Cuando se ejecuta una aplicación habitualmente el formulario aparece en pantalla en la posición y con las dimensiones que se establecieron durante el diseño. Este es el estado normal de la ventana, que equivale al valor vbNormal de esta propiedad. Asignándole el valor vbMinimized la ventana aparecerá inicialmente minimizada, como un icono, y usando el valor vbMaximized conseguiremos que la ventana esté inicialmente maximizada, ocupando toda la pantalla. Como verá, muchas de estas propiedades toman su valor automáticamente según trabajamos con el formulario mientras lo diseñamos, mientras que otras toman por defecto el valor más apropiado, por lo que son habitualmente pocas las propiedades que tendremos que modificar en el diseño. 3.3.4. La rejilla. Como habrá observado en la figura 1.1, el formulario tiene en su interior una rejilla o matriz de puntos, que en ningún caso aparecerá en la ventana durante la ejecución. La finalidad de esta matriz de puntos es facilitarnos la correcta alineación de los distintos controles que vayamos insertando, siendo definible tanto la densidad de la matriz como la característica de que los controles se alineen siempre con uno de los puntos de la rejilla. Si abre la página General de la ventana que aparece al elegir la opción Opciones del menú Herramientas, podrá ver, como en la figura 3.3, una serie de opciones agrupadas en varios apartados. En ella podemos indicar que la rejilla aparezca o no, marcando o no la opción Mostrar cuadrícula, así como fijar el número de twips, tanto en sentido horizontal como vertical, que habrá de distancia entre un punto y otro. Por último podemos, con la opción Forzar controles a cuadrícula, indicar a Visual Basic que cada vez que se inserte o mueva un control éste se coloquen el punto más cercano de la matriz a la posición donde nosotros lo hemos dejado, pero siempre ajustándose a las líneas y columnas de la matriz, lo que facilita enormemente el posicionamiento de los controles. Una vez haya fijado las opciones según sus preferencias simplemente pulse Intro o el botón Aceptar para que éstas tengan efecto.

Introducción a Visual Basic 6.0

41

Figura 3.3. Configuración de las opciones generales del entorno.

3.3.5. El menú emergente. Pulsando el botón derecho del ratón sobre cualquier punto del formulario, excepto la barra de título, aparecerá un pequeño menú de opciones que nos da acceso a operaciones habituales durante el diseño. Tenga en cuenta que si debajo del cursor del ratón hay un control, el menú que aparece será el correspondiente a ese control y no al formulario. Debe por lo tanto buscar un área en la que realmente pulse sobre el formulario. La primera opción de este menú es Ver código. Al seleccionarla se abrirá la ventana de código, en la que podremos seleccionar uno de los posibles eventos y asociarle el código, en la que podremos seleccionar uno de los posibles eventos y asociarle el código que nos interese. También podemos abrir la ventana de código simplemente haciendo doble clic en cualquier punto de la superficie del formulario. En segundo lugar tenemos la opción Editor de menús, que nos permitirá diseñar un menú para el formulario sobre el que estamos trabajando. A continuación encontramos la opción Bloquear controles, cuya finalidad es impedir la alteración de la posición y dimensiones de los controles. Esto es útil cuando se está trabajando con un formulario pero la interfaz ya está definida y no se quiere correr el riesgo de modificarla por error. La cuarta opción de este menú es Pegar, que no s permite pegar un control que hayamos copiado previamente en el portapapeles. Para cortar, copiar y pegar elementos de un formulario puede utilizar la técnica común a muchas aplicaciones Windows, Control+X corta, Control+C copia y Control+V pega. También podemos utilizar <Control+Insert> para copiar y <Mayúsculas+Insert> para pegar. Una tercera posibilidad es utilizar las opciones Cortar, Copiar y Pegar del menú Edición.

Introducción a Visual Basic 6.0

42

Propiedades es la siguiente opción del menú emergente. Su finalidad es activar la ventana de propiedades, mostrándola si es que no está visible, seleccionando las propiedades del formulario y activándola. Si, como es habitual, tiene abierta siempre la ventana de propiedades a la derecha del formulario que está diseñando, bastará con pulsar sobre el formulario, con el botón izquierdo del ratón, para que aparezcan sus propiedades. Por último tenemos una opción que tan sólo estará activada en caso de que en el formulario existan controles de usuario, es decir, controles que estamos creando nosotros en el mismo proyecto. Dicha opción actualiza el aspecto y comportamiento del control en el formulario, acción precisa tras realizar modificaciones al control. 3.3.6. La ventana de propiedades. El aspecto y muchas de las características de los formularios y controles que podemos encontrar en una aplicación Visual Basic vienen definidos por sus propiedades. Las propiedades se pueden establecer en el momento del diseño, aunque algunas de ellas pueden ser también modificadas durante la ejecución. Mientras estamos diseñando un formulario tendremos que trabajar continuamente con propiedades, tanto del formulario como de los controles que éste contenga. En la barra de título de la ventana podemos ver la palabra Propiedades seguida del nombre del control al que corresponde la lista. Si deseamos ver las propiedades de cualquier otro control pulsando sobre él con el botó izquierdo del ratón, o bien abrir la lista que hay en la ventana de propiedades justo debajo del título y elegir entre todos los objetos el que deseamos. La lista de propiedades se divide en dos columnas: la izquierda contiene el nombre de la propiedad, que es invariable, mientras que la derecha contiene el valor actual de esa propiedad. La modificación de una determinada propiedad se llevará a cabo de un modo u otro dependiendo de su tipo. Si la propiedad contiene un nombre, como puede ser el título del objeto (propiedad Caption), o un número, como la anchura (propiedad Width), bastará con poner el cursor sobre el valor actual de la propiedad y escribir sobre ella o modificarla. Al pulsar Intro la propiedad tomará el nuevo valor. En caso de que el valor de la propiedad deba ser tomado de una lista, al pulsar sobre el valor aparecerá en el extremo derecho una flecha que nos permitirá abrir esta lista, seleccionando el nuevo valor. En este caso también cabe otra opción., que es hacer doble clic sobre el nombre de la propiedad, cada vez que lo hagamos ésta tomará el siguiente valor de la lista. El tercer tipo de valor que puede tomar una propiedad puede ser un código de color, un determinado tipo de letra, un icono o un mapa de bits, etc. En todos estos casos podemos hacer doble clic sobre el nombre de la propiedad, momento en el que aparecerá una ventana con los posibles colores, una lista con los tipos de letra disponibles o una ventana de selección de un archivo. Aquellas propiedades que contienen un dibujo o icono pueden obtener esa información directamente desde el portapapeles, lo único que tendremos que hacer es almacenarla en el portapapeles, desde cualquier programa de dibujo o de creación de iconos, y a continuación situar el cursor sobre la propiedad y pegar. De esta forma podríamos, por

Introducción a Visual Basic 6.0

43

ejemplo, realizar un dibujo con el programa Saint para a continuación copiarlo en el portapapeles y pegarlo como fondo de un formulario, usando la propiedad Picture.

Figura 3.4. Ventana de propiedades.

3.3.7. La paleta de herramientas. Otra de las ventanas que habitualmente siempre se tiene abierta, junto al formulario que se está diseñando, es la de herramientas, ya que en ella seleccionamos los controles que deseamos insertar. Esta caja de componentes es la que puede ver en la figura 3.5. Como ya vimos anteriormente, esta ventana no podemos minimizarla, no tiene título y la barra en la que normalmente aparece éste es sólo lo suficientemente alta como para contener el control que nos permite mover la ventana y cerrarla. En caso de que no tengamos a la vista la paleta de herramientas bastará con seleccionar la opción Cuadro de herramientas del menú Ver para que aparezca. Al igual que ocurría con la ventana de

Introducción a Visual Basic 6.0

44

propiedades, podemos indicar a Visual Basic que esta ventana esté acoplada a las de su alrededor.

Figura 3.5. La caja de herramientas de Visual Basic.

La paleta de herramientas contiene una serie de iconos, cada uno de los cuales representa un determinado control o una herramienta. Por regla general a partir del propio icono sabremos el control del que se trata pero, en cualquier caso, y al igual que ocurría con la barra de botones, dejando el puntero del ratón un momento sobre cualquiera de los iconos aparecerá una etiqueta indicándonos el nombre del control. 3.3.8. Inserción de un control. La herramienta seleccionada siempre por defecto y que aparece pulsada en la paleta de herramientas es el cursor o Puntero. Con él podemos seleccionar cualquier objeto, moverlo, modificar su tamaño, etc. Para insertar en el formulario cualquiera de los controles disponibles en la paleta de herramientas lo primero que tendremos que hacer será pulsarlo, tras lo cual podremos desplazar el cursor, que cambiará a una cruz, hasta el formulario. Fijaremos la cruz en lo que será la esquina superior izquierda del control y pulsaremos el botón izquierdo del ratón, sin soltarlo nos desplazaremos hasta la esquina opuesta, fijando así las dimensiones del control. Tras la inserción de un control se selecciona automáticamente de nuevo el Puntero, permitiéndonos así recolocarlo o modificar su tamaño. Tenga en cuenta que no todos los

Introducción a Visual Basic 6.0

45

controles son redimensionables, algunos tienen un tamaño fijo, por lo cual por mucho que intentemos modificarlos siempre recuperarán su tamaño original. Si tiene activada la opción Forzar controles a cuadrícula que vimos anteriormente, notará que al desplazar un control por el formulario se mueve a pequeños saltos, de punto a punto de la rejilla, evitando así que el control quede entre dos puntos y sea posteriormente más difícil su alineación con otros. Mientras tengamos seleccionado un control alrededor de él aparecerá un recuadro, como puede ver en la figura 3.6, con varios puntos marcados con unos pequeños cuadraditos. Este recuadro nos indica que es ése y no otro el control sobre el que recaerán las acciones que llevemos a cabo. Si, por ejemplo, pulsamos la tecla Suprimir el control se borrará, pulsando Control+Insert el control se copiará en el portapapeles. Los cuadraditos que aparecen en el recuadro nos marcan los puntos a partir de los que podremos redimensionar el control, horizontalmente, verticalmente o en ambos sentidos. Al posicionar un control, y establecer su tamaño fíjese en el extremo derecho de la barra de botones de Visual Basic, allí encontrará la posición en la que está el control y sus dimensiones.

Figura 3.6. Un control seleccionado en el formulario.

3.3.9. El menú emergente. Al igual que ocurría con el formulario, pulsar el botón derecho del ratón sobre cualquier control, no en la paleta de herramientas sino ya insertado, aparecerá un menú con opciones relacionadas con él. Las opciones de este menú dependerán del control de que se trate, aunque existen algunas comunes a todos ellos, como las que se describen a continuación. Cortar/Copiar/Pegar. Son las operaciones de cortar, copiar y pegar del portapapeles. Cualquier control puede ser copiado al portapapeles y pegado posteriormente, obteniéndose un control idéntico, en título, dimensiones, etc., porque el control se copia junto con todas sus propiedades. Eliminar. Equivale a pulsar la tecla Suprimir teniendo el control seleccionado. Su finalidad es eliminar el control del formulario.

Introducción a Visual Basic 6.0

46

Traer al frente/Enviar al fondo. Modifica la posición del control en el eje Z o de profundidad, trayéndolo encima de todos los demás o enviándolo debajo de los ya insertados. Ver código. Seleccionar esta opción equivale a hacer doble clic sobre el control, acción que abre la ventana de código con el cursor situado en el lugar correspondiente a sus métodos. Alinear a la cuadrícula. En caso de que tengamos seleccionada la opción Forzar controles a la cuadrícula, en el menú Herramientas opción Opciones, es posible que un control se quede entre dos puntos. Con esta opción del menú emergente el control modificará su posición moviéndose a la más cercana marcada por un punto. Propiedades. Esta opción activa la ventana de propiedades, haciéndola visible si no lo era, y selecciona las propiedades del control activo, permitiéndonos su edición. S i tenemos siempre abierta la ventana de propiedades, como es habitual, bastará con seleccionar un control, pulsándolo con el botón izquierdo del ratón, para que automáticamente aparezcan sus propiedades. Ciertos controles al seleccionar la opción Propiedades del menú emergente no actúan así, sino que abren una ventana a veces con varias pestañas, en la que es posible establecer las propiedades del control de una forma más simple y directa. En caso de que se hayan seleccionado varios controles simultáneamente, pulsando sobre ellos con el botón izquierdo del ratón mientras se mantiene pulsada la tecla de mayúsculas, las acciones que llevemos a cabo con las opciones de este menú emergente recaerán sobre todos ellos. Si seleccionamos Eliminar todos ellos desaparecerán, si elegimos Propiedades aparecerán las propiedades comunes a todos ellos, modificando una de ellas se modificará la propiedad correspondiente de cada uno de los controles. Esto en ocasiones puede ser muy útil, imagine que tiene un formulario con varios botones dispuestos verticalmente, uno debajo de otro, y desea darle a todos ellos la misma altura y anchura. En lugar de ir seleccionando cada uno de los controles y modificando estas propiedades individualmente, es más fácil seleccionar todos los botones y seguidamente establecer las nuevas dimensiones, que afectarán a todos los controles seleccionados. También podemos utilizar las opciones del menú Formato para conseguir el mismo efecto. Una forma rápida de seleccionar varios controles, en lugar de pulsar uno a uno manteniendo pulsada la techa de mayúsculas, es marcar un cuadro, con el puntero normal, sobre el formulario que contenga todos los controles que deseamos marcar. Situamos el cursor por encima y a la izquierda del primer control, pulsamos el botón izquierdo del ratón y, sin soltarlo, nos desplazamos algo más abajo y a la derecha del último control. Cuando soltemos el botón del ratón aparecerán como seleccionados todos los controles que quedaban dentro del cuadro. 3.3.10. Bloquear controles. A veces ocurre que durante la edición de un formulario, cuando ya se tienen perfectamente colocados los controles y lo único que se quiere es editar algunas propiedades o escribir nuevo código, al pulsar sobre un control inadvertidamente lo desplazamos, lo que provoca que tengamos que emplear de nuevo una parte de nuestro tiempo realineándolo. Para evitar

Introducción a Visual Basic 6.0

47

esto podemos bloquear los controles, evitando tanto su desplazamiento como su redimensionamiento. Para bloquear los controles de un formulario tenemos dos posibilidades: pulsar el botón Alternar bloqueo de controles, que se encuentra en la barra de botones de edición de formularios, o bien seleccionar del menú Formato la opción Bloquear controles. Cuando un formulario tiene sus controles bloqueados el icono del botón aparece pulsado, de tal forma que volviendo a pulsarlo se desbloquean. Tenga en cuenta que no es posible bloquear ciertos controles del formulario mientras se trabaja moviendo otros, el bloqueo es a nivel del formulario completo. Mientras el bloqueo está activo comprobará que al seleccionar cualquier control los cuadraditos que aparecen alrededor de él han cambiado, no están rellenos de color negro sino vacíos, indicando que no es posible redimensionar el control. De hecho, si desplazamos el cursor del ratón hasta uno de esos puntos comprobará que no cambia, no aparece la típica flecha doble. 3.3.11. Añadir y eliminar controles de la paleta. Aunque en principio la paleta de herramientas contenga sólo los controles estándar de Visual Basic, podemos añadirle cualquier otro control del que dispongamos y deseemos utilizar en nuestra aplicación. Visual Basic, en realidad, se distribuye con más controles de los que en principio están visibles en la paleta de herramientas, pudiendo seleccionar dichos controles a partir de una lista. Abra el menú emergente de la caja de herramientas y elija la opción Componentes. Aparecerá una ventana similar a la mostrada en la figura 3.7 conteniendo una lista de posibles objetos a mostrar/ocultar en la paleta de herramientas y algunas opciones más. Cada uno de los controles que aparece en la lista tiene a su izquierda una caja de selección, marcando en ella indicaremos que deseamos que ese objeto aparezca en la paleta, desmarcándolo lo eliminaremos.

Figura 3.7. Selección de objetos en la paleta de herramientas.

Introducción a Visual Basic 6.0

48

Además de controles AcriveX en un formulario, también se pueden insertar todos aquellos objetos asociados con un servidor OLE, como pueda ser una imagen de Paint, un documento de WordPad o un sonido. En la página Objetos insertables podemos ver dichos objetos. Por medio del botón Examinar podemos añadir a la lista otros controles que no estén en ella y tengamos almacenados en disco. Al pulsarlo aparecerá una ventana en la que podremos indicar el camino y nombre del archivo que contiene el control, que normalmente tendrá extensión OCX. En cualquier momento podemos utilizar esta ventana para eliminar de la paleta de herramientas aquellos controles que no nos vayan a ser útiles a excepción de los básicos de Visual Basic. No podremos eliminar de la paleta, sin embargo, un control que hayamos insertado en el formulario, ya que se trata de un control en uso. 3.3.12. Añadir páginas a la caja de herramientas. Inicialmente en la caja de herramientas tan sólo existe una página, llamada General, en la que se muestran los componentes más habituales. Al añadir nuevos elementos, según el procedimiento descrito en el punto anterior, éstos aparecen en la página de la caja de herramientas que está activa en ese momento. Para añadir una nueva página bastará con abrir el menú emergente y seleccionar la opción Agregar ficha. Debemos facilitar el nombre que deseamos asignarle, nombre que aparecerá en forma de botón en la parte inferior de la caja de herramientas. La página recién creada estará vacía, pero podemos añadirle componentes siguiendo los pasos anteriores o bien arrastrándolos desde la página General. 3.3.13. Asociar código a eventos. Una vez tengamos diseñado nuestro formulario, insertando controles y estableciendo las propiedades de cada uno de ellos, tendremos creada la interfaz de nuestra aplicación. Nos quedará un último paso en su diseño: la inserción del código necesario tanto para los métodos de los eventos que precisemos en la aplicación, como para los demás procedimientos y funciones que defina su funcionamiento. Ya sabemos que haciendo doble clic sobre el formulario o uno de los controles se abre automáticamente la ventana de código cuyo aspecto será similar al mostrado en la figura 3.8. También podemos abrir esta ventana haciendo aparecer el menú emergente, con la pulsación del botón derecho del ratón, y seleccionando la opción Ver código. En cualquier caso nos encontraremos con una ventana cuyo título es una combinación del nombre del proyecto y del formulario sobre el que trabajamos. Debajo del título pueden verse dos lista: la de la izquierda muestra el objeto al que corresponde el código, mientras que en la de la derecha aparece el evento de ese objeto al que responderá el código. Abriendo cualquiera de estas dos listas podemos seleccionar otro objeto de los existentes y por cada objeto uno de los eventos posibles.

Introducción a Visual Basic 6.0

49

Figura 3.8. La ventana de código.

3.3.14. Codificación de eventos. Cada uno de los objetos posibles, formularios y controles, dispone de una determinada serie de eventos a los que puede responder, aunque en su mayoría sólo se codifican una pequeña parte de ellos. Cuando se hace doble clic sobre un objeto la ventana de código selecciona un evento por defecto, que suele ser el que de forma más habitual se codifica. Si hace doble clic sobre un formulario la ventana de código seleccionará el evento Load, mientras que si realiza la misma acción sobre un botón verá que el evento que aparece elegido es Clic. Esto es así porque mientras que el código asociado a un formulario se suele ejecutar cuando éste se carga, evento Load, el que se asocia a un botón se ejecuta habitualmente cuando éste se pulsa, evento Click. De cualquier forma, utilizando la lista de eventos podemos seleccionar cualquier otro. En el caso de un formulario podemos establecer un código que se ejecute cada vez que sea modificado su tamaño, evento Resize, cada vez que se haga doble clic sobre el formulario, evento DblClick, o cada vez que el cursor del ratón pase sobre él, evento MouseMove. Al seleccionar cualquiera de los eventos veremos que automáticamente aparece en la ventan de código un procedimiento privado, cuyo nombre es combinación del objeto, formulario o control, y el nombre del evento. Por ejemplo, si tenemos un botón llamado Boton Vale y codificamos el evento Click, el procedimiento se llamará Boton Vale_Click. Tras el nombre del procedimiento veremos unos paréntesis que pueden estar vacíos, si el evento no genera parámetro alguno, o tener en su interior una serie de declaraciones enumerado cada uno de los parámetros generado. Por ejemplo, mientras que el evento Click de un botón no tiene parámetros, simplemente indica que se ha pulsado, el método asociado al evento MouseMove recibirá tres parámetros: uno indicando el estado de los botones y dos facilitando la posición del cursor del ratón. Que el procedimiento sea privado indica que sólo podrá ser utilizado desde el mismo módulo en que se define. En este caso, al estar tratando con el código de los métodos de respuesta a eventos, los procedimientos residen en el mismo módulo que el formulario, por lo que sólo podrá ser utilizado desde otros métodos. El final de cad uno de los procedimientos viene marcado por la línea End Sub, que también aparece automáticamente cuando se comienza su definición. Nosotros, por lo tanto, tan sólo tenemos que preocuparnos de la codificación del método, pero en ningún caso de se nombre, los

Introducción a Visual Basic 6.0

50

parámetros que toma o el lugar donde hay que definirlo. Todo esto lo hace automáticamente Visual Basic por nosotros. Anteriormente se comentó la diferencia existente entre un procedimiento, como los métodos de respuesta a eventos, y una función. Esta última puede devolver un valor, pero no así los procedimientos, por lo que nunca un método de respuesta a evento podrá devolver un valor, algo lógico. Si Windows cuando detecta una pulsación de ratón sobre un objeto llama al método correspondiente y éste, pongamos por caso, devuelve un valor, ¿Quién recibe ese valor? Dado que los procedimientos definidos para responder a eventos son habitualmente llamados de forma directa por Windows, no tendría ningún sentido que éstos devolvieran valor alguno, por ello se definen como procedimientos y no como funciones. 3.3.15. Uso de colores en el código. A medida que vaya introduciendo código notará que Visual Basic usa distintos colores para diferenciar unas partes de otras. Si define una variable verá que la palabra Dim aparece en azul, mientras que el nombre de la variable aparece en negro. Una línea conteniendo un error aparecerá en rojo, mientras que un comentario aparece en verde. Esta diferenciación facilita el trabajo con el código, permitiéndonos ver de una forma mucho más rápida lo que necesitemos en cada momento. Aunque Visual Basic tiene un esquema de colores predeterminados, es posible modificarlo por medio de la opción Opciones del menú Herramientas, que da paso a la página Formato del editor. 3.3.16. Inserción de comentarios. Una buena costumbre, durante la escritura de código, es insertar comentarios que aclaren cuál es la finalidad de una variable o qué hace una cierta línea de código. El añadido de comentarios beneficia tanto al propio programador, al que le será más fácil el trabajo si retoma su programa un tiempo después de haberlo escrito, como a cualquier otra persona que posteriormente necesite trabajar con ese código.

Figura 3.9. Selección de opciones del editor de código.

Introducción a Visual Basic 6.0

51

Podemos insertar un comentario en cualquier línea, incluso si en ella existe ya alguna sentencia, utilizando el carácter. Cualquier texto que pongamos tras este carácter, hasta el final de línea, no será procesado por Visual Basic. Es posible también insertar un comentario en una línea por medio de Rem, tal y como se hace en cualquier versión de BASIC. En este caso tenemos menos flexibilidad, ya que al tratarse de una instrucción ésta no puede ir directamente detrás de cualquier sentencia, siendo necesario establecer una separación por medio del carácter dos puntos (:). 3.3.17. Continuación de línea. El final de una línea de código viene determinado por la pulsación de la tecla Intro y, en la mayoría de las ocasiones, esto indica asimismo el final de la sentencia que se estaba escribiendo. Cuando una sentencia es muy larga lo más apropiado es dividirla en varias líneas, pero la pulsación de la tecla Intro daría por terminada la sentencia sin estarlo, obteniéndose el correspondiente error. La solución es el uso del carácter que dispuesto al final de una línea, antes de la pulsación de Intro, indicará que la línea actual continúa en la línea siguiente, siendo de forma lógica una sola. 3.3.18. La ventana de proyecto. Hasta ahora hemos estado viendo qué es un formulario, cómo se define, insertan objetos, establecen propiedades, etc. Una aplicación Visual Basic puede estar formada por más de un formulario, en realidad por tantos como nos sea necesario. Además de formularios podemos también tener módulos de código, datos, informes, recursos, definición de clases, etc. Obviamente no es muy usual tener abiertos simultáneamente todos estos elementos, por ello existe la ventana de proyecto, que podemos ver en la figura 3.10. Esta ventana es en realidad una lista de los componentes de nuestra aplicación, a ella se irán añadiendo automáticamente cada formulario y módulo de cada proyecto que insertemos. Para seleccionar uno de los elementos de la ventana de proyecto bastará con pulsarlo con el ratón. Si el elemento que se muestra destacado cuenta con un diseñador, como es el caso de los formularios, en la parte superior de la ventana tendremos activados dos botones: uno permite abrir el objeto para editarlo con el diseñador y otro abre directamente la ventana de código asociada. En caso de que el elemento seleccionado en la ventana de proyecto sea un módulo de código o clase, tan sólo estará activado el botón que nos permite ver el código. Siempre podemos hacer doble clic sobre un componente de la aplicación, si éste tiene un diseñador se abrirá, si es un módulo aparecerá la ventana de código. Utilizando las distintas opciones del menú Proyecto podemos añadir a nuestro proyecto formularios, módulos de código y módulos de definición de clases, controles de usuario, entornos de datos, etc. Cada uno de estos elementos se añadirá, como ya se ha dicho, de forma automática al proyecto seleccionado en ese momento. Podemos eliminar cualquier componente de nuestra aplicación que no nos sea necesario. Para ello primero marcaremos dicho componente en la ventana de proyecto, moviéndonos

Introducción a Visual Basic 6.0

52

a él con los cursores o marcándolo con el ratón, y acto seguido seleccionaremos la opción Quitar del menú emergente, el elemento desaparecerá. Este proceso elimina el archivo de nuestro proyecto, pero en ningún caso lo borra del disco, de tal forma que en cualquier momento podremos volver a añadirlo según el procedimiento explicado anteriormente. Cada uno de los elementos de una aplicación se almacena en un archivo separado, mientras que el proyecto en sí está contenido en otro archivo distinto, con referencias a cada uno de los elementos de los que consta. Si se elimina un elemento de un proyecto lo que está borrando es esa referencia, pero la definición del objeto seguirá almacenada en el archivo correspondiente.

Figura 3.10. Lista de componentes en la ventana de proyecto.

También disponemos, en el menú Archivo, de las opciones necesarias para crear un nuevo proyecto, guardar el proyecto actual, cargar un proyecto ya existente, añadir otro proyecto o eliminarlo. Visual Basic 6.0 permite trabajar simultáneamente con más de un proyecto, facilitando así tareas como la depuración de un componente ActiveX mientras éste está aún diseñándose. 3.3.19. El proyecto por defecto. Cuándo entramos en Visual Basic, así como cuando cerramos un proyecto y abrimos otro nuevo, el aspecto del entorno viene fijado por el proyecto por defecto. Éste fija las herramientas que existirán en nuestra paleta y algunas de las opciones de entorno que hemos visto anteriormente, como el establecimiento de la rejilla de puntos, las ventanas que deben aparecer siempre sobre las demás, etc. Nosotros podemos modificar toadas estas opciones para nuestro proyecto, pero cuando comencemos uno nuevo volverán a tomarse las opciones por defecto. Es posible modificar el proyecto por defecto, fijando así las opciones deseadas cada vez que se cree un nuevo proyecto. Para ello bastará con abrir el menú emergente asociado al proyecto, seleccionando la opción Establecer como inicial.

Introducción a Visual Basic 6.0

53

3.3.20. Ejecución y parada de un programa. Una vez terminada la aplicación, es momento de verla en funcionamiento. Nada más fácil, tan sólo tiene que pulsar la tecla F5 o el botón Iniciar de la barra de herramientas. También puede seleccionar la opción del mismo nombre del menú Ejecutar. En cualquiera de los caso verá aparecer el formulario, con su barra de título y su botón. Pulse sobre el botón Saludo. Puede utilizar el ratón, la Barra espaciadora o la tecla Intro, verá cómo en la parte superior de la ventan aparece el efecto de la sentencia Print que introdujo en el procedimiento BotonSaludo_Click, que se ejecuta cada vez que pulsemos el botón. Superponga al formulario cualquier otra ventana, por ejemplo cambiando al Explorador de Windows, y después vuelva a ponerlo en primer plano. Como verá, la cadena que se imprimió al pulsar el botón no ha desaparecido, sigue ahí. Esto, que parece obvio, no lo es tanto. Al crear el formulario se dio el valor True a la propiedad AutoRedraw, indicando así que las operaciones de escritura o dibujo no se llevasen a cabo directamente en pantalla, sino en memoria, y de ahí a pantalla. Por esto cuando hemos tapado la ventana al destaparla vuelve aparecer el texto, porque el aspecto del formulario está realmente almacenado en memoria. Si quiere ver la diferencia, dé el valor False a esa propiedad y repita la prueba de tapar y recuperar la ventana. Para terminar la aplicación tenemos dos opciones: pulsar el botón que hay en la parte superior derecha de la ventana o, puesto que estamos ejecutando la aplicación desde el entorno de Visual Basic, pulsar el botón Terminar. En ese momento volveremos al proceso de diseño.

Figura 3.12. Aspecto del programa Saludo en ejecución.

3.3.21. Generación de un ejecutable. Durante la etapa de diseño de una aplicación, en la que es posible ejecutar múltiples veces para observar los resultados, Visual Basic no genera ningún ejecutable sino que trabaja siempre en memoria. Sin embargo, una vez que nuestra aplicación esté finalizada desearemos obtener un código ejecutable que poder distribuir y no un conjunto de proyecto, formularios y módulos de código. En el menú Archivo encontraremos un opción, Generar Saludo.Exe, que abrirá una ventana en la que dispondremos el camino y el nombre que tendrá nuestro ejecutable. Pulsando el botón Opciones accederemos a una ventana, como la mostrada en la figura 3.13, en la que podremos establecer el número de la versión, el título de la aplicación y cualquier otra información adicional que deseemos incluir, como el nombre de nuestra

Introducción a Visual Basic 6.0

54

compañía, del producto o un mensaje de derecho legales. La segunda página de esta ventana nos permitirá seleccionar el tipo de código a generar, que puede ser p-code, necesita una interpretación posterior para poder ejecutarse, o bien código nativo. En este segundo caso también podemos elegir las optimizaciones que se aplicarán al código. Volviendo a la ventana anterior, bastará con que pulsemos el botón Aceptar para iniciar la generación del ejecutable. A pesar de que haya generado un ejecutable, siempre que ejecute su aplicación desde el entorno de Visual Basic se realizará una compilación en memoria y en ningún caso se utilizará el ejecutable. Esto nos permite seguir realizando modificaciones sobre el proyecto e ir viéndolas en funcionamiento, a pesar de que en el ejecutable sigamos teniendo una versión antigua de la aplicación. A la hora de distribuir una aplicación desarrollada con Visual Basic hay que tener en cuenta que además de nuestro ejecutable deberemos incluir algunos archivos más, como MSVBVM60.DLL y los correspondientes a todos los controles adicionales que hayamos usado. Llegados a este punto puede guardar el formulario y el proyecto, por ejemplo con el nombre SALUDO (uno tomará la extensión FRM y otro VBP), y salir de Visual Basic. Puede ejecutar su primer programa desde el Explorador de Windows.

Figura 3.13. Ventana con opciones de compilación.

3.4. Constantes variables y expresiones. Sin duda uno de los pilares de cualquier lenguaje de programación está formado por los tipos de datos que es capaz de manejar. 3.4.1. Tipos de datos. En la tabla 3.2 puede ver un resumen de los tipos de datos disponibles en Visual Basic 6.0, tipos que vamos a analizar seguidamente de forma individualizada.

Introducción a Visual Basic 6.0

55

El tipo de dato Bolean puede contener tan sólo dos valores: True, cierto, o False, falso. El valor True corresponde con el entero-1, mientras que False se corresponde, numéricamente hablando, con 0. Podemos usar este tipo de dato en múltiples situaciones, por ejemplo para almacenar el resultado de una expresión relacional, que sólo puede ser cierta o falsa, o para devolver un valor de una función indicando si todo ha ido bien, se suele devolver True, o se ha producido un error, devuelve False.

Tabla 3.2. Muestra los diferentes tipos de datos que posee Visual Basic 6.0

Tipo Valores que puede contener Boolean True o False Byte Enteros en el rango de 0 a 255 Interger Enteros en el rango de -32768 a 32767 Long Enteros largos, de -2147483648 a 2147483647 Single Punto flotante simple precisión Double Punto flotante doble precisión Currency Entero con punto decimal fijo String Cadenas de longitud fija o variable Date Fechas en el rango de 1/1/100 a 31/12/9999 Object Referencias a objetos Variant Cualquier tipo de dato

El tipo Byte es adecuado para contener cualquier número entero que no sea negativo ni mayor que 255, por ejemplo un código ASCIL. También podemos usarlo para controlar bucles pequeños. Tiene la ventaja de que al ocupar sólo un byte el trabajo con una variable de este tipo es muy rápido, además de ocupar bastante menos que cualquier otro tipo de dato. Integer es el tipo numérico más utilizado, ya que nos permite trabajar con números enteros, tanto negativos como positivos, en un rango que en la mayoría de las ocasiones es suficiente para nuestras necesidades. Ocupa dos bytes en memoria. Cuando aún trabajando con números enteros, necesitemos un mayor número de dígitos, deberemos usar el tipo Long. Una variable Long ocupa cuatro bytes en memoria y en ella podemos almacenar prácticamente cualquier número entero, positivo o negativo. Los tipos Single y Double son los que nos permiten utilizar números en punto o como flotante, lo que significa que la coma decimal no tiene una posición predeterminada, sino que puede estar en cualquier lugar donde sea necesario. Desde cantidades íntimas, en las que la coma decimal tiene detrás decenas o centenas de ceros, hasta magnitudes casi impensables. El tipo Single, simple precisión, ocupa cuatro bytes y el rango de valores que puede almacenar va, aproximadamente, desde -1.401298E-45 hasta 3.402823E38. El tipo Double, doble precisión, ocupa ocho bytes, pudiendo almacenar cantidades, aproximadamente, desde -4.94065645841247E-324 a 1.79769313486232E308. Para trabajar con números conteniendo parte decimal, además de los tipos de coma flotante disponemos también del tipo Currency, que se caracteriza por tener una coma fija, con cuatro dígitos decimales. Este tipo de dato está especialmente indicado para trabajar con cantidades grandes que siempre tendrán una parte decimal fija, por ejemplo cálculos monetarios. La ocupación en memoria de una variable de este tipo es de 8 bytes y el rango

Introducción a Visual Basic 6.0

56

de valores que puede contener va hasta los cientos de billones, tanto positivos como negativos. Mientras que en el BASIC tradicional las variables de tipo cadena siempre han sido de tipo variable, era posible almacenar en ellas una cadena de cuatro caracteres y a continuación otra de ochenta, en Visual Basic podemos trabajar tanto con cadenas de longitud variable, capaz de contener hasta dos billones de caracteres. Para definir una cadena de longitud fija pondremos detrás del tipo, String, el signo * y el número de caracteres que deseamos, que deberá estar entre 1 y 65526. Aparentemente no tiene ningún sentido utilizar cadenas de longitud fija cuando siempre se pueden utilizar de longitud variable, con la flexibilidad de saber que podremos utilizar cadenas con cualquier número de caracteres. Sin embargo, mientras que una cadena de longitud fija de un carácter ocupa 1 byte, una de longitud variable conteniendo el mismo carácter ocupará 11 bytes. Esto es así porque las variables de tipo cadena de longitud variable además de asignar memoria para almacenar los caracteres de la cadena necesitan un espacio adicional, para conocer la longitud actual de la cadena y su dirección. Esto es así porque las variables de tipo cadena de longitud variable además de asignar memoria para almacenar los caracteres de la cadena necesitan un espacio adicional, para conocer la longitud actual de la cadena y su dirección. Este espacio adicional es de 10 bytes. Con el fin de almacenar fechas y horas en Visual Basic existe el tipo Date, que nos permite almacenar cualquier fecha desde el 1 de enero del año 100 hasta el 31 de diciembre del año 9999. En realidad la representación interna de una variable de este tipo, que ocupa ocho bytes, es la de un número en coma flotante, en el que la parte entera contiene la fecha y la parte decimal la hora. El tipo Object, que ocupa 4 bytes en memoria, es capaz de contener una referencia a cualquier objeto de la aplicación, por ejemplo un formulario o un componente OLE. Como vemos posteriormente es un tipo de dato muy potente, a partir del cual podemos, por ejemplo, crear varias instancias de un mismo formulario. Por último nos encontramos con el tipo más polifacético de Visual Basic, el tipo Variant. Una variable Variant es capaz de contener cualquier tipo de dato, un número, una cadena, una fecha, incluso una matriz. Esto no es lo más destacable de Variant, lo realmente importante es que cada vez que hacemos referencia al valor contenido en un expresión u operación, el tipo asignamos a una variable de tipo Variant el valor “123” , que es una cadena, y a continuación intentamos realizar una operación aritmética, automáticamente la representación interna cambiará de cadena a entero. Si una operación posterior, por ejemplo una concatenación, necesitase otra conversión ésta se realizaría en sentido inverso sin ningún problema. A medida que vayamos utilizando este tipo se dará cuenta de sus posibilidades. 3.4.2. Definición de variables en Visual Basic. En el BASIC tradicional, aquel que prácticamente todos utilizábamos en nuestros inicios en Spectrum, MSX, Amstard o los primeros PC, cuando necesitaba una variable simplemente se utilizaba, no existía el concepto de definición. Si a mitad de un programa era necesaria una variable temporal uno se inventaba un nombre para ella y le asignaba el valor, sin más. Esta técnica era y es uno de los puntos en los que BASIC se diferencia de la práctica totalidad de los lenguajes, en los que antes de utilizar cualquier variable hay que definirla, indicando su nombre y su tipo.

Introducción a Visual Basic 6.0

57

¿Qué ventajas tiene definir una variable antes de ser usada?. Principalmente clarifica el código y elimina potenciales errores. Si al inicio de un procedimiento encontramos una serie de definiciones que nos comunican qué variables se utilizan, sus nombres y tipos, no cabe duda de que se trata de una referencia inestimable para a compresión del código, al no tener que ir buscando cada vez que se encuentra una variable de dónde viene, cómo ha tomado su valor o qué tipo de dato contiene. También podemos evitar errores difícilmente localizables en la etapa de depuración. Si asignamos un valor a una variable llamándola NUM_DIAS, y luego realizamos cualquier cálculo utilizando NUMDIAS, BASIC no genera ningún tipo de error, simplemente crea dos variables. Forzando la definición de una variable antes de su uso, el uso de NUMDIAS en lugar de NUM_DIAS generaría un error fácilmente localizable, en el que Visual Basic nos comunicaría que estamos intentando utilizar una variable no definida. Visual Basic permite tanto definir variables como utilizarlas directamente, según el método tradicional de BASIC. Para conseguir que ante la utilización de esta última técnica, uso de variables indefinidas, siempre se genere un error tan sólo tendremos que añadir al principio de nuestro código la sentencia Option Explicit. Esta sentencia tiene vigencia en el módulo de código o formulario en el que se haya incluido, lo que quiere decir que en cualquier otro módulo distinto sí estaría permitido el uso de variables indefinidas a nos ser que incluyamos la sentencia en todos los módulos. Para evitar tener que realizar este proceso a mano no tenemos más que abrir el menú Herramientas, seleccionar la opción Opciones, que hemos utilizado ya con anterioridad, y activar el campo Requerir declaración de variables, que se encuentra en la página Editor. A partir de ahora en todo nuevo módulo o formulario que insertemos en nuestro proyecto, Visual Basic añadirá automáticamente la sentencia Option Explicit al principio, evitándonos este trabajo repetitivo. La activación de la citada opción tiene vigencia no sólo en el proyecto actual, sino en todos los proyectos que creemos de ahora en adelante, hasta que nosotros mismos entremos de nuevo en Herramientas \ Opciones y la desactivemos. 3.4.3. Valores de inicialización. Seguidamente vamos a ver la forma de definir variables en Visual Basic, pero antes de ello es necesario conocer el valor que toman por defecto las variables cuando no se les asigna ninguno. A diferencia de lo que ocurre con el BASIC tradicional, en el que cuando se crea una variable directamente se le asigna un valor, en Visual Basic podemos tener una variable que no ha sido utilizada hasta un momento dado. En este caso, ¿qué valor tendrá la variable?. El valor por defecto con el que se inicializa una variable depende, como es lógico por otra parte, de su tipo. Si la variable es numérica, indistintamente de que sea entera o decimal y de su precisión, el valor tomado será 0; si es una cadena será una cadena vacía, si es una fecha será el día 30 del mes 12 del año 1899, si es de tipo Boolean tomará el valor False y si es de tipo Variant el valor será Empty. 3.4.4. La sentencia Dim. El método más habitual para definir una variable es usando la sentencia Dim, seguida del nombre de la variable, la partícula As y el tipo que se desea.

Introducción a Visual Basic 6.0

58

Al utilizar Dim el ámbito de la variable dependerá del lugar en que se ha definido. Si la variable se define al principio de un módulo, ya sea de código o un formulario, la variable tendrá un ámbito restringido a ese módulo. Es decir, cualquier procedimiento o función existente en dicho módulo podrá utilizar esa variable, pero no así otros procedimientos o funciones que residan en módulos separados. En caso de que la declaración de la variable se realice en el cuerpo de un procedimiento o función, el ámbito será local. Esto significa que la variable sólo podrá ser utilizada desde el interior de dicho procedimiento pero no desde cualquier otro, resida éste o no en el mismo módulo. El tiempo de vida de una variable local es el tiempo de ejecución del código contenido en el procedimiento o función. La variable se crea automáticamente al entrar en ese bloque de código y al salir de él se destruye. Por lo tanto, una variable local no puede conservar un valor más allá del código en que se ha definido y, además, sólo ocupa memoria durante la ejecución de esa parte del código, en el momento en que el procedimiento es abandonado la memoria que ocupa es liberada. Una variable definida al nivel de módulo, por el contrario, se crea al principio de la ejecución y no se destruye hasta que la aplicación termina, por lo que aún cuando la variable no pueda ser usada desde módulos o formularios externos, cada vez que se ejecute algún procedimiento o función en el módulo en que está definida se obtendrá el último valor que almacenó la variable. Es posible declarar variables a nivel de módulo utilizando la sentencia Private en lugar de Dim, consiguiendo un variable local al módulo, al igual que con Dim. Dicha sentencia no puede ser usada, sin embargo, en un procedimiento o función. 3.4.5. Variables globales. En ocasiones puede ser necesario que una variable esté disponible más allá del ámbito de un procedimiento, e incluso del de un módulo o formulario. En este caso se utilizan variables con ámbito global, que pueden ser utilizadas desde cualquier punto de la aplicación, sin importar el módulo en el que esté el procedimiento que accede a ella. Sólo es posible declarar una variable global a nivel de módulo, es decir, fura de cualquier procedimiento o función. Para ello utilizaremos la sentencia Public, seguida del nombre de la variable, la partícula As y el tipo. La sintaxis es idéntica a la de Dim y Private. Si intenta declarar una variable global en el interior de una función o un procedimiento, obtendrá un error durante la compilación de la aplicación, no podrá siquiera llegar a ejecutarla. Como es lógico, el tiempo de vida de una variable global comienza en el mismo momento en el que se carga la aplicación y no muere hasta que ésta termina. 3.4.6. Variables estáticas. Como se ha dicho anteriormente, una variable local se crea automáticamente al entrar en el procedimiento o función en que se declara y se destruye al salir. Por ello una variable local perderá cualquier valor que le asignemos de una llamada a otra. Esto, sin embargo, es modificable mediante la sentencia Static, que siguiendo la misma sintaxis que Dim, Private o Public nos permite declarar, en el interior de un procedimiento o función, variables estáticas.

Introducción a Visual Basic 6.0

59

Una variable estática es aquella que, aún siendo local, se crea al arrancar la aplicación y se destruye sólo cuando ésta termina. De esta forma es posible asignar un valor a la variable que se conservará hasta la próxima llamada. Por regla general todas las variables declaradas en un procedimiento o función son locales no estáticas, a no ser que se especifique lo contrario utilizando Static en lugar de Dim. En caso de que todas las variables de nuestro procedimiento deban ser estáticas no tenemos por que utilizar Static en cada declaración, en su lugar podemos anteponer esta misma palabra clave delante de la definición del procedimiento o función. 3.4.7. Nomenclatura de las variables. Antes de poder crear cualquier variable necesitamos conocer las reglas que hay que seguir para poder asignarles un nombre. Un nombre de variable debe comenzar siempre con una letra (sorprendentemente es posible utilizar eñes y acentuadas) y estar seguido de hasta 39 caracteres más, que pueden ser letras, dígitos y el carácter de subrayado. Visual Basic no diferencia entre mayúsculas y minúsculas, por lo que una variable que se ha definido como Num puede después ser utilizada como num, NUM o nUm. De hecho cuando utilicemos una variable, por ejemplo en el interior de un procedimiento, cada vez que escribamos su nombre Visual Basic comprobará las declaraciones que se han efectuado al principio del procedimiento y escribirá el nombre de la variable tal y como la definimos. Es más, si después de haber hecho referencia en varios puntos a la variable cambiamos su definición, alterando sólo mayúsculas, minúsculas o acentos, veremos que en todos los puntos donde aparezca también será cambiada. Obviamente si cambia totalmente el nombre de la variable Visual Basic no realizará esta operación, por lo que al intentar la ejecución obtendrá errores de variable no definida. Aunque se trate de una técnica actualmente en desuso, Visual Basic permite añadir al final del nombre de una variable, así como al final de una constante, un carácter que hace referencia al tipo de dato. Por ejemplo, una variable seguida del carácter % denota que se trata de un entero, mientras que el carácter $ indica que se trata de una cadena. Es posible declarar una variable prescindiendo del As tipo utilizando estos caracteres. En la tabla 3.3 puede encontrar una enumeración de estos indicadores y el tipo de dato asociado. Como podrá observar no hay caracteres especiales para los tipos Boolean, Byte, Date y Variant.

Tabla 3.3. Indicadores de tipo de dato

% Integer & Long ¡ Single # Double @ Currency $ String 3.4.8. Tipo por defecto. En caso de que al declarar una variable no indiquemos su tipo directamente, por medio de As tipo, ni de forma simbólica, con uno de los indicadores mostrados en la tabla 3.3, la variante será de tipo Variant.

Introducción a Visual Basic 6.0

60

Variant es el tipo por defecto para todas las variables a no ser que se indique lo contrario. Esto es así porque, como se ha dicho anteriormente, se trata de un tipo de dato que permite el almacenamiento de cualquier categoría de las vistas, realizando conversiones automáticas entre tipos según las expresiones en que la variable se vea envuelta. Visual Basic, como puede ver, tiene una gran flexibilidad en el tratamiento de datos. Declarando una variable, sin indicar tipo alguno, nos encontramos que podemos tratar con cadenas, números enteros y en como flotante, fechas e incluso matrices. Todo ello sin tener que preocuparnos en absoluto de convertir una cadena a número para ciertas operaciones o realizar la operación inversa para otras. Sin embargo esta flexibilidad tiene un precio, que es la mayor ocupación en memoria. Una variable Variant conteniendo un valor de un determinado tipo puede ocupar, según los casos, entre 16 y 22 bytes más que si utilizásemos el tipo de dato original. En contrapartida habría que evaluar el código que ahorramos en realizar conversiones si es que las necesitamos. La diferencia entre lo negativo y lo positivo nos indicará qué método utilizar en cada caso. 3.4.9. Conversiones entre tipos. En ocasiones ocurre que un dato que tenemos almacenado en una variable de un determinado tipo lo necesitamos para realizar una operación en la que el tipo debe ser distinto. Todos los que hemos programado en BASIC alguna vez hemos tenido que convertir números en cadenas, con la función Str,o viceversa, con la función Val, para llevar a cabo diversas manipulaciones. Aunque estas dos funciones siguen estando disponibles en Visual Basic, se han visto superadas por otras más completas que nos permitirán, como veremos en un momento, convertir un dato de cualquier tipo al tipo que nosotros deseamos, mientras que Str y Val sólo pueden realizar la conversión de un tipo en otro. Para convertir cualquier tipo de dato a un tipo dado disponemos de una familia de funciones que puede encontrar enumerada en la tabla 3.4. No siempre es posible realizar correctamente la conversión, caso en el que se generará un error durante la ejecución del programa. Esto ocurre, por ejemplo, cuando al realizar una conversión a un tipo numérico éste se ve desbordado o el tipo de dato original no contiene un número.

Tabla 3.4. Funciones para conversión de datos

Función Tipo que devuelve CBool Boolean CByte Byte Clnt Integer CLng Long CSng Single CDbl Double CCur Currency CStr String CDate Date CVar Variant

Además de la posibilidad de conversión desde cualquier tipo, estas funciones tienen otra serie de ventajas. Clnt, por poner un caso, realiza una conversión a número entero

Introducción a Visual Basic 6.0

61

realizando un redondeo, no simplemente cortando la parte decimal y, además, reconoce el carácter decimal y el separador de miles según la configuración internacional que tengamos fijada, mientras que la función Val no lo hace. Si almacenamos en una variable de tipo Byte el valor 65, por ejemplo, y utilizamos la función CStr para convertirlo a cadena, obtendremos una cadena de dos caracteres, “65”, y no la letra ‘A’, que sería el carácter con código 65. Para obtener el código de cualquier carácter y viceversa disponemos de las funciones Chr y Asc. La primera toma como parámetro un entero entre 0 y 255 y devuelve el carácter correspondiente, mientras que la segunda toma un solo carácter y devuelve el código. 3.4.10. Operadores. Para conseguir la mayoría de las operaciones que un programa necesita es necesario construir expresiones, que sobre la base de unos operandos y unos operadores se resolverán en un resultado. Los operandos pueden ser números, cadenas, fechas, etc., ya sea en forma de literales o de variables. Vamos a conocer ahora los operadores de los que disponemos en Visual Basic y que nos permitirán componer, básicamente, expresiones aritméticas, relacionales y lógicas. 3.4.11. Operadores aritméticos. La finalidad de esta familia de operadores es permitirnos realizar el conjunto de operaciones matemáticas más básico, como son la suma, resta, multiplicación y división. Cualquiera de estos operadores siempre toma dos operandos y genera un resultado. En la tabla 3.5 podemos ver un resumen de estos operadores, junto con la operación que realiza. En esta tabla N1 representa al primer parámetro, el que se sitúa a la izquierda del operador, y N2 al segundo, a la derecha del operador.

Tabla 3.5. Operadores aritméticos

Operador Operación aritmética que efectúa + Suma de N1y N2 - Halla la diferencia entre N1y N2 * Multiplicar N1 por N2 / Divide N1 entre N2 \ Divide N1 entre N2 sin hallar decimales ^ Eleva N1 al exponente indicados por N2 Mod Resto de la operación N1\ N2

Estos operadores, como es obvio, trabajan sobre cualquiera de los tipos numéricos que conocemos, enteros o coma flotante, independientemente de su precisión. Sin embargo, cuando en una misma expresión utilicemos operandos de distinto tipo numérico Visual Basic realizará las conversiones necesarias para guardar la mayor precisión posible. Trabajando con números los primeros cuatro operadores no requieren ningún comentario adicional, se limitan a realizar las cuatro operaciones aritméticas indicadas. El operador \

Introducción a Visual Basic 6.0

62

realiza la división entera, es decir, la única diferencia con el operador / es que éste último puede generar una parte decimal en el cociente de la división, mientras que el primero no. Precisamente para hallar el resto de esa división entera podemos utilizar el operador Mod, que toma exactamente los mismos parámetros y realiza la misma operación que \, la división entera con la única diferencia de que no nos devuelve el cociente obtenido, sino el resto. Por último tenemos el operador ^, que nos permitirá realizar potenciaciones, actuando como base el operando que se sitúe a la izquierda y como exponente el que se encuentre a la derecha. Por medio del operador + podemos trabajar además con dos tipos de datos no numéricos. Con él podemos sumar un número a una fecha, obteniendo así una nueva fecha que vendrá determinada por los días transcurridos, especificados por el número, desde una fecha dada. También con + podemos sumar dos cadenas, tipo String, siendo este caso el resultado la concatenación de ambas. Obtendremos, por tanto, una nueva cadena formada por la primera más la segunda. En Visual Basic existe un operador, &, que tiene precisamente la finalidad de concatenar dos datos formando una cadena, siendo preferente el uso de este operador sobre +. Al igual que podemos sumar un número de días a una fecha también podemos restarlo, utilizando el operador -. Con él también podemos hallar el número de días transcurridos entre dos fechas dadas. Cuando realicemos operaciones aritméticas con el tipo de dato Variant el resultado vendrá dado por el tipo de dato que en ese momento contenga la variable, que puede ser numérico, de cadena, fecha u otro tipo. En cada caso se actuará de la misma forma que si la variable fuese del tipo correspondiente al valor que contiene en ese momento, por lo que en unos casos dos variables Variant pueden producir un valor numérico, al realizar una suma, mientras que en otra podemos obtener una cadena, si una de las dos variables contiene una cadena. En caso de que en una misma expresión se utilicen distintos operadores aritméticos y no se alteren las prioridades, por medio de paréntesis, siempre se evaluarán primero las potenciaciones, después los operadores /, *,\ y Mod de izquierda a derecha, y por último + y – de izquierda a derecha. 3.4.12. Operadores relacionales. Este conjunto de operadores nos permitirán evaluar expresiones y obtener dos resultados posibles: True, si la expresión es cierta o devuelve un valor distinto de cero, o False, si la expresión es falsa o devuelve cero. También se le conoce como operadores de comparación. Se utilizan principalmente en estructuras de decisión, en las que dependiendo del valor obtenido se toma un camino u otro. En la tabla 3.6 se enumera cada uno de los operadores de comparación, junto con una pequeña descripción en la que N1 representa al primer operando y N2 al segundo.

Introducción a Visual Basic 6.0

63

Además de los valores True y False una expresión relacional también puede devolver como resultado Null, en caso de que uno de los operadores sea de tipo Variant y contenga el valor Null.

Tabla 3.6. Operadores relacionales o de comparación Operador Devuelve True si Devuelve False si = N1 y N2 son iguales N1y N2 son distintos ¡ N1y N2 son distintos N1y N2 son iguales < N1es menor que N2 N1 es igual o mayor que N2 <= N1 es menor o igual a N2 N1 es mayor que N2 > N1 es mayor que N2 N1 es igual o menor que N2 >= N1 es mayor o igual a N2 N1 es menor que N2 Por medio de estos operadores podemos comparar números, cadenas y fechas. En el caso de los números será su valor el que intervenga directamente en la relación. Si comparamos dos cadenas en realidad se compararán los códigos de cada uno de los caracteres que la componen, de tal forma que “Mañana” no será igual a “mañana”, ya que el código de ‘M’ no es el mismo que ‘m’. Al trabajar con dos fechas se utilizará la representación interna de las variables tipo Date, comentada anteriormente, para saber si una fecha es igual, anterior o posterior a otra. Hay que tener en cuenta que una variable del tipo Date además de la fecha también puede contener la hora, por lo que al realizar un comparación puede que no obtengamos el resultado esperado. Por ejemplo, dos variables Date pueden contener la fecha del día de hoy, pero si una tiene una hora y otra no, o tiene una hora distinta, las variables no cumplirán la relación de igualdad. Es posible utilizar en una misma expresión operadores aritméticos y relacionales, caso éste en el que, antes de que se evalúe una expresión relacional, previamente se realizarán los cálculos aritméticos necesarios para que los operandos a comparar sean sólo dos. 3.4.13. Operadores lógicos. En ocasiones una expresión relacional no está compuesta tan sólo de los operadores y un operador de comparación, sino que son necesarios varios operadores y más operandos. En estos casos hay que unir las distintas subexpresiones por medio de algún elemento, que fije a su vez unas reglas entre cada una de las relaciones. Entre otras ésta es la finalidad de los operadores lógicos. Los operadores lógicos, a excepción del operador Not, toman dos expresiones normalmente relaciones, que como sabemos pueden devolver True o False. Con esta pareja de valores el operador realiza otra operación, en este caso lógica, para obtener un solo valor. En la tabla 3.7 puede encontrar los distintos operadores lógicos, así como los valores que devuelven según que las expresiones de entrada sean ciertas o falsas. E1 representa el valor devuelto por la primera expresión y E2 el devuelto por la segunda. Como ya se ha dicho estos valores sólo serán True o False.

Introducción a Visual Basic 6.0

64

Tabla 3.7. Operadores lógicos

Operador Devuelve True si Devuelve False si And E1=True y E2=True En cualquier otro caso Or E1=True o E2=True E1=False y E2=False Xor E1=True y E2=False o E1=True y e2=True o

E1=False y E2=True E1=False y E2=False Eqv E1 es igual a E2 E1 es distinto de E2 Imp E1=True y E2=True o E1=True y E2=False

E1=False y E2=True o E1=False y E2=False

Not E1=False E1=True Como podrá ver, el operador Not sólo toma un parámetro y lo que hace es devolver el valor inverso al devuelto por la expresión. Por ello se le llama operador de negación. 3.4.14. Trabajo con números. Obviamente los operadores aritméticos sólo permiten realizar operaciones básicas con números, pero sería bastante complejo realizar, por ejemplo, una raíz cuadrada a partir de divisiones, sumas y restas. Para llevar a cabo estas operaciones Visual Basic dispone de una serie de funciones ya “fabricadas”, por lo que podemos utilizarlas directamente sin tener que definirlas. A continuación vamos a conocer las funciones numéricas más habitualmente utilizadas. 3.4.15. Funciones generales. Estas funciones nos permiten realizar algunas operaciones matemáticas más complejas. En la tabla 3.8 puede encontrar cada una de las funciones junto con una pequeña descripción de su contenido.

Tabla 3.8. Funciones generales

Abs Devuelve el valor absoluto del número dado Sgn Indica el signo de un número Sqr Halla la raíz cuadrada del número dado Exp Calcula el núm. “e” elevado al exponente indicado Log Halla el logaritmo natural del número dado Round Redondea un número con las posiciones decimales

indicadas La función Abs toma como parámetro cualquier número, positivo o negativo, y devuelve su valor absoluto, lo que equivale a eliminar el signo de los números negativos. Sgn devolverá 1 si el número que se pasa como parámetro es positivo, -1 si es negativo y 0 si el número es 0, ya que éste no se considera ni negativo ni positivo. Mediante Round podemos redondear cualquier dato numérico al número de decimales que nos interese, para

Introducción a Visual Basic 6.0

65

lo cual deberemos facilitar dos parámetros: el número a procesar y un entero opcional indicando el número de posiciones decimales. 3.4.16. Funciones trigonométricas. Al utilizar estas funciones hemos de tener en cuenta que los valores referidos a ángulos que no devuelve Visual Basic, o que nosotros tengamos que facilitar, estarán expresados en radiantes y no en grados, por lo que será necesaria la conversión cada vez que la unidad no sea ésta. Tenemos disponibles cuatro funciones trigonométricas, las más habituales, con las que podemos obtener el seno, coseno, y tangente de un ángulo, o el arco correspondiente a una proporción dada. Las funciones son las mostradas en la tabla 3.9.

Tabla 3.9. Funciones trigonométricas

Sin Seno de un ángulo Cos Coseno de un ángulo Tan Tangente de un ángulo Atn Arco de una tangente

Si necesita convertir una medida de grados a radianes, antes de pasarla como parámetro a Sin, Cos o Tan, multiplique el número por P (pi) y divida entre 180. La conversión en sentido inverso, para convertir los radianes devueltos por Atn en grados, la conseguirá multiplicando por 180 y dividiendo por P. 3.4.17. Número aleatorios. Visual Basic dispone de dos funciones para la obtención de números aleatorios. La primera de ellas, Randomize, inicializa el generador aleatorio bien a partir del número pasado como parámetro o a partir del valor devuelto por la función Timer. Este valor se utilizará en distintos cálculos que generarán los números aleatorios. Cada vez que deseemos obtener un número aleatorio usaremos la función Rnd, con la que obtendremos un número decimal comprendido entre 0 y 1, valor éste último que nunca llegará a tomar. Si necesitamos un número aleatorio comprendido en un determinado rango bastará con multiplicar el número devuelto por Rnd. Si no nos interesa la parte decimal podemos utilizar la función Clnt, que vimos anteriormente. Por ejemplo la sentencia Print Clnt (Rnd*49+1) devolverá siempre un número entero comprendido entre 1 y 49. 3.4.18. Trabajo con cadena. Hasta ahora la única operación que hemos realizado con cadenas es la concatenación, por medio del operador &. Además de él disponemos de un conjunto de funciones que nos permitirán realizar distintas operaciones con cadenas, como extracción de caracteres,

Introducción a Visual Basic 6.0

66

conversiones, eliminación de espacios, etc. La tabla 3.10. contiene cada una de estas funciones y una breve descripción de su finalidad.

Tabla 3.10. Funciones para tratamiento de cadenas

Left Extrae caracteres contando de izquierda a derecha Right Extrae caracteres contando de derecha a izquierda Mid Extrae caracteres de cualquier punto de la cadena LTrim Elimina espacios al principio de una cadena RTrim Elimina espacios al final de una cadena Trim Elimina espacios tanto al principio como al final LCase Convierte las mayúsculas en minúsculas UCase Convierte las minúsculas en mayúsculas StrConv Convierte una cadena según una opción StrReverse Invierte la secuencia de carac que forman la cadena Space Genera una cadena de espacios String Genera una cadena de un cierto carácter indicado Len Devuelve la longitud de una cadena InStr Busca una cadena dentro de otro cadena Replace Realiza búsquedas y sustituciones en una cadena

3.4.19. Trabajo con fechas. Ya hemos visto anteriormente que por medio de los operadores aritméticos de suma y diferencia es posible operar sobre fechas, añadiendo un determinado número de días a una fecha, o hallando los días transcurridos entre dos fechas dadas. Además de estas operaciones básicas Visual Basic dispone de una serie de funciones, enumeradas en la tabla 3.11, con las que podremos realizar otras, como extraer una cierta porción de la fecha u hora, o saber el día de la semana. Una variable del tipo Date es capaz de contener tanto la fecha actual como la hora. Para asignar un valor directamente a una variable de este tipo pondremos la fecha entre dos almohadillas, pudiendo utilizarse distintas notaciones que se convertirán automáticamente al formato de Visual Basic. Por ejemplo, para introducir el día 28 de abril de 1998 podemos escribir la fecha como #Apr 28 98#,#4/28/98# o #1998 April 28#. En el mismo momento en que validemos la línea, pulsando INTRO o pasando a cualquier otra línea, la fecha será comprobada y convertida a un formato común. Además, tras la fecha podemos añadir la hora, por ejemplo 17:05 ó 4:12 PM, siempre dentro de las almohadillas.

Tabla 3.11. Funciones para manipulación de fechas

Date Devuelve la fecha actual Now Devuelve la fecha y hora actuales Time Devuelve la hora actual Day Obtiene el día de una fecha Month Obtiene el mes de una fecha Year Obtiene el año de una fecha WeekDay Obtiene el día de la semana correspondiente Hour Obtiene la hora

Introducción a Visual Basic 6.0

67

Minute Obtiene el minuto Second Obtiene el segundo DateAdd Añade un intervalo de tiempo a una fecha DateDiff Obtiene el intervalo de transcurrido entre dos fechas DatePart Devuelve parte de una fecha (semana, trimestre, etc.) DateSerial Compone una fecha a partir de parámetros relativos TimeSerial Compone una hora a partir de parámetros relativos MonhtName Obtiene el nombre de un mes WeekdayName Obtiene el nombre de un día de la semana

El valor devuelto por las funciones Date, Now y Time puede ser asignado en los tres casos a una variable Date, con la diferencia de que en el primer caso sólo existirá información acerca de la fecha actual, en el segundo tanto la fecha como la hora y en el tercero sólo la hora. Pruebe simplemente a imprimir: Print Date, Print Now y Print Time, verá la diferencia. Una vez que tenemos una fecha podemos obtener distintas parte de ella. La función Day devolverá el día del mes, Month el número del mes y Year el año. Para obtener el día de la semana utilizaremos WeekDay, que devolverá un número, entre 1 y 7, indicando el día. Normalmente el 1 corresponde al domingo, 2 al lunes, etc. Pasando el valor devuelto por Mouth a MouthName obtendremos el nombre del mes actual. De forma similar, usando el valor WeekDay con la función WeekdayName podremos recuperar el nombre del día de la semana. También podemos obtener las distintas partes de la hora, si es que la variable contiene esa información. Las funciones Hour, Minute y Second nos facilitarán la hora, minuto y segundo, respectivamente. Con los operadores de suma y resta podemos añadir días a una fecha o sustraer días de una fecha. Sin embargo, en ocasiones puede ser necesario trabajar con intervalos de tiempo distintos al día, por ejemplo meses, semanas o trimestres. En este caso podemos utilizar la función DateAdd, a la que pasaremos tres parámetros: una cadena indicativa del intervalo de tiempo a usar, un número positivo o negativo, con el número de intervalos a desplazar y, como tercer parámetro, la fecha de partida. Las cadenas por medio de las cuales podremos facilitar el tipo de intervalo son las mostradas en la tabla 3.12. Supongamos que tenemos una fecha y deseamos hallar otra con una diferencia de tres semanas; la operación a realizar sería DateAdd (“ww”,3,FechaOrigen).

Tabla 3.12. Intervalos de tiempo

s Segundos n Minutos h Horas y Días de año d Días de mes w Días de la semana ww Semanas m Meses q Trimestres yyy Años

Introducción a Visual Basic 6.0

68

3.4.20. Trabajo con Variant. El tipo Variant es seguramente el más flexible con el que ningún lenguaje ha sido dotado. Permite almacenar números enteros y decimales, con distintas precisiones, cadenas, fechas y matrices, realizando automáticamente las conversiones necesarias según la operación en que se vea envuelta la variable. En ocasiones puede ocurrir que al trabajar con una variable de tipo Variant no conozcamos de antemano su tipo. Suponga que creamos una función propia que recibe como parámetro un Variant, que puede contener una cadena, un número o una fecha. Seguramente la función necesitará saber qué tipo de dato contiene antes de proceder. Para ello tenemos a nuestra disposición las funciones mostradas en la tabla 3.13. Todas ellas toman un parámetro y devuelven True, si éste contiene un dato del tipo indicando, o False en caso contrario.

Tabla 3.13. Funciones para obtener el tipo de un dato

Función Devuelve True si tiene IsNumeric Cualquier tipo numérico IsDate Una fecha u hora IsObjet Una referencia a un objeto IsArray Una matriz IsNull Contenido nulo IsEmpty No se ha inicializado IsError Contiene un error

Si necesitamos una información más detallada sobre el tipo, por ejemplo no saber sólo que contiene un número, sino también a qué rango se ajusta, podemos utilizar la función VarType .Ésta toma como parámetro una variable y devuelve una constante indicando el tipo o contenido de una forma más específica. Las posibles constantes se muestran en la tabla 3.14. En lugar de estas constantes podemos obtener directamente el nombre del tipo utilizando en lugar de VarType la función TypeName.

Tabla 3.14. Constantes devueltas por Var Type

Constante Tipo del valor vbBoolean Contiene un Boolean vbByte Contiene un Byte vbInteger Contiene un Integer vbLong Contiene un Long vbCurrency Contiene un Currency vbSingle Contiene un Single

Constante Tipo del valor vbDouble Contiene un Double vbDate Contiene un Date vbString Contiene un String vbObject Referencia a un objeto OLE vbDataObject Referencia a un objeto no OLE

Introducción a Visual Basic 6.0

69

vbArray Contiene una matriz vbNull Contenido nulo vbEmpty No ha sido inicializado vbError Contiene un error

3.4.21. Matrices. Hasta el momento hemos trabajado con variables individuales, cada una de las cuales contiene un valor. En muchas ocasiones, sin embargo, necesitamos trabajar con múltiples valores distintos del mismo tipo y relacionados entre sí. Por ejemplo, si deseamos hallar la media de un conjunto de diez mediciones, por poner un caso, debemos disponer de estos diez datos. En este caso se podrían crear diez variables del mismo tipo y con distinto nombre y después operar sobre ellas. Pero imagine que no se trata de diez valores, sino de cientos, o miles. Está claro que no es posible mantener tantas variables independientes. La solución a este problema son las matrices, variables con un solo nombre pero con múltiples valores a los que es posible acceder por medio de un índice puesto entre paréntesis a continuación del nombre de la variable. Las matrices se declaran como cualquier otra variable, con la única diferencia de que tras el nombre abriremos unos paréntesis e indicaremos el índice superior que deseamos. Continuando con el supuesto citado anteriormente, para crear una matriz capaz de contener las diez mediciones la sentencia podría ser Dim Medidas(9) As Double.Fíjese en que se ha especificado como índice máximo el 9 y no el 10, ya que por defecto los índices de las matrices comienza en el 0. Esto puede ser modificado con la sentencia Option Base 1, que en caso de utilizarse debe aparecer al principio del módulo o formulario y, por supuesto, antes de cualquier declaración de una matriz. Podemos optar por otro método más flexible en cuanto a los límites de la matriz, que consiste en especificar, al declararla, tanto el límite inferior como el superior. De esta forma no tenemos que preocuparnos por la sentencia Option Base ni por el límite inferior por defecto. Para hacer esto introduciremos en el interior de los paréntesis el límite inferior, la partícula To y el límite superior. Por ejemplo, la declaración Dim Medidas (5 To 14) As Double crea una matriz, llamada Medidas, consistente en diez elementos de tipo Double, con índices que van desde el 5 al 14. Para acceder a cualquier de los elementos de una matriz tan sólo tendremos que especificar su nombre y, entre paréntesis, el número de elementos que deseamos. En caso de que no conozcamos los límites de la matriz, podemos obtener el índice inferior con la función LBound y el superior con UBound. Ambas funciones toman como parámetro el nombre de la matriz. 3.4.22. Matrices multidimensionales. Una matriz con una sola dimensión, como las definidas anteriormente, se puede representar como una lista. Puede ser una columna con múltiples filas o bien una fila con múltiples columnas. En caso necesario podemos definir matrices con más de una dimensión, separando los límites de una dimensión de los de la siguiente mediante comas. Supongamos que deseamos crear una matriz con cien elementos estructurados en 10 filas por 10 columnas cada una. La declaración necesaria sería Dim N(1 To 10, 1 To 10) As Byte. Para acceder a cualquiera de los elementos de esta matriz dispondríamos detrás de su

Introducción a Visual Basic 6.0

70

nombre, en el interior de los paréntesis, el número de fila y columna correspondiente al elemento deseado. De igual forma es posible declarar matrices de tres, cuatro o más dimensiones. Al hacerlo hay que tener en cuenta que el número de elementos de cada dimensión multiplica por los demás índices, por lo que una matriz con 10 elementos por dimensión y dos dimensiones tendrá cien elementos, pero una con tres dimensiones tendrá mil. El número máximo de dimensiones permitido por Visual Basic es 60, un número difícilmente utilizable en cualquier caso. Para conocer lo límites de cada una de las dimensiones de una matriz usaremos las mismas funciones vistas anteriormente, LBound y UBound, pero además de facilitar el nombre de la variable habrá que pasar como segundo parámetro el número de la dimensión. 3.4.23. Matrices dinámicas. Aunque el caso más habitual es que una matriz mantenga unos límites fijos a lo largo de la ejecución de un programa, en Visual Basic es posible crear matrices dinámicas cuyos límites pueden ser alterados a lo largo de la ejecución según las necesidades de cada caso. Para declarar una matriz de este tipo utilizaremos las mismas sentencias que ya conocemos, Dim, Public o Static, pero dejaremos vacíos los paréntesis que caracterizan la declaración de una matriz, sin indicar límites. Una vez conozcamos el tamaño necesitado, generalmente a partir de parámetros o cálculos obtenidos en un procedimiento o función, usaremos la sentencia ReDim para indicar los límites de cada una de las dimensiones que existan. Podemos redimensionar una matriz tantas veces como necesitamos. Cuando se redimensiona una matriz, por defecto los datos que había contenidos en ella en ese momento se pierden. Esto no será ningún inconveniente si cada vez que se modifican los límites es para asignar nuevos valores, pero en el caso de que la matriz simplemente crezca, sería interesante preservar los valores ya existentes. En este caso usaremos la opción Preserve, que pondremos detrás de Redim y antes del nombre de la matriz a redimensionar. Aún así, si se da a la matriz un tamaño inferior al actual irremediablemente se perderán algunos elementos, ya que la nueva matriz no tendrá capacidad para ellos. Al redimensionar una matriz utilizando Preserve no puede alterar el número de dimensiones, ni el límite inferior. 3.4.24. Asignación e inicialización de matrices. A diferencia de una variable simple, cuyo identificador hace referencia a un solo valor, las matrices no representan valores individuales, por lo cual tareas tales como la asignación o inicialización son proporcionalmente más complejas. Si declara una variable de tipo String y quiere inicializarla dándole un valor bastaría el siguiente código: DimUnaCadena As String UnaCadena = “Hola”

Introducción a Visual Basic 6.0

71

Suponiendo que tuviésemos otra variable del mismo tipo, por ejemplo llamada OtraCadena, la asignación de una a otra sería tan sencilla como escribir: OtraCadena = UnaCadena Para inicializar cualquier matriz de tamaño fijo, en la que se ha indicado el número de elementos en el momento de la declaración, hay que hacer referencia de forma individual a cada uno de los elementos. De forma análoga, para asignar el contenido de una matriz a otra hay que tratar también todos los elementos de forma separada. 3.4.25. Constantes. A lo largo de este capítulo hemos podido ver que ciertos valores devueltos por Visual Basic, o que podemos facilitar, están representados por constantes, lo que hace bastante más fácil su comprensión. Una constante no es más que un nombre, como el de una variable, al que se asigna un valor que no podrá ser modificado posteriormente. Además de la ventaja indicada de trabajar con un nombre descriptivo, en lugar de con el dato directamente, al utilizar constantes tenemos la facilidad de que si es necesario alterar ese valor tan sólo tendremos que modificar la definición de la constante y no el valor en cada uno de los puntos donde se utiliza. Una constante puede ser definida en cualquier ámbito de forma similar a como se define una variable. En lugar de utilizar Dim, Public o Static utilizaremos Const, seguido del nombre de la constante, su tipo y el valor que deseamos darle. En caso de no indicarse el tipo éste se deducirá del valor asignado. Obviamente el valor de una constante no puede ser modificado durante la ejecución de un programa, el valor se asigna durante el diseño y sólo podrá ser modificado editando de nuevo el código. 3.4.26. Definición de tipos. Partiendo de los tipos de datos fundamentales que hemos conocido: número, cadenas, fechas, matrices, etc., Visual Basic nos permite crear nuestros propios tipos de datos. Se tratará, por lo tanto, de tipos más complejos compuestos por una o más partes de los tipos básicos que ya conocemos. La creación de nuestros propios tipos nos permitirá manipular con facilidad conjuntos de información relacionados, como puede ser la ficha de datos de una persona, las características de un ordenador personal o cualquier otro conjunto relacionado de datos. La definición de un tipo siempre se ha de encontrar a nivel de módulo, no podemos crear un nuevo tipo en el interior de un procedimiento o función. Por defecto en los formularios y módulos de código los tipos que definamos serán públicos, es decir, aunque lo hayamos definido en un formulario, el tipo ya será conocido para el resto. Si deseamos que un tipo se conozca solamente en el interior del módulo donde se ha creado antepondremos a su definición la palabra Private, que es lo opuesto de Public. En los módulos de clase, sin embargo, los tipos tan sólo pueden ser privados.

Introducción a Visual Basic 6.0

72

Para iniciar la creación de un nuevo tipo usaremos la instrucción Type, que irá seguida del nombre que vamos a darle. La definición terminará con la sentencia End Type. Entre ambas líneas, de inicio y fin, enumeraremos cada uno de los componentes indicando nombre, tipo y, si es necesario, longitud o límites. En el interior de un nuevo tipo se pueden utilizar, como se ha dicho, cualquier tipo de dato básico, así como otros tipos definidos por el usuario, ya existentes. Por ejemplo, suponga que desea almacenar los distintos componentes de una dirección, como son la calle, número, código postal, población y provincia. En lugar de manejar variables dispersas puede crear el siguiente tipo. Private Type Dirección Calle As String Número As Integer CodPostal As String * 5 Población As String Provincia As String End Type A partir de este momento podrá declarar variables del tipo Dirección como de cualquier otro tipo. Usando Dim, Public o Static, con ámbito local o a nivel de módulo, e incluso crear matrices. Para acceder a uno de los componentes de un tipo se utiliza la notación Objeto. Elemento, donde objeto es la variable del tipo que hemos creado y Elemento es el componente al que deseamos acceder. Por ejemplo, podríamos realizar la asignación MiDireccion. CodPostal=”23004”, suponiendo que la variable MiDireccion sea del tipo Dirección. Esta notación se repite en el caso de que el elemento al que accedamos sea a su vez un tipo compuesto. Por ejemplo, suponga que creamos un nuevo tipo, al que llamamos Ficha, que tiene como uno de sus componentes una variable del tipo Dirección. Para acceder a sus elementos se utilizará la siguiente notación. Private Type Ficha Nombre As String Dir As Dirección En Type … 3.5. Controles más habituales. La finalidad principal de un formulario es servir de contenedor para los controles que nuestro programa necesite. Estos controles permitirán mostrar información al usuario de una forma más controlada que con Print, solicitar datos en distintas formas, ofrecer listas de elementos, etc. A continuación tendremos ocasión de conocer los controles estándar de Visual Basic, aquellos que aparecen automáticamente en la paleta de herramientas aún cuando nosotros no lo hayamos indicado. Cada uno de los controles estándar tiene una serie de propiedades, implementa unos métodos y puede responder a un conjunto de eventos. Muchos de estos elementos son comunes a todos los controles, por ejemplo las propiedades Name o Left, o el evento MouseDown existen en casi todos. Por ello, una vez que conozcamos estos elementos no será necesario volver a aprenderlos en cada control, ya que son comunes y se darán por conocidos.

Introducción a Visual Basic 6.0

73

3.5.1. Etiquetas de texto. El control Label, representado en la paleta de herramientas por una letra A mayúscula, nos servirá para situar cualquier texto estático en el interior de un formulario, indicando posición, color, tipo de letra, etc. Que el texto sea estático quiere decir que el usuario del programa no podrá interactuar con él, modificándolo o borrándolo, ya que se trata de un texto fijo sólo modificable desde el propio código o durante el diseño del formulario. 3.5.2. Entrada de texto. El control TextBox, que aparece en la paleta de herramientas junto al control Label simbolizado por un recuadro conteniendo las letras ab y un cursor, nos permitirá solicitar la entrada de datos en un formulario. Como veremos a continuación, un control de este tipo puede tratar una o varias líneas de texto, incorporando funciones de selección, cortar y pegar, barras de desplazamiento para textos largos, etc. 3.5.3. Grupos de controles. El control Frame, representado en la paleta de herramientas como un recuadro con las letras xyz en su parte superior. Visualmente porque el control traza un recuadro alrededor de los controles que forman el grupo, asignándose un título. De esta forma el usuario percibe la noción de que se trata de una serie de datos relacionados. 3.5.4. Botones. Un botón es un control que aparece como un rectángulo o cuadrado con un título en su interior, al pulsarlo parece hundirse y se ejecuta un código que es la acción asociada al botón (a su evento Click, en realidad). Este control aparece a la derecha del control Frame en la paleta de herramientas, representado por un icono en forma de rectángulo redondeado y con una pequeña sombra. Su nombre es CommandButton. 3.5.5. El control CheckBox. En muchas ocasiones la única respuesta que se necesita del usuario es un sí o un no, un lo quiero o no lo quiero, es cierto o no lo es. En estas ocasiones podemos utilizar una caja de selección o control CheckBox. 3.5.6. Uso de listas. Una lista es un control capaz de contener cadenas de texto que aparecen en una ventana. Ésta, en caso necesario, dispondrá de barras de desplazamiento. Esta lista puede aparecer en una sola columna o en varias y a partir de ella el usuario puede elegir uno o varios de los elementos mostrados. En cualquier momento desde el código de nuestro programa podemos saber qué elemento está elegido, añadir o eliminar elementos, etc.

Introducción a Visual Basic 6.0

74

3.5.7. Listas combinadas. Una lista combinada es la unión de un control TextBox con un control ListBox. Es decir, dispone de un espacio en el que el usuario puede opcionalmente introducir un dato o en el que se puede mostrar la opción actual. También tiene la posibilidad de desplegar una lista desde la que elegir un valor de entre los existentes. 3.5.8. Barras de desplazamiento. En la paleta de herramientas, debajo de las listas, encontraremos dos controles llamados HScrollBar y VScrollBar, que corresponden a la barra de desplazamiento horizontal y vertical, respectivamente. Aunque se trate de dos controles distintos, funcionalmente son idénticos, teniendo las mismas propiedades y métodos y respondiendo a los mismos eventos. 3.5.9. Programación de eventos periódicos. El control que vamos a ver ahora funciona de forma totalmente distinta, al no aparecer en el formulario durante la ejecución, sólo en el proceso de diseño. El control en cuestión aparece en la paleta de herramientas representado como un cronómetro y su nombre es Timer. La finalidad de un control Timer es generar un evento cada cierto intervalo de tiempo, que especificaremos en la propiedad Interval. La medida de tiempo es el milisengundo, por lo que si deseamos que el evento se produzca cada medio segundo el valor a asignar será 500. 3.5.10. Uso de líneas y polígonos. En la paleta de herramientas encontraremos dos controles que de forma simple nos permitirán dibujar líneas, control Line, y distintas figuras o polígonos, control Shape. Estos dos controles son realmente estáticos, no pueden responder a ningún tipo de evento, y prácticamente no tienen métodos, sólo están definidos por sus propiedades. 3.5.11. Matrices de controles. Una matriz de controles puede contener tantos controles como necesitamos, en realidad el valor máximo es 32767, difícil de alcanzar. Todos los controles que forman parte de una matriz han de ser del mismo tipo, tener el mismo nombre y, lo que es más interesante, comparten el mismo código. Sin embargo, cada uno de ellos puede tener sus propiedades particulares, por lo que es posible asignar títulos distintos, contenidos o estados, etc..

Introducción a Visual Basic 6.0

75

3.5.12. Creación de controles durante la ejecución. Cuando se utilizan matrices de controles tenemos a nuestra disposición una característica quizá aún más potente que la de compartir código, la creación de controles adicionales en tiempo de ejecución. Siempre que tengamos una matriz de controles en nuestro formulario, aunque sea tan sólo con un elemento, durante la ejecución del programa podremos crear elementos adicionales. Para ello utilizaremos la sentencia Load, seguida del nombre del control y, entre paréntesis, el índice del nuevo elemento, que como es lógico no puede estar asignado ya a otro control de la misma matriz. 3.6. Programación orientada a objetos. Una de las mejoras más importantes incorporadas en las últimas versiones de Visual Basic es la posibilidad de definir nuestras propias clases o tipos de objetos. Visual Basic sigue sin ser un lenguaje totalmente orientado a objetos, al menos en el sentido más puritano de la aceptación. En teoría cualquier lenguaje orientado a objetos debe incorporar tres características: encapsulación, herencia y polimorfismo. 3.6.1. ¿Qué es un objeto?. Podemos describir un objeto como una entidad en cuyo interior existen datos y código relacionados entre sí, de tal forma que el usuario del objeto generalmente no tiene acceso a los datos, sino que éstos son manipulados de forma indirecta a través del código del objeto, que se ejecuta en base a procedimientos y funciones a los que se denomina habitualmente métodos. Un objeto puede ver visto desde dos puntos diferentes: el del programador del objeto, que lo ha diseñado, y el del usuario del objeto, que puede ser el mismo u otro programador. El primero, el diseñador del objeto, es el que define los datos que son necesarios y escribe el código que permitirá que el objeto realice lo que se espera de él. El segundo, el programador-usuario, se limitará a crear objetos de esa clase y utilizarlos llamando a sus métodos. El diseñador en realidad lo que construye es la clase, que podríamos describir como un molde a partir del cual se van creando posteriormente los objetos que, lógicamente, tendrán las características que se hayan fijado en ese molde. Utilizando una analogía con algo más cercano seguramente comprenderemos mejor estos términos. Tomemos un objeto cualquiera de nuestra vivienda, como puede ser el reproductor de vídeo que estamos acostumbrados a usar diariamente. Este aparato es un objeto que nosotros podemos manipular, programar mediante una serie de botones, que son los métodos que el diseñador, fabricante del vídeo, ha puesto a nuestra disposición. Internamente este objeto cuenta con una serie de datos, en este caso almacenados en la electrónica o circuitería, a los que nosotros no podemos acceder directamente. Pues bien, informáticamente hablando, un objeto es algo muy similar, es una caja cerrada que contiene código y datos y una serie de botones en la parte externa, que son los métodos, que permiten trabajar con él.

Introducción a Visual Basic 6.0

76

3.6.2. Encapsulación. La encapsulación es una característica que se deriva de la propia descripción de lo que es un objeto, en la que se acaba de decir qué código y datos están contenidos en una única entidad, como si fuese una cápsula. Esta propiedad, la encapsulación, hace que no sea posible la incorrecta manipulación del objeto, siempre, obviamente, que esté correctamente diseñado. En Visual Basic cuenta con esta propiedad tanto los módulos de formulario como los módulos de clase, que pueden contener datos, públicos y privados, y procedimientos y funciones en forma de métodos. 3.6.3. Herencia. Es quizá la característica más preciada y requerida en un lenguaje orientado a objetos, basándose en el pensamiento lógico de que todo objeto está compuesto de otros objetos más básicos y pequeños. Mediante la herencia es posible ahorrar gran cantidad de tiempo y trabajo, siempre que a cambio se dedique algo de tiempo al diseño de las distintas clases que se van a crear. En la herencia siempre están relacionadas dos clases: la que actúa como base, a partir de la cual se crea otra nueva que hereda sus características, y la nueva clase, a la que se denomina derivada. Tomando como partida diferentes clases base, que actúan como componentes, sería posible construir clases de objetos más complejos. Visual Basic no soporta el concepto de herencia tal y como existe en C++ u Object Pascal, por lo cual no se le considera un verdadero lenguaje orientado a objetos. Sin embargo, es posible construir un cierto tipo de herencia mediante la contención de un objeto dentro de otro. 3.6.4. Polimorfismo. Esta es una propiedad de los lenguajes orientados a objetos que está íntimamente ligada a la herencia y, como su propio nombre indica, es la cualidad por la cual un objeto puede adoptar diversas formas. Esta definición, algo confusa, significa que cuando se llame a un método de un determinado objeto del cual se tiene una referencia, el lenguaje se encargará en tiempo de ejecución de realizar el enlace necesario para que se llame al método apropiado para ese objeto. Visual Basic incorpora, además, la posibilidad de crear objetos polimórficos basándose es interfaces ActiveX. 3.6.5. Fundamentos de creación de controles ActiveX. Una de las posibilidades más incesantes que incorpora Visual Basic es la posibilidad de desarrollar controles ActiveX, bien partiendo desde cero, con una plantilla vacía, o bien ampliado y combinando controles ya existentes. La creación de un control, como podremos

Introducción a Visual Basic 6.0

77

ver en este capítulo, se asemeja al diseño de un formulario, tan sólo necesitamos conocer una serie de propiedades, eventos y métodos adicionales. No cabe duda de que Visual Basic incorpora un número importante de controles, tanto visuales como no visuales, con los que es posible atender la mayoría de las necesidades de un programador. Sin embargo, a veces es deseable que un determinado control tuviese una cierta capacidad adicional con la que no cuenta, o simplemente no existe un control adecuado para una función específica que hemos encontrado. En estos casos tenemos dos caminos posibles: buscar un control desarrollado por un tercero que se ajuste a nuestras necesidades, o bien escribir nuestro propio control. La finalidad que se persigue en este capítulo es que el lector sea capaz de escribir sus propios controles, pero no la de facilitar un conjunto de controles ya terminados para ser usados en sus programas. Por lo tanto los ejemplos que se facilitan deben ser tomados como tales, simplemente ejemplos que usted puede tomar base para desarrollar sus propios controles. 3.6.6. Creación de un control. Para crear un nuevo control el primer paso será la apertura de un nuevo proyecto conteniendo un módulo UserControl, en el que se definirán las características del control. Este proceso, que puede ser realizado manualmente, es mucho más simple si nos servimos de la opción Control ActiveX de la ventana de creación de nuevo proyecto, tal y como puede ver en la figura 3.14.

Figura 3.14. Creación de un nuevo componente.

También puede añadir un módulo UserControl a un proyecto estándar, pero en ese caso el control será privado, de uso interno de ese proyecto, no pudiendo generarse el correspondiente archivo OCX. 3.6.7. La clase UserControl. Para crear nuevo control partiremos del diseño de una nueva clase de objeto que contendrá, como cualquier otro objeto, variables, propiedades, eventos, procedimientos y métodos.

Introducción a Visual Basic 6.0

78

Todos los controles se crean a partir del tipo UserControl. Cualquier control ActiveX debe “saber” cómo hacer ciertas cosas, que son comunes a todos ellos. Esta funcionalidad común es la que está implementada en UserControl, de tal forma que un control que diseñemos ya sabrá cómo mostrarse en la caja de herramientas, contener su nombre, colocarse en un formulario, etc. El primer dato que deberemos modificar en la ventana de propiedades es precisamente el nombre del control, que es en realidad el nombre de clase con el que se conocerá una vez que se instale. CommandButton, TexrBox o ListBox son nombres de clase de controles que estamos acostumbrados a utilizar. Al asignar un nombre de clase a un control trate siempre de encontrar uno que sea lo más descriptivo posible, sabiendo de antemano las limitaciones de nomenclatura a las que deberá atenerse, que son las mismas que cuando da nombre a un variable, por ejemplo. 3.6.8. Instalación de un componente. Para que un componente pueda ser utilizado en otros proyectos, propios o de terceros, antes es necesario compilarlo generando el correspondiente archivo OCX. Para ello tendremos que elegir la opción Generar proyecto.ocx del menú Archivo. Generalmente el nombre del archivo en el que se aloje el control será el nombre del proyecto, mientras que el nombre de clase de control es el que se haya asignado a la propiedad Name del UserControl. Esto es lógico, ya que en un mismo archivo OCX se pueden almacenar múltiples controles, cada uno de ellos con su nombre de clase. Antes de compilar y generar el control ActiveX abra la ventana de propiedades del proyecto y facilite una descripción, como puede ver en la figura 3.15. Esa descripción será la que posteriormente aparezca en la lista de controles disponibles. Ahora sí, compile el proyecto para obtener el archivo Cuadro de dibujo.OCX.

Figura 3.15. Se facilita una descripción para el control.

Introducción a Visual Basic 6.0

79

Una vez guardado el proyecto de nuestro primer control, inicie un nuevo proyecto estándar, en el que inicialmente aparecerá un formulario vacío. Observe que en la caja de herramientas no está el nuevo control, por lo que habrá que usar el menú emergente de dicha caja para seleccionar la opción Componentes y hacer aparecer la ventana que se muestra en la figura 3.16 y que ya conoce. En ella podrá encontrar nuestro control de ejemplo, márquelo para hacerlo aparecer en la caja de herramientas.

Figura. 3.16. El control de ejemplo en la lista de controles disponibles.

Observe en la parte inferior de la ventana el nombre del archivo en que se aloja el control, es el archivo OCX que hemos generado hace un momento. Pulse el botón Aceptar y verá cómo en la caja de herramientas aparece un nuevo icono. Este es el icono por defecto usado para los controles de usuario. Si se sitúa sobre él podrá ver el nombre de clase del nuevo control, Dibujo.

Figura 3.17. El control de ejemplo en la caja de herramientas.

Seleccione el control Dibujo e insértelo en el formulario, en cualquier posición y sin importar las dimensiones. Como podrá ver tan sólo aparece un área delimitada sin nada en

Introducción a Visual Basic 6.0

80

su interior, realmente el control ahora mismo no tiene un aspecto visual, está vacío. Observe en la ventana de propiedades el nombre que se ha asignado a este control, Dibujo 1. Visual Basic lo trata como a cualquier otro control, añadiendo un número detrás del nombre de clase para crear el nombre del control. 3.6.9. Desarrollo de un control. Desde el mismo momento en que se inicia la creación de un nuevo control éste aparece automáticamente en la caja de herramientas, aunque inicialmente estará desactivado. Permanecerá en este estado mientras tengamos abierta la ventana de diseño del control, en el momento en que la cerremos éste quedará disponible para ser insertado en el formulario del proyecto estándar, lo que permite comprobar su funcionamiento sin necesidad de compilar ni dar ninguno de los pasos anteriores. Cada vez que se abra la ventana de diseño del control éste se desactivará en la caja de herramientas y en el formulario en que se haya insertado, lo cual es lógico, ya que Visual Basic no puede ejecutar un código que se está alterando. Hechas las modificaciones precisas, y cerrada la ventana de diseño, el control estará de nuevo disponible para ser probado. Si observa que el control insertado en el formulario permanece desactivado utilice la opción Actualizar controles de usuario del menú emergente del formulario. 3.6.10. Definición de propiedades. El primer paso que tendremos que dar para conseguir algo más útil consistirá en definir las propiedades de Dibujo, que dependerán de la finalidad que vayamos a dar a este control. 3.6.11. Creación de una propiedad. Aunque desde el punto de vista del programador que usa un componente una propiedad parece ser una variable, a la que es posible asignar y de la que se pueden obtener valores, realmente una propiedad es algo bastante más complejo, que además de servir para asignar u obtener un dato bastante más complejo, que además de servir para asignar u obtener un dato puede provocar la ejecución de métodos internos del objeto. Ya sabemos cómo definir propiedades, lo estudiamos en un capítulo previo. Una propiedad puede ser de lectura y escritura, de sólo lectura o, más raramente, de sólo escritura. Si nuestra propiedad va a ser de sólo facilitaremos el procedimiento Property Get. Si la propiedad va a ser de sólo escritura sólo deberá existir el procedimiento Property Let. En caso de que se vayan a permitir operaciones tanto de lectura como de escritura será preciso facilitar ambos procedimientos o bien declarar la variable asociada a la propiedad como pública, caso éste en que no se necesitarán los citados procedimientos. Por regla general aquellas variables que van a ser usadas en la definición de un control para contener valores de propiedades se deben declarar siempre como Private, de tal forma que no sean accesibles para el usuario del control.

Introducción a Visual Basic 6.0

81

Ya sabemos, por los componentes que hemos usado hasta ahora, que unas propiedades están accesibles durante el diseño, en la ventana de propiedades, y durante la ejecución, mientras que otras sólo se pueden usar durante la ejecución. Habrá observado que todas aquellas propiedades que son de sólo lectura no están disponibles en tiempo de diseño, por regla general porque los valores que contienen se obtienen durante la ejecución. Si queremos que nuestra propiedad sea accesible tanto en tiempo de diseño como de ejecución, ésta deberá de ser de un tipo simple y contar con los procedimientos Get y Let. Visual Basic no facilita en la ventana de propiedades la edición de aquellas de tipo complejo, como pueden ser matrices. 3.6.12. Métodos de lectura y escritura de propiedades. Aunque es posible declarar una propiedad que lee y escribe su valor directamente de una variable, declarada como pública, en la mayoría de las ocasiones necesitaremos escribir dos procedimientos, uno para lectura y otro para escritura, que serán los que se ejecuten cuando el usuario del control intente leer o escribir una propiedad. Esta posibilidad permite que cuando el usuario asigne o lea el valor de una propiedad no sólo esté realizando esa acción, sino que indirectamente ejecutará una porción de código que nosotros determinaremos. La posibilidad de utilizar procedimientos de lectura y escritura de propiedades nos permite un mayor control sobre las actuaciones que se llevan a cabo con el componente y también realizar muchas operaciones que de otra forma exigirían la creación de un método, al que el usuario del control tendría que llamar pasando los parámetros apropiados. A diferencia de las variables cuya finalidad es mantener valores de propiedades, que serán Private, todos aquellos procedimientos y funciones que actúen como métodos de lectura o escritura de una propiedad deben ser Public, ya que de lo contrario no estarían accesibles desde fuera del objeto. 3.6.13. Almacenar valores de propiedades. Al salvarse un formulario, los controles que se encuentran en él salvan automáticamente los valores asignados a sus propiedades en el archivo FRM. Dichos valores también se guardan en el ejecutable cuando éste es generado. Un control diseñado por nosotros recibirá un evento WriteProperties cada vez que sea preciso salvar las propiedades. El procedimiento asociado a este evento recibe como parámetro un objeto PropertyBag, el cual cuenta con un método, llamado WriteProperty, que podemos usar para salvar nuestras propiedades. Este método toma tres parámetros: una cadena con el nombre de la propiedad, el valor a escribir y el valor por defecto de dicha propiedad. Este tercer dato se utilizará para escribir el valor de la propiedad sólo en caso necesario, es decir, si el valor actual de la propiedad coincide con el valor por defecto, ¿qué sentido tiene almacenarlo y ocupar espacio?. Cada vez que se carga un formulario en el que está insertado un control, independientemente de que sea en tiempo de diseño o de ejecución, se genera un evento ReadProperties. Éste nos da la oportunidad de recuperar los valores de las propiedades que

Introducción a Visual Basic 6.0

82

se escribieron en el evento WriteProperties. El procedimiento asociado a ReadProperties recibe como parámetro un objeto PropertyBag, al igual que el anterior. En este caso usaremos el método ReadProperty de ese objeto para leer el valor de la propiedad, siendo precisos dos parámetros: una cadena con el nombre de la propiedad y un valor por defecto, que será el devuelto en caso de que no se haya salvado previamente. 3.6.14. Definición de eventos. Si inserta un control ActiveX en un formulario, abre la ventana de código y despliega la lista de eventos de dicho control podrá ver que no existe ninguno específico, sólo cuenta con los cuatro eventos generales a todo UserControl. Prácticamente todos los componentes ActiveX cuentan con uno o más eventos, cada uno de los cuales se genera cuando se produce una cierta situación. Un evento se genera cuando se cumple una cierta condición, por ejemplo cuando ha pasado un cierto tiempo, cuando es necesario dibujar el contenido, cuando se ha recibido una pulsación de ratón, etc. En todos estos casos el control lo que hace es llamar al procedimiento facilitado por el usuario del control en tiempo de diseño. Mediante las sentencias Event y RaiseEvent. Sólo con estos dos elementos podremos crear controles con eventos propios. 3.6.15. Definición de métodos. Además de propiedades y eventos, un control también puede contar con métodos, que son funciones y procedimientos públicos que el usuario del control puede utilizar en tiempo de ejecución. Muchos controles simples no disponen de métodos definidos. La creación de un método es, por lo tanto, tan simple como escribir una función o un procedimiento. La única diferencia es que para llamar a este método será necesario haber creado previamente el control.

Implementación del Programa SCADA

83

4. Implementación del PFC 4.1. Filosofía a seguir Una vez sabemos en que consiste una aplicación SCADA y teniendo los conocimientos del lenguaje de programación de Visual Basic 6.0 podemos plantearnos la manera de llevar a cabo el objetivo del PFC. Ante de empezar a programar deberemos plantearnos cual va a ser la línea de trabajo que se va a seguir. Esta línea de trabajo debe recoger el propósito principal que nos hemos marcado para la realización del proyecto, que es la realización de un programa que sea capaz de desarrollar aplicaciones de control de proceso. Esto pasa a su vez por la realización de un programa que genere los sinópticos que necesitemos y los dote de funcionalidad. Para conseguirlo seguiremos el principio de “divide y vencerás”, es decir, crearemos dos aplicaciones independientes pero complementarias la una de la otra. Estas dos aplicaciones las estructuraremos de forma modular, de manera que parte del esfuerzo que se realice para realizar la programación de una pueda ser reinvertido en la otra. A las aplicaciones las dotaremos de ventanas con apariencia de aplicación Windows, de controles personalizados y de módulos donde se programaran procedimientos que realicen tareas rutinarias. Los procedimientos que se realicen deben de evitar utilizar parámetros que los hagan exclusivos de alguna tarea, para ello se evitará hacer referencia a una variable concreta. Marcado el camino y teniendo presente nuestro objetivo procederemos a explicar aquellos procedimientos, funciones, ventanas, controles personalizados, etc que tengan más relevancia. 4.2. Controles Personalizados (Controles ActiveX) Un control ActiveX creado con Visual Basic se compone siempre de un objeto UserControl y de otros controles, denominados controles constituyentes, que se colocan en él. Los objetos UserControl se almacenan en archivos de texto normal que contienen el código fuente y los valores de las propiedades del objeto UserControl y de sus controles constituyentes. Visual Basic emplea la extensión .ctl para estos archivos de origen. Los controles ActiveX que crearemos nosotros están basados en la utilización de controles constituyentes, de los cuales aprovecharemos sus propiedades, métodos y eventos y añadiremos las propiedades y eventos que creamos necesarios. Para crear nuestras propias propiedades haremos uso de los procedimientos de propiedad que nos ofrece Visual Basic 6 llamados Get y Let. El primero de ellos se usa cuando desee obtener el contenido de una propiedad, mientras que el segundo se utiliza en el momento

Implementación del Programa SCADA

84

en que se vaya a modificar dicho contenido con una asignación directa. La nomenclatura hecha servir es la siguiente:

Public Property Get NombrePropiedad () ...

End Property

Public Property Let NombrePropiedad (Parámetros) ...

End Property Estos procedimientos se llevan a cabo dentro de los módulos de código de los que dispone los objetos UserControl. Para acceder a las propiedades de los controles diseñados por nosotros bastará con escribir el nombre del control seguido de un punto y el nombre de la propiedad a la que se quiera acceder. Para el programa hemos diseñado seis controles ActiveX diferentes, cada uno de los cuales realizan una función concreta y especifica en el programa. Estos controles tienen todos ellos unas propiedades comunes, que son las que hemos definido nosotros y que nos servirán para poderlos identificar (Identificador), para identificarlo en la trama del proceso de comunicación (Alias) y para modificar su aspecto (Ancho y Alto). Los nombres de estos controles son:

Dibujo.

Etiqueta.

Texto.

Pulsador.

Figura.

Tubería. 4.3. Ventanas Para realizar las ventanas típicas de las aplicaciones Windows Visual Basic ofrece los formularios. El proyecto utiliza un total de cinco formularios principales, lo que implica un total de cinco interfaces diferentes.

Editor.

Propiedades.

Implementación del Programa SCADA

85

Presentación.

Lienzo.

Galactic. Dentro de los formularios es donde se gestionan los eventos que desencadena el usuario cuando mueve el puntero, clica sobre la pantalla, pulsa un icono de la barra de herramientas, etc. Dentro de cada evento escribiremos el código que queremos que se ejecute cuando se produzca dicho evento. 4.4. Módulos Estándar En el proyecto hemos utilizado un total de siete módulos diferentes donde se almacenan las variables globales utilizadas, los procedimientos y las funciones.

VariablesyMetodos.

AparienciaEditor.

OperacionesArchivo.

PropiedadesFunciones

EdiListarPropiedades.

EdiOperacionesArchivo

MatadorAbrir. 4.5. Acciones Principales En este apartado se procederá a explicar las principales acciones que realiza el programa. 4.5.1. Inserción de Controles Esta acción consistirá en insertar un control en la aplicación para cuando cree un sinóptico. A priori el número de controles que se necesitará para crear una pantalla no lo sabemos por lo que se tendrá que utilizar un método que nos permita la inserción de controles de una manera dinámica.

Implementación del Programa SCADA

86

Para conseguirlo previamente se ha insertado el control ActiveX declarándolo como una matriz de controles, lo que nos permite insertar un total de aproximadamente 32.767 (capacidad del tipo Integer que actuará como índice) controles de cada tipo. Para insertarlo habrá que llamar al procedimiento: insertar(grafico As String, orient As String, identifica As String, formula As Form), el cual recibirá el tipo de control que desee insertar y el formulario donde se quiera insertar. La instrucción de Visual Basic que permite la inserción dinámica de controles recibe el nombre de Load. En el caso que quiera insertar un control Figura el procedimiento insertar ejecutaría el siguiente código: Case "F" ReDim Preserve indices(ind) 'metemos en un vector la identificacion indices(ind) = identifica Load formula!Figura(ind) With formula!Figura(ind) .Identificador = identifica End With moveX = formula!Figura(ind).Width / 2 moveY = formula!Figura(ind).Height / 2 marcador = ind formula!Figura(marcador).Drag vbBeginDrag 4.5.2. Salvar Sinóptico Para salvar los sinópticos será necesario crear un archivo de texto donde queden recogidas todas las propiedades de los controles insertados (posición, tamaño, color,...), el bitmap que se haya insertado de fondo (si es que se ha insertado alguno), etc. Esta operación la realizará el procedimiento: operacion_guardar(formula As Form), el cual se encargará de crear un archivo de texto e ir recorriendo todos los controles insertados para leer el valor de sus propiedades y después escribirlas en el archivo. El código será el siguiente: Public Sub operacion_guardar(formula As Form) Dim nom As String Dim num As Integer Dim nfile As Integer 'Activamos la deteccion de errores y preparamos el cuadro de dialogo On Error Resume Next If nombrearchivo <> "" Then formula!cajacomun.FileName = nombrearchivo Else With formula.cajacomun: .DialogTitle = "Guardar como..." .Filter = "Archivo de sistema|*.rzd|Archivos jpeg|*.jpg|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt

Implementación del Programa SCADA

87

.ShowSave End With 'Crear el fichero de codigo adjunto nombrearchivo = formula!cajacomun.FileName num = Len(nombrearchivo): nom = Left(nombrearchivo, num - 3) nombrearchivo = nom & "txt" nfile = FreeFile Open nombrearchivo For Output As nfile 'Write #nfile, "Option Explicit" Close #nfile End If 'Cambiamos la apariencia del puntero del mouse y definimos las variables y 'elementos necesarios para guardar la informacion en un archivo Dim anterpuntero As Byte Dim i As Integer 'Asignamos un valor para abrir el canal, tratamos la apariencia del puntero y 'abrimos el archivo q queremoes leer nfile = FreeFile anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass fondo = formula!Tapiz.BackColor Open formula!cajacomun.FileName For Output As nfile 'guardamos la imagen de fondo y en su defecto el color de fondo Write #nfile, fotos, fondo 'Salvamos el archivo For i = 1 To ind Select Case indices(i): Case "D" With formula!Dibujo(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .Pintura, .alto, .ancho, .visible ', fondo End With Case "T" With formula!Tuberia(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .Height, .Width, .visible End With Case "P" With formula!Pulsador(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .Caption, .Enabled Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .MousePointer, .visible End With Case "F" With formula!Figura(i)

Implementación del Programa SCADA

88

Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .BackStyle, .BorderColor, .BorderStyle, .BorderWidth Write #nfile, .FillColor, .FillStyle, .Shape, .visible End With Case "E" With formula!Etiqueta(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .AutoSize, .BackColor, .BackStyle, .BorderStyle, .Caption, .Enabled, .Alignment Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .ForeColor, .MousePointer, .visible, .WordWrap End With Case "TE" With formula!Texto(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .BorderStyle, .Text, .Enabled, .Alignment, .Appearance Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .ForeColor, .MousePointer, .visible End With End Select Next Close nfile 'Restablecemos el puntero y indicamos en tipo de error Screen.MousePointer = anterpuntero 'Modificar el valor de modificado modificado = False On Error GoTo 0 'desactivamos los errores End Sub 4.5.3. Cargar Sinóptico Para cargar un sinóptico se procederá de forma similar a lo realizado para salvarlo, esta vez

en lugar de escribir en el archivo lo que haremos es leerlo y posteriormente insertar los controles con la función Load. Esta operación se realiza en el siguiente procedimiento:

operacion_abrir(formula As Form)

4.5.4. Capturar Propiedades Este procedimiento se encarga de capturar y mostrar las propiedades de los controles insertados. El nombre del procedimiento es:

Captura_Propiedades(formula As Form).

Implementación del Programa SCADA

89

4.5.5. Creación del archivo ejecutable Para crear el archivo ejecutable ha sido necesario crear un archivo de ejecución por lotes, es decir, un archivo con extensión *.bat. En este archivo se han escrito las órdenes necesarias para poder acceder a la línea de comandos de la aplicación Visual Basic.

:PRINCIPIO @ECHO OFF cls "C:\Archivos de programa\Microsoft Visual Studio\VB98\VB6.EXE" /m "C:\Proyecto\matador.vbp" "C:\Proyecto\sinombre" :FIN

Con estas órdenes se consigue acceder al compilador de Visual Basic y al constructor de archivos ejecutables. 4.5.6. Comunicación Para facilitarnos la comunicación por el puerto serie se ha utilizado en control que a tal efecto proporciona Visual Basic: MSComm. Mediante este control podemos controlar el proceso de transmisión o recepción de datos.

Manual de Usuario

90

5. Documentación de Usuario (Manual de Uso) Como se ha comentado en el apartado anterior el programa se ha estructurado en dos aplicaciones independientes entre ellas pero complementarias entre si ya que la una sin la otra no dotan a la aplicación de funcionalidad. Una vez sabida la estructuración que se ha seguido para realizar la aplicación SCGalactic, es hora de conocer su forma de uso y sus principales características para obtener su máximo rendimiento. 5.1. Puesta en Marcha Antes de poder ejecutar la aplicación habrá que localizarla dentro del equipo donde haya sido instalada. Para ello sólo será necesario buscar mediante el Explorador de Windows o mediante la opción Buscar del menú Inicio el nombre de la aplicación.

Figura 5.1. Icono de la aplicación.

Cuando haya localizado la aplicación y desee ejecutarla deberá clicar dos veces consecutivas sobre el icono, produciendo así la ejecución de la misma. Una vez ejecutada la aplicación aparecerá la siguiente pantalla

Figura 5.2. Pantalla informativa del programa.

Como puede observar en la figura 5.2., la pantalla le informa del nombre del programa, del autor, de la entidad para la que ha sido creada, etc. Para hacerla desaparecer bastará con que clique fuera de ella, desapareciendo de forma inmediata la pantalla informativa. La pantalla que visualizará a continuación será la que puede observar en la figura 5.3.

Manual de Usuario

91

Figura 5.3. Programa SCGalactic.

Una vez llegados a este punto podrá certificar que se encuentra en disposición de hacer uso de la aplicación. Como puede observar el programa le ofrece la oportunidad de escoger entre dos opciones, que son: Editor Sinópticos y/o Editor Código. El Editor Sinópticos le permitirá crear el aspecto gráfico que desee para el proceso de control que tenga que realizar, permitiéndole insertar etiquetas, cuadros de texto, pulsadores, figuras geométricas, elementos diseñados especialmente para el proceso de control, bitmaps, etc. Esta opción será la que deberá escoger si desea crear un sinóptico nuevo acorde al proceso que deba controlar. El Editor Código le permite dotar a los sinópticos creados con la funcionalidad que desee, permitiéndole editar el código que crea necesario para gestionar el proceso de control. 5.2. Editor Sinópticos Para acceder a él deberá clicar en el botón “Editor Sinópticos” que aparece en la pantalla inicial. Una vez realizada esta acción se pondrá en funcionamiento el editor con el que podrá desarrollar las pantallas de monitorización de su proceso de control. 5.2.1. Entorno El entorno de la aplicación es el que aparece en la figura 5.4., en la que se puede apreciar una serie de elementos comunes y fácilmente reconocibles por todos los usuarios de aplicaciones Windows.

Manual de Usuario

92

Figura 5.4. Entorno Editor Sinópticos.

La parte superior del editor está ocupa por una barra de herramientas donde se ubican los iconos (pequeños gráficos que tienen como función indicar de forma visual la operación que realizan). Los iconos se encuentran distribuidos en la barra de herramientas en grupos funcionales, es decir, se han agrupado aquellas funciones que realizan tareas parecidas y/o complementarias. Esta agrupación se diferencia en la barra de herramientas mediante las líneas verticales que aparecen en ella. Además en la barra de herramientas también podrá identificar una caja de texto que será útil para cuando realice la inserción de algún elemento ya que en ella aparecerá en nombre de la variable del elemento insertado o la posición dentro de la pantalla. Los otros elementos comunes a las aplicaciones Windows son la existencia de un control de menú de sistema (permite que en la parte inferior de la pantalla pueda observar las aplicaciones que están en funcionamiento en su equipo) y unos botones para cerrar, minimizar y maximizar la aplicación. 5.2.2. Rejilla Consiste en un conjunto de puntos dispuestos de forma matricial (fila/columna) cuya finalidad es la correcta alineación de los elementos insertados. Esta rejilla facilita el diseño de los sinópticos ya que fuerza que la colocación de los elementos se realice sobre los puntos. La rejilla aparece en forma de puntos de color azul y será siempre visible.

Manual de Usuario

93

Figura 5.5. Rejilla.

5.2.3. Barra de Herramientas Como se comentado anteriormente la barra de herramientas está ubicada en la parte superior del editor, y es el elemento que permite la interacción entre el usuario y el programa ya que dentro de cada icono se establece una función determinada. Los iconos elegidos son fácilmente identificables ya que se ha seguido el criterio de las aplicaciones Windows y se aplicado el sentido común, de tal forma que no tenga ningún problema para reconocer la función que realizan. Para más ayuda se ha dotado a cada icono de una ayuda visual en forma de texto que aparece cuando se sitúa con el puntero durante un instante encima del icono, indicando su nombre. Los grupos de funciones que se han establecido están relacionados con temas que van des de la realización de las operaciones de abrir/guardar una pantalla, crear una pantalla nueva, insertar/eliminar elementos, insertar/eliminar un bitmap de fondo, cambiar el color de fondo de la pantalla, salir, etc.

Figura 5.6. Iconos de la Barra de Herramientas.

Para acceder a cualquiera de las funciones recogidas en la barra de herramientas solo deberá clicar sobre el icono que tenga recogida la operación que desee realizar. 5.2.3.4. Nuevo

Figura 5.7. Icono Nuevo.

Manual de Usuario

94

Esta función le permite eliminar todos los elementos y el fondo de pantalla que tenga, ya sea una imagen o un color. Es útil para cuando tenga que crear una pantalla nueva ya que le permite borrar todo el contenido dejando el fondo blanco, pero manteniendo la rejilla. 5.2.3.5. Abrir

Figura 5.8. Icono Abrir.

Este icono le permite realizar la operación de abrir los ficheros donde haya almacenado las pantallas diseñadas con anterioridad. Cuando active este icono le aparecerá un cuadro de dialogo con título “Abrir dibujo” como los que le aparece en cualquier aplicación comercial, en los que mediante una lista desplegable podrá establecer la ubicación donde se encuentre el archivo que quiera abrir. Por defecto cuando establezca una ruta le aparecerá en la caja de texto del cuadro de dialogo todos aquellos ficheros que hayan sido almacenados con extensión *.rzd.

Figura 5.9. Cuadro de dialogo “Abrir dibujo”.

En la figura 5.9. puede observar la apariencia que tiene el cuadro de dialogo. En su interior aparecen todos los archivos que se han localizado en la carpeta seleccionada con la extensión válida para el programa. Para abrir uno de los archivos encontrados bastará con clicar sobre el nombre del archivo que se desee abrir y a continuación pulsar el botón Abrir que aparece en la parte inferior derecha del cuadro de dialogo.

Manual de Usuario

95

Los cuadros de diálogos aparecen de forma modal por lo que una vez activados necesitan de la realización de una acción, es decir, si activa la acción Abrir del editor de sinópticos deberá abrir un archivo, o bien cancelar la operación de apertura mediante el botón Cancelar. De no ser así no podrá realizar ninguna actividad ya que el cuadro de dialogo permanecerá activo impidiéndole poder realizar otra actividad dentro del editor. Si opta por la opción de cancelar abortará la función Abrir manteniendo en pantalla el contenido que tuviese antes de realizar la operación de apertura. La función Abrir la puede llevar acabo en cualquier momento de utilización del editor, de manera que si durante la realización de una pantalla desea abrir otra le aparecerá un cuadro de dialogo informándole de si desea guardar los cambios realizados en la pantalla actual. Este cuadro tendrá la apariencia de la figura 5.10., el cual aparecerá de forma modal al igual que el cuadro de dialogo anterior, viéndose obligado a escoger entre una de las tres opciones que le ofrecerá.

Figura 5.10. Cuadro de dialogo para guardar los cambios antes de abrir.

Si escoge la opción Sí las modificaciones realizadas en la pantalla actual se guardaran y seguidamente se activará el cuadro de dialogo Abrir dibujo, por contra si escoge la opción No las modificaciones no se guardaran y se procederá a la apertura del cuadro de dialogo. La tercera opción cancelará el proceso de apertura manteniendo en el tapiz de diseño la pantalla actual. 5.2.3.6. Guardar

Figura 5.11. Icono Guardar.

La operación Guardar está regida por la misma condiciones que la anteriormente comentada operación Abrir, con las salvedades que ahora además de escoger la ruta donde se quiere guardar también se deberá introducir el nombre con el que se quiere guardar el fichero y el titulo del cuadro de dialogo será Guardar como... . Cuando se guarde una pantalla nueva que no haya sido creada anteriormente se creará simultáneamente un archivo con idéntico nombre e igual ubicación pero con extensión de texto (*.txt) que se utilizará en la aplicación Editor Código.

Manual de Usuario

96

La función Guardar además de activarse cuando pulse su icono, también se activará cada vez que realice una modificación y posteriormente quiera realizar otra operación que no sea la de guardar, es decir, cuando desee abrir otra pantalla, crear una pantalla nueva y/o salir de la aplicación. En cada caso le aparecerá el cuadro de dialogo de la figura 5.10. pidiéndole su decisión. 5.2.3.7. Color de Fondo

Figura 5.12. Icono ColorFondo.

Esta opción le permite cambiar el fondo del tapiz donde insertará los elementos de la planta, de manera que la visualización de la pantalla sea más estética y agradable para el usuario final. Al igual que sucedía con las operaciones Abrir/Guardar, cuando active esta función le aparecerá un cuadro de dialogo que recogerá todos los colores de los que dispone su equipo.

Figura 5.13. Cuadro de dialogo Color.

El color que elija lo puede matizar moviendo la flecha que aparece en la parte derecha del cuadro de dialogo, consiguiendo el matiz que precise para su pantalla. Para seleccionar un color solo deberá clicar sobre el color que desee y posteriormente pulsar el botón Aceptar, de lo contrario si no quiere modificar el color de fondo pero ya ha

Manual de Usuario

97

activado el cuadro de dialogo Color pulse el botón Cancelar conservando el color de fondo actual. Debe tener en cuenta que el fondo del tapiz de diseño puede estar ocupado por un color, o bien como se especificará más adelante por un bitmap. La prioridad para visualizar en pantalla un color de fondo o un bitmap favorece a la última, es decir, el bitmap prevalecerá sobre el color de fondo. 5.2.3.8. Eliminar

Figura 5.14. Icono Eliminar.

La función Eliminar como su propio nombre indica le posibilitará la opción de eliminar individualmente les elementos que haya insertado pero que por algún motivo precise hacer desaparecer. Para llevar a cabo esta operación lo único que deberá realizar es situarse sobre el elemento a eliminar y posteriormente desplazarse hacia el icono y clicarlo, de esta manera el elemento seleccionado desaparecerá del tapiz de diseño. 5.2.3.9. Etiqueta

Figura 5.15. Icono Etiqueta.

El control Etiqueta le permite la opción de insertar en el tapiz de diseño un control con el que podrá rotular títulos en los sinópticos, crear señales luminosas, visualizar los datos recibidos del RTU, crear alarmas visuales, etc. Para insertarlo lo único que deberá hacer es pulsar con el botón izquierdo del ratón sobre su icono, tras lo cual podrá desplazarlo al punto de inserción que desee dentro del tapiz de diseño. Para poder desplazarlo una vez lo haya insertado bastará con que pulse el botón izquierdo del ratón y lo mantenga apretado, soltándolo en el punto donde quiera volver a colocarlo. Inicialmente la apariencia con la que se inserta es la mostrada en la figura 5.16., en la cual puede observar que se trata de un rectángulo de color verde y de apariencia 3D.

Figura 5.16. Apariencia inicial del control Etiqueta.

Manual de Usuario

98

A fin de que pueda modificar el aspecto inicial del control y lo pueda adecuar a sus necesidades, se ha creado un formulario de propiedades donde quedan recogidas las propiedades del control que pueden ser modificadas. Para acceder al formulario de propiedades bastará con situarse encima del control y pulsar el botón derecho del ratón.

Figura 5.17. Formulario de las propiedades del control Etiqueta.

En la ficha donde quedan recogidas las propiedades del control Etiqueta puede identificar cinco grupos en los que se enmarcan las distintas propiedades que podrá modificar. El primero de los grupos (Alias) no tienen incidencia visual sobre el aspecto del control pero en él queda recogido el nombre de la variable (Nombre Variable) y podrá editar el nombre de identificación que usará el control en la comunicación (Nombre Trabajo). La identificación del control debe cumplir la condición de ser una palabra formada por cinco caracteres ya sean letras (ETIQU), números (13579) o letras y números (ETI79). El segundo grupo de propiedades (General) tiene ya una incidencia visual sobre el control. En él podrá editar el texto (Texto) que desee hacer aparecer en la etiqueta y si dicho texto quiere que aparezca alineado (Alineación) a la izquierda, a la derecha o en el centro. Además si la propiedad AutoAjuste está desactivada podrá modificar el tamaño horizontal y/o vertical del control, para ello solo deberá clicar sobre las flechas de las cajas de texto Alto y Ancho.

Manual de Usuario

99

El tercer grupo (Color) le permite cambiar el color de fondo del control y el de la letra que aparezca en su interior, para ello solo deberá desplegar las cajas desplegables que se han dispuesto para dicho propósito y seleccionar el color que desee. En el cuarto grupo (Marco/Fondo) podrá modificar las propiedades que hacen referencia a la apariencia 3D del control (Marco) y si el control tiene un fondo opaco o transparente (Transparente) adaptándose así al color de fondo del tapiz. Cuando utilice la propiedad Transparente y la etiqueta contenga texto evite la utilización del tipo de letra MS Sans Serif y Courier ya que debido a la poca densidad de estos tipos de fuentes el texto desaparece. El quinto grupo (Fuente) permite modificar la apariencia del texto de la etiqueta, permitiéndole que el texto aparezca en negrita, cursiva, subrayado y/o tachado y pudiendo aumentar o disminuir su tamaño. Todas estas modificaciones son independientes entre ellas, a excepción de la propiedad AutoAjuste que es incompatible con la modificación del tamaño del control. De manera que puede utilizar dichas propiedades de manera indistinta. En la figura 5.18. puede observar una pequeña muestra de los resultados obtenidos al aplicar la modificación de las propiedades.

Figura 5.18. Modificación de propiedades.

5.2.3.10. Cuadro Texto

Figura 5.19. Icono Cuadro Texto.

Manual de Usuario

100

El control Cuadro Texto le ofrece la posibilidad de visualizar e introducir texto en el editor. El control le permitirá tratar una o varias líneas de texto incorporando funciones de selección, cortar, copiar y pegar. La aparición inicial del control es la de un rectángulo de color blanco con apariencia 3D tal y como se muestra en la figura 5.20.

Figura 5.20. Apariencia inicial del Cuadro Texto.

Para introducir texto en el control bastará con pulsar el botón izquierdo del ratón y a continuación le aparecerá dentro del control un cursor (un guión vertical) que le indicará que puede ya llevar a cabo la operación de escritura. El Cuadro Texto es una especie de mini editor por lo que su funcionamiento se asemeja bastante a aplicaciones como WordPad y/o Bloc de Notas, manteniendo las distancias ya que las dos aplicaciones mencionadas proporcionan una cantidad de funciones superior a las de nuestro control. No obstante la esencia es la misma, y esta no es más que la de poder leer e introducir información. Las operaciones de selección, cortar, copiar y/o pegar se realizan de la misma forma que en otras aplicaciones Windows. Así para seleccionar bastará con clicar con el botón izquierdo del ratón en el punto de inicio que desee y a posteriormente arrastrar, con el botón aún pulsado, hasta el punto final de selección. Una vez tenga seleccionado el texto podrá realizar las operaciones de cortar (CTRL + X), copiar (CTRL + C) y pegar (CTRL + V).

Figura 5.21. Formulario de las propiedades del control Cuadro Texto.

Manual de Usuario

101

Las propiedades que podrá modificar quedan recogidas en el formulario de la figura 5.21. Si observa el formulario podrá percatarse que las propiedades mostradas en él son prácticamente iguales a las expuestas en el control anterior. La única diferencia es que en el control Cuadro Texto el texto no se puede auto ajustar y el fondo del control no se puede hacer transparente, por lo que dicho control carece de las propiedades AutoAjuste y Transparente. La forma de actuar para modificar las propiedades es idéntica a la explicada anteriormente para el control Etiqueta. En la figura 5.22. puede observar una pequeña muestra de los resultados obtenidos al aplicar la modificación de las propiedades.

Figura 5.22. Modificación de propiedades.

5.2.3.11. Pulsador

Figura 5.23. Icono Pulsador.

El control Pulsador le proporcionará la posibilidad de poder ejecutar acciones, funciones y operaciones cuando así lo desee. En él, y mediante el editor de código que más adelante se explicará, podrá definir la tarea que desea que se realice cuando el usuario pulse sobre el pulsador.

Manual de Usuario

102

La apariencia inicial del control es la que aparece en la figura 5.24.

Figura 5.24. Apariencia inicial del Pulsador.

Las propiedades que podrá modificar quedan recogidas en el formulario de la figura 5.25.

Figura 5.25. Formulario de las propiedades del control Pulsador.

Este control permite modificar un número inferior de propiedades que los controles anteriores. Algunas de las propiedades que podrá modificar serán las de cambiar el color de fondo del control, el tamaño tanto vertical como horizontal, los efectos del texto, el contenido del texto, etc. Por el contrario no podrá cambiar el color de la fuente, auto ajustar el texto al control, hacerlo transparente, alinear el texto de su interior, etc. Para realizar las modificaciones deberá actuar de igual forma que ha actuado para modificar las propiedades de los controles anteriores.

Manual de Usuario

103

En la figura 5.26. puede observar una pequeña muestra de los resultados obtenidos al aplicar la modificación de las propiedades.

Figura 5.26. Modificación de propiedades.

5.2.3.12. Figura

Figura 5.27. Icono Figura.

El control Figura le permitirá la posibilidad de insertar la principales figuras geométricas, tales figuras son el cuadrado, el rectángulo, el círculo y el óvalo. Además de estas también le ofrece el cuadrado y el rectángulo con bordes redondeados. La apariencia inicial del control es la mostrada en la figura 5.28., en la que podrá observar un rectángulo con los bordes redondeados y con el color verde como fondo.

Figura 5.28. Apariencia inicial de Figura.

Manual de Usuario

104

Algunas de las propiedades que podrá modificar ahora difieren de las explicadas para los controles anteriores. Estas propiedades quedan recogidas en el siguiente formulario.

Figura 5.29. Formulario de las propiedades del control Figura.

En los dos primeros recuadros podrá reconocer propiedades que ya han sido utilizadas en los controles anteriores, tales propiedades son Nombre Trabajo, Visible, Alto y Ancho. En el recuadro tercero encontrará una propiedad que es novedosa para este control. Dicha propiedad recibe el nombre de Estilo y podrá contener el valor Opaco o Transparente. Si opta por darle el valor Opaco el control tendrá su propio color de fondo y no podrá introducir ningún control en su interior, mientras que si por el contrario opta por darle e valor Transparente el control solo mantendrá el contorno confundiéndose el fondo suyo con el del tapiz y pudiendo insertar en su interior otros controles. Debe tener en cuenta que las propiedades del recuadro cuarto son aplicables al control Figura si dicho control tiene establecida a Opaco la propiedad Estilo. Si esto no es así cualquier modificación que haga de alguna de las propiedades del recuadro cuarto no se aplicará al control. En el recuadro cuarto la propiedad nueva es la que lleva por nombre Estilo Relleno, la cual ofrece ocho tipos distintos de relleno que podrá ver si despliega la lista combinada que los alberga. Como nota cabe comentar que no es aconsejable que el grosor del borde esté muy sobredimensionado ya que esto produce una distorsión sobre el control que hace que su apariencia visual no sea demasiado estética. El control también le ofrece la posibilidad de variar la apariencia y el grosor del borde mediante las propiedades Color, Estilo y Ancho. Estas propiedades quedan recogidas en el recuadro quinto con el nombre Marco.

Manual de Usuario

105

Por último, en el recuadro Forma podrá modificar la forma geométrica del control, pudiendo escoger entre las seis formas distintas que se ofrecen en la lista combinada. Recuerde que todas estas propiedades pueden ser modificadas de forma independiente las unas de las otras a excepción de la propiedad Estilo Relleno que dependerá de la propiedad Estilo del cuadro Fondo. En la siguiente figura podrá ver un resumen de las modificaciones sufridas por los controles Figura.

Figura 5.30. Modificación de propiedades.

5.2.3.13. Tuberías

Figura 5.31. Iconos para Tuberías.

Los controles Tuberías le ofrece una forma rápida y sencilla de establecer una conexión visual entre dos o varios elementos que haya insertado. Son especialmente útiles para simular tuberías en procesos de control de las empresas del sector químico. Elegirá un icono u otro dependiendo de la orientación que precise por lo que el primero lo utilizará para dibujar conexiones horizontales y segundo para verticales. Para dibujar bastará con que clique sobre el icono deseado y posteriormente vuelva a clicar con el botón izquierdo del ratón sobre el punto del tapiz donde desee empezar a trazar la

Manual de Usuario

106

conexión. Para finalizar solo deberá clicar el botón derecho del ratón en el punto final del trazado que quiera realizar. Observe que trazado se realiza de forma ortogonal, es decir, las conexiones vertical y horizontal formaran un ángulo de 90º siempre, además el trazado solo se fijará si pulsa el botón derecho del ratón. 5.2.3.14. Elemento

Figura 5.32. Icono Elemento.

El control Elemento será el control que le permitirá customizarse su pantalla al proceso de control que deba visualizar ya que le permitirá que inserte un su interior cualquier elemento gráfico con extensión igual a las siguientes: BMP, JPG, WMF, EMF, ICO, CUR, etc. Para ello deberá previamente diseñar mediante cualquier programa gráfico comercial, escáner o foto digital el elemento que quiera insertar y archivarlo en una carpeta. Una vez tenga archivado el elemento podrá proceder a su inserción en Editor Sinópticos. Para realizar la inserción solo deberá pulsar el icono y de seguida le aparecerá un cuadro de dialogo con título Insertar Elemento, donde deberá establecer la ruta donde haya guardado el elemento y a continuación escoger el elemento que desee insertar.

Figura 5.33. Ventana Insertar Elemento.

Manual de Usuario

107

De esta manera será usted mismo el que se pueda crear su propia biblioteca según las necesidades que precise para su empresa. Una vez insertado el elemento podrá moverlo y colocarlo en el tapiz del mismo modo que ha colocado los anteriores controles. 5.2.3.15. ImagenFondo

Figura 5.34. Icono ImagenFondo.

Esta operación permite la opción de insertar como fondo de pantalla un archivo gráfico. Es especialmente recomendable para aquellas pantallas de monitorización que sean realmente complicas de realizar mediante elementos gráficos. Hoy en día gracias al uso masivo de las cámaras digitales, esta manera de proceder está muy extendida entre los creadores de aplicaciones SCADA. La forma de proceder es idéntica a la explicada anteriormente para la inserción de un elemento discreto. 5.2.3.16. EliminarImagenFondo

Figura 5.35. Icono EliminarImagenFondo.

Esta operación elimina el gráfico que haya establecido como fondo, para ello solo será necesario clicar el icono. 5.2.3.17. Salir

Figura 5.36. Icono Salir.

Le permite abandonar la aplicación Editor Sinópticos.

Manual de Usuario

108

5.3. Editor Código Para acceder a él deberá clicar en el botón “Editor Código” que aparece en la pantalla inicial. Una vez realizada esta acción se pondrá en funcionamiento el editor con el que podrá desarrollar las funciones para controlar su proceso de control. 5.3.1. Entorno El entorno de la aplicación es el que aparece en la figura 5.37., en la que se puede apreciar una serie de elementos comunes y fácilmente reconocibles por todos los usuarios de aplicaciones Windows.

Figura 5.37. Entorno Editor Código.

La parte superior del editor está ocupa por una barra de herramientas donde se ubican los iconos y una caja de texto. Los iconos que se utilizan en el Editor código tienen una funcionalidad idéntica a la descrita en el apartado anterior, por lo que nos centraremos en explicar la utilización de las fichas. 5.3.2. Fichas En el editor podrá identificar tres fichas que tienen por título: Sinóptico, Código Asociado y Linkador.

Figura 5.38. Fichas.

5.3.2.1. Sinóptico La ficha Sinóptico es la única ficha que está activa cuando se inicia la aplicación, de manera que será la única ficha que podrá visualizar inicialmente. Esta ficha es puramente

Manual de Usuario

109

visual por lo que no podrá realizar ninguna otra acción que no sea la de visualizar el sinóptico diseñado con la aplicación Editor Sinóptico. Para poder empezar a dotar la pantalla diseñada de funcionalidad deberá primeramente abrir el archivo de extensión *.rzd, para ello deberá clicar el icono que aparece en la barra de herramientas y proceder de igual forma que en la aplicación anterior, es decir, seleccionará la pantalla que desea abrir mediante el cuadro de dialogo que le aparecerá una vez haya pulsado el icono. Cuando realice la operación anterior abrirá no tan solo el archivo gráfico sino que también abrirá un archivo de idéntico nombre pero con extensión de texto, que será el que visualizará en la ficha Código Asociado. Como habrá podido observar seguidamente se ha habilitado la segunda ficha que será donde editará el código necesario para dar vida a la aplicación. 5.3.2.2. Código Asociado Una vez activada la segunda ficha podrá observar que en su interior hay dos elementos destacados. El más voluminoso y que ocupa la mayor parte de la ficha es la caja de texto que será donde se introducirá el código necesario, mientras que en la parte derecha y de menor tamaño encontrará un grupo de elementos que le ayudarán a la hora de editar el código. En el grupo de elementos encontrará dos listas desplegables y una tabla, donde podrá elegir y visualizar las variables de las que dispone la pantalla, las propiedades de cada uno de los controles insertados y los eventos de los que disponen. Esto lo puede visualizar en la siguiente figura.

Figura 5.39. Ficha Código Asociado.

Manual de Usuario

110

Cuando seleccione un evento su nomenclatura aparecerá en la caja de texto de la barra de herramientas por lo que para insertarla en el código lo único que deberá hacer es seleccionarla y copiarla luego en el editor. Recuerde que cuando haya introducido el código en el evento este debe finalizar con la instrucción End Sub. El lenguaje utilizado para editar el código será el utilizado por la aplicación Microsoft Visual Basic 6.0. Una vez introducido el código que crea necesario o cuando desee salir de la aplicación deberá guardar las modificaciones realizadas, para ello clique sobre el icono guardar. Realizada esta operación se habilitará la tercera ficha Linkador y se deshabilitará la segunda. 5.2.3.3. Linkador Llegados a este punto deberá tomar una decisión que consistirá en decidir si desea realizar ya el archivo ejecutable de la aplicación que controla su proceso de control, o bien si aún no ha acabado de editar el código y desea abandonar la aplicación. Si opta por la segunda opción solo deberá dirigirse al icono Salir de la barra de herramientas y abandonar la aplicación, sino deberá pulsar el botón EJECUTABLE.

Figura 5.40. Ficha Linkador.

Cuando pulse el botón EJECUTABLE se iniciará el proceso de generación de un archivo *.EXE. Este archivo se creará en la carpeta C:\Proyecto y recibirá inicialmente en nombre de SinNombre. Para evitar que en futuras generaciones de archivos *.EXE se elimine su

Manual de Usuario

111

aplicación deberá cambiarle el nombre, esto lo puede llevar a cabo mediante las opciones que le ofrece el sistema Windows. 5.4. Monitorización Para acceder a la pantalla ejecutable que haya creado bastará con que la localice y a continuación clique dos veces consecutivas sobre su icono. 5.4.1. Entorno Su entorno dependerá de la pantalla que haya creado, no obstante la barra de herramientas de todas las pantallas ejecutables que cree será la misma. Esta barra de herramientas será la de la figura 5.41.

Figura 5.41. Barra Herramientas Pantalla Ejecutable.

En ella encontrará cuatro iconos que le permitirán realizar las siguientes operaciones: Establecer comunicación con la planta. Acceder a la aplicación Excel. Acceder a la aplicación Word. Salir.

Conclusiones

112

6. Conclusiones Una vez realizado nuestro objetivo, que no era otro que la realización de un programa capaz de realizar aplicaciones que controlasen un proceso industrial (SCADA), estamos en condición de poder extraer algunas conclusiones: ? La realización del proyecto por mi parte ha supuesto una inmersión en el mundo del control industrial ya que para poder realizar el proyecto con garantías he tenido que conocer y estudiar a fondo todo lo que lo rodea. A este conocimiento he llegado mediante la lectura de revista especializadas y buscando información en las páginas webs de los principales proveedores de aplicaciones SCADA (Siemens, Citect,..). ? He podido también comprobar como a lo largo del tiempo el uso de aplicaciones SCADA por parte de las empresas se ha ido extendiendo, dejando de ser una herramienta exclusiva de algunos sectores empresariales. Buena parte de la culpa es debida a la implantación casi total de los PC’s en el entorno industrial que han mejorado sus prestaciones de velocidad y de potencia de cálculo. ? La llegada al mercado de lenguajes de programación orientados a objetos (POO) ha hecho que las interfaces de las aplicaciones sean más fáciles y agradables para el usuario final, que ahora se limitará a pulsar un botón o a mover un puntero. ? La mayor utilización de programas SCADA también ha provocado que los elementos de planta sean cada vez más rápidos y fiables. ? Las aplicaciones no solo son utilizadas hoy en día para controlar sino que se han convertido en una fuente inmensa de generar información que puede ser utilizada por la mayoría de los departamentos de una empresa.

Listado del Código

113

Editor Option Explicit ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el elemento activo, variables para saber la posicion donde' 'se ha clicado e inicio del proceso de arrastre para el control DIBUJO' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Dibujo_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) marcador = Index fichado = Dibujo(marcador).Name moveX = X moveY = Y Dibujo(Index).Drag vbBeginDrag End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Si pulsa boton izquierdo inicia el proceso de arrastre, mientras q si' 'pulsa el boton derecho activara la ventana de propiedades del control' 'ETIQUETA. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Etiqueta_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then marcador = Index fichado = Etiqueta(marcador).Name moveX = X moveY = Y Etiqueta(Index).Drag vbBeginDrag Else fichado = Etiqueta(marcador).Name frmpropiedades.Show vbModal End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el control tan solo con mover el cursor del raton por ' 'encima del control, ademas muestra su identificacion en el textbox ' 'de la barra de herramientas. ETIQUETA ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Etiqueta_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) marcador = Index fichado = Etiqueta(marcador).Name Text1.Text = Etiqueta(marcador).Name & marcador End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Si pulsa boton izquierdo inicia el proceso de arrastre, mientras q si' 'pulsa el boton derecho activara la ventana de propiedades del control' 'FIGURA. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Figura_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then marcador = Index fichado = Figura(marcador).Name

Listado del Código

114

moveX = X moveY = Y Figura(Index).Drag vbBeginDrag Else fichado = Figura(marcador).Name frmpropiedades.Show vbModal End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el control tan solo con mover el cursor del raton por ' 'encima del control, ademas muestra su identificacion en el textbox ' 'de la barra de herramientas. FIGURA ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Figura_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) marcador = Index fichado = Figura(marcador).Name Text1.Text = Figura(marcador).Name & marcador End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Borrar el contenido de la variable que almacena el nombre del archivo' 'y establecer el valor False a la variable q indica si ha habido ' 'alguna modificacion. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Form_Load() nombrearchivo = "" modificado = False End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Si pulsa boton izquierdo inicia el proceso de arrastre, mientras q si' 'pulsa el boton derecho activara la ventana de propiedades del control' 'PULSADOR. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Pulsador_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then marcador = Index fichado = Pulsador(marcador).Name moveX = X moveY = Y Pulsador(Index).Drag vbBeginDrag Else fichado = Pulsador(marcador).Name frmpropiedades.Show vbModal End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el control tan solo con mover el cursor del raton por ' 'encima del control, ademas muestra su identificacion en el textbox ' 'de la barra de herramientas. PULSADOR ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Pulsador_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)

Listado del Código

115

marcador = Index fichado = Pulsador(marcador).Name Text1.Text = Pulsador(marcador).Name & marcador End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Se lleva a cabo las operaciones necesarias para iniciar el proceso de' 'de dibujo de las tuberias. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Tapiz_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) 'si no hay ninguna operacion de dibujo seleccionada If entidad = -1 Then Exit Sub End If 'iniciar el trazado de una tuberia estableciendo los puntos iniciales If Button = vbLeftButton Then Select Case orientacion: Case "horizontal" Tuberia(ind).Top = par(Y) Tuberia(ind).Left = par(X) iniX = par(X) anterX = par(X) Case "vertical" Tuberia(ind).Left = par(X) Tuberia(ind).Top = par(Y) iniY = par(Y) anterY = par(Y) End Select 'actualizar la variable q indica q se esta dibujando, hacer visible 'en pantalla el trazado y establecer el modo de dibujo provisional. dibujando = True Tuberia(ind).visible = True Tuberia(ind).DrawMode = vbNotXorPen Else 'finalizar el trazado de la tuberia estableciendo el modo de dibujo 'en formato fijo. Tuberia(ind).DrawMode = vbCopyPen Select Case orientacion: Case "horizontal" X = par(X) Tuberia(ind).Width = Abs(par(X - iniX)) Tuberia(ind).visible = True Case "vertical" Y = par(Y) Tuberia(ind).Height = Abs(par(Y - iniY)) Tuberia(ind).visible = True End Select 'desactivar el modo dibujo,deseleccionar la entidad y establecer 'el cursor normal del raton dibujando = False entidad = -1 Tapiz.MousePointer = vbArrow End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Se lleva a cabo las operaciones necesarias para trazar tuberias sobre' 'el tapiz de dibujo. '

Listado del Código

116

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Tapiz_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'Si no esta activo el modo dibujo: dibujando=False, entonces salir. If Not dibujando Then Exit Sub End If X = par(X) Y = par(Y) Select Case orientacion: Case "horizontal" 'primero borrar el trazo anterior Tuberia(ind).Width = Abs(par(iniX - anterX)) 'trazar hasta las coordenadas actuales Tuberia(ind).Width = Abs(par(iniX - X)) 'Actualizar las coordenadas anterX = par(X) anterY = par(Y) Case "vertical" 'primero borrar el trazo anterior Tuberia(ind).Height = Abs(par(iniY - anterY)) 'trazar hasta las coordenadas actuales Tuberia(ind).Height = Abs(par(iniY - Y)) 'Actualizar las coordenadas anterX = par(X) anterY = par(Y) End Select End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Si pulsa boton izquierdo inicia el proceso de arrastre, mientras q si' 'pulsa el boton derecho activara la ventana de propiedades del control' 'TEXTO. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Texto_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) If Button = vbLeftButton Then marcador = Index fichado = Texto(marcador).Name moveX = X moveY = Y Texto(Index).Drag vbBeginDrag Else fichado = Texto(marcador).Name frmpropiedades.Show vbModal End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el control tan solo con mover el cursor del raton por ' 'encima del control, ademas muestra su identificacion en el textbox ' 'de la barra de herramientas. TEXTO ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Texto_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) marcador = Index fichado = Texto(marcador).Name Text1.Text = Texto(marcador).Name & marcador End Sub

Listado del Código

117

''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Se realiza las operaciones q le corresponde a cada uno de los botones' 'de la barra de herramientas. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button) Select Case Button.Key Case "custom" On Error Resume Next With InserElemento: .DialogTitle = "Insertar elemento" .Filter = "Archivos bmp|*.bmp|Archivos jpeg|*.jpg|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt .ShowOpen End With If Err Then Exit Sub End If EleFantasma.Picture = LoadPicture(InserElemento.FileName) EleAncho = EleFantasma.Width EleAlto = EleFantasma.Height insertar InserElemento.FileName, "", "D", Me Case "bitmap" cargar_bitmap Me Case "eliminarbitmap" Tapiz.Picture = LoadPicture("") fotos = "" modificado = True rejilla Case "shapes" 'Set CoolBar1.Bands(3).Child = Toolbar2 'para otra barra herramientas insertar "", "", "F", Me Case "pincel" colores Me Case "guardar" operacion_guardar Me Case "abrir" If modificado Then respuesta = MsgBox("¿Desea guardar los cambios realizados?", vbYesNoCancel + vbExclamation + vbDefaultButton1, "Editor Sinópticos") Select Case respuesta Case vbYes operacion_guardar Me modificado = False Editor.Caption = "Editor de Sinópticos" nuevo Me operacion_abrir Me Case vbNo Editor.Caption = "Editor de Sinópticos" nuevo Me operacion_abrir Me Case vbCancel End Select Else Editor.Caption = "Editor de Sinópticos" operacion_abrir Me End If

Listado del Código

118

Case "borrar" borrar Me Case "nuevo" If modificado Then respuesta = MsgBox("¿Desea guardar los cambios realizados?", vbYesNoCancel + vbExclamation + vbDefaultButton1, "Editor Sinópticos") Select Case respuesta Case vbYes operacion_guardar Me Unload Me Case vbNo nuevo Me Case vbCancel End Select Else nuevo Me End If Case "etiqueta" insertar "", "", "E", Me Case "pulsador" cantidad Me insertar "", "", "P", Me Case "texto" insertar "", "", "TE", Me Case "horizonte" insertar "", "horizontal", "T", Me Case "vertical" insertar "", "vertical", "T", Me Case "cerrar" If modificado Then respuesta = MsgBox("¿Desea guardar los cambios realizados?", vbYesNoCancel + vbExclamation + vbDefaultButton1, "Editor Sinópticos") Select Case respuesta Case vbYes operacion_guardar Me Unload Me Case vbNo Unload Me Case vbCancel End Select Else Unload Me End If End Select End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Se ajusta el tamaño del tapiz al de la pantalla y se llama al proced.' 'rejilla para q la dibuje sobre el tapiz. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Form_Resize() With Tapiz: .Top = CoolBar1.Top + CoolBar1.Height .Left = 30 .Height = 9920 .Width = Editor.Width - 165 End With rejilla

Listado del Código

119

End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Completa el proceso de arrastre de cada uno de los controles q hayan ' 'sido desplazados una insertados. ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Tapiz_DragDrop(Source As Control, X As Single, Y As Single) modificado = True If TypeOf Source Is Pulsador Then Source.Move par(X - moveX), par(Y - moveY) Pulsador(marcador).visible = True End If If TypeOf Source Is Etiqueta Then Source.Move par(X - moveX), par(Y - moveY) Etiqueta(marcador).visible = True End If If TypeOf Source Is Texto Then Source.Move par(X - moveX), par(Y - moveY) Texto(marcador).visible = True End If If TypeOf Source Is Dibujo Then Source.Move par(X - moveX), par(Y - moveY) Dibujo(marcador).visible = True End If If TypeOf Source Is Figura Then Source.Move par(X - moveX), par(Y - moveY) Figura(marcador).visible = True End If End Sub ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' 'Identifica el control tan solo con pulsar el cursor del raton por ' 'encima del control TUBERIA ' ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' Private Sub Tuberia_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single) marcador = Index fichado = Tuberia(marcador).Name End Sub

Listado del Código

120

FrmPropiedades Option Explicit Private Sub Command1_Click() modificado = True Unload Me End Sub Private Sub Command2_Click() Command1.SetFocus End Sub Private Sub EtiAlias_Change() Editor!Etiqueta(marcador).Alias = EtiAlias.Text End Sub Private Sub EtiCheAutosize_Click() Reajuste Me End Sub Private Sub EtiCheMarco_Click() If EtiCheMarco.Value = Checked Then prop_marco = 1 Else prop_marco = 0 End If Editor!Etiqueta(marcador).BorderStyle = prop_marco Reajuste Me End Sub Private Sub EtiCheNegra_Click() If EtiCheNegra.Value = Checked Then prop_letranegrita = True EtiEjemplo.FontBold = True Else prop_letranegrita = False EtiEjemplo.FontBold = False End If Editor!Etiqueta(marcador).FontBold = prop_letranegrita Reajuste Me End Sub Private Sub EtiCheCursiva_Click() If EtiCheCursiva.Value = Checked Then prop_letracursiva = True EtiEjemplo.FontItalic = True Else prop_letracursiva = False EtiEjemplo.FontItalic = False End If Editor!Etiqueta(marcador).FontItalic = prop_letracursiva Reajuste Me End Sub Private Sub EtiCheSubrayada_Click() If EtiCheSubrayada.Value = Checked Then prop_letrasubrayada = True EtiEjemplo.FontUnderline = True Else prop_letrasubrayada = False

Listado del Código

121

EtiEjemplo.FontUnderline = False End If Editor!Etiqueta(marcador).FontUnderline = prop_letrasubrayada Reajuste Me End Sub Private Sub EtiCheTachada_Click() If EtiCheTachada.Value = Checked Then prop_letratachada = True EtiEjemplo.FontStrikethru = True Else prop_letratachada = False EtiEjemplo.FontStrikethru = False End If Editor!Etiqueta(marcador).FontStrikethru = prop_letratachada Reajuste Me End Sub Private Sub EtiCheTrans_Click() If EtiCheTrans.Value = Checked Then prop_transpa = 0 Else prop_transpa = 1 End If Editor!Etiqueta(marcador).BackStyle = prop_transpa End Sub Private Sub EtiListaFuentes_Click() prop_letra = EtiListaFuentes.Text Editor!Etiqueta(marcador).FontName = prop_letra Reajuste Me Command2.SetFocus End Sub Private Sub EtiListaAlig_Click() prop_justifi = EtiListaAlig.ListIndex Editor!Etiqueta(marcador).Alignment = prop_justifi Reajuste Me Command2.SetFocus End Sub Private Sub EtiCheVisible_Click() If EtiCheVisible.Value = Checked Then prop_visible = True Else prop_visible = False End If Editor!Etiqueta(marcador).visible = prop_visible End Sub Private Sub EtiTamano_KeyPress(KeyAscii As Integer) Select Case KeyAscii Case 13 KeyAscii = 0 Case 8, 43 To 46, 48 To 57, 68, 69, 100, 101 Case Else KeyAscii = 0 Beep End Select End Sub

Listado del Código

122

Private Sub FigAlias_Change() Editor!Figura(marcador).Alias = FigAlias.Text End Sub Private Sub FigCheVisible_Click() If FigCheVisible.Value = Checked Then prop_visible = True Else prop_visible = False End If Editor!Figura(marcador).visible = prop_visible End Sub Private Sub FigListaEstiloFondo_Click() prop_justifi = FigListaEstiloFondo.ListIndex Editor!Figura(marcador).BackStyle = prop_justifi Editor!Figura(marcador).BackColor = prop_color Command2.SetFocus End Sub Private Sub FigListaEstiloMarco_Click() prop_marco = FigListaEstiloMarco.ListIndex Editor!Figura(marcador).BorderStyle = prop_marco Command2.SetFocus End Sub Private Sub FigListaEstiloRelleno_Click() prop_relleno = FigListaEstiloRelleno.ListIndex Editor!Figura(marcador).FillStyle = prop_relleno Command2.SetFocus End Sub Private Sub FigListaFondo_Click() prop_color= ImageList1.ListImages.Item(FigListaFondo.SelectedItem.Index).Tag Editor!Figura(marcador).BackColor = prop_color Command2.SetFocus End Sub Private Sub FigListaForma_Click() prop_transpa = FigListaForma.ListIndex Editor!Figura(marcador).Shape = prop_transpa Editor!Figura(marcador).BackColor = prop_color Command2.SetFocus End Sub Private Sub FigListaMarco_Click() prop_colorborde= ImageList1.ListImages.Item(FigListaMarco.SelectedItem.Index).Tag Editor!Figura(marcador).BorderColor = prop_colorborde Command2.SetFocus End Sub Private Sub FigListaRelleno_Click() prop_colorrelleno= ImageList1.ListImages.Item(FigListaRelleno.SelectedItem.Index).Tag Editor!Figura(marcador).FillColor = prop_colorrelleno Command2.SetFocus End Sub

Listado del Código

123

Private Sub FigTamano_Change() On Error Resume Next If FigTamano.Text = "" Then Editor!Figura(marcador).BorderWidth = 1 Else Editor!Figura(marcador).BorderWidth = FigTamano.Text End If On Error GoTo 0 End Sub Private Sub FigTamano_KeyPress(KeyAscii As Integer) Select Case KeyAscii Case 13 KeyAscii = 0 Case 8, 43 To 46, 48 To 57, 68, 69, 100, 101 Case Else KeyAscii = 0 Beep End Select End Sub Private Sub FigUpDown1_Change() Editor!Figura(marcador).ancho = FigTAncho.Text + 10 End Sub Private Sub FigUpDown2_Change() Editor!Figura(marcador).alto = FigTAlto.Text + 10 End Sub Private Sub Form_Load() Dim n As Integer 'Hacemos un select case para los tres tipos de elementos que podemos insertar y 'modificar, cargando sus propiedades. Select Case fichado: Case "Etiqueta": SSTab1.Tab = 0 'Abrimos la primera página sstab SSTab1.TabEnabled(1) = False SSTab1.TabEnabled(2) = False SSTab1.TabEnabled(3) = False llenar_listas Me Captura_Propiedades Me Case "Pulsador": SSTab1.Tab = 1 'Abrimos la primera página sstab SSTab1.TabEnabled(0) = False SSTab1.TabEnabled(2) = False SSTab1.TabEnabled(3) = False llenar_listas Me Captura_Propiedades Me Case "Texto": SSTab1.Tab = 2 'Abrimos la primera página sstab SSTab1.TabEnabled(0) = False SSTab1.TabEnabled(1) = False SSTab1.TabEnabled(3) = False llenar_listas Me Captura_Propiedades Me Case "Figura": SSTab1.Tab = 3 'Abrimos la primera página sstab SSTab1.TabEnabled(0) = False SSTab1.TabEnabled(1) = False

Listado del Código

124

SSTab1.TabEnabled(2) = False llenar_listas Me Captura_Propiedades Me End Select End Sub Private Sub EtiListaColorLetra_Click() prop_colorletra= ImageList1.ListImages.Item(EtiListaColorLetra.SelectedItem.Index).Tag Editor!Etiqueta(marcador).ForeColor = prop_colorletra Reajuste Me Command2.SetFocus End Sub Private Sub EtiListaFondo_Click() prop_color= ImageList1.ListImages.Item(EtiListaFondo.SelectedItem.Index).Tag Editor!Etiqueta(marcador).BackColor = prop_color Reajuste Me Command2.SetFocus End Sub Private Sub EtiTitulo_Change() Editor!Etiqueta(marcador).Caption = EtiTitulo.Text Reajuste Me End Sub Private Sub EtiTamano_Change() On Error Resume Next If EtiTamano.Text = "" Then Editor!Etiqueta(marcador).FontSize = 12 Else Editor!Etiqueta(marcador).FontSize = EtiTamano.Text End If Reajuste Me On Error GoTo 0 End Sub Private Sub EtiUpDown1_Change() Editor!Etiqueta(marcador).ancho = EtiTAncho.Text + 10 End Sub Private Sub EtiUpDown2_Change() Editor!Etiqueta(marcador).alto = EtiTAlto.Text + 10 End Sub Private Sub PulsAlias_Change() Editor!Pulsador(marcador).Alias = PulsAlias.Text End Sub Private Sub PulsCheCursiva_Click() If PulsCheCursiva.Value = Checked Then prop_letracursiva = True PulsEjemplo.FontItalic = True Else prop_letracursiva = False PulsEjemplo.FontItalic = False End If Editor!Pulsador(marcador).FontItalic = prop_letracursiva End Sub

Listado del Código

125

Private Sub PulsCheNegra_Click() If PulsCheNegra.Value = Checked Then prop_letranegrita = True PulsEjemplo.FontBold = True Else prop_letranegrita = False PulsEjemplo.FontBold = False End If Editor!Pulsador(marcador).FontBold = prop_letranegrita End Sub Private Sub PulsCheSubrayada_Click() If PulsCheSubrayada.Value = Checked Then prop_letrasubrayada = True PulsEjemplo.FontUnderline = True Else prop_letrasubrayada = False PulsEjemplo.FontUnderline = False End If Editor!Pulsador(marcador).FontUnderline = prop_letrasubrayada End Sub Private Sub PulsCheTachada_Click() If PulsCheTachada.Value = Checked Then prop_letratachada = True PulsEjemplo.FontStrikethru = True Else prop_letratachada = False PulsEjemplo.FontStrikethru = False End If Editor!Pulsador(marcador).FontStrikethru = prop_letratachada End Sub Private Sub PulsCheVisible_Click() If PulsCheVisible.Value = Checked Then prop_visible = True Else prop_visible = False End If Editor!Pulsador(marcador).visible = prop_visible End Sub Private Sub PulsListaFondo_Click() prop_color= ImageList1.ListImages.Item(PulsListaFondo.SelectedItem.Index).Tag Editor!Pulsador(marcador).BackColor = prop_color Command2.SetFocus End Sub Private Sub PulsListaFuentes_Click() prop_letra = PulsListaFuentes.Text Editor!Pulsador(marcador).FontName = prop_letra Command2.SetFocus End Sub Private Sub PulsTamano_Change() On Error Resume Next If PulsTamano.Text = "" Then Editor!Pulsador(marcador).FontSize = 12 Else Editor!Pulsador(marcador).FontSize = PulsTamano.Text

Listado del Código

126

End If On Error GoTo 0 End Sub Private Sub PulsTamano_KeyPress(KeyAscii As Integer) Select Case KeyAscii Case 13 KeyAscii = 0 Case 8, 43 To 46, 48 To 57, 68, 69, 100, 101 Case Else KeyAscii = 0 Beep End Select End Sub Private Sub PulsTitulo_Change() Editor!Pulsador(marcador).Caption = PulsTitulo.Text End Sub Private Sub PulsUpDown1_Change() Editor!Pulsador(marcador).ancho = PulsTAncho.Text + 10 End Sub Private Sub PulsUpDown2_Change() Editor!Pulsador(marcador).alto = PulsTAlto.Text + 10 End Sub Private Sub TexAlias_Change() Editor!Texto(marcador).Alias = TexAlias.Text End Sub Private Sub TexCheCursiva_Click() If TexCheCursiva.Value = Checked Then prop_letracursiva = True TexEjemplo.FontItalic = True Else prop_letracursiva = False TexEjemplo.FontItalic = False End If Editor!Texto(marcador).FontItalic = prop_letracursiva End Sub Private Sub TexCheMarco_Click() If TexCheMarco.Value = Checked Then prop_marco = 1 Else prop_marco = 0 End If Editor!Texto(marcador).Appearance = prop_marco End Sub Private Sub TexCheNegra_Click() If TexCheNegra.Value = Checked Then prop_letranegrita = True TexEjemplo.FontBold = True Else prop_letranegrita = False TexEjemplo.FontBold = False End If Editor!Texto(marcador).FontBold = prop_letranegrita

Listado del Código

127

End Sub Private Sub TexCheSubrayada_Click() If TexCheSubrayada.Value = Checked Then prop_letrasubrayada = True TexEjemplo.FontUnderline = True Else prop_letrasubrayada = False TexEjemplo.FontUnderline = False End If Editor!Texto(marcador).FontUnderline = prop_letrasubrayada End Sub Private Sub TexCheTachada_Click() If TexCheTachada.Value = Checked Then prop_letratachada = True TexEjemplo.FontStrikethru = True Else prop_letratachada = False TexEjemplo.FontStrikethru = False End If Editor!Texto(marcador).FontStrikethru = prop_letratachada End Sub Private Sub TexCheVisible_Click() If TexCheVisible.Value = Checked Then prop_visible = True Else prop_visible = False End If Editor!Texto(marcador).visible = prop_visible End Sub Private Sub TexListaAlig_Click() prop_justifi = TexListaAlig.ListIndex Editor!Texto(marcador).Alignment = prop_justifi Command2.SetFocus End Sub Private Sub texListaColorLetra_Click() prop_colorletra= ImageList1.ListImages.Item(texListaColorLetra.SelectedItem.Index).Tag Editor!Texto(marcador).ForeColor = prop_colorletra Command2.SetFocus End Sub Private Sub TexListaFondo_Click() prop_color= ImageList1.ListImages.Item(TexListaFondo.SelectedItem.Index).Tag Editor!Texto(marcador).BackColor = prop_color Command2.SetFocus End Sub Private Sub TexListaFuentes_Click() prop_letra = TexListaFuentes.Text Editor!Texto(marcador).FontName = prop_letra Command2.SetFocus End Sub Private Sub TexTamano_Change() On Error Resume Next

Listado del Código

128

If TexTamano.Text = "" Then Editor!Texto(marcador).FontSize = 12 Else Editor!Texto(marcador).FontSize = TexTamano.Text End If On Error GoTo 0 End Sub Private Sub TexTamano_KeyPress(KeyAscii As Integer) Select Case KeyAscii Case 13 KeyAscii = 0 Case 8, 43 To 46, 48 To 57, 68, 69, 100, 101 Case Else KeyAscii = 0 Beep End Select End Sub Private Sub TexTitulo_Change() Editor!Texto(marcador).Text = TexTitulo.Text End Sub Private Sub TexUpDown1_Change() Editor!Texto(marcador).ancho = TexTAncho.Text + 10 End Sub Private Sub TexUpDown2_Change() Editor!Texto(marcador).alto = TexTAlto.Text + 10 End Sub

Listado del Código

129

Presentación Option Explicit Private Sub Combo1_Click() TipoIndice = Combo1.ListIndex TipoElemento = Combo1.List(TipoIndice) TipoElemento = Left(TipoElemento, 3) Select Case TipoElemento Case "Eti" Listar_PropEtiqueta Me TipoElemento = "Etiqueta" Case "Tex" Listar_PropTexto Me TipoElemento = "Texto" Case "Pul" Listar_PropPulsador Me TipoElemento = "Pulsador" Case "Fig" Listar_PropFigura Me TipoElemento = "Figura" End Select End Sub Private Sub Combo2_Click() TipoIndice = Combo2.ListIndex Select Case TipoIndice: Case 0: Text1.Text = "Private Sub " & TipoElemento & "_Click(Index As Integer)" Case 1: Text1.Text = "Private Sub " & TipoElemento & "_DblClick(Index As Integer)" Case 2: Text1.Text = "Private Sub " & TipoElemento & "_MouseDown(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)" Case 3: Text1.Text = "Private Sub " & TipoElemento & "_MouseMove(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)" Case 4: Text1.Text = "Private Sub " & TipoElemento & "_MouseUp(Index As Integer, Button As Integer, Shift As Integer, X As Single, Y As Single)" Case 5: Text1.Text = "Private Sub " & TipoElemento & "_KeyDown(Index As Integer, KeyCode As Integer, Shift As Integer)" Case 6: Text1.Text = "Private Sub " & TipoElemento & "_KeyPress(Index As Integer, KeyAscii As Integer)" Case 7: Text1.Text = "Private Sub " & TipoElemento & "_KeyUp(Index As Integer, KeyCode As Integer, Shift As Integer)" Case 8: Text1.Text = "Private Sub " & TipoElemento & "_Change(Index As Integer)" End Select End Sub Private Sub Command1_Click() Dim retval retval = Shell("C:\Proyecto\Ejecucion.bat") End Sub Private Sub Form_Load() SSTab1.Tab = 0 'la pestaña q sta activa al inicio SSTab1.TabEnabled(1) = False SSTab1.TabEnabled(2) = False End Sub

Listado del Código

130

Private Sub Form_Resize() With SSTab1: .Top = CoolBar1.Top + CoolBar1.Height .Left = 0 .Height = presentacion.Height - SSTab1.Top .Width = presentacion.Width End With With Tapiz: .Top = SSTab1.Top - 90 .Left = SSTab1.Left + 50 .Width = SSTab1.Width - 170 .Height = Abs(SSTab1.Height - (Tapiz.Top + 530)) End With With RichText .Top = SSTab1.Top - 90 .Left = 3100 .Width = Abs(SSTab1.Width - 3270) .Height = Abs(SSTab1.Height - (RichText.Top + 530)) End With With Frame1 .Top = SSTab1.Top - 100 .Left = SSTab1.Left + 60 .Width = 3000 .Height = Abs(SSTab1.Height - (Frame1.Top + 530)) End With End Sub Private Sub SSTab1_Click(PreviousTab As Integer) Select Case SSTab1.Tab: Case 0 Text1.Text = "" RichText.visible = False Frame1.visible = False Case 1 RichText.visible = True Frame1.visible = True End Select End Sub Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button) Select Case Button.Key Case "abrir" SSTab1.Tab = 0 Text1.Text = "" Combo1.Clear Combo2.Clear ListView1.ListItems.Clear operacion_abrir Me Listar_alias Me SSTab1.TabEnabled(1) = True SSTab1.TabEnabled(2) = False Case "guardar" SSTab1.Tab = 1 operacion_GuardararchivoTexto operacion_AbrirarchivoTexto RichText.visible = True Frame1.visible = True

Listado del Código

131

SSTab1.TabEnabled(2) = True SSTab1.Tab = 2 SSTab1.TabEnabled(1) = False EdiOperacion_abrir Me EdiOperacion_guardar Me Case "cerrar" Unload Me End Select End Sub

Listado del Código

132

Lienzo Option Explicit Dim Conectado As Boolean Dim cadena As String Dim n As Integer Private Sub Comunicacion_OnComm() 'Si aún no se ha comprobado la conexión o no se está realizando ninguna de las 'operaciones posibles no continuar If Not Conectado Then Exit Sub 'Para leer el contenido actual del control Dim SubCadena As String 'Comprobar si se ha recibido algo If(Comunicacion.CommEvent=comEvReceive And Comunicacion.InBufferCount <> 0) Then 'leerlo SubCadena = Comunicacion.Input 'y añadirlo a la cadena cadena = cadena & SubCadena 'si recibimos retorno de carro If Asc(Right(cadena, 1)) = 13 Then SubCadena = Left(cadena, 5) For n = 1 To ind Select Case indices(n): Case "E" If SubCadena = Etiqueta(n).Alias Then Etiqueta(n).Caption = "" extraer_cadena cadena Etiqueta(n).Caption = cadena cadena = "" 'Comunicacion.RThreshold=1 End If Case "P" If SubCadena = Pulsador(n).Alias Then Pulsador(n).Caption = "" extraer_cadena cadena Pulsador(n).Caption = cadena cadena = "" End If Case "TE" If SubCadena = Texto(n).Alias Then Texto(n).Text = "" extraer_cadena cadena Texto(n).Text = cadena cadena = "" 'Comunicacion.RThreshold=1 End If End Select 'tratar_cadena Next End If 'Si el evento recibido es un error ElseIf Comunicacion.CommEvent <> comEvReceive Then 'se ha producido un error MsgBox "Se produce el error " & Comunicacion.CommEvent & " durante la comunicación" End If End Sub

Listado del Código

133

Private Sub Form_Resize() With Tapiz: .Top = CoolBar1.Top + CoolBar1.Height .Left = 30 .Height = 9920 .Width = Lienzo.Width - 165 End With On Error Resume Next 'Abrir el puerto Comunicacion.PortOpen = True End Sub Private Sub Form_Unload(Cancel As Integer) On Error Resume Next ' Cerrar el puerto de comunicación Comunicacion.PortOpen = False End Sub Private Sub Reloj_Timer() 'contador de intentos Static intentos As Byte 'NO recibido VALE If Comunicacion.Input <> "VALE" Then If intentos < 3 Then intentos = intentos + 1 Comunicacion.Output = "IDEN" & vbCr Exit Sub Else Text1.Text = "" Text1.Text = "Imposible Conectar" MousePointer = vbArrow End If Else 'SI recibido VALE Conectado = True Text1.Text = "" Text1.Text = "Conexión Efectuada" Comunicacion.RThreshold = 1 MousePointer = vbArrow End If 'No generar más veces el evento Reloj.Interval = 0 intentos = 0 End Sub Private Sub Toolbar1_ButtonClick(ByVal Button As MSComctlLib.Button) Dim xl As Object Select Case Button.Key Case "cerrar" Unload Me Case "comuni" MousePointer = vbHourglass Text1.Text = "" 'intetamos comun. Text1.Text = "Intentando Conectar, espere..." Comunicacion.RThreshold = 0 'enviar cadena Comunicacion.Output = "IDEN" & vbCr 'esperar 3 segundos Reloj.Interval = 3000 Case "excel"

Listado del Código

134

Set xl = CreateObject("C:\Proyecto\HojaBlanca.xls") xl.Application.visible = True Case "word" Set xl = CreateObject("Word.Application") xl.Application.visible = True End Select End Sub

Listado del Código

135

Galactic Option Explicit Dim retval Private Sub Command1_Click() retval = Shell("C:\Proyecto\ProEditor.exe", 1) End Sub Private Sub Command2_Click() retval = Shell("C:\Proyecto\ProCodigo.exe", 1) End Sub Private Sub Form_Resize() With Image1: .Top = galactic.Top .Left = galactic.Left .Height = galactic.Height .Width = galactic.Width End With frmSplash.Show End Sub Private Sub Image2_Click() End End Sub

Listado del Código

136

VariablesyMetodos Option Explicit 'Definiciones de constantes Public Const margen = 120 Const cursores = "C:\WINDOWS\cursores\hcross.cur" 'Definicion de variables globales Public ind As Integer, ind1 As Integer, marcador As Integer Public fichado As String Public fondo As OLE_COLOR Public moveX As Integer, moveY As Integer 'variables q utilizamos para dibujar las lineas Public iniX As Single, iniY As Single Public anterX As Single, anterY As Single 'indican el estado de la operacion para trazar una linea Public dibujando As Boolean Public entidad As Integer Public EleAncho As Integer, EleAlto As Integer Public colocX As Integer, colocY As Integer Public orientacion As String Public indices() As String Public elemento As ComboItem Public fotos As String 'para depositar ruta bitmaps Public modificado As Boolean 'mirar cambios Public respuesta Public nombrearchivo As String Public nombrearchivo1 As String Public fichero As String Public LineaTexto As String Public LineaTexto3 As String Public Sub insertar(grafico As String, orient As String, identifica As String, formula As Form) 'Para controlar si ha habido alguna variación modificado = True 'Insertamos los dibujos graficos q necesitamos para realizar los sinopticos ind = ind + 1 Select Case identifica: Case "D" 'Depositos ReDim Preserve indices(ind) indices(ind) = identifica Load formula!Dibujo(ind) With formula!Dibujo(ind) .Pintura = grafico .Identificador = identifica .ancho = EleAncho .alto = EleAlto End With moveX = formula!Dibujo(ind).Width / 2 moveY = formula!Dibujo(ind).Height / 2 marcador = ind formula!Dibujo(marcador).Drag vbBeginDrag Case "F" ReDim Preserve indices(ind)

Listado del Código

137

indices(ind) = identifica Load formula!Figura(ind) With formula!Figura(ind) .Identificador = identifica End With moveX = formula!Figura(ind).Width / 2 moveY = formula!Figura(ind).Height / 2 marcador = ind formula!Figura(marcador).Drag vbBeginDrag Case "P" 'Pulsadores ReDim Preserve indices(ind) indices(ind) = identifica Load formula!Pulsador(ind) With formula!Pulsador(ind) .Identificador = identifica .BackColor = &HC0C0C0 End With moveX = formula!Pulsador(ind).Width / 2 moveY = formula!Pulsador(ind).Height / 2 marcador = ind formula!Pulsador(ind).Drag vbBeginDrag Case "E" 'Etiquetas ReDim Preserve indices(ind) indices(ind) = identifica Load formula!Etiqueta(ind) With formula!Etiqueta(ind) .Identificador = identifica .BorderStyle = 1 .Width = .ancho .Height = .alto .BackColor = vbGreen End With moveX = formula!Etiqueta(ind).Width / 2 moveY = formula!Etiqueta(ind).Height / 2 marcador = ind formula!Etiqueta(ind).Drag vbBeginDrag Case "TE" ReDim Preserve indices(ind) indices(ind) = identifica Load formula!Texto(ind) With formula!Texto(ind) .Identificador = identifica End With moveX = formula!Texto(ind).Width / 2 moveY = formula!Texto(ind).Height / 2 marcador = ind formula!Texto(ind).Drag vbBeginDrag Case "T" 'Tuberias entidad = 1 formula!Tapiz.MousePointer = vbCustom formula!Tapiz.MouseIcon = LoadPicture(cursores) ReDim Preserve indices(ind) indices(ind) = identifica Select Case orient: Case "horizontal" Load formula!Tuberia(ind) With formula!Tuberia(ind) .Height = 250 .BackColor = &H8000000C .Identificador = identifica

Listado del Código

138

End With orientacion = orient 'indica orientacion al evento MOVE Case "vertical" Load formula!Tuberia(ind) With formula!Tuberia(ind) .Width = 250 .BackColor = &H8000000C .Identificador = identifica End With orientacion = orient End Select End Select End Sub Public Function par(numero As Single) As Single Dim calculo As Boolean Dim resto As Single, resto1 As Single Dim numero1 As Single numero1 = numero calculo = True Do While calculo resto = numero Mod margen resto1 = numero1 Mod margen If resto = 0 Or resto1 = 0 Then If resto1 = 0 Then calculo = False par = numero1 Else calculo = False par = numero End If Else numero = numero - 1 numero1 = numero1 + 1 End If Loop End Function Public Sub cargar_bitmap(formula As Form) modificado = True On Error Resume Next With formula!cajacomun: .Filter= "Archivo jpg|*.jpg|Archivos bmp|*.bmp|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt .ShowOpen End With fotos = formula!cajacomun.FileName formula!cajacomun.FileName = nombrearchivo formula!Tapiz.Picture = LoadPicture(fotos) rejilla End Sub

Listado del Código

139

AparienciaEditor Option Explicit Public Sub colores(formula As Form) 'Activamos la deteccion de errores On Error Resume Next formula!cajacomun.ShowColor formula!Tapiz.BackColor = formula!cajacomun.Color fondo = formula!cajacomun.Color 'si se pulsa el boton CANCELAR dejamos el color de fondo actual If Err Then formula!Tapiz.BackColor = &H80000005 'blanco formulario End If On Error GoTo 0 'desactivamos los errores rejilla modificado = True End Sub Public Sub borrar(formula As Form) On Error Resume Next Select Case fichado: Case "Dibujo" formula!Dibujo(marcador).Pintura = "" formula!Dibujo(marcador).visible = False Case "Tuberia" formula!Tuberia(marcador).visible = False Case "Pulsador" formula!Pulsador(marcador).visible = False Case "Texto" formula!Texto(marcador).visible = False Case "Etiqueta" formula!Etiqueta(marcador).visible = False Case "Figura" formula!Figura(marcador).visible = False End Select modificado = True End Sub Public Sub nuevo(formula As Form) Dim n As Integer For n = 1 To ind Select Case indices(n): Case "D" Unload formula.Dibujo(n) Case "P" Unload formula.Pulsador(n) Case "E" Unload formula.Etiqueta(n) Case "TE" Unload formula.Texto(n) Case "T" Unload formula.Tuberia(n) Case "F" Unload formula.Figura(n) End Select Next With formula!Tapiz: .BackColor = &H80000005 .Picture = LoadPicture("") End With

Listado del Código

140

ind = 0 ReDim indices(0) If formula.Name = "Editor" Then formula.Caption = "Editor de Sinópticos" rejilla End If If formula.Name = "presentacion" Then formula.Caption = "Trends" End If modificado = False End Sub Public Sub cantidad(formula As Form) Dim total As Integer If ind = 0 Then formula!Text1.Text = 0 Else formula!Text1.Text = ind End If End Sub Public Sub rejilla() Dim puntoX As Single, puntoY As Single puntoY = 0 Do While Editor!Tapiz.Height > puntoY Do While Editor!Tapiz.Width > puntoX Editor!Tapiz.PSet (puntoX, puntoY), RGB(0, 0, 255) puntoX = puntoX + margen Loop puntoY = puntoY + margen puntoX = 0 Loop entidad = -1 End Sub

Listado del Código

141

OperacionesArchivo Option Explicit Public Sub operacion_guardar(formula As Form) Dim nom As String Dim num As Integer Dim nfile As Integer 'Activamos la deteccion de errores y preparamos el cuadro de dialogo On Error Resume Next If nombrearchivo <> "" Then formula!cajacomun.FileName = nombrearchivo Else With formula.cajacomun: .DialogTitle = "Guardar como..." .Filter = "Archivo de sistema|*.rzd|Archivos jpeg|*.jpg|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt .ShowSave End With 'Crear el fichero de codigo adjunto nombrearchivo = formula!cajacomun.FileName num = Len(nombrearchivo): nom = Left(nombrearchivo, num - 3) nombrearchivo = nom & "txt" nfile = FreeFile Open nombrearchivo For Output As nfile Close #nfile End If 'Cambiamos la apariencia del puntero del mouse y definimos las variables y 'elementos necesarios para guardar la informacion en un archivo Dim anterpuntero As Byte Dim i As Integer 'Asignamos un valor para abrir el canal, tratamos la apariencia del puntero y 'abrimos el archivo q queremoes leer nfile = FreeFile anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass fondo = formula!Tapiz.BackColor Open formula!cajacomun.FileName For Output As nfile 'guardamos la imagen de fondo y en su defecto el color de fondo Write #nfile, fotos, fondo 'Salvamos el archivo For i = 1 To ind Select Case indices(i): Case "D" With formula!Dibujo(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .Pintura, .alto, .ancho, .visible ', fondo End With Case "T" With formula!Tuberia(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .Height, .Width, .visible End With Case "P" With formula!Pulsador(i):

Listado del Código

142

Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .Caption, .Enabled Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .MousePointer, .visible End With Case "F" With formula!Figura(i) Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .BackStyle, .BorderColor, .BorderStyle, .BorderWidth Write #nfile, .FillColor, .FillStyle, .Shape, .visible End With Case "E" With formula!Etiqueta(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .AutoSize, .BackColor, .BackStyle, .BorderStyle, .Caption, .Enabled, .Alignment Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .ForeColor, .MousePointer, .visible, .WordWrap End With Case "TE" With formula!Texto(i): Write #nfile, .Identificador, .Alias Write #nfile, .Top, .Left, .alto, .ancho Write #nfile, .BackColor, .BorderStyle, .Text, .Enabled, .Alignment, .Appearance Write #nfile, .FontName, .FontSize, .FontBold, .FontItalic, .FontStrikethru, .FontUnderline Write #nfile, .ForeColor, .MousePointer, .visible End With End Select Next Close nfile 'Restablecemos el puntero y indicamos en tipo de error Screen.MousePointer = anterpuntero 'Modificar el valor de modificado modificado = False On Error GoTo 0 'desactivamos los errores End Sub Public Sub operacion_abrir(formula As Form) On Error Resume Next 'Activamos la deteccion de errores y preparamos el cuadro de dialog If formula.Name = "Lienzo" Then formula!cajacomun.FileName = fichero Else With formula.cajacomun: .DialogTitle = "Abrir dibujo" .Filter="Archivo de sistema|*.rzd|Archivos jpeg|*.jpg|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt .ShowOpen End With End If

Listado del Código

143

'Llamamos al procedimiento nuevo para limpiar la pantalla, si cancelamos 'la apertura del archivo salimos del procedimiento manteniendo el contenido If Err Then Exit Sub Else nuevo formula End If formula.Caption= formula.Caption & " [" & formula!cajacomun.FileName & "]" 'Variables para leer el contenido del archivo Dim nfile As Integer Dim ini As Integer, izq As Integer, ancho As Integer Dim estilo As Integer, i As Integer, j As Integer Dim estado As Boolean Dim anterpuntero As Byte Dim graf As String, appelle As String, Texto As String, fuente As String Dim arriba As Single, izquierda As Single, alto As Single, ancho1 As Single, tamañoletra As Single Dim ajuste As Boolean, habilitado As Boolean, visible As Boolean, multilinea As Boolean Dim negrita As Boolean, cursiva As Boolean, tachado As Boolean, subrayado As Boolean Dim colorfondo As Long, colortexto As Long, colormarco As Long, colorrelleno As Long Dim marco As Integer, justificado As Integer, puntero As Integer, alineacion As Integer, formato As Integer Dim detras As Integer, anchomarco As Integer, formarelleno As Integer, forma As Integer Dim nombreguerra As String, basura As String 'Forzamos q el valor de inicio de los controles sea 1 y asignamos un valor para 'abrir el canal nfile = FreeFile 'Tratamos la apariencia del puntero para cuando abrimos un archivo guardado anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass 'Cogemos el nombre del fichero nombrearchivo = formula!cajacomun.FileName nombrearchivo1 = formula!cajacomun.FileName 'Abrimos el archivo de sistema donde esta guardada la informacion Open formula!cajacomun.FileName For Input As nfile If formula!cajacomun.FileName = "" Then MsgBox "No es posible abrir el dibujo elegido." Screen.MousePointer = anterpuntero Exit Sub End If On Error GoTo 0 'desactivamos los errores 'Cargamos la imagen de fondo o en su defecto el color de fondo Input #nfile, fotos, fondo With formula!Tapiz: .Picture = LoadPicture(fotos)

Listado del Código

144

.BackColor = fondo End With 'Cargamos el archivo Do While Not EOF(nfile) Input #nfile, appelle, nombreguerra Select Case appelle: Case "D" ind = ind + 1 Input #nfile, ini, izq, graf, alto, ancho1, estado Load formula!Dibujo(ind) With formula!Dibujo(ind): .Identificador = appelle: .Alias = nombreguerra: .Top = ini: .Left = izq .Pintura = graf: .alto = alto: .ancho = ancho1: .visible = estado End With ReDim Preserve indices(ind) indices(ind) = appelle formula!Tapiz.BackColor = fondo Case "T" ind = ind + 1 Input #nfile, ini, izq, estilo, ancho, estado Load formula!Tuberia(ind) With formula!Tuberia(ind): .Identificador = appelle: .Alias = nombreguerra .Top = ini: .Left = izq: .Height = estilo: .Width = ancho .visible = estado End With ReDim Preserve indices(ind) indices(ind) = appelle Case "P" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, Texto, habilitado Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, puntero, visible Load formula!Pulsador(ind) With formula!Pulsador(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .Caption = Texto: .Enabled = habilitado .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .MousePointer = puntero: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle Case "F" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, detras, colormarco, marco, anchomarco Input #nfile, colorrelleno, formarelleno, forma, visible Load formula!Figura(ind) With formula!Figura(ind): .Identificador = appelle: .Alias = nombreguerra

Listado del Código

145

.Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .BackStyle = detras: .BorderColor = colormarco: .BorderStyle = marco .BorderWidth = anchomarco: .FillColor = colorrelleno: .FillStyle = formarelleno .Shape = forma: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle Case "E" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, ajuste, colorfondo, detras, marco, Texto, habilitado, justificado Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, colortexto, puntero, visible, multilinea Load formula!Etiqueta(ind) With formula!Etiqueta(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .AutoSize = ajuste: .BackColor = colorfondo: .BackStyle = detras: .BorderStyle = marco: .Caption = Texto .Enabled = habilitado: .Alignment = justificado: .Font = fuente: .FontSize = tamañoletra .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .ForeColor = colortexto: .MousePointer = puntero: .visible = visible: .WordWrap = multilinea End With ReDim Preserve indices(ind) indices(ind) = appelle Case "TE" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, marco, Texto, habilitado, justificado, formato Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, colortexto, puntero, visible Load formula!Texto(ind) With formula!Texto(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .BorderStyle = marco: .Text = Texto .Enabled = habilitado: .Alignment = justificado: .Appearance = formato: .Font = fuente: .FontSize = tamañoletra .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .ForeColor = colortexto: .MousePointer = puntero: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle End Select Loop Close nfile 'cerramos el canal de lectura

Listado del Código

146

If formula.Name = "Editor" Then rejilla 'util para diseño End If 'Abre fichero texto If formula.Name = "presentacion" Then operacion_AbrirarchivoTexto 'presentacion End If 'Restablecemos el puntero Screen.MousePointer = anterpuntero End Sub Public Sub operacion_AbrirarchivoTexto() Dim num As Integer Dim nom As String 'Generar el nommbre con extension *.txt num = Len(nombrearchivo): nom = Left(nombrearchivo, num - 3) nombrearchivo = nom & "txt" presentacion!cajacomun.FileName = nombrearchivo 'Ocultar el cuadro de texto para evitar los parpadeos y borrar contenido presentacion!RichText.visible = False presentacion!RichText.Text = "" 'Variables para leer el contenido del archivo Dim nfile As Integer Dim Separador As String, LineaTexto1 As String Dim anterpuntero As Byte 'Asignamos un canal libre para leer el fichero y retorno de carro nfile = FreeFile Separador = Chr(13) + Chr(10) 'Tratamos la apariencia del puntero para cuando abrimos un archivo guardado anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass 'Abrimos el archivo de sistema donde esta guardada la informacion Open presentacion!cajacomun.FileName For Input As nfile If presentacion!cajacomun.FileName = "" Then MsgBox "No es posible abrir el dibujo elegido." Screen.MousePointer = anterpuntero Exit Sub End If On Error GoTo 0 'desactivamos los errores 'Cargamos el archivo Do While Not EOF(nfile) Line Input #nfile, LineaTexto1 presentacion!RichText.Text=presentacion!RichText.Text& LineaTexto1 & Separador If Err Then MsgBox "El archivo no se ha podido leer" Exit Do End If Loop LineaTexto = presentacion!RichText.Text 'Volver a visualizar el cuadro de texto presentacion!RichText.visible = True 'Cerrar fichero Close #nfile 'Restablecemos el puntero Screen.MousePointer = anterpuntero 'Desactivar deteccion de errores On Error GoTo 0 'Hacemos invisible y limpiamos las listas

Listado del Código

147

presentacion!RichText.visible = False presentacion!Frame1.visible = False End Sub Public Sub operacion_GuardararchivoTexto() Dim num As Integer Dim nom As String 'Generar el nommbre con extension *.txt num = Len(nombrearchivo): nom = Left(nombrearchivo, num - 3) nombrearchivo = nom & "txt" presentacion!cajacomun.FileName = nombrearchivo 'Variables para guardar el contenido del archivo Dim nfile As Integer nfile = FreeFile 'Activar la deteccion de errores On Error Resume Next 'Intentar abrir archivo Open presentacion!cajacomun.FileName For Output As nfile 'Si se ha producido un error If Err Then MsgBox "El archivo no se ha podido escribir" Exit Sub End If 'Escribir lo almacenado antes de "Option Explicit" Print #nfile, presentacion!RichText.Text 'Cerrar el fichero Close #nfile LineaTexto = presentacion!RichText.Text 'Desactivar errores On Error GoTo 0 End Sub

Listado del Código

148

PropiedadesFunciones Option Explicit Public prop_justifi As Integer, prop_marco As Integer, prop_transpa As Integer, prop_relleno As Integer Public prop_color As OLE_COLOR, prop_colorletra As OLE_COLOR, prop_colorrelleno As OLE_COLOR, prop_colorborde As OLE_COLOR Public prop_letra As String Public prop_letracursiva As Boolean, prop_letranegrita As Boolean, prop_letrasubrayada As Boolean, prop_letratachada As Boolean Public prop_visible As Boolean, prop_autoajuste As Boolean Public Sub Captura_Propiedades(formula As Form) Dim n As Integer Select Case fichado: Case "Etiqueta": 'Coger nombre de la variable y nombre de guerra formula!EtiLab8.Caption = Editor!Etiqueta(marcador).Name & marcador formula!EtiAlias.Text = Editor!Etiqueta(marcador).Alias 'Si AutoSize=True, entonces deshabilitamos algunas opciones If Editor!Etiqueta(marcador).AutoSize = True Then formula!EtiCheAutosize.Value = Checked formula!EtiTAncho.Enabled = False: formula!EtiTAlto.Enabled = False formula!EtiLab2.Enabled = False: formula!EtiLab3.Enabled = False: formula!EtiLab4.Enabled = False formula!EtiUpDown1.Value = Editor!Etiqueta(marcador).ancho formula!EtiUpDown2.Value = Editor!Etiqueta(marcador).alto formula!EtiUpDown1.Enabled = False: formula!EtiUpDown2.Enabled = False formula!EtiListaAlig.Enabled = False End If prop_autoajuste = Editor!Etiqueta(marcador).AutoSize 'Mostramos el valor actual de los elementos (alto y ancho) formula!EtiUpDown1.Value = Editor!Etiqueta(marcador).ancho - 10 formula!EtiUpDown2.Value = Editor!Etiqueta(marcador).alto - 10 'Miramos el tipo de Alineación que hay en el elemento, y lo fijamos en Combo3 prop_justifi = Editor!Etiqueta(marcador).Alignment formula!EtiListaAlig.Text = formula!EtiListaAlig.List(prop_justifi) 'Miramos si el elemento es visible prop_visible = Editor!Etiqueta(marcador).visible If Editor!Etiqueta(marcador).visible = True Then formula!EtiCheVisible.Value = Checked End If 'Miramos los efectos de letra q hay seleccionados prop_letranegrita = Editor!Etiqueta(marcador).FontBold If Editor!Etiqueta(marcador).FontBold = True Then formula!EtiCheNegra.Value = Checked End If prop_letracursiva = Editor!Etiqueta(marcador).FontItalic If Editor!Etiqueta(marcador).FontItalic = True Then formula!EtiCheCursiva.Value = Checked End If prop_letrasubrayada = Editor!Etiqueta(marcador).FontUnderline If Editor!Etiqueta(marcador).FontUnderline = True Then formula!EtiCheSubrayada.Value = Checked End If

Listado del Código

149

prop_letratachada = Editor!Etiqueta(marcador).FontStrikethru If Editor!Etiqueta(marcador).FontStrikethru = True Then formula!EtiCheTachada.Value = Checked End If 'Miramos el marco del elemento prop_marco = Editor!Etiqueta(marcador).BorderStyle If Editor!Etiqueta(marcador).BorderStyle = 1 Then formula!EtiCheMarco.Value = Checked End If 'Mirar si el fondo es transparente prop_transpa = Editor!Etiqueta(marcador).BackStyle If Editor!Etiqueta(marcador).BackStyle = 0 Then formula!EtiCheTrans.Value = Checked End If 'Establecemos el texto en el TextBox1 formula!EtiTitulo.Text = Editor!Etiqueta(marcador).Caption 'Miramos el Backcolor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Etiqueta(marcador).BackColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!EtiListaFondo.SelectedItem = formula!EtiListaFondo.ComboItems(n) 'Establece el elemento inicial prop_color = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el foreColor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Etiqueta(marcador).ForeColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!EtiListaColorLetra.SelectedItem = formula!EtiListaColorLetra.ComboItems(n) 'Establece el elemento inicial prop_colorletra = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el FontName del elemento y lo mostramos en el ComboBox For n = 0 To Screen.FontCount - 1 If Editor!Etiqueta(marcador).FontName = Screen.Fonts(n) Then formula!EtiListaFuentes.Text = Screen.Fonts(n) prop_letra = formula!EtiListaFuentes.Text Exit For End If Next 'Miramos el tamaño de la fuente formula!EtiTamano.Text = Editor!Etiqueta(marcador).FontSize Case "Pulsador": 'Coger nombre de la variable y nombre de guerra formula!PulsLab6.Caption = Editor!Pulsador(marcador).Name & marcador formula!PulsAlias.Text = Editor!Pulsador(marcador).Alias 'Mostramos el valor actual de los elementos (alto y ancho) formula!PulsUpDown1.Value = Editor!Pulsador(marcador).ancho - 10 formula!PulsUpDown2.Value = Editor!Pulsador(marcador).alto - 10 'Miramos si el elemento es visible prop_visible = Editor!Pulsador(marcador).visible If Editor!Pulsador(marcador).visible = True Then formula!PulsCheVisible.Value = Checked End If

Listado del Código

150

'Miramos si el elemento esta habilitado prop_visible = Editor!Pulsador(marcador).Enabled If Editor!Pulsador(marcador).Enabled = True Then formula!PulsCheHabilitado.Value = Checked formula!PulsCheHabilitado.Enabled = False End If 'Miramos los efectos de letra q hay seleccionados prop_letranegrita = Editor!Pulsador(marcador).FontBold If Editor!Pulsador(marcador).FontBold = True Then formula!PulsCheNegra.Value = Checked End If prop_letracursiva = Editor!Pulsador(marcador).FontItalic If Editor!Pulsador(marcador).FontItalic = True Then formula!PulsCheCursiva.Value = Checked End If prop_letrasubrayada = Editor!Pulsador(marcador).FontUnderline If Editor!Pulsador(marcador).FontUnderline = True Then formula!PulsCheSubrayada.Value = Checked End If prop_letratachada = Editor!Pulsador(marcador).FontStrikethru If Editor!Pulsador(marcador).FontStrikethru = True Then formula!PulsCheTachada.Value = Checked End If 'Establecemos el texto en el TextBox1 formula!PulsTitulo.Text = Editor!Pulsador(marcador).Caption 'Miramos el Backcolor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Pulsador(marcador).BackColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!PulsListaFondo.SelectedItem = formula!PulsListaFondo.ComboItems(n) 'Establece el elemento inicial prop_color = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el FontName del elemento y lo mostramos en el ComboBox For n = 0 To Screen.FontCount - 1 If Editor!Pulsador(marcador).FontName = Screen.Fonts(n) Then formula!PulsListaFuentes.Text = Screen.Fonts(n) prop_letra = formula!PulsListaFuentes.Text Exit For End If Next 'Miramos el tamaño de la fuente formula!PulsTamano.Text = Editor!Pulsador(marcador).FontSize Case "Texto" 'Coger nombre de la variable y nombre de guerra formula!TexLab8.Caption = Editor!Texto(marcador).Name & marcador formula!TexAlias.Text = Editor!Texto(marcador).Alias 'Mostramos el valor actual de los elementos (alto y ancho) formula!TexUpDown1.Value = Editor!Texto(marcador).ancho - 10 formula!TexUpDown2.Value = Editor!Texto(marcador).alto - 10 'Miramos el tipo de Alineación que hay en el elemento, y lo fijamos en Combo3 prop_justifi = Editor!Texto(marcador).Alignment formula!TexListaAlig.Text = formula!TexListaAlig.List(prop_justifi) 'Miramos si el elemento es visible prop_visible = Editor!Texto(marcador).visible If Editor!Texto(marcador).visible = True Then

Listado del Código

151

formula!TexCheVisible.Value = Checked End If 'Miramos los efectos de letra q hay seleccionados prop_letranegrita = Editor!Texto(marcador).FontBold If Editor!Texto(marcador).FontBold = True Then formula!TexCheNegra.Value = Checked End If prop_letracursiva = Editor!Texto(marcador).FontItalic If Editor!Texto(marcador).FontItalic = True Then formula!TexCheCursiva.Value = Checked End If prop_letrasubrayada = Editor!Texto(marcador).FontUnderline If Editor!Texto(marcador).FontUnderline = True Then formula!TexCheSubrayada.Value = Checked End If prop_letratachada = Editor!Texto(marcador).FontStrikethru If Editor!Texto(marcador).FontStrikethru = True Then formula!TexCheTachada.Value = Checked End If 'Miramos el marco del elemento prop_marco = Editor!Texto(marcador).Appearance If Editor!Texto(marcador).Appearance = 1 Then formula!TexCheMarco.Value = Checked End If 'Establecemos el texto en el TextBox1 formula!TexTitulo.Text = Editor!Texto(marcador).Text 'Miramos el Backcolor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Texto(marcador).BackColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!TexListaFondo.SelectedItem = formula!TexListaFondo.ComboItems(n) 'Establece el elemento inicial prop_color = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el foreColor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Texto(marcador).ForeColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!texListaColorLetra.SelectedItem = formula!texListaColorLetra.ComboItems(n) 'Establece el elemento inicial prop_colorletra = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el FontName del elemento y lo mostramos en el ComboBox For n = 0 To Screen.FontCount - 1 If Editor!Texto(marcador).FontName = Screen.Fonts(n) Then formula!TexListaFuentes.Text = Screen.Fonts(n) prop_letra = formula!TexListaFuentes.Text Exit For End If Next 'Miramos el tamaño de la fuente formula!TexTamano.Text = Editor!Texto(marcador).FontSize Case "Figura" 'Coger nombre de la variable y nombre de guerra formula!FigLab2.Caption = Editor!Figura(marcador).Name & marcador

Listado del Código

152

formula!FigAlias.Text = Editor!Figura(marcador).Alias 'Mostramos el valor actual de los elementos (alto y ancho) formula!FigUpDown1.Value = Editor!Figura(marcador).ancho - 10 formula!FigUpDown2.Value = Editor!Figura(marcador).alto - 10 'Miramos si el elemento es visible prop_visible = Editor!Figura(marcador).visible If Editor!Figura(marcador).visible = True Then formula!FigCheVisible.Value = Checked End If 'Miramos el estilo de fondo que hay en el elemento, y lo fijamos en el Combo prop_justifi = Editor!Figura(marcador).BackStyle formula!FigListaEstiloFondo.Text = formula!FigListaEstiloFondo.List(prop_justifi) 'Miramos el BackColor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Figura(marcador).BackColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!FigListaFondo.SelectedItem = formula!FigListaFondo.ComboItems(n) 'Establece el elemento inicial prop_color = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el estilo de relleno que hay en el elemento, y lo fijamos en el Combo prop_relleno = Editor!Figura(marcador).FillStyle formula!FigListaEstiloRelleno.Text = formula!FigListaEstiloRelleno.List(prop_relleno) 'Miramos el FillColor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Figura(marcador).FillColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!FigListaRelleno.SelectedItem = formula!FigListaRelleno.ComboItems(n) 'Establece el elemento inicial prop_colorrelleno = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el marco del elemento prop_marco = Editor!Figura(marcador).BorderStyle formula!FigListaEstiloMarco.Text = formula!FigListaEstiloMarco.List(prop_marco) 'Miramos el BorderColor del elemento y lo mostramos en el ImageCombo For n = 1 To formula!ImageList1.ListImages.Count If Editor!Figura(marcador).BorderColor = formula!ImageList1.ListImages.Item(n).Tag Then Set formula!FigListaMarco.SelectedItem = formula!FigListaMarco.ComboItems(n) 'Establece el elemento inicial prop_colorborde = formula!ImageList1.ListImages.Item(n).Tag Exit For End If Next 'Miramos el tamaño del marco formula!FigTamano.Text = Editor!Figura(marcador).BorderWidth 'Mirar la forma de la figura prop_transpa = Editor!Figura(marcador).Shape formula!FigListaForma.Text = formula!FigListaForma.List(prop_transpa)

Listado del Código

153

End Select End Sub Public Sub llenar_listas(formula As Form) Dim n As Integer Dim Texto As String Select Case fichado: Case "Etiqueta": 'Para las ETIQUETAS''''''''''''''''''''''''''''''''' 'Cargamos los colores de fondo en el ImageCombo Set formula!EtiListaFondo.ImageList = formula.ImageList1 Set formula!EtiListaColorLetra.ImageList = formula.ImageList1 '''' For n = 1 To formula!ImageList1.ListImages.Count Set elemento = formula!EtiListaFondo.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Set elemento = formula!EtiListaColorLetra.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Next 'Cargamos los 3 tipos de alineaciones For n = 0 To 2 Select Case n: Case 0: Texto = "Izquierda" Case 1: Texto = "Derecha" Case 2: Texto = "Centro" End Select formula!EtiListaAlig.AddItem Texto Next 'Cargamos todos los tipos de fuentes de los q disponemos en el equipo With Screen: For n = 0 To .FontCount - 1 formula!EtiListaFuentes.AddItem .Fonts(n) Next End With Case "Pulsador": 'Para los PULSADORES''''''''''''''''''''''''''''''''''''' 'Cargamos los colores de fondo en el ImageCombo Set formula!PulsListaFondo.ImageList = formula.ImageList1 For n = 1 To formula!ImageList1.ListImages.Count Set elemento = formula!PulsListaFondo.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Next 'Cargamos todos los tipos de fuentes de los q disponemos en el equipo With Screen: For n = 0 To .FontCount - 1 formula!PulsListaFuentes.AddItem .Fonts(n) Next End With Case "Texto" 'Para los CUADRO DE TEXTO''''''''''''''''''''''''''''''''''' 'Cargamos los colores de fondo en el ImageCombo Set formula!TexListaFondo.ImageList = formula.ImageList1 Set formula!texListaColorLetra.ImageList = formula.ImageList1 ''''' For n = 1 To formula!ImageList1.ListImages.Count Set elemento = formula!TexListaFondo.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n)

Listado del Código

154

Set elemento = formula!texListaColorLetra.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Next 'Cargamos los 3 tipos de alineaciones For n = 0 To 2 Select Case n: Case 0: Texto = "Izquierda" Case 1: Texto = "Derecha" Case 2: Texto = "Centro" End Select formula!TexListaAlig.AddItem Texto Next 'Cargamos todos los tipos de fuentes de los q disponemos en el equipo With Screen: For n = 0 To .FontCount - 1 formula!TexListaFuentes.AddItem .Fonts(n) Next End With Case "Figura" 'Para las FIGURAS'''''''''''''''''''''''''''''''''''''''''' 'Cargamos los colores de fondo en el ImageCombo Set formula!FigListaFondo.ImageList = formula.ImageList1 Set formula!FigListaRelleno.ImageList = formula.ImageList1 Set formula!FigListaMarco.ImageList = formula.ImageList1 For n = 1 To formula!ImageList1.ListImages.Count Set elemento = formula!FigListaFondo.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Set elemento = formula!FigListaRelleno.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Set elemento = formula!FigListaMarco.ComboItems.Add(n, formula!ImageList1.ListImages.Item(n).Key, formula!ImageList1.ListImages.Item(n).Key, n) Next 'Cargamos los 2 tipos de estilos para el fondo For n = 0 To 1 Select Case n: Case 0: Texto = n & "-" & " Transparente" Case 1: Texto = n & "-" & " Opaco" End Select formula!FigListaEstiloFondo.AddItem Texto Next 'Cargamos los 8 tipos de relleno para el fondo For n = 0 To 7 Select Case n: Case 0: Texto = n & "-" & " Sólido" Case 1: Texto = n & "-" & " Transparente" Case 2: Texto = n & "-" & " Líneas Horizontales" Case 3: Texto = n & "-" & " Líneas Verticales" Case 4: Texto = n & "-" & " Diagonales Negativas" Case 5: Texto = n & "-" & " Diagonales Positivas" Case 6: Texto = n & "-" & " Cuadriculado" Case 7: Texto = n & "-" & " Cuadriculado Diagonal" End Select formula!FigListaEstiloRelleno.AddItem Texto Next 'Cargamos los 7 tipos de marco For n = 0 To 6

Listado del Código

155

Select Case n: Case 0: Texto = n & "-" & " Transparente" Case 1: Texto = n & "-" & " Sólido" Case 2: Texto = n & "-" & " Raya Discontinua Grande" Case 3: Texto = n & "-" & " Raya Discontinua Pequeña" Case 4: Texto = n & "-" & " Raya Discont. Grande/Pequeña" Case 5: Texto = n & "-" & " Raya Discont. Grande/Pequeñas" Case 6: Texto = n & "-" & " Borde Interior" End Select formula!FigListaEstiloMarco.AddItem Texto Next 'Cargamos las 6 formas distintas For n = 0 To 5 Select Case n: Case 0: Texto = n & "-" & " Rectángulo" Case 1: Texto = n & "-" & " Cuadrado" Case 2: Texto = n & "-" & " Óvalo" Case 3: Texto = n & "-" & " Círculo" Case 4: Texto = n & "-" & " Rectángulo Redondeado" Case 5: Texto = n & "-" & " Cuadrado Redondeado" End Select formula!FigListaForma.AddItem Texto Next End Select End Sub Public Sub Reajuste(formula As Form) If formula!EtiCheAutosize.Value = Checked Then formula!EtiTAncho.Enabled = False: formula!EtiTAlto.Enabled = False formula!EtiLab2.Enabled = False: formula!EtiLab3.Enabled = False: formula!EtiLab4.Enabled = False formula!EtiUpDown1.Enabled = False: formula!EtiUpDown2.Enabled = False formula!EtiListaAlig.Enabled = False prop_autoajuste = True Editor!Etiqueta(marcador).Alignment = 0 'prop_justifi Editor!Etiqueta(marcador).AutoSize = prop_autoajuste Editor!Etiqueta(marcador).Width = Editor!Etiqueta(marcador).ancho Editor!Etiqueta(marcador).Height = Editor!Etiqueta(marcador).alto Else formula!EtiTAncho.Enabled = True: formula!EtiTAlto.Enabled = True formula!EtiLab2.Enabled = True: formula!EtiLab3.Enabled = True: formula!EtiLab4.Enabled = True formula!EtiUpDown1.Enabled = True: formula!EtiUpDown2.Enabled = True prop_autoajuste = False prop_justifi = Editor!Etiqueta(marcador).Alignment formula!EtiListaAlig.Text = formula!EtiListaAlig.List(prop_justifi) formula!EtiListaAlig.Enabled = True Editor!Etiqueta(marcador).AutoSize = prop_autoajuste Editor!Etiqueta(marcador).ancho = formula!EtiTAncho.Text Editor!Etiqueta(marcador).alto = formula!EtiTAlto.Text End If End Sub

Listado del Código

156

EdiListarPropiedades Option Explicit Public TipoIndice As Integer Public TipoElemento As String Public Sub Listar_alias(formula As Form) Dim n As Integer 'Eliminar el contenido anterior del ComboBox1 formula!Combo1.Clear 'Cargar en el ComboBox1 el nombre y tipo objeto de los elementos For n = 1 To ind Select Case indices(n): Case "D" formula!Combo1.AddItem formula!Dibujo(n).Name & " " & "(" & n & ")" & " " & formula!Dibujo(n).Alias Case "E" formula!Combo1.AddItem formula!Etiqueta(n).Name & " " & "(" & n & ")" & " " & formula!Etiqueta(n).Alias Case "P" formula!Combo1.AddItem formula!Pulsador(n).Name & " " & "(" & n & ")" & " " & formula!Pulsador(n).Alias Case "F" formula!Combo1.AddItem formula!Figura(n).Name & " " & "(" & n & ")" & " " & formula!Figura(n).Alias Case "TE" formula!Combo1.AddItem formula!Texto(n).Name & " " & "(" & n & ")" & " " & formula!Texto(n).Alias End Select Next End Sub Public Sub Listar_PropEtiqueta(formula As Form) Dim n As Integer Dim itmX As ListItem formula!Text1.Text = "" 'Borrar y listar las propiedades del objeto ETIQUETA formula!ListView1.ListItems.Clear For n = 1 To 22 Set itmX = formula!ListView1.ListItems.Add(n, , n) Select Case n: Case 1: itmX.SubItems(1) = "Alias" Case 2: itmX.SubItems(1) = "Alignment" Case 3: itmX.SubItems(1) = "Alto" Case 4: itmX.SubItems(1) = "Ancho" Case 5: itmX.SubItems(1) = "Autosize" Case 6: itmX.SubItems(1) = "BackColor" Case 7: itmX.SubItems(1) = "Backstyle" Case 8: itmX.SubItems(1) = "BorderStyle" Case 9: itmX.SubItems(1) = "Caption" Case 10: itmX.SubItems(1) = "Enabled" Case 11: itmX.SubItems(1) = "FontBold" Case 12: itmX.SubItems(1) = "FontItalic" Case 13: itmX.SubItems(1) = "FontName" Case 14: itmX.SubItems(1) = "FontSize" Case 15: itmX.SubItems(1) = "FontStriketru" Case 16: itmX.SubItems(1) = "FontUnderline" Case 17: itmX.SubItems(1) = "ForeColor" Case 18: itmX.SubItems(1) = "Identificador" Case 19: itmX.SubItems(1) = "Left"

Listado del Código

157

Case 20: itmX.SubItems(1) = "MousePointer" Case 21: itmX.SubItems(1) = "Top" Case 22: itmX.SubItems(1) = "Visible" End Select Next 'Borrar y listar los eventos del objeto ETIQUETA formula!Combo2.Clear formula!Combo2.AddItem "Click()" formula!Combo2.AddItem "DblClick()" formula!Combo2.AddItem "MouseDown()" formula!Combo2.AddItem "MouseMove()" formula!Combo2.AddItem "MouseUp()" formula!Combo2.AddItem "KeyDown()" formula!Combo2.AddItem "KeyPress()" formula!Combo2.AddItem "KeyUp()" formula!Combo2.AddItem "Change()" End Sub Public Sub Listar_PropTexto(formula As Form) Dim n As Integer Dim itmX As ListItem formula!Text1.Text = "" 'Borrar y listar las propiedades del objeto TEXTO formula!ListView1.ListItems.Clear For n = 1 To 21 Set itmX = formula!ListView1.ListItems.Add(n, , n) Select Case n: Case 1: itmX.SubItems(1) = "Alias" Case 2: itmX.SubItems(1) = "Alignment" Case 3: itmX.SubItems(1) = "Alto" Case 4: itmX.SubItems(1) = "Ancho" Case 5: itmX.SubItems(1) = "Appearance" Case 6: itmX.SubItems(1) = "BackColor" Case 7: itmX.SubItems(1) = "BorderStyle" Case 8: itmX.SubItems(1) = "Enabled" Case 9: itmX.SubItems(1) = "FontBold" Case 10: itmX.SubItems(1) = "FontItalic" Case 11: itmX.SubItems(1) = "FontName" Case 12: itmX.SubItems(1) = "FontSize" Case 13: itmX.SubItems(1) = "FontStriketru" Case 14: itmX.SubItems(1) = "FontUnderline" Case 15: itmX.SubItems(1) = "ForeColor" Case 16: itmX.SubItems(1) = "Identificador" Case 17: itmX.SubItems(1) = "Left" Case 18: itmX.SubItems(1) = "MousePointer" Case 19: itmX.SubItems(1) = "Text" Case 20: itmX.SubItems(1) = "Top" Case 21: itmX.SubItems(1) = "Visible" End Select Next 'Borrar y listar los eventos del objeto TEXTO formula!Combo2.Clear formula!Combo2.AddItem "Click()" formula!Combo2.AddItem "DblClick()" formula!Combo2.AddItem "MouseDown()" formula!Combo2.AddItem "MouseMove()" formula!Combo2.AddItem "MouseUp()" formula!Combo2.AddItem "KeyDown()" formula!Combo2.AddItem "KeyPress()" formula!Combo2.AddItem "KeyUp()" formula!Combo2.AddItem "Change()"

Listado del Código

158

End Sub Public Sub Listar_PropPulsador(formula As Form) Dim n As Integer Dim itmX As ListItem formula!Text1.Text = "" 'Borrar y listar las propiedades del objeto PULSADOR formula!ListView1.ListItems.Clear For n = 1 To 18 Set itmX = formula!ListView1.ListItems.Add(n, , n) Select Case n: Case 1: itmX.SubItems(1) = "Alias" Case 2: itmX.SubItems(1) = "Alto" Case 3: itmX.SubItems(1) = "Ancho" Case 4: itmX.SubItems(1) = "BackColor" Case 5: itmX.SubItems(1) = "Caption" Case 6: itmX.SubItems(1) = "Enabled" Case 7: itmX.SubItems(1) = "FontBold" Case 8: itmX.SubItems(1) = "FontItalic" Case 9: itmX.SubItems(1) = "FontName" Case 10: itmX.SubItems(1) = "FontSize" Case 11: itmX.SubItems(1) = "FontStriketru" Case 12: itmX.SubItems(1) = "FontUnderline" Case 13: itmX.SubItems(1) = "ForeColor" Case 14: itmX.SubItems(1) = "Identificador" Case 15: itmX.SubItems(1) = "Left" Case 16: itmX.SubItems(1) = "MousePointer" Case 17: itmX.SubItems(1) = "Top" Case 18: itmX.SubItems(1) = "Visible" End Select Next 'Borrar y listar los eventos del objeto PULSADOR formula!Combo2.Clear formula!Combo2.AddItem "Click()" formula!Combo2.AddItem "DblClick()" formula!Combo2.AddItem "MouseDown()" formula!Combo2.AddItem "MouseMove()" formula!Combo2.AddItem "MouseUp()" formula!Combo2.AddItem "KeyDown()" formula!Combo2.AddItem "KeyPress()" formula!Combo2.AddItem "KeyUp()" End Sub Public Sub Listar_PropFigura(formula As Form) Dim n As Integer Dim itmX As ListItem formula!Text1.Text = "" 'Borrar y listar las propiedades del objeto FIGURA formula!ListView1.ListItems.Clear For n = 1 To 15 Set itmX = formula!ListView1.ListItems.Add(n, , n) Select Case n: Case 1: itmX.SubItems(1) = "Alias" Case 2: itmX.SubItems(1) = "Alto" Case 3: itmX.SubItems(1) = "Ancho" Case 4: itmX.SubItems(1) = "BackColor" Case 5: itmX.SubItems(1) = "BackStyle" Case 6: itmX.SubItems(1) = "BorderColor" Case 7: itmX.SubItems(1) = "BorderStyle" Case 8: itmX.SubItems(1) = "BorderWidth" Case 9: itmX.SubItems(1) = "FillColor"

Listado del Código

159

Case 10: itmX.SubItems(1) = "FillStyle" Case 11: itmX.SubItems(1) = "Left" Case 12: itmX.SubItems(1) = "Identificador" Case 13: itmX.SubItems(1) = "Shape" Case 14: itmX.SubItems(1) = "Top" Case 15: itmX.SubItems(1) = "Visible" End Select Next 'Borrar y listar los eventos del objeto FIGURA formula!Combo2.Clear formula!Combo2.AddItem "Click()" formula!Combo2.AddItem "DblClick()" formula!Combo2.AddItem "MouseDown()" formula!Combo2.AddItem "MouseMove()" formula!Combo2.AddItem "MouseUp()" End Sub

Listado del Código

160

EdiOperacionesArchivo Option Explicit Public Sub EdiOperacion_abrir(formula As Form) 'Activamos la deteccion de errores y preparamos el cuadro de dialogo On Error Resume Next formula!cajacomun.FileName = "C:\Proyecto\Lienzo.frm" 'Si cancelamos la apertura del archivo salimos del procedimiento 'manteniendo el contenido If Err Then Exit Sub End If 'Variables para leer el contenido del archivo Dim nfile As Integer Dim Separador As String, LineaTexto2 As String Dim anterpuntero As Byte 'Asignamos un canal libre para leer el fichero y retorno de carro nfile = FreeFile Separador = Chr(13) + Chr(10) 'Tratamos la apariencia del puntero para cuando abrimos un archivo guardado anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass 'Abrimos el archivo de sistema donde esta guardada la informacion Open formula!cajacomun.FileName For Input As nfile If formula!cajacomun.FileName = "" Then MsgBox "No es posible abrir el dibujo elegido." Screen.MousePointer = anterpuntero Exit Sub End If 'Borramos en contenido anterior formula!RichTextBox1.Text = "" 'Cargamos el archivo On Error GoTo 0 'desactivamos los errores Do While Not EOF(nfile) Line Input #nfile, LineaTexto2 If LineaTexto2 = "'Option Explicit" Then LineaTexto3 = LineaTexto3 & LineaTexto2 & Separador Exit Do Else LineaTexto3 = LineaTexto3 & LineaTexto2 & Separador End If If Err Then MsgBox "El archivo no se ha podido leer" Exit Do End If Loop formula!RichTextBox1.Text = LineaTexto3 & Separador LineaTexto3 = "Private Sub Form_Load()" formula!RichTextBox1.Text = formula!RichTextBox1.Text & LineaTexto3 & Separador LineaTexto3 = "fichero=" & Chr(34) & nombrearchivo1 & Chr(34) formula!RichTextBox1.Text = formula!RichTextBox1.Text & LineaTexto3 & Separador LineaTexto3 = " operacion_abrir Me" formula!RichTextBox1.Text = formula!RichTextBox1.Text & LineaTexto3 & Separador LineaTexto3 = "End Sub"

Listado del Código

161

formula!RichTextBox1.Text = formula!RichTextBox1.Text & LineaTexto3 & Separador LineaTexto3 = formula!RichTextBox1.Text Close #nfile 'Restablecemos el puntero Screen.MousePointer = anterpuntero 'Desactivar deteccion de errores On Error GoTo 0 End Sub Public Sub EdiOperacion_guardar(formula As Form) 'Obtenemos el nombre del archivo formula!cajacomun.FileName = "C:\Proyecto\Lienzo.frm" 'Variables para guardar el contenido del archivo Dim nfile As Integer nfile = FreeFile 'Activar la deteccion de errores On Error Resume Next 'Intentar abrir archivo Open formula!cajacomun.FileName For Output As nfile 'Si se ha producido un error If Err Then MsgBox "El archivo no se ha podido escribir" Exit Sub End If 'Escribir lo almacenado antes de "Option Explicit" Print #nfile, LineaTexto3 & LineaTexto 'Cerrar el fichero Close #nfile 'Desactivar errores On Error GoTo 0 End Sub Public Sub nuevo(formula As Form) Dim n As Integer For n = 1 To ind Select Case indices(n): Case "D" Unload formula.Dibujo(n) Case "P" Unload formula.Pulsador(n) Case "E" Unload formula.Etiqueta(n) Case "TE" Unload formula.Texto(n) Case "T" Unload formula.Tuberia(n) Case "F" Unload formula.Figura(n) End Select Next With formula!Tapiz: .BackColor = &H80000005 .Picture = LoadPicture("") End With ind = 0 ReDim indices(0) End Sub Public Sub rejilla()

Listado del Código

162

Exit Sub End Sub

Listado del Código

163

MatadorAbrir Option Explicit 'Definiciones de constantes Public Const margen = 120 Const cursores = "C:\WINDOWS\cursores\hcross.cur" 'Definicion de variables globales Public ind As Integer, ind1 As Integer, marcador As Integer Public fichado As String Public fondo As OLE_COLOR Public moveX As Integer, moveY As Integer 'variables q utilizamos para dibujar las lineas Public iniX As Single, iniY As Single Public anterX As Single, anterY As Single 'indican el estado de la operacion para trazar una linea Public dibujando As Boolean Public entidad As Integer Public EleAncho As Integer, EleAlto As Integer Public colocX As Integer, colocY As Integer Public orientacion As String Public indices() As String Public elemento As ComboItem Public fotos As String 'para depositar ruta bitmaps Public modificado As Boolean 'mirar cambios Public respuesta Public nombrearchivo As String Public nombrearchivo1 As String Public fichero As String Public Sub operacion_abrir(formula As Form) ', nombreform As String) On Error Resume Next 'Activamos la deteccion de errores y preparamos el cuadro de dialog If formula.Name = "Lienzo" Then formula!cajacomun.FileName = fichero Else With formula.cajacomun: .DialogTitle = "Abrir dibujo" .Filter = "Archivo de sistema|*.rzd|Archivos jpeg|*.jpg|Iconos|*.ico|Meta-Archivos|*.wmf" .Flags = cdlOFNOverwritePrompt .ShowOpen End With End If 'Llamamos al procedimiento nuevo para limpiar la pantalla, si cancelamos 'la apertura del archivo salimos del procedimiento manteniendo el contenido If Err Then Exit Sub End If 'Variables para leer el contenido del archivo Dim nfile As Integer Dim ini As Integer, izq As Integer, ancho As Integer Dim estilo As Integer, i As Integer, j As Integer Dim estado As Boolean Dim anterpuntero As Byte

Listado del Código

164

Dim graf As String, appelle As String, Texto As String, fuente As String Dim arriba As Single, izquierda As Single, alto As Single, ancho1 As Single, tamañoletra As Single Dim ajuste As Boolean, habilitado As Boolean, visible As Boolean, multilinea As Boolean Dim negrita As Boolean, cursiva As Boolean, tachado As Boolean, subrayado As Boolean Dim colorfondo As Long, colortexto As Long, colormarco As Long, colorrelleno As Long Dim marco As Integer, justificado As Integer, puntero As Integer, alineacion As Integer, formato As Integer Dim detras As Integer, anchomarco As Integer, formarelleno As Integer, forma As Integer Dim nombreguerra As String, basura As String 'Forzamos q el valor de inicio de los controles sea 1 y asignamos un valor para 'abrir el canal nfile = FreeFile 'Tratamos la apariencia del puntero para cuando abrimos un archivo guardado anterpuntero = Screen.MousePointer Screen.MousePointer = vbHourglass 'Cogemos el nombre del fichero nombrearchivo = formula!cajacomun.FileName nombrearchivo1 = formula!cajacomun.FileName 'Abrimos el archivo de sistema donde esta guardada la informacion Open formula!cajacomun.FileName For Input As nfile If formula!cajacomun.FileName = "" Then MsgBox "No es posible abrir el dibujo elegido." Screen.MousePointer = anterpuntero Exit Sub End If On Error GoTo 0 'desactivamos los errores 'Cargamos la imagen de fondo o en su defecto el color de fondo Input #nfile, fotos, fondo With formula!Tapiz: .Picture = LoadPicture(fotos) .BackColor = fondo End With 'Cargamos el archivo Do While Not EOF(nfile) Input #nfile, appelle, nombreguerra Select Case appelle: Case "D" ind = ind + 1 Input #nfile, ini, izq, graf, alto, ancho1, estado Load formula!Dibujo(ind) With formula!Dibujo(ind): .Identificador = appelle: .Alias = nombreguerra: .Top = ini: .Left = izq .Pintura = graf: .alto = alto: .ancho = ancho1: .visible = estado End With ReDim Preserve indices(ind) indices(ind) = appelle

Listado del Código

165

formula!Tapiz.BackColor = fondo Case "T" ind = ind + 1 Input #nfile, ini, izq, estilo, ancho, estado Load formula!Tuberia(ind) With formula!Tuberia(ind): .Identificador = appelle: .Alias = nombreguerra .Top = ini: .Left = izq: .Height = estilo: .Width = ancho .visible = estado End With ReDim Preserve indices(ind) indices(ind) = appelle Case "P" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, Texto, habilitado Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, puntero, visible Load formula!Pulsador(ind) With formula!Pulsador(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .Caption = Texto: .Enabled = habilitado .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .MousePointer = puntero: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle Case "F" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, detras, colormarco, marco, anchomarco Input #nfile, colorrelleno, formarelleno, forma, visible Load formula!Figura(ind) With formula!Figura(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .BackStyle = detras: .BorderColor = colormarco: .BorderStyle = marco .BorderWidth = anchomarco: .FillColor = colorrelleno: .FillStyle = formarelleno .Shape = forma: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle Case "E" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, ajuste, colorfondo, detras, marco, Texto, habilitado, justificado Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, colortexto, puntero, visible, multilinea Load formula!Etiqueta(ind)

Listado del Código

166

With formula!Etiqueta(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .AutoSize = ajuste: .BackColor = colorfondo: .BackStyle = detras: .BorderStyle = marco: .Caption = Texto .Enabled = habilitado: .Alignment = justificado: .Font = fuente: .FontSize = tamañoletra .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .ForeColor = colortexto: .MousePointer = puntero: .visible = visible: .WordWrap = multilinea End With ReDim Preserve indices(ind) indices(ind) = appelle Case "TE" ind = ind + 1 Input #nfile, arriba, izquierda, alto, ancho1 Input #nfile, colorfondo, marco, Texto, habilitado, justificado, formato Input #nfile, fuente, tamañoletra, negrita, cursiva, tachado, subrayado Input #nfile, colortexto, puntero, visible Load formula!Texto(ind) With formula!Texto(ind): .Identificador = appelle: .Alias = nombreguerra .Top = arriba: .Left = izquierda: .alto = alto: .ancho = ancho1 .BackColor = colorfondo: .BorderStyle = marco: .Text = Texto .Enabled = habilitado: .Alignment = justificado: .Appearance = formato: .Font = fuente: .FontSize = tamañoletra .FontBold = negrita: .FontItalic = cursiva: .FontStrikethru = tachado: .FontUnderline = subrayado .ForeColor = colortexto: .MousePointer = puntero: .visible = visible End With ReDim Preserve indices(ind) indices(ind) = appelle End Select Loop Close nfile 'cerramos el canal de lectura 'Restablecemos el puntero Screen.MousePointer = anterpuntero End Sub Public Sub extraer_cadena(cad As String) Dim i As Integer i = Len(cad) cad = Right(cad, i - 5) i = Len(cad) cad = Left(cad, i - 1) End Sub

Listado del Código

167

Control ActiveX (DIBUJO) Option Explicit 'Default Property Values: Const m_def_BackStyle = 0 'Property Variables: Dim m_BackStyle As Integer Dim m_nombre As String Dim m_pintura As String Dim vindice As Integer Dim venlace As String 'Event Declarations: Event Click() 'MappingInfo=Picture1,Picture1,-1,Click Event DblClick() 'MappingInfo=Picture1,Picture1,-1,DblClick Event KeyDown(KeyCode As Integer, Shift As Integer) 'MappingInfo=Picture1,Picture1,-1,KeyDown Event KeyPress(KeyAscii As Integer) 'MappingInfo=Picture1,Picture1,-1,KeyPress Event KeyUp(KeyCode As Integer, Shift As Integer) 'MappingInfo=Picture1,Picture1,-1,KeyUp Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Picture1,Picture1,-1,MouseDown Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Picture1,Picture1,-1,MouseMove Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Picture1,Picture1,-1,MouseUp Event Change() 'MappingInfo=Picture1,Picture1,-1,Change Event OLECompleteDrag(Effect As Long) 'MappingInfo=Picture1,Picture1,-1,OLECompleteDrag Event OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Picture1,Picture1,-1,OLEDragDrop Event OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) 'MappingInfo=Picture1,Picture1,-1,OLEDragOver Event OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) 'MappingInfo=Picture1,Picture1,-1,OLEGiveFeedback Event OLESetData(Data As DataObject, DataFormat As Integer) 'MappingInfo=Picture1,Picture1,-1,OLESetData Event OLEStartDrag(Data As DataObject, AllowedEffects As Long) 'MappingInfo=Picture1,Picture1,-1,OLEStartDrag Event Paint() 'MappingInfo=Picture1,Picture1,-1,Paint Event Resize() 'MappingInfo=Picture1,Picture1,-1,Resize Event Validate(Cancel As Boolean) 'MappingInfo=Picture1,Picture1,-1,Validate Public Property Get tubXQ1() As Integer tubXQ1 = vtubXQ1 End Property Public Property Let tubXQ1(numero As Integer) vtubXQ1 = numero PropertyChanged "tubXQ1" Refresh End Property Public Property Get tubYQ1() As Integer tubYQ1 = vtubYQ1 End Property Public Property Let tubYQ1(numero As Integer) vtubYQ1 = numero

Listado del Código

168

PropertyChanged "tubYQ1" Refresh End Property Public Property Get enlace() As String enlace = venlace End Property Public Property Let enlace(eleccion As String) venlace = eleccion PropertyChanged "enlace" Refresh End Property Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" Refresh End Property Public Property Get Ancho() As Single Ancho = Picture1.Width 'm_ancho End Property Public Property Let Ancho(ByVal numero As Single) Picture1.Width = numero PropertyChanged "Ancho" UserControl.Width = Picture1.Width End Property Public Property Get Alto() As Single Alto = Picture1.Height 'm_alto End Property Public Property Let Alto(ByVal numero As Single) Picture1.Height = numero PropertyChanged "Alto" UserControl.Height = Picture1.Height End Property Public Property Get Pintura() As String Pintura = m_pintura End Property Public Property Let Pintura(eleccion As String) m_pintura = eleccion PropertyChanged "Pintura" Picture1.Picture = LoadPicture(eleccion) UserControl.Height = 1810 'Picture1.Height UserControl.Width = 1810 'Picture1.Width Refresh End Property Public Property Get indice() As Integer indice = vindice End Property Public Property Let indice(numero As Integer) vindice = numero PropertyChanged "indice" Refresh End Property Public Property Get BackColor() As OLE_COLOR BackColor = Picture1.BackColor

Listado del Código

169

End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Picture1.BackColor() = New_BackColor PropertyChanged "BackColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ForeColor Public Property Get ForeColor() As OLE_COLOR ForeColor = Picture1.ForeColor End Property Public Property Let ForeColor(ByVal New_ForeColor As OLE_COLOR) Picture1.ForeColor() = New_ForeColor PropertyChanged "ForeColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Enabled Public Property Get Enabled() As Boolean Enabled = Picture1.Enabled End Property Public Property Let Enabled(ByVal New_Enabled As Boolean) Picture1.Enabled() = New_Enabled PropertyChanged "Enabled" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Font Public Property Get Font() As Font Set Font = Picture1.Font End Property Public Property Set Font(ByVal New_Font As Font) Set Picture1.Font = New_Font PropertyChanged "Font" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=7,0,0,0 Public Property Get BackStyle() As Integer BackStyle = m_BackStyle End Property Public Property Let BackStyle(ByVal New_BackStyle As Integer) m_BackStyle = New_BackStyle PropertyChanged "BackStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,BorderStyle Public Property Get BorderStyle() As Integer BorderStyle = Picture1.BorderStyle End Property Public Property Let BorderStyle(ByVal New_BorderStyle As Integer) Picture1.BorderStyle() = New_BorderStyle PropertyChanged "BorderStyle" End Property

Listado del Código

170

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Refresh Public Sub Refresh() Picture1.Refresh End Sub Private Sub Picture1_Click() RaiseEvent Click End Sub Private Sub Picture1_DblClick() RaiseEvent DblClick End Sub Private Sub Picture1_KeyDown(KeyCode As Integer, Shift As Integer) RaiseEvent KeyDown(KeyCode, Shift) End Sub Private Sub Picture1_KeyPress(KeyAscii As Integer) RaiseEvent KeyPress(KeyAscii) End Sub Private Sub Picture1_KeyUp(KeyCode As Integer, Shift As Integer) RaiseEvent KeyUp(KeyCode, Shift) End Sub Private Sub Picture1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y) End Sub Private Sub Picture1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub Picture1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Align Public Property Get Align() As Integer Align = Picture1.Align End Property Public Property Let Align(ByVal New_Align As Integer) Picture1.Align() = New_Align PropertyChanged "Align" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Appearance Public Property Get Appearance() As Integer Appearance = Picture1.Appearance End Property Public Property Let Appearance(ByVal New_Appearance As Integer) Picture1.Appearance() = New_Appearance

Listado del Código

171

PropertyChanged "Appearance" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,AutoRedraw Public Property Get AutoRedraw() As Boolean AutoRedraw = Picture1.AutoRedraw End Property Public Property Let AutoRedraw(ByVal New_AutoRedraw As Boolean) Picture1.AutoRedraw() = New_AutoRedraw PropertyChanged "AutoRedraw" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,AutoSize Public Property Get AutoSize() As Boolean AutoSize = Picture1.AutoSize End Property Public Property Let AutoSize(ByVal New_AutoSize As Boolean) Picture1.AutoSize() = New_AutoSize PropertyChanged "AutoSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,CausesValidation Public Property Get CausesValidation() As Boolean CausesValidation = Picture1.CausesValidation End Property Public Property Let CausesValidation(ByVal New_CausesValidation As Boolean) Picture1.CausesValidation() = New_CausesValidation PropertyChanged "CausesValidation" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ClipControls Public Property Get ClipControls() As Boolean ClipControls = Picture1.ClipControls End Property Public Property Let ClipControls(ByVal New_ClipControls As Boolean) Picture1.ClipControls() = New_ClipControls PropertyChanged "ClipControls" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,CurrentX Public Property Get CurrentX() As Single CurrentX = Picture1.CurrentX End Property Public Property Let CurrentX(ByVal New_CurrentX As Single) Picture1.CurrentX() = New_CurrentX PropertyChanged "CurrentX" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,CurrentY

Listado del Código

172

Public Property Get CurrentY() As Single CurrentY = Picture1.CurrentY End Property Public Property Let CurrentY(ByVal New_CurrentY As Single) Picture1.CurrentY() = New_CurrentY PropertyChanged "CurrentY" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,DataMember Public Property Get DataMember() As String DataMember = Picture1.DataMember End Property Public Property Let DataMember(ByVal New_DataMember As String) Picture1.DataMember() = New_DataMember PropertyChanged "DataMember" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,DrawMode Public Property Get DrawMode() As Integer DrawMode = Picture1.DrawMode End Property Public Property Let DrawMode(ByVal New_DrawMode As Integer) Picture1.DrawMode() = New_DrawMode PropertyChanged "DrawMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,DrawStyle Public Property Get DrawStyle() As Integer DrawStyle = Picture1.DrawStyle End Property Public Property Let DrawStyle(ByVal New_DrawStyle As Integer) Picture1.DrawStyle() = New_DrawStyle PropertyChanged "DrawStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,DrawWidth Public Property Get DrawWidth() As Integer DrawWidth = Picture1.DrawWidth End Property Public Property Let DrawWidth(ByVal New_DrawWidth As Integer) Picture1.DrawWidth() = New_DrawWidth PropertyChanged "DrawWidth" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FillColor Public Property Get FillColor() As OLE_COLOR FillColor = Picture1.FillColor End Property Public Property Let FillColor(ByVal New_FillColor As OLE_COLOR) Picture1.FillColor() = New_FillColor

Listado del Código

173

PropertyChanged "FillColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FillStyle Public Property Get FillStyle() As Integer FillStyle = Picture1.FillStyle End Property Public Property Let FillStyle(ByVal New_FillStyle As Integer) Picture1.FillStyle() = New_FillStyle PropertyChanged "FillStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontBold Public Property Get FontBold() As Boolean FontBold = Picture1.FontBold End Property Public Property Let FontBold(ByVal New_FontBold As Boolean) Picture1.FontBold() = New_FontBold PropertyChanged "FontBold" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontItalic Public Property Get FontItalic() As Boolean FontItalic = Picture1.FontItalic End Property Public Property Let FontItalic(ByVal New_FontItalic As Boolean) Picture1.FontItalic() = New_FontItalic PropertyChanged "FontItalic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontName Public Property Get FontName() As String FontName = Picture1.FontName End Property Public Property Let FontName(ByVal New_FontName As String) Picture1.FontName() = New_FontName PropertyChanged "FontName" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontSize Public Property Get FontSize() As Single FontSize = Picture1.FontSize End Property Public Property Let FontSize(ByVal New_FontSize As Single) Picture1.FontSize() = New_FontSize PropertyChanged "FontSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontStrikethru Public Property Get FontStrikethru() As Boolean

Listado del Código

174

FontStrikethru = Picture1.FontStrikethru End Property Public Property Let FontStrikethru(ByVal New_FontStrikethru As Boolean) Picture1.FontStrikethru() = New_FontStrikethru PropertyChanged "FontStrikethru" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontTransparent Public Property Get FontTransparent() As Boolean FontTransparent = Picture1.FontTransparent End Property Public Property Let FontTransparent(ByVal New_FontTransparent As Boolean) Picture1.FontTransparent() = New_FontTransparent PropertyChanged "FontTransparent" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,FontUnderline Public Property Get FontUnderline() As Boolean FontUnderline = Picture1.FontUnderline End Property Public Property Let FontUnderline(ByVal New_FontUnderline As Boolean) Picture1.FontUnderline() = New_FontUnderline PropertyChanged "FontUnderline" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,HasDC Public Property Get HasDC() As Boolean HasDC = Picture1.HasDC End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,hDC Public Property Get hDC() As Long hDC = Picture1.hDC End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,hWnd Public Property Get hWnd() As Long hWnd = Picture1.hWnd End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Image Public Property Get Image() As Picture Set Image = Picture1.Image End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkItem Public Property Get LinkItem() As String LinkItem = Picture1.LinkItem End Property Public Property Let LinkItem(ByVal New_LinkItem As String)

Listado del Código

175

Picture1.LinkItem() = New_LinkItem PropertyChanged "LinkItem" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkMode Public Property Get LinkMode() As Integer LinkMode = Picture1.LinkMode End Property Public Property Let LinkMode(ByVal New_LinkMode As Integer) Picture1.LinkMode() = New_LinkMode PropertyChanged "LinkMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkTimeout Public Property Get LinkTimeout() As Integer LinkTimeout = Picture1.LinkTimeout End Property Public Property Let LinkTimeout(ByVal New_LinkTimeout As Integer) Picture1.LinkTimeout() = New_LinkTimeout PropertyChanged "LinkTimeout" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkTopic Public Property Get LinkTopic() As String LinkTopic = Picture1.LinkTopic End Property Public Property Let LinkTopic(ByVal New_LinkTopic As String) Picture1.LinkTopic() = New_LinkTopic PropertyChanged "LinkTopic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,MouseIcon Public Property Get MouseIcon() As Picture Set MouseIcon = Picture1.MouseIcon End Property Public Property Set MouseIcon(ByVal New_MouseIcon As Picture) Set Picture1.MouseIcon = New_MouseIcon PropertyChanged "MouseIcon" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,MousePointer Public Property Get MousePointer() As Integer MousePointer = Picture1.MousePointer End Property Public Property Let MousePointer(ByVal New_MousePointer As Integer) Picture1.MousePointer() = New_MousePointer PropertyChanged "MousePointer" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,OLEDragMode

Listado del Código

176

Public Property Get OLEDragMode() As Integer OLEDragMode = Picture1.OLEDragMode End Property Public Property Let OLEDragMode(ByVal New_OLEDragMode As Integer) Picture1.OLEDragMode() = New_OLEDragMode PropertyChanged "OLEDragMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,OLEDropMode Public Property Get OLEDropMode() As Integer OLEDropMode = Picture1.OLEDropMode End Property Public Property Let OLEDropMode(ByVal New_OLEDropMode As Integer) Picture1.OLEDropMode() = New_OLEDropMode PropertyChanged "OLEDropMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Picture Public Property Get Picture() As Picture Set Picture = Picture1.Picture End Property Public Property Let Picture(ByVal New_Picture As Picture) Set Picture1.Picture = New_Picture PropertyChanged "Picture" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,RightToLeft Public Property Get RightToLeft() As Boolean RightToLeft = Picture1.RightToLeft End Property Public Property Let RightToLeft(ByVal New_RightToLeft As Boolean) Picture1.RightToLeft() = New_RightToLeft PropertyChanged "RightToLeft" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleHeight Public Property Get ScaleHeight() As Single ScaleHeight = Picture1.ScaleHeight End Property Public Property Let ScaleHeight(ByVal New_ScaleHeight As Single) Picture1.ScaleHeight() = New_ScaleHeight PropertyChanged "ScaleHeight" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleLeft Public Property Get ScaleLeft() As Single ScaleLeft = Picture1.ScaleLeft End Property Public Property Let ScaleLeft(ByVal New_ScaleLeft As Single) Picture1.ScaleLeft() = New_ScaleLeft

Listado del Código

177

PropertyChanged "ScaleLeft" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleMode Public Property Get ScaleMode() As Integer ScaleMode = Picture1.ScaleMode End Property Public Property Let ScaleMode(ByVal New_ScaleMode As Integer) Picture1.ScaleMode() = New_ScaleMode PropertyChanged "ScaleMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleTop Public Property Get ScaleTop() As Single ScaleTop = Picture1.ScaleTop End Property Public Property Let ScaleTop(ByVal New_ScaleTop As Single) Picture1.ScaleTop() = New_ScaleTop PropertyChanged "ScaleTop" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleWidth Public Property Get ScaleWidth() As Single ScaleWidth = Picture1.ScaleWidth End Property Public Property Let ScaleWidth(ByVal New_ScaleWidth As Single) Picture1.ScaleWidth() = New_ScaleWidth PropertyChanged "ScaleWidth" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ToolTipText Public Property Get ToolTipText() As String ToolTipText = Picture1.ToolTipText End Property Public Property Let ToolTipText(ByVal New_ToolTipText As String) Picture1.ToolTipText() = New_ToolTipText PropertyChanged "ToolTipText" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,WhatsThisHelpID Public Property Get WhatsThisHelpID() As Long WhatsThisHelpID = Picture1.WhatsThisHelpID End Property Public Property Let WhatsThisHelpID(ByVal New_WhatsThisHelpID As Long) Picture1.WhatsThisHelpID() = New_WhatsThisHelpID PropertyChanged "WhatsThisHelpID" End Property 'The Underscore following "Circle" is necessary because it 'is a Reserved Word in VBA. 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!

Listado del Código

178

'MappingInfo=Picture1,Picture1,-1,Circle Public Sub Circle_(X As Single, Y As Single, Radius As Single, Color As Long, StartPos As Single, EndPos As Single, Aspect As Single) Picture1.Circle (X, Y), Radius, Color, StartPos, EndPos, Aspect End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Cls Public Sub Cls() Picture1.Cls End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Line Public Sub Line(ByVal Flags As Integer, ByVal X1 As Single, ByVal Y1 As Single, ByVal X2 As Single, ByVal Y2 As Single, ByVal Color As Long) 'Picture1.Line Flags,X1,Y1,X2,Y2,Color End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkExecute Public Sub LinkExecute(ByVal Command As String) Picture1.LinkExecute Command End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkPoke Public Sub LinkPoke() Picture1.LinkPoke End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkRequest Public Sub LinkRequest() Picture1.LinkRequest End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,LinkSend Public Sub LinkSend() Picture1.LinkSend End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,OLEDrag Public Sub OLEDrag() Picture1.OLEDrag End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,PaintPicture Public Sub PaintPicture(ByVal Picture As Picture, ByVal X1 As Single, ByVal Y1 As Single, Optional ByVal Width1 As Variant, Optional ByVal Height1 As Variant, Optional ByVal X2 As Variant, Optional ByVal Y2 As Variant, Optional ByVal Width2 As Variant, Optional ByVal Height2 As Variant, Optional ByVal Opcode As Variant) Picture1.PaintPicture Picture, X1, Y1, Width1, Height1, X2, Y2, Width2, Height2, Opcode End Sub 'The Underscore following "Point" is necessary because it

Listado del Código

179

'is a Reserved Word in VBA. 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Point Public Function Point(X As Single, Y As Single) As Long Point = Picture1.Point(X, Y) End Function 'The Underscore following "PSet" is necessary because it 'is a Reserved Word in VBA. 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,PSet Public Sub PSet_(X As Single, Y As Single, Color As Long) Picture1.PSet Step(X, Y), Color End Sub 'The Underscore following "Scale" is necessary because it 'is a Reserved Word in VBA. 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,Scale Public Sub Scale_(Optional X1 As Variant, Optional Y1 As Variant, Optional X2 As Variant, Optional Y2 As Variant) Picture1.Scale (X1, Y1)-(X2, Y2) End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleX Public Function ScaleX(ByVal Width As Single, Optional ByVal FromScale As Variant, Optional ByVal ToScale As Variant) As Single ScaleX = Picture1.ScaleX(Width, FromScale, ToScale) End Function 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,ScaleY Public Function ScaleY(ByVal Height As Single, Optional ByVal FromScale As Variant, Optional ByVal ToScale As Variant) As Single ScaleY = Picture1.ScaleY(Height, FromScale, ToScale) End Function 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,TextHeight Public Function TextHeight(ByVal Str As String) As Single TextHeight = Picture1.TextHeight(Str) End Function 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Picture1,Picture1,-1,TextWidth Public Function TextWidth(ByVal Str As String) As Single TextWidth = Picture1.TextWidth(Str) End Function Private Sub Picture1_Change() RaiseEvent Change End Sub Private Sub Picture1_OLECompleteDrag(Effect As Long) RaiseEvent OLECompleteDrag(Effect) End Sub Private Sub Picture1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent OLEDragDrop(Data, Effect, Button, Shift, X, Y)

Listado del Código

180

End Sub Private Sub Picture1_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) RaiseEvent OLEDragOver(Data, Effect, Button, Shift, X, Y, State) End Sub Private Sub Picture1_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) RaiseEvent OLEGiveFeedback(Effect, DefaultCursors) End Sub Private Sub Picture1_OLESetData(Data As DataObject, DataFormat As Integer) RaiseEvent OLESetData(Data, DataFormat) End Sub Private Sub Picture1_OLEStartDrag(Data As DataObject, AllowedEffects As Long) RaiseEvent OLEStartDrag(Data, AllowedEffects) End Sub Private Sub Picture1_Paint() RaiseEvent Paint End Sub Private Sub Picture1_Resize() RaiseEvent Resize End Sub Private Sub Picture1_Validate(Cancel As Boolean) RaiseEvent Validate(Cancel) End Sub 'Initialize Properties for User Control Private Sub UserControl_InitProperties() m_BackStyle = m_def_BackStyle End Sub 'Load property values from storage Private Sub UserControl_ReadProperties(PropBag As PropertyBag) Picture1.BackColor = PropBag.ReadProperty("BackColor", &H8000000F) Picture1.ForeColor = PropBag.ReadProperty("ForeColor", &H80000012) Picture1.Enabled = PropBag.ReadProperty("Enabled", True) Set Picture1.Font = PropBag.ReadProperty("Font", Ambient.Font) m_BackStyle = PropBag.ReadProperty("BackStyle", m_def_BackStyle) Picture1.BorderStyle = PropBag.ReadProperty("BorderStyle", 1) Picture1.Align = PropBag.ReadProperty("Align", 0) Picture1.Appearance = PropBag.ReadProperty("Appearance", 1) Picture1.AutoRedraw = PropBag.ReadProperty("AutoRedraw", False) Picture1.AutoSize = PropBag.ReadProperty("AutoSize", False) Picture1.CausesValidation = PropBag.ReadProperty("CausesValidation", True) Picture1.ClipControls = PropBag.ReadProperty("ClipControls", True) Picture1.CurrentX = PropBag.ReadProperty("CurrentX", 0) Picture1.CurrentY = PropBag.ReadProperty("CurrentY", 0) Picture1.DataMember = PropBag.ReadProperty("DataMember", "") Picture1.DrawMode = PropBag.ReadProperty("DrawMode", 13) Picture1.DrawStyle = PropBag.ReadProperty("DrawStyle", 0)

Listado del Código

181

Picture1.DrawWidth = PropBag.ReadProperty("DrawWidth", 1) Picture1.FillColor = PropBag.ReadProperty("FillColor", &H0&) Picture1.FillStyle = PropBag.ReadProperty("FillStyle", 1) Picture1.FontBold = PropBag.ReadProperty("FontBold", 0) Picture1.FontItalic = PropBag.ReadProperty("FontItalic", 0) Picture1.FontStrikethru = PropBag.ReadProperty("FontStrikethru", 0) Picture1.FontTransparent = PropBag.ReadProperty("FontTransparent", True) Picture1.FontUnderline = PropBag.ReadProperty("FontUnderline", 0) Picture1.LinkItem = PropBag.ReadProperty("LinkItem", "") Picture1.LinkMode = PropBag.ReadProperty("LinkMode", 0) Picture1.LinkTimeout = PropBag.ReadProperty("LinkTimeout", 50) Picture1.LinkTopic = PropBag.ReadProperty("LinkTopic", "") Set MouseIcon = PropBag.ReadProperty("MouseIcon", Nothing) Picture1.MousePointer = PropBag.ReadProperty("MousePointer", 0) Picture1.OLEDragMode = PropBag.ReadProperty("OLEDragMode", 0) Picture1.OLEDropMode = PropBag.ReadProperty("OLEDropMode", 0) Picture1.RightToLeft = PropBag.ReadProperty("RightToLeft", False) Picture1.ScaleHeight = PropBag.ReadProperty("ScaleHeight", 2355) Picture1.ScaleLeft = PropBag.ReadProperty("ScaleLeft", 0) Picture1.ScaleMode = PropBag.ReadProperty("ScaleMode", 1) Picture1.ScaleTop = PropBag.ReadProperty("ScaleTop", 0) Picture1.ScaleWidth = PropBag.ReadProperty("ScaleWidth", 3435) Picture1.ToolTipText = PropBag.ReadProperty("ToolTipText", "") Picture1.WhatsThisHelpID = PropBag.ReadProperty("WhatsThisHelpID", 0) End Sub 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) Call PropBag.WriteProperty("BackColor", Picture1.BackColor, &H8000000F) Call PropBag.WriteProperty("ForeColor", Picture1.ForeColor, &H80000012) Call PropBag.WriteProperty("Enabled", Picture1.Enabled, True) Call PropBag.WriteProperty("Font", Picture1.Font, Ambient.Font) Call PropBag.WriteProperty("BackStyle", m_BackStyle, m_def_BackStyle) Call PropBag.WriteProperty("BorderStyle", Picture1.BorderStyle, 1) Call PropBag.WriteProperty("Align", Picture1.Align, 0) Call PropBag.WriteProperty("Appearance", Picture1.Appearance, 1) Call PropBag.WriteProperty("AutoRedraw", Picture1.AutoRedraw, False) Call PropBag.WriteProperty("AutoSize", Picture1.AutoSize, False) Call PropBag.WriteProperty("CausesValidation", Picture1.CausesValidation, True) Call PropBag.WriteProperty("ClipControls", Picture1.ClipControls, True) Call PropBag.WriteProperty("CurrentX", Picture1.CurrentX, 0) Call PropBag.WriteProperty("CurrentY", Picture1.CurrentY, 0) Call PropBag.WriteProperty("DataMember", Picture1.DataMember, "") Call PropBag.WriteProperty("DrawMode", Picture1.DrawMode, 13) Call PropBag.WriteProperty("DrawStyle", Picture1.DrawStyle, 0) Call PropBag.WriteProperty("DrawWidth", Picture1.DrawWidth, 1) Call PropBag.WriteProperty("FillColor", Picture1.FillColor, &H0&) Call PropBag.WriteProperty("FillStyle", Picture1.FillStyle, 1) Call PropBag.WriteProperty("FontBold", Picture1.FontBold, 0) Call PropBag.WriteProperty("FontItalic", Picture1.FontItalic, 0) Call PropBag.WriteProperty("FontName", Picture1.FontName, "") Call PropBag.WriteProperty("FontSize", Picture1.FontSize, 0) Call PropBag.WriteProperty("FontStrikethru", Picture1.FontStrikethru, 0)

Listado del Código

182

Call PropBag.WriteProperty("FontTransparent", Picture1.FontTransparent, True) Call PropBag.WriteProperty("FontUnderline", Picture1.FontUnderline, 0) Call PropBag.WriteProperty("LinkItem", Picture1.LinkItem, "") Call PropBag.WriteProperty("LinkMode", Picture1.LinkMode, 0) Call PropBag.WriteProperty("LinkTimeout", Picture1.LinkTimeout, 50) Call PropBag.WriteProperty("LinkTopic", Picture1.LinkTopic, "") Call PropBag.WriteProperty("MouseIcon", MouseIcon, Nothing) Call PropBag.WriteProperty("MousePointer", Picture1.MousePointer, 0) Call PropBag.WriteProperty("OLEDragMode", Picture1.OLEDragMode, 0) Call PropBag.WriteProperty("OLEDropMode", Picture1.OLEDropMode, 0) Call PropBag.WriteProperty("Picture", Picture, Nothing) Call PropBag.WriteProperty("RightToLeft", Picture1.RightToLeft, False) Call PropBag.WriteProperty("ScaleHeight", Picture1.ScaleHeight, 2355) Call PropBag.WriteProperty("ScaleLeft", Picture1.ScaleLeft, 0) Call PropBag.WriteProperty("ScaleMode", Picture1.ScaleMode, 1) Call PropBag.WriteProperty("ScaleTop", Picture1.ScaleTop, 0) Call PropBag.WriteProperty("ScaleWidth", Picture1.ScaleWidth, 3435) Call PropBag.WriteProperty("ToolTipText", Picture1.ToolTipText, "") Call PropBag.WriteProperty("WhatsThisHelpID", Picture1.WhatsThisHelpID, 0) End Sub

Listado del Código

183

Control ActiveX (ETIQUETA) 'Default Property Values: 'Const m_def_FontTransparent = 0 Const m_def_Identificador = "E" 'Property Variables: Dim m_FontTransparent As Boolean Dim m_nombre As String 'Event Declarations: Event Click() 'MappingInfo=Label1,Label1,-1,Click Event DblClick() 'MappingInfo=Label1,Label1,-1,DblClick Event KeyDown(KeyCode As Integer, Shift As Integer) Event KeyPress(KeyAscii As Integer) Event KeyUp(KeyCode As Integer, Shift As Integer) Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Label1,Label1,-1,MouseDown Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Label1,Label1,-1,MouseMove Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Label1,Label1,-1,MouseUp Event Change() 'MappingInfo=Label1,Label1,-1,Change Event OLECompleteDrag(Effect As Long) 'MappingInfo=Label1,Label1,-1,OLECompleteDrag Event OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Label1,Label1,-1,OLEDragDrop Event OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) 'MappingInfo=Label1,Label1,-1,OLEDragOver Event OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) 'MappingInfo=Label1,Label1,-1,OLEGiveFeedback Event OLESetData(Data As DataObject, DataFormat As Integer) 'MappingInfo=Label1,Label1,-1,OLESetData Event OLEStartDrag(Data As DataObject, AllowedEffects As Long) 'MappingInfo=Label1,Label1,-1,OLEStartDrag Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(ByVal eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" End Property Public Property Get Ancho() As Single Ancho = Label1.Width 'm_ancho End Property Public Property Let Ancho(ByVal numero As Single) Label1.Width = numero PropertyChanged "Ancho" UserControl.Width = Label1.Width End Property Public Property Get Alto() As Single Alto = Label1.Height 'm_alto End Property Public Property Let Alto(ByVal numero As Single) Label1.Height = numero PropertyChanged "Alto" UserControl.Height = Label1.Height End Property

Listado del Código

184

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,BackColor Public Property Get BackColor() As OLE_COLOR BackColor = Label1.BackColor End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Label1.BackColor() = New_BackColor PropertyChanged "BackColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,ForeColor Public Property Get ForeColor() As OLE_COLOR ForeColor = Label1.ForeColor End Property Public Property Let ForeColor(ByVal New_ForeColor As OLE_COLOR) Label1.ForeColor() = New_ForeColor PropertyChanged "ForeColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Enabled Public Property Get Enabled() As Boolean Enabled = Label1.Enabled End Property Public Property Let Enabled(ByVal New_Enabled As Boolean) Label1.Enabled() = New_Enabled PropertyChanged "Enabled" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Font Public Property Get Font() As Font Set Font = Label1.Font End Property Public Property Set Font(ByVal New_Font As Font) Set Label1.Font = New_Font PropertyChanged "Font" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,BackStyle Public Property Get BackStyle() As Integer BackStyle = Label1.BackStyle End Property Public Property Let BackStyle(ByVal New_BackStyle As Integer) Label1.BackStyle() = New_BackStyle PropertyChanged "BackStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,BorderStyle Public Property Get BorderStyle() As Integer BorderStyle = Label1.BorderStyle End Property

Listado del Código

185

Public Property Let BorderStyle(ByVal New_BorderStyle As Integer) Label1.BorderStyle() = New_BorderStyle PropertyChanged "BorderStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Refresh Public Sub Refresh() Label1.Refresh End Sub Private Sub Label1_Click() RaiseEvent Click End Sub Private Sub Label1_DblClick() RaiseEvent DblClick End Sub Private Sub Label1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y) End Sub Private Sub Label1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub Label1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Alignment Public Property Get Alignment() As Integer Alignment = Label1.Alignment End Property Public Property Let Alignment(ByVal New_Alignment As Integer) Label1.Alignment() = New_Alignment PropertyChanged "Alignment" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Appearance Public Property Get Appearance() As Integer Appearance = Label1.Appearance End Property Public Property Let Appearance(ByVal New_Appearance As Integer) 'Label1.Appearance() = New_Appearance Label1.Appearance = New_Appearance PropertyChanged "Appearance" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,AutoSize Public Property Get AutoSize() As Boolean

Listado del Código

186

AutoSize = Label1.AutoSize End Property Public Property Let AutoSize(ByVal New_AutoSize As Boolean) Label1.AutoSize() = New_AutoSize PropertyChanged "AutoSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,Caption Public Property Get Caption() As String Caption = Label1.Caption End Property Public Property Let Caption(ByVal New_Caption As String) Label1.Caption() = New_Caption PropertyChanged "Caption" End Property Private Sub Label1_Change() RaiseEvent Change End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,DataFormat 'Public Property Get DataFormat() As IStdDataFormatDisp ' Set DataFormat = Label1.DataFormat 'End Property 'Public Property Set DataFormat(ByVal New_DataFormat As IStdDataFormatDisp) ' Set Label1.DataFormat = New_DataFormat ' PropertyChanged "DataFormat" 'End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,DataMember Public Property Get DataMember() As String DataMember = Label1.DataMember End Property Public Property Let DataMember(ByVal New_DataMember As String) Label1.DataMember() = New_DataMember PropertyChanged "DataMember" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,DataSource 'Public Property Get DataSource() As DataSource ' Set DataSource = Label1.DataSource 'End Property 'Public Property Set DataSource(ByVal New_DataSource As DataSource) ' Set Label1.DataSource = New_DataSource ' PropertyChanged "DataSource" 'End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontBold Public Property Get FontBold() As Boolean FontBold = Label1.FontBold

Listado del Código

187

End Property Public Property Let FontBold(ByVal New_FontBold As Boolean) Label1.FontBold() = New_FontBold PropertyChanged "FontBold" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontItalic Public Property Get FontItalic() As Boolean FontItalic = Label1.FontItalic End Property Public Property Let FontItalic(ByVal New_FontItalic As Boolean) Label1.FontItalic() = New_FontItalic PropertyChanged "FontItalic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontName Public Property Get FontName() As String FontName = Label1.FontName End Property Public Property Let FontName(ByVal New_FontName As String) Label1.FontName() = New_FontName PropertyChanged "FontName" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontSize Public Property Get FontSize() As Single FontSize = Label1.FontSize End Property Public Property Let FontSize(ByVal New_FontSize As Single) Label1.FontSize() = New_FontSize PropertyChanged "FontSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontStrikethru Public Property Get FontStrikethru() As Boolean FontStrikethru = Label1.FontStrikethru End Property Public Property Let FontStrikethru(ByVal New_FontStrikethru As Boolean) Label1.FontStrikethru() = New_FontStrikethru PropertyChanged "FontStrikethru" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=0,0,0,0 Public Property Get FontTransparent() As Boolean FontTransparent = m_FontTransparent End Property Public Property Let FontTransparent(ByVal New_FontTransparent As Boolean) m_FontTransparent = New_FontTransparent PropertyChanged "FontTransparent" End Property

Listado del Código

188

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,FontUnderline Public Property Get FontUnderline() As Boolean FontUnderline = Label1.FontUnderline End Property Public Property Let FontUnderline(ByVal New_FontUnderline As Boolean) Label1.FontUnderline() = New_FontUnderline PropertyChanged "FontUnderline" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkItem Public Property Get LinkItem() As String LinkItem = Label1.LinkItem End Property Public Property Let LinkItem(ByVal New_LinkItem As String) Label1.LinkItem() = New_LinkItem PropertyChanged "LinkItem" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkMode Public Property Get LinkMode() As Integer LinkMode = Label1.LinkMode End Property Public Property Let LinkMode(ByVal New_LinkMode As Integer) Label1.LinkMode() = New_LinkMode PropertyChanged "LinkMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkTimeout Public Property Get LinkTimeout() As Integer LinkTimeout = Label1.LinkTimeout End Property Public Property Let LinkTimeout(ByVal New_LinkTimeout As Integer) Label1.LinkTimeout() = New_LinkTimeout PropertyChanged "LinkTimeout" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkTopic Public Property Get LinkTopic() As String LinkTopic = Label1.LinkTopic End Property Public Property Let LinkTopic(ByVal New_LinkTopic As String) Label1.LinkTopic() = New_LinkTopic PropertyChanged "LinkTopic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,MouseIcon Public Property Get MouseIcon() As Picture Set MouseIcon = Label1.MouseIcon End Property

Listado del Código

189

Public Property Set MouseIcon(ByVal New_MouseIcon As Picture) Set Label1.MouseIcon = New_MouseIcon PropertyChanged "MouseIcon" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,MousePointer Public Property Get MousePointer() As Integer MousePointer = Label1.MousePointer End Property Public Property Let MousePointer(ByVal New_MousePointer As Integer) Label1.MousePointer() = New_MousePointer PropertyChanged "MousePointer" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,OLEDropMode Public Property Get OLEDropMode() As Integer OLEDropMode = Label1.OLEDropMode End Property Public Property Let OLEDropMode(ByVal New_OLEDropMode As Integer) Label1.OLEDropMode() = New_OLEDropMode PropertyChanged "OLEDropMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,RightToLeft Public Property Get RightToLeft() As Boolean RightToLeft = Label1.RightToLeft End Property Public Property Let RightToLeft(ByVal New_RightToLeft As Boolean) Label1.RightToLeft() = New_RightToLeft PropertyChanged "RightToLeft" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,ToolTipText Public Property Get ToolTipText() As String ToolTipText = Label1.ToolTipText End Property Public Property Let ToolTipText(ByVal New_ToolTipText As String) Label1.ToolTipText() = New_ToolTipText PropertyChanged "ToolTipText" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,UseMnemonic Public Property Get UseMnemonic() As Boolean UseMnemonic = Label1.UseMnemonic End Property Public Property Let UseMnemonic(ByVal New_UseMnemonic As Boolean) Label1.UseMnemonic() = New_UseMnemonic PropertyChanged "UseMnemonic" End Property

Listado del Código

190

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,WhatsThisHelpID Public Property Get WhatsThisHelpID() As Long WhatsThisHelpID = Label1.WhatsThisHelpID End Property Public Property Let WhatsThisHelpID(ByVal New_WhatsThisHelpID As Long) Label1.WhatsThisHelpID() = New_WhatsThisHelpID PropertyChanged "WhatsThisHelpID" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,WordWrap Public Property Get WordWrap() As Boolean WordWrap = Label1.WordWrap End Property Public Property Let WordWrap(ByVal New_WordWrap As Boolean) Label1.WordWrap() = New_WordWrap PropertyChanged "WordWrap" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkExecute Public Sub LinkExecute(ByVal Command As String) Label1.LinkExecute Command End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkPoke Public Sub LinkPoke() Label1.LinkPoke End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkRequest Public Sub LinkRequest() Label1.LinkRequest End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,LinkSend Public Sub LinkSend() Label1.LinkSend End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Label1,Label1,-1,OLEDrag Public Sub OLEDrag() Label1.OLEDrag End Sub Private Sub Label1_OLECompleteDrag(Effect As Long) RaiseEvent OLECompleteDrag(Effect) End Sub Private Sub Label1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent OLEDragDrop(Data, Effect, Button, Shift, X, Y) End Sub

Listado del Código

191

Private Sub Label1_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) RaiseEvent OLEDragOver(Data, Effect, Button, Shift, X, Y, State) End Sub Private Sub Label1_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) RaiseEvent OLEGiveFeedback(Effect, DefaultCursors) End Sub Private Sub Label1_OLESetData(Data As DataObject, DataFormat As Integer) RaiseEvent OLESetData(Data, DataFormat) End Sub Private Sub Label1_OLEStartDrag(Data As DataObject, AllowedEffects As Long) RaiseEvent OLEStartDrag(Data, AllowedEffects) End Sub 'Initialize Properties for User Control Private Sub UserControl_InitProperties() m_FontTransparent = m_def_FontTransparent End Sub 'Load property values from storage Private Sub UserControl_ReadProperties(PropBag As PropertyBag) Label1.BackColor = PropBag.ReadProperty("BackColor", &H8000000F) Label1.ForeColor = PropBag.ReadProperty("ForeColor", &H0) '&H80000012) Label1.Enabled = PropBag.ReadProperty("Enabled", True) Set Label1.Font = PropBag.ReadProperty("Font", Ambient.Font) 'Label1.BackStyle = PropBag.ReadProperty("BackStyle", 1) Label1.BorderStyle = PropBag.ReadProperty("BorderStyle", 0) Label1.Alignment = PropBag.ReadProperty("Alignment", 0) 'Label1.Appearance = PropBag.ReadProperty("Appearance", 1) Label1.AutoSize = PropBag.ReadProperty("AutoSize", False) Label1.Caption = PropBag.ReadProperty("Caption", "") ' "Label1") Set DataFormat = PropBag.ReadProperty("DataFormat", Nothing) Label1.DataMember = PropBag.ReadProperty("DataMember", "") Set DataSource = PropBag.ReadProperty("DataSource", Nothing) Label1.FontBold = PropBag.ReadProperty("FontBold", 0) Label1.FontItalic = PropBag.ReadProperty("FontItalic", 0) Label1.FontName = PropBag.ReadProperty("FontName", "") Label1.FontSize = PropBag.ReadProperty("FontSize", 0) Label1.FontStrikethru = PropBag.ReadProperty("FontStrikethru", 0) m_FontTransparent = PropBag.ReadProperty("FontTransparent", 0) ' m_def_FontTransparent) Label1.FontUnderline = PropBag.ReadProperty("FontUnderline", 0) Label1.LinkItem = PropBag.ReadProperty("LinkItem", "") Label1.LinkMode = PropBag.ReadProperty("LinkMode", 0) Label1.LinkTimeout = PropBag.ReadProperty("LinkTimeout", 50) Label1.LinkTopic = PropBag.ReadProperty("LinkTopic", "") Set MouseIcon = PropBag.ReadProperty("MouseIcon", Nothing) Label1.MousePointer = PropBag.ReadProperty("MousePointer", 0) Label1.OLEDropMode = PropBag.ReadProperty("OLEDropMode", 0) Label1.RightToLeft = PropBag.ReadProperty("RightToLeft", False) Label1.ToolTipText = PropBag.ReadProperty("ToolTipText", "Label1") Label1.UseMnemonic = PropBag.ReadProperty("UseMnemonic", True) Label1.WhatsThisHelpID = PropBag.ReadProperty("WhatsThisHelpID", 0) Label1.WordWrap = PropBag.ReadProperty("WordWrap", False)

Listado del Código

192

m_nombre = PropBag.ReadProperty("Identificador", m_def_Identificador) Label1.Height = PropBag.ReadProperty("Alto", 370) Label1.Width = PropBag.ReadProperty("Ancho", 1210) End Sub 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) Call PropBag.WriteProperty("BackColor", Label1.BackColor, &H8000000F) Call PropBag.WriteProperty("ForeColor", Label1.ForeColor, &H0) '&H80000012) Call PropBag.WriteProperty("Enabled", Label1.Enabled, True) Call PropBag.WriteProperty("Font", Label1.Font, Ambient.Font) 'Call PropBag.WriteProperty("BackStyle", Label1.BackStyle, 1) Call PropBag.WriteProperty("BorderStyle", Label1.BorderStyle, 0) Call PropBag.WriteProperty("Alignment", Label1.Alignment, 2) 'Call PropBag.WriteProperty("Appearance", Label1.Appearance, 1) Call PropBag.WriteProperty("AutoSize", Label1.AutoSize, False) Call PropBag.WriteProperty("Caption", Label1.Caption, "") '"Label1") Call PropBag.WriteProperty("DataFormat", DataFormat, Nothing) Call PropBag.WriteProperty("DataMember", Label1.DataMember, "") Call PropBag.WriteProperty("DataSource", DataSource, Nothing) Call PropBag.WriteProperty("FontBold", Label1.FontBold, 0) Call PropBag.WriteProperty("FontItalic", Label1.FontItalic, 0) Call PropBag.WriteProperty("FontName", Label1.FontName, "") Call PropBag.WriteProperty("FontSize", Label1.FontSize, 0) Call PropBag.WriteProperty("FontStrikethru", Label1.FontStrikethru, 0) Call PropBag.WriteProperty("FontTransparent", m_FontTransparent, 0) ' m_def_FontTransparent) Call PropBag.WriteProperty("FontUnderline", Label1.FontUnderline, 0) Call PropBag.WriteProperty("LinkItem", Label1.LinkItem, "") Call PropBag.WriteProperty("LinkMode", Label1.LinkMode, 0) Call PropBag.WriteProperty("LinkTimeout", Label1.LinkTimeout, 50) Call PropBag.WriteProperty("LinkTopic", Label1.LinkTopic, "") Call PropBag.WriteProperty("MouseIcon", MouseIcon, Nothing) Call PropBag.WriteProperty("MousePointer", Label1.MousePointer, 0) Call PropBag.WriteProperty("OLEDropMode", Label1.OLEDropMode, 0) Call PropBag.WriteProperty("RightToLeft", Label1.RightToLeft, False) Call PropBag.WriteProperty("ToolTipText", Label1.ToolTipText, "Label1") Call PropBag.WriteProperty("UseMnemonic", Label1.UseMnemonic, True) Call PropBag.WriteProperty("WhatsThisHelpID", Label1.WhatsThisHelpID, 0) Call PropBag.WriteProperty("WordWrap", Label1.WordWrap, False) Call PropBag.WriteProperty("Identificador", m_nombre, m_def_Identificador) Call PropBag.WriteProperty("Alto", Label1.Height, 370) Call PropBag.WriteProperty("Ancho", Label1.Width, 1210) End Sub

Listado del Código

193

Control ActiveX (PULSADOR) 'Default Property Values: Const m_def_ForeColor = 0 Const m_def_BackStyle = 0 Const m_def_BorderStyle = 0 Const m_def_FontTransparent = 0 Const m_def_Identificador = "P" 'Property Variables: Dim m_ForeColor As Long Dim m_BackStyle As Integer Dim m_BorderStyle As Integer Dim m_FontTransparent As Boolean Dim m_nombre As String 'Dim m_ancho As Single 'Dim m_alto As Single 'Event Declarations: Event Click() 'MappingInfo=Command1,Command1,-1,Click Event DblClick() 'MappingInfo=Command1,Command1,-1,DblClick Event KeyDown(KeyCode As Integer, Shift As Integer) 'MappingInfo=Command1,Command1,-1,KeyDown Event KeyPress(KeyAscii As Integer) 'MappingInfo=Command1,Command1,-1,KeyPress Event KeyUp(KeyCode As Integer, Shift As Integer) 'MappingInfo=Command1,Command1,-1,KeyUp Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Command1,Command1,-1,MouseDown Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Command1,Command1,-1,MouseMove Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Command1,Command1,-1,MouseUp Event OLECompleteDrag(Effect As Long) 'MappingInfo=Command1,Command1,-1,OLECompleteDrag Event OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Command1,Command1,-1,OLEDragDrop Event OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) 'MappingInfo=Command1,Command1,-1,OLEDragOver Event OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) 'MappingInfo=Command1,Command1,-1,OLEGiveFeedback Event OLESetData(Data As DataObject, DataFormat As Integer) 'MappingInfo=Command1,Command1,-1,OLESetData Event OLEStartDrag(Data As DataObject, AllowedEffects As Long) 'MappingInfo=Command1,Command1,-1,OLEStartDrag Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(ByVal eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" End Property Public Property Get Ancho() As Single Ancho = Command1.Width 'm_ancho End Property Public Property Let Ancho(ByVal numero As Single) Command1.Width = numero PropertyChanged "Ancho" UserControl.Width = Command1.Width

Listado del Código

194

End Property Public Property Get Alto() As Single Alto = Command1.Height 'm_alto End Property Public Property Let Alto(ByVal numero As Single) Command1.Height = numero PropertyChanged "Alto" UserControl.Height = Command1.Height End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,BackColor Public Property Get BackColor() As OLE_COLOR BackColor = Command1.BackColor End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Command1.BackColor() = New_BackColor PropertyChanged "BackColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=8,0,0,0 Public Property Get ForeColor() As Long ForeColor = m_ForeColor End Property Public Property Let ForeColor(ByVal New_ForeColor As Long) m_ForeColor = New_ForeColor PropertyChanged "ForeColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Enabled Public Property Get Enabled() As Boolean Enabled = Command1.Enabled End Property Public Property Let Enabled(ByVal New_Enabled As Boolean) Command1.Enabled() = New_Enabled PropertyChanged "Enabled" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Font Public Property Get Font() As Font Set Font = Command1.Font End Property Public Property Set Font(ByVal New_Font As Font) Set Command1.Font = New_Font PropertyChanged "Font" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=7,0,0,0 Public Property Get BackStyle() As Integer BackStyle = m_BackStyle End Property

Listado del Código

195

Public Property Let BackStyle(ByVal New_BackStyle As Integer) m_BackStyle = New_BackStyle PropertyChanged "BackStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=7,0,0,0 Public Property Get BorderStyle() As Integer BorderStyle = m_BorderStyle End Property Public Property Let BorderStyle(ByVal New_BorderStyle As Integer) m_BorderStyle = New_BorderStyle PropertyChanged "BorderStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Refresh Public Sub Refresh() Command1.Refresh End Sub Private Sub Command1_Click() RaiseEvent Click End Sub Private Sub Command1_DblClick() RaiseEvent DblClick End Sub Private Sub Command1_KeyDown(KeyCode As Integer, Shift As Integer) RaiseEvent KeyDown(KeyCode, Shift) End Sub Private Sub Command1_KeyPress(KeyAscii As Integer) RaiseEvent KeyPress(KeyAscii) End Sub Private Sub Command1_KeyUp(KeyCode As Integer, Shift As Integer) RaiseEvent KeyUp(KeyCode, Shift) End Sub Private Sub Command1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y) End Sub Private Sub Command1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Appearance Public Property Get Appearance() As Integer Appearance = Command1.Appearance

Listado del Código

196

End Property Public Property Let Appearance(ByVal New_Appearance As Integer) Command1.Appearance() = New_Appearance PropertyChanged "Appearance" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Cancel Public Property Get Cancel() As Boolean Cancel = Command1.Cancel End Property Public Property Let Cancel(ByVal New_Cancel As Boolean) Command1.Cancel() = New_Cancel PropertyChanged "Cancel" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Caption Public Property Get Caption() As String Caption = Command1.Caption End Property Public Property Let Caption(ByVal New_Caption As String) Command1.Caption() = New_Caption PropertyChanged "Caption" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,CausesValidation Public Property Get CausesValidation() As Boolean CausesValidation = Command1.CausesValidation End Property Public Property Let CausesValidation(ByVal New_CausesValidation As Boolean) Command1.CausesValidation() = New_CausesValidation PropertyChanged "CausesValidation" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Default Public Property Get Default() As Boolean Default = Command1.Default End Property Public Property Let Default(ByVal New_Default As Boolean) Command1.Default() = New_Default PropertyChanged "Default" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,DisabledPicture Public Property Get DisabledPicture() As Picture Set DisabledPicture = Command1.DisabledPicture End Property Public Property Set DisabledPicture(ByVal New_DisabledPicture As Picture) Set Command1.DisabledPicture = New_DisabledPicture PropertyChanged "DisabledPicture"

Listado del Código

197

End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,DownPicture Public Property Get DownPicture() As Picture Set DownPicture = Command1.DownPicture End Property Public Property Set DownPicture(ByVal New_DownPicture As Picture) Set Command1.DownPicture = New_DownPicture PropertyChanged "DownPicture" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontBold Public Property Get FontBold() As Boolean FontBold = Command1.FontBold End Property Public Property Let FontBold(ByVal New_FontBold As Boolean) Command1.FontBold() = New_FontBold PropertyChanged "FontBold" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontItalic Public Property Get FontItalic() As Boolean FontItalic = Command1.FontItalic End Property Public Property Let FontItalic(ByVal New_FontItalic As Boolean) Command1.FontItalic() = New_FontItalic PropertyChanged "FontItalic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontName Public Property Get FontName() As String FontName = Command1.FontName End Property Public Property Let FontName(ByVal New_FontName As String) Command1.FontName() = New_FontName PropertyChanged "FontName" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontSize Public Property Get FontSize() As Single FontSize = Command1.FontSize End Property Public Property Let FontSize(ByVal New_FontSize As Single) Command1.FontSize() = New_FontSize PropertyChanged "FontSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontStrikethru Public Property Get FontStrikethru() As Boolean FontStrikethru = Command1.FontStrikethru

Listado del Código

198

End Property Public Property Let FontStrikethru(ByVal New_FontStrikethru As Boolean) Command1.FontStrikethru() = New_FontStrikethru PropertyChanged "FontStrikethru" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=0,0,0,0 Public Property Get FontTransparent() As Boolean FontTransparent = m_FontTransparent End Property Public Property Let FontTransparent(ByVal New_FontTransparent As Boolean) m_FontTransparent = New_FontTransparent PropertyChanged "FontTransparent" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,FontUnderline Public Property Get FontUnderline() As Boolean FontUnderline = Command1.FontUnderline End Property Public Property Let FontUnderline(ByVal New_FontUnderline As Boolean) Command1.FontUnderline() = New_FontUnderline PropertyChanged "FontUnderline" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,hWnd Public Property Get hWnd() As Long hWnd = Command1.hWnd End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,MaskColor Public Property Get MaskColor() As Long MaskColor = Command1.MaskColor End Property Public Property Let MaskColor(ByVal New_MaskColor As Long) Command1.MaskColor() = New_MaskColor PropertyChanged "MaskColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,MouseIcon Public Property Get MouseIcon() As Picture Set MouseIcon = Command1.MouseIcon End Property Public Property Set MouseIcon(ByVal New_MouseIcon As Picture) Set Command1.MouseIcon = New_MouseIcon PropertyChanged "MouseIcon" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,MousePointer Public Property Get MousePointer() As Integer MousePointer = Command1.MousePointer

Listado del Código

199

End Property Public Property Let MousePointer(ByVal New_MousePointer As Integer) Command1.MousePointer() = New_MousePointer PropertyChanged "MousePointer" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,OLEDropMode Public Property Get OLEDropMode() As Integer OLEDropMode = Command1.OLEDropMode End Property Public Property Let OLEDropMode(ByVal New_OLEDropMode As Integer) Command1.OLEDropMode() = New_OLEDropMode PropertyChanged "OLEDropMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Picture Public Property Get Picture() As Picture Set Picture = Command1.Picture End Property Public Property Set Picture(ByVal New_Picture As Picture) Set Command1.Picture = New_Picture PropertyChanged "Picture" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,RightToLeft Public Property Get RightToLeft() As Boolean RightToLeft = Command1.RightToLeft End Property Public Property Let RightToLeft(ByVal New_RightToLeft As Boolean) Command1.RightToLeft() = New_RightToLeft PropertyChanged "RightToLeft" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Style Public Property Get Style() As Integer Style = Command1.Style End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,ToolTipText Public Property Get ToolTipText() As String ToolTipText = Command1.ToolTipText End Property Public Property Let ToolTipText(ByVal New_ToolTipText As String) Command1.ToolTipText() = New_ToolTipText PropertyChanged "ToolTipText" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,UseMaskColor Public Property Get UseMaskColor() As Boolean UseMaskColor = Command1.UseMaskColor

Listado del Código

200

End Property Public Property Let UseMaskColor(ByVal New_UseMaskColor As Boolean) Command1.UseMaskColor() = New_UseMaskColor PropertyChanged "UseMaskColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,Value Public Property Get Value() As Boolean Value = Command1.Value End Property Public Property Let Value(ByVal New_Value As Boolean) Command1.Value() = New_Value PropertyChanged "Value" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,WhatsThisHelpID Public Property Get WhatsThisHelpID() As Long WhatsThisHelpID = Command1.WhatsThisHelpID End Property Public Property Let WhatsThisHelpID(ByVal New_WhatsThisHelpID As Long) Command1.WhatsThisHelpID() = New_WhatsThisHelpID PropertyChanged "WhatsThisHelpID" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Command1,Command1,-1,OLEDrag Public Sub OLEDrag() Command1.OLEDrag End Sub Private Sub Command1_OLECompleteDrag(Effect As Long) RaiseEvent OLECompleteDrag(Effect) End Sub Private Sub Command1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent OLEDragDrop(Data, Effect, Button, Shift, X, Y) End Sub Private Sub Command1_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) RaiseEvent OLEDragOver(Data, Effect, Button, Shift, X, Y, State) End Sub Private Sub Command1_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) RaiseEvent OLEGiveFeedback(Effect, DefaultCursors) End Sub Private Sub Command1_OLESetData(Data As DataObject, DataFormat As Integer) RaiseEvent OLESetData(Data, DataFormat) End Sub

Listado del Código

201

Private Sub Command1_OLEStartDrag(Data As DataObject, AllowedEffects As Long) RaiseEvent OLEStartDrag(Data, AllowedEffects) End Sub 'Initialize Properties for User Control Private Sub UserControl_InitProperties() m_ForeColor = m_def_ForeColor m_BackStyle = m_def_BackStyle m_BorderStyle = m_def_BorderStyle m_FontTransparent = m_def_FontTransparent End Sub 'Load property values from storage Private Sub UserControl_ReadProperties(PropBag As PropertyBag) Command1.BackColor = PropBag.ReadProperty("BackColor", &H8000000F) m_ForeColor = PropBag.ReadProperty("ForeColor", m_def_ForeColor) Command1.Enabled = PropBag.ReadProperty("Enabled", True) Set Command1.Font = PropBag.ReadProperty("Font", Ambient.Font) m_BackStyle = PropBag.ReadProperty("BackStyle", m_def_BackStyle) m_BorderStyle = PropBag.ReadProperty("BorderStyle", m_def_BorderStyle) Command1.Appearance = PropBag.ReadProperty("Appearance", 1) Command1.Cancel = PropBag.ReadProperty("Cancel", False) Command1.Caption = PropBag.ReadProperty("Caption", "") Command1.CausesValidation = PropBag.ReadProperty("CausesValidation", True) Command1.Default = PropBag.ReadProperty("Default", False) Set DisabledPicture = PropBag.ReadProperty("DisabledPicture", Nothing) Set DownPicture = PropBag.ReadProperty("DownPicture", Nothing) Command1.FontBold = PropBag.ReadProperty("FontBold", 0) Command1.FontItalic = PropBag.ReadProperty("FontItalic", 0) Command1.FontName = PropBag.ReadProperty("FontName", "") Command1.FontSize = PropBag.ReadProperty("FontSize", 0) Command1.FontStrikethru = PropBag.ReadProperty("FontStrikethru", 0) m_FontTransparent = PropBag.ReadProperty("FontTransparent", m_def_FontTransparent) Command1.FontUnderline = PropBag.ReadProperty("FontUnderline", 0) Command1.MaskColor = PropBag.ReadProperty("MaskColor", 12632256) Set MouseIcon = PropBag.ReadProperty("MouseIcon", Nothing) Command1.MousePointer = PropBag.ReadProperty("MousePointer", 0) Command1.OLEDropMode = PropBag.ReadProperty("OLEDropMode", 0) Set Picture = PropBag.ReadProperty("Picture", Nothing) Command1.RightToLeft = PropBag.ReadProperty("RightToLeft", False) Command1.ToolTipText = PropBag.ReadProperty("ToolTipText", "Pulsador") Command1.UseMaskColor = PropBag.ReadProperty("UseMaskColor", False) Command1.Value = PropBag.ReadProperty("Value", 0) Command1.WhatsThisHelpID = PropBag.ReadProperty("WhatsThisHelpID", 0) m_nombre = PropBag.ReadProperty("Identificador", m_def_Identificador) Command1.Height = PropBag.ReadProperty("Alto", 490) '360) Command1.Width = PropBag.ReadProperty("Ancho", 970) '1200) End Sub 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) Call PropBag.WriteProperty("BackColor", Command1.BackColor, &H8000000F)

Listado del Código

202

Call PropBag.WriteProperty("ForeColor", m_ForeColor, m_def_ForeColor) Call PropBag.WriteProperty("Enabled", Command1.Enabled, True) Call PropBag.WriteProperty("Font", Command1.Font, Ambient.Font) Call PropBag.WriteProperty("BackStyle", m_BackStyle, m_def_BackStyle) Call PropBag.WriteProperty("BorderStyle", m_BorderStyle, m_def_BorderStyle) Call PropBag.WriteProperty("Appearance", Command1.Appearance, 1) Call PropBag.WriteProperty("Cancel", Command1.Cancel, False) Call PropBag.WriteProperty("Caption", Command1.Caption, "") Call PropBag.WriteProperty("CausesValidation", Command1.CausesValidation, True) Call PropBag.WriteProperty("Default", Command1.Default, False) Call PropBag.WriteProperty("DisabledPicture", DisabledPicture, Nothing) Call PropBag.WriteProperty("DownPicture", DownPicture, Nothing) Call PropBag.WriteProperty("FontBold", Command1.FontBold, 0) Call PropBag.WriteProperty("FontItalic", Command1.FontItalic, 0) Call PropBag.WriteProperty("FontName", Command1.FontName, "") Call PropBag.WriteProperty("FontSize", Command1.FontSize, 0) Call PropBag.WriteProperty("FontStrikethru", Command1.FontStrikethru, 0) Call PropBag.WriteProperty("FontTransparent", m_FontTransparent, m_def_FontTransparent) Call PropBag.WriteProperty("FontUnderline", Command1.FontUnderline, 0) Call PropBag.WriteProperty("MaskColor", Command1.MaskColor, 12632256) Call PropBag.WriteProperty("MouseIcon", MouseIcon, Nothing) Call PropBag.WriteProperty("MousePointer", Command1.MousePointer, 0) Call PropBag.WriteProperty("OLEDropMode", Command1.OLEDropMode, 0) Call PropBag.WriteProperty("Picture", Picture, Nothing) Call PropBag.WriteProperty("RightToLeft", Command1.RightToLeft, False) Call PropBag.WriteProperty("ToolTipText", Command1.ToolTipText, "Pulsador") Call PropBag.WriteProperty("UseMaskColor", Command1.UseMaskColor, False) Call PropBag.WriteProperty("Value", Command1.Value, 0) Call PropBag.WriteProperty("WhatsThisHelpID", Command1.WhatsThisHelpID, 0) Call PropBag.WriteProperty("Identificador", m_nombre, m_def_Identificador) Call PropBag.WriteProperty("Alto", Command1.Height, 490) '360) Call PropBag.WriteProperty("Ancho", Command1.Width, 970) '1200) End Sub

Listado del Código

203

Control ActiveX (TEXTO) 'Default Property Values: Const m_def_FontTransparent = 0 Const m_def_Identificador = "TE" 'Property Variables: Dim m_FontTransparent As Boolean Dim m_nombre As String 'Event Declarations: Event Click() 'MappingInfo=Text1,Text1,-1,Click Event DblClick() 'MappingInfo=Text1,Text1,-1,DblClick Event KeyDown(KeyCode As Integer, Shift As Integer) 'MappingInfo=Text1,Text1,-1,KeyDown Event KeyPress(KeyAscii As Integer) 'MappingInfo=Text1,Text1,-1,KeyPress Event KeyUp(KeyCode As Integer, Shift As Integer) 'MappingInfo=Text1,Text1,-1,KeyUp Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Text1,Text1,-1,MouseDown Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Text1,Text1,-1,MouseMove Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Text1,Text1,-1,MouseUp Event Change() 'MappingInfo=Text1,Text1,-1,Change Event OLECompleteDrag(Effect As Long) 'MappingInfo=Text1,Text1,-1,OLECompleteDrag Event OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) 'MappingInfo=Text1,Text1,-1,OLEDragDrop Event OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) 'MappingInfo=Text1,Text1,-1,OLEDragOver Event OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) 'MappingInfo=Text1,Text1,-1,OLEGiveFeedback Event OLESetData(Data As DataObject, DataFormat As Integer) 'MappingInfo=Text1,Text1,-1,OLESetData Event OLEStartDrag(Data As DataObject, AllowedEffects As Long) 'MappingInfo=Text1,Text1,-1,OLEStartDrag Event Validate(Cancel As Boolean) 'MappingInfo=Text1,Text1,-1,Validate Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(ByVal eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" End Property Public Property Get Ancho() As Single Ancho = Text1.Width 'm_ancho End Property Public Property Let Ancho(ByVal numero As Single) Text1.Width = numero PropertyChanged "Ancho" UserControl.Width = Text1.Width End Property Public Property Get Alto() As Single Alto = Text1.Height 'm_alto End Property Public Property Let Alto(ByVal numero As Single) Text1.Height = numero

Listado del Código

204

PropertyChanged "Alto" UserControl.Height = Text1.Height End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,BackColor Public Property Get BackColor() As OLE_COLOR BackColor = Text1.BackColor End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Text1.BackColor() = New_BackColor PropertyChanged "BackColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,ForeColor Public Property Get ForeColor() As OLE_COLOR ForeColor = Text1.ForeColor End Property Public Property Let ForeColor(ByVal New_ForeColor As OLE_COLOR) Text1.ForeColor() = New_ForeColor PropertyChanged "ForeColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Enabled Public Property Get Enabled() As Boolean Enabled = Text1.Enabled End Property Public Property Let Enabled(ByVal New_Enabled As Boolean) Text1.Enabled() = New_Enabled PropertyChanged "Enabled" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Font Public Property Get Font() As Font Set Font = Text1.Font End Property Public Property Set Font(ByVal New_Font As Font) Set Text1.Font = New_Font PropertyChanged "Font" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,BorderStyle Public Property Get BorderStyle() As Integer BorderStyle = Text1.BorderStyle End Property Public Property Let BorderStyle(ByVal New_BorderStyle As Integer) Text1.BorderStyle() = New_BorderStyle PropertyChanged "BorderStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES!

Listado del Código

205

'MappingInfo=Text1,Text1,-1,Refresh Public Sub Refresh() Text1.Refresh End Sub Private Sub Text1_Click() RaiseEvent Click End Sub Private Sub Text1_DblClick() RaiseEvent DblClick End Sub Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer) RaiseEvent KeyDown(KeyCode, Shift) End Sub Private Sub Text1_KeyPress(KeyAscii As Integer) RaiseEvent KeyPress(KeyAscii) End Sub Private Sub Text1_KeyUp(KeyCode As Integer, Shift As Integer) RaiseEvent KeyUp(KeyCode, Shift) End Sub Private Sub Text1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y) End Sub Private Sub Text1_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub Text1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Alignment Public Property Get Alignment() As Integer Alignment = Text1.Alignment End Property Public Property Let Alignment(ByVal New_Alignment As Integer) Text1.Alignment() = New_Alignment PropertyChanged "Alignment" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Appearance Public Property Get Appearance() As Integer Appearance = Text1.Appearance End Property Public Property Let Appearance(ByVal New_Appearance As Integer) Text1.Appearance() = New_Appearance PropertyChanged "Appearance" End Property

Listado del Código

206

'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,CausesValidation Public Property Get CausesValidation() As Boolean CausesValidation = Text1.CausesValidation End Property Public Property Let CausesValidation(ByVal New_CausesValidation As Boolean) Text1.CausesValidation() = New_CausesValidation PropertyChanged "CausesValidation" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,DataFormat 'Public Property Get DataFormat() As IStdDataFormatDisp ' Set DataFormat = Text1.DataFormat 'End Property 'Public Property Set DataFormat(ByVal New_DataFormat As IStdDataFormatDisp) ' Set Text1.DataFormat = New_DataFormat ' PropertyChanged "DataFormat" 'End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,DataMember Public Property Get DataMember() As String DataMember = Text1.DataMember End Property Public Property Let DataMember(ByVal New_DataMember As String) Text1.DataMember() = New_DataMember PropertyChanged "DataMember" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,DataSource 'Public Property Get DataSource() As DataSource ' Set DataSource = Text1.DataSource 'End Property 'Public Property Set DataSource(ByVal New_DataSource As DataSource) ' Set Text1.DataSource = New_DataSource ' PropertyChanged "DataSource" 'End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontBold Public Property Get FontBold() As Boolean FontBold = Text1.FontBold End Property Public Property Let FontBold(ByVal New_FontBold As Boolean) Text1.FontBold() = New_FontBold PropertyChanged "FontBold" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontItalic Public Property Get FontItalic() As Boolean

Listado del Código

207

FontItalic = Text1.FontItalic End Property Public Property Let FontItalic(ByVal New_FontItalic As Boolean) Text1.FontItalic() = New_FontItalic PropertyChanged "FontItalic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontName Public Property Get FontName() As String FontName = Text1.FontName End Property Public Property Let FontName(ByVal New_FontName As String) Text1.FontName() = New_FontName PropertyChanged "FontName" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontSize Public Property Get FontSize() As Single FontSize = Text1.FontSize End Property Public Property Let FontSize(ByVal New_FontSize As Single) Text1.FontSize() = New_FontSize PropertyChanged "FontSize" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontStrikethru Public Property Get FontStrikethru() As Boolean FontStrikethru = Text1.FontStrikethru End Property Public Property Let FontStrikethru(ByVal New_FontStrikethru As Boolean) Text1.FontStrikethru() = New_FontStrikethru PropertyChanged "FontStrikethru" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MemberInfo=0,0,0,0 Public Property Get FontTransparent() As Boolean FontTransparent = m_FontTransparent End Property Public Property Let FontTransparent(ByVal New_FontTransparent As Boolean) m_FontTransparent = New_FontTransparent PropertyChanged "FontTransparent" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,FontUnderline Public Property Get FontUnderline() As Boolean FontUnderline = Text1.FontUnderline End Property Public Property Let FontUnderline(ByVal New_FontUnderline As Boolean) Text1.FontUnderline() = New_FontUnderline PropertyChanged "FontUnderline"

Listado del Código

208

End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,HideSelection Public Property Get HideSelection() As Boolean HideSelection = Text1.HideSelection End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,hWnd Public Property Get hWnd() As Long hWnd = Text1.hWnd End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkItem Public Property Get LinkItem() As String LinkItem = Text1.LinkItem End Property Public Property Let LinkItem(ByVal New_LinkItem As String) Text1.LinkItem() = New_LinkItem PropertyChanged "LinkItem" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkMode Public Property Get LinkMode() As Integer LinkMode = Text1.LinkMode End Property Public Property Let LinkMode(ByVal New_LinkMode As Integer) Text1.LinkMode() = New_LinkMode PropertyChanged "LinkMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkTimeout Public Property Get LinkTimeout() As Integer LinkTimeout = Text1.LinkTimeout End Property Public Property Let LinkTimeout(ByVal New_LinkTimeout As Integer) Text1.LinkTimeout() = New_LinkTimeout PropertyChanged "LinkTimeout" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkTopic Public Property Get LinkTopic() As String LinkTopic = Text1.LinkTopic End Property Public Property Let LinkTopic(ByVal New_LinkTopic As String) Text1.LinkTopic() = New_LinkTopic PropertyChanged "LinkTopic" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Locked Public Property Get Locked() As Boolean

Listado del Código

209

Locked = Text1.Locked End Property Public Property Let Locked(ByVal New_Locked As Boolean) Text1.Locked() = New_Locked PropertyChanged "Locked" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,MaxLength Public Property Get MaxLength() As Long MaxLength = Text1.MaxLength End Property Public Property Let MaxLength(ByVal New_MaxLength As Long) Text1.MaxLength() = New_MaxLength PropertyChanged "MaxLength" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,MouseIcon Public Property Get MouseIcon() As Picture Set MouseIcon = Text1.MouseIcon End Property Public Property Set MouseIcon(ByVal New_MouseIcon As Picture) Set Text1.MouseIcon = New_MouseIcon PropertyChanged "MouseIcon" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,MousePointer Public Property Get MousePointer() As Integer MousePointer = Text1.MousePointer End Property Public Property Let MousePointer(ByVal New_MousePointer As Integer) Text1.MousePointer() = New_MousePointer PropertyChanged "MousePointer" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,MultiLine Public Property Get MultiLine() As Boolean MultiLine = Text1.MultiLine End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,OLEDragMode Public Property Get OLEDragMode() As Integer OLEDragMode = Text1.OLEDragMode End Property Public Property Let OLEDragMode(ByVal New_OLEDragMode As Integer) Text1.OLEDragMode() = New_OLEDragMode PropertyChanged "OLEDragMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,OLEDropMode Public Property Get OLEDropMode() As Integer

Listado del Código

210

OLEDropMode = Text1.OLEDropMode End Property Public Property Let OLEDropMode(ByVal New_OLEDropMode As Integer) Text1.OLEDropMode() = New_OLEDropMode PropertyChanged "OLEDropMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,PasswordChar Public Property Get PasswordChar() As String PasswordChar = Text1.PasswordChar End Property Public Property Let PasswordChar(ByVal New_PasswordChar As String) Text1.PasswordChar() = New_PasswordChar PropertyChanged "PasswordChar" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,RightToLeft Public Property Get RightToLeft() As Boolean RightToLeft = Text1.RightToLeft End Property Public Property Let RightToLeft(ByVal New_RightToLeft As Boolean) Text1.RightToLeft() = New_RightToLeft PropertyChanged "RightToLeft" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,ScrollBars Public Property Get ScrollBars() As Integer ScrollBars = Text1.ScrollBars End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,SelLength Public Property Get SelLength() As Long SelLength = Text1.SelLength End Property Public Property Let SelLength(ByVal New_SelLength As Long) Text1.SelLength() = New_SelLength PropertyChanged "SelLength" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,SelStart Public Property Get SelStart() As Long SelStart = Text1.SelStart End Property Public Property Let SelStart(ByVal New_SelStart As Long) Text1.SelStart() = New_SelStart PropertyChanged "SelStart" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,SelText Public Property Get SelText() As String

Listado del Código

211

SelText = Text1.SelText End Property Public Property Let SelText(ByVal New_SelText As String) Text1.SelText() = New_SelText PropertyChanged "SelText" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,Text Public Property Get Text() As String Text = Text1.Text End Property Public Property Let Text(ByVal New_Text As String) Text1.Text() = New_Text PropertyChanged "Text" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,ToolTipText Public Property Get ToolTipText() As String ToolTipText = Text1.ToolTipText End Property Public Property Let ToolTipText(ByVal New_ToolTipText As String) Text1.ToolTipText() = New_ToolTipText PropertyChanged "ToolTipText" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,WhatsThisHelpID Public Property Get WhatsThisHelpID() As Long WhatsThisHelpID = Text1.WhatsThisHelpID End Property Public Property Let WhatsThisHelpID(ByVal New_WhatsThisHelpID As Long) Text1.WhatsThisHelpID() = New_WhatsThisHelpID PropertyChanged "WhatsThisHelpID" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkExecute Public Sub LinkExecute(ByVal Command As String) Text1.LinkExecute Command End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkPoke Public Sub LinkPoke() Text1.LinkPoke End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkRequest Public Sub LinkRequest() Text1.LinkRequest End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,LinkSend

Listado del Código

212

Public Sub LinkSend() Text1.LinkSend End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Text1,Text1,-1,OLEDrag Public Sub OLEDrag() Text1.OLEDrag End Sub Private Sub Text1_Change() RaiseEvent Change End Sub Private Sub Text1_OLECompleteDrag(Effect As Long) RaiseEvent OLECompleteDrag(Effect) End Sub Private Sub Text1_OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent OLEDragDrop(Data, Effect, Button, Shift, X, Y) End Sub Private Sub Text1_OLEDragOver(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single, State As Integer) RaiseEvent OLEDragOver(Data, Effect, Button, Shift, X, Y, State) End Sub Private Sub Text1_OLEGiveFeedback(Effect As Long, DefaultCursors As Boolean) RaiseEvent OLEGiveFeedback(Effect, DefaultCursors) End Sub Private Sub Text1_OLESetData(Data As DataObject, DataFormat As Integer) RaiseEvent OLESetData(Data, DataFormat) End Sub Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long) RaiseEvent OLEStartDrag(Data, AllowedEffects) End Sub Private Sub Text1_Validate(Cancel As Boolean) RaiseEvent Validate(Cancel) End Sub 'Initialize Properties for User Control Private Sub UserControl_InitProperties() m_FontTransparent = m_def_FontTransparent End Sub 'Load property values from storage Private Sub UserControl_ReadProperties(PropBag As PropertyBag) Text1.BackColor = PropBag.ReadProperty("BackColor", &HFFFFFF) '&H80000005) Text1.ForeColor = PropBag.ReadProperty("ForeColor", &H0) '&H80000008) Text1.Enabled = PropBag.ReadProperty("Enabled", True) Set Text1.Font = PropBag.ReadProperty("Font", Ambient.Font) Text1.BorderStyle = PropBag.ReadProperty("BorderStyle", 1)

Listado del Código

213

Text1.Alignment = PropBag.ReadProperty("Alignment", 0) Text1.Appearance = PropBag.ReadProperty("Appearance", 1) Text1.CausesValidation = PropBag.ReadProperty("CausesValidation", False) ' True) Set DataFormat = PropBag.ReadProperty("DataFormat", Nothing) Text1.DataMember = PropBag.ReadProperty("DataMember", "") Set DataSource = PropBag.ReadProperty("DataSource", Nothing) Text1.FontBold = PropBag.ReadProperty("FontBold", 0) Text1.FontItalic = PropBag.ReadProperty("FontItalic", 0) Text1.FontName = PropBag.ReadProperty("FontName", "") Text1.FontSize = PropBag.ReadProperty("FontSize", 0) Text1.FontStrikethru = PropBag.ReadProperty("FontStrikethru", 0) m_FontTransparent = PropBag.ReadProperty("FontTransparent", 0) ' m_def_FontTransparent) Text1.FontUnderline = PropBag.ReadProperty("FontUnderline", 0) Text1.LinkItem = PropBag.ReadProperty("LinkItem", "") Text1.LinkMode = PropBag.ReadProperty("LinkMode", 0) Text1.LinkTimeout = PropBag.ReadProperty("LinkTimeout", 50) Text1.LinkTopic = PropBag.ReadProperty("LinkTopic", "") Text1.Locked = PropBag.ReadProperty("Locked", False) Text1.MaxLength = PropBag.ReadProperty("MaxLength", 0) Set MouseIcon = PropBag.ReadProperty("MouseIcon", Nothing) Text1.MousePointer = PropBag.ReadProperty("MousePointer", 0) Text1.OLEDragMode = PropBag.ReadProperty("OLEDragMode", 0) Text1.OLEDropMode = PropBag.ReadProperty("OLEDropMode", 0) Text1.PasswordChar = PropBag.ReadProperty("PasswordChar", "") Text1.RightToLeft = PropBag.ReadProperty("RightToLeft", False) Text1.SelLength = PropBag.ReadProperty("SelLength", 0) Text1.SelStart = PropBag.ReadProperty("SelStart", 0) Text1.SelText = PropBag.ReadProperty("SelText", "") Text1.Text = PropBag.ReadProperty("Text", "Text1") Text1.ToolTipText = PropBag.ReadProperty("ToolTipText", "Cuadro Texto") Text1.WhatsThisHelpID = PropBag.ReadProperty("WhatsThisHelpID", 0) m_nombre = PropBag.ReadProperty("Identificador", m_def_Identificador) Text1.Height = PropBag.ReadProperty("Alto", 490) Text1.Width = PropBag.ReadProperty("Ancho", 2410) End Sub 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) Call PropBag.WriteProperty("BackColor", Text1.BackColor, &HFFFFFF) '&H80000005) Call PropBag.WriteProperty("ForeColor", Text1.ForeColor, &H0) '&H80000008) Call PropBag.WriteProperty("Enabled", Text1.Enabled, True) Call PropBag.WriteProperty("Font", Text1.Font, Ambient.Font) Call PropBag.WriteProperty("BorderStyle", Text1.BorderStyle, 1) Call PropBag.WriteProperty("Alignment", Text1.Alignment, 0) Call PropBag.WriteProperty("Appearance", Text1.Appearance, 1) Call PropBag.WriteProperty("CausesValidation", Text1.CausesValidation, False) ' True) Call PropBag.WriteProperty("DataFormat", DataFormat, Nothing) Call PropBag.WriteProperty("DataMember", Text1.DataMember, "") Call PropBag.WriteProperty("DataSource", DataSource, Nothing) Call PropBag.WriteProperty("FontBold", Text1.FontBold, 0) Call PropBag.WriteProperty("FontItalic", Text1.FontItalic, 0) Call PropBag.WriteProperty("FontName", Text1.FontName, "") Call PropBag.WriteProperty("FontSize", Text1.FontSize, 0) Call PropBag.WriteProperty("FontStrikethru", Text1.FontStrikethru, 0)

Listado del Código

214

Call PropBag.WriteProperty("FontTransparent", m_FontTransparent, 0) 'm_def_FontTransparent) Call PropBag.WriteProperty("FontUnderline", Text1.FontUnderline, 0) Call PropBag.WriteProperty("LinkItem", Text1.LinkItem, "") Call PropBag.WriteProperty("LinkMode", Text1.LinkMode, 0) Call PropBag.WriteProperty("LinkTimeout", Text1.LinkTimeout, 50) Call PropBag.WriteProperty("LinkTopic", Text1.LinkTopic, "") Call PropBag.WriteProperty("Locked", Text1.Locked, False) Call PropBag.WriteProperty("MaxLength", Text1.MaxLength, 0) Call PropBag.WriteProperty("MouseIcon", MouseIcon, Nothing) Call PropBag.WriteProperty("MousePointer", Text1.MousePointer, 0) Call PropBag.WriteProperty("OLEDragMode", Text1.OLEDragMode, 0) Call PropBag.WriteProperty("OLEDropMode", Text1.OLEDropMode, 0) Call PropBag.WriteProperty("PasswordChar", Text1.PasswordChar, "") Call PropBag.WriteProperty("RightToLeft", Text1.RightToLeft, False) Call PropBag.WriteProperty("SelLength", Text1.SelLength, 0) Call PropBag.WriteProperty("SelStart", Text1.SelStart, 0) Call PropBag.WriteProperty("SelText", Text1.SelText, "") Call PropBag.WriteProperty("Text", Text1.Text, "Text1") Call PropBag.WriteProperty("ToolTipText", Text1.ToolTipText, "") Call PropBag.WriteProperty("WhatsThisHelpID", Text1.WhatsThisHelpID, 0) Call PropBag.WriteProperty("Identificador", m_nombre, m_def_Identificador) Call PropBag.WriteProperty("Alto", Text1.Height, 490) Call PropBag.WriteProperty("Ancho", Text1.Width, 2410) End Sub

Listado del Código

215

Control ActiveX (FIGURA) 'Default Property Values: Const m_def_Identificador = "F" 'Property Variables: Dim m_nombre As String 'Event Declarations: Event Click() Event DblClick() Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Event OLEDragDrop(Data As DataObject, Effect As Long, Button As Integer, Shift As Integer, X As Single, Y As Single) Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(ByVal eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" End Property Public Property Get Ancho() As Single Ancho = Shape1.Width 'm_ancho End Property Public Property Let Ancho(ByVal numero As Single) Shape1.Width = numero PropertyChanged "Ancho" UserControl.Width = Shape1.Width End Property Public Property Get Alto() As Single Alto = Shape1.Height 'm_alto End Property Public Property Let Alto(ByVal numero As Single) Shape1.Height = numero PropertyChanged "Alto" UserControl.Height = Shape1.Height End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,BackColor Public Property Get BackColor() As OLE_COLOR BackColor = Shape1.BackColor End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Shape1.BackColor() = New_BackColor PropertyChanged "BackColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,BackStyle Public Property Get BackStyle() As Integer BackStyle = Shape1.BackStyle End Property

Listado del Código

216

Public Property Let BackStyle(ByVal New_BackStyle As Integer) Shape1.BackStyle() = New_BackStyle PropertyChanged "BackStyle" 'UserControl.BackStyle = Shape1.BackStyle End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,BorderStyle Public Property Get BorderStyle() As Integer BorderStyle = Shape1.BorderStyle End Property Public Property Let BorderStyle(ByVal New_BorderStyle As Integer) Shape1.BorderStyle() = New_BorderStyle PropertyChanged "BorderStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,Refresh Public Sub Refresh() Shape1.Refresh End Sub 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,BorderColor Public Property Get BorderColor() As Long BorderColor = Shape1.BorderColor End Property Public Property Let BorderColor(ByVal New_BorderColor As Long) Shape1.BorderColor() = New_BorderColor PropertyChanged "BorderColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,BorderWidth Public Property Get BorderWidth() As Integer BorderWidth = Shape1.BorderWidth End Property Public Property Let BorderWidth(ByVal New_BorderWidth As Integer) Shape1.BorderWidth() = New_BorderWidth PropertyChanged "BorderWidth" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,DrawMode Public Property Get DrawMode() As Integer DrawMode = Shape1.DrawMode End Property Public Property Let DrawMode(ByVal New_DrawMode As Integer) Shape1.DrawMode() = New_DrawMode PropertyChanged "DrawMode" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,FillColor Public Property Get FillColor() As OLE_COLOR FillColor = Shape1.FillColor End Property

Listado del Código

217

Public Property Let FillColor(ByVal New_FillColor As OLE_COLOR) Shape1.FillColor() = New_FillColor PropertyChanged "FillColor" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,FillStyle Public Property Get FillStyle() As Integer FillStyle = Shape1.FillStyle End Property Public Property Let FillStyle(ByVal New_FillStyle As Integer) Shape1.FillStyle() = New_FillStyle PropertyChanged "FillStyle" End Property 'WARNING! DO NOT REMOVE OR MODIFY THE FOLLOWING COMMENTED LINES! 'MappingInfo=Shape1,Shape1,-1,Shape Public Property Get Shape() As Integer Shape = Shape1.Shape End Property Public Property Let Shape(ByVal New_Shape As Integer) Shape1.Shape() = New_Shape PropertyChanged "Shape" End Property Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y) End Sub Private Sub UserControl_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub UserControl_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub Private Sub UserControl_Click() RaiseEvent Click End Sub Private Sub UserControl_DblClick() RaiseEvent DblClick End Sub 'Load property values from storage Private Sub UserControl_ReadProperties(PropBag As PropertyBag) Shape1.BackColor = PropBag.ReadProperty("BackColor", &HC0C000) Shape1.BackStyle = PropBag.ReadProperty("BackStyle", 1) Shape1.BorderStyle = PropBag.ReadProperty("BorderStyle", 1) Shape1.BorderColor = PropBag.ReadProperty("BorderColor", -2147483640) Shape1.BorderWidth = PropBag.ReadProperty("BorderWidth", 1) Shape1.DrawMode = PropBag.ReadProperty("DrawMode", 13) Shape1.FillColor = PropBag.ReadProperty("FillColor", &H0&)

Listado del Código

218

Shape1.FillStyle = PropBag.ReadProperty("FillStyle", 4) Shape1.Shape = PropBag.ReadProperty("Shape", 0) m_nombre = PropBag.ReadProperty("Identificador", m_def_Identificador) Shape1.Height = PropBag.ReadProperty("Alto", 2295) ' 370) Shape1.Width = PropBag.ReadProperty("Ancho", 2295) '1210) End Sub 'Write property values to storage Private Sub UserControl_WriteProperties(PropBag As PropertyBag) Call PropBag.WriteProperty("BackColor", Shape1.BackColor, &HC0C000) Call PropBag.WriteProperty("BackStyle", Shape1.BackStyle, 1) Call PropBag.WriteProperty("BorderStyle", Shape1.BorderStyle, 1) Call PropBag.WriteProperty("BorderColor", Shape1.BorderColor, -2147483640) Call PropBag.WriteProperty("BorderWidth", Shape1.BorderWidth, 1) Call PropBag.WriteProperty("DrawMode", Shape1.DrawMode, 13) Call PropBag.WriteProperty("FillColor", Shape1.FillColor, &H0&) Call PropBag.WriteProperty("FillStyle", Shape1.FillStyle, 4) Call PropBag.WriteProperty("Shape", Shape1.Shape, 0) Call PropBag.WriteProperty("Identificador", m_nombre, m_def_Identificador) Call PropBag.WriteProperty("Alto", Shape1.Height, 2295) '370) Call PropBag.WriteProperty("Ancho", Shape1.Width, 2295) '1210) End Sub

Listado del Código

219

Control ActiveX (TUBERIA) Option Explicit Event MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) Event MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) Event MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) Event Click() Event DblClick() 'Dim m_DrawWidth As Integer Dim m_nombre As String Public Property Get DrawMode() As Integer DrawMode = Shape1.DrawMode End Property Public Property Let DrawMode(ByVal New_DrawMode As Integer) Shape1.DrawMode() = New_DrawMode PropertyChanged "DrawMode" Shape1.Width = UserControl.Width Shape1.Height = UserControl.Height End Property Public Property Get Identificador() As String Identificador = m_nombre End Property Public Property Let Identificador(ByVal eleccion As String) m_nombre = eleccion PropertyChanged "Identificador" Refresh End Property 'Public Property Get DrawWidth() As Integer 'DrawWidth = m_DrawWidth 'End Property 'Public Property Let DrawWidth(ByVal New_DrawWidth As Integer) 'm_DrawWidth = New_DrawWidth 'PropertyChanged "DrawWidth" 'End Property Public Property Get BackColor() As OLE_COLOR BackColor = Shape1.BackColor End Property Public Property Let BackColor(ByVal New_BackColor As OLE_COLOR) Shape1.BackColor() = New_BackColor PropertyChanged "BackColor" UserControl.BackColor = New_BackColor End Property Private Sub UserControl_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseDown(Button, Shift, X, Y)

Listado del Código

220

End Sub Private Sub UserControl_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseMove(Button, Shift, X, Y) End Sub Private Sub UserControl_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single) RaiseEvent MouseUp(Button, Shift, X, Y) End Sub Private Sub UserControl_Click() RaiseEvent Click End Sub Private Sub UserControl_DblClick() RaiseEvent DblClick End Sub

Bibliografía

220

Enciclopedia de Microsoft VISUAL BASIC 6

Fco. Javier Ceballos Sierra

Editoria Ra-Ma, 2000

Programación Avanzada en Visual Basic

Francesco Balena

Editorial McGraw Hill, 2001

Programación en Visual Basic

P. Charte

Editorial ANAYA, 2000

MSDN Library Visual Studio 6.0 (Soporte informático)

Páginas web de las empresas Siemens y Logitec.