Curso de Visual Basic 4.0 Edición Empresarial Fecha: Verano de 1997 Inicio a las GUI de Windows // Uso de Informe Diseño de aplicaciones Cliente / Servidor // GUI = Graphics User Interface (Interficies gráficas de usuario). Formas estandarizadas de Windows y Apple para interaccionar con el usuario. − Diversas ventajas y presentación de ejemplo en página 3. − Tipos de ventanas .. p 4; Controles usuales p5; Uso de menús p14 − Mensajes diversos p15; Técnicas Drag&Drop p17 − Consideraciones de diseño p23−26 − Criterios diversos p38−39 − OOUI p40−44 Apuntes curso Programación Visual Basic 4.0 Ed. Empresarial Visual Basic 4.0 Herramienta de desarrollo rápido de aplicaciones en Sistema Windows: 16 Bits −−> Windows 3.11 y 32 bits −−> Windows 95 y Windows NT Herramienta de aplicaciones Cliente /Servidor distribuidas Herramienta de integración de aplicaciones OLE Herramienta de creación de servidores OLE Lenguaje Basic estructurado + conjunto de objetos windows manipulables a través de sus propiedades, metodos y eventos. Dos versiones de VB : 16 y 32 bastante compatibles entre sí HISTORIA 1991 VB 1.0 1 1992 VB 2.0 1993 VB 3.0 1995 VB 4.0 1998 VB 5.0 VB 4.0 se encuentra en tres formas comerciales: • Standard : Sin algunos controles y sin acceso flexible a la B.D. • Profesional : Sin desarrollo en grupo, sin OLE remoto, sin RDO • Empresarial : La más completa A parte de la diferencia de entornos de programación (16 y 32 bits), la versión de 32 bits, permite crear Archivos DLL OLE así como Servidores OLE. ESTRUCTURA DE UNA APLICACIÓN EN VISUAL BASIC Una aplicación VB consta de : − Código Fuente Conjunto de ventanas o Forms donde se insertan controles incluidas en el proyecto Físicamente con extensión .FRM Conjunto de clases y módulos que contienen código .BAS y .CLS − Conjunto de gráficos incrustados en los forms (Iconos, imagenes,etc..) .FRX − Conjunto de ficheros binarios correspondientes a los controles Extensión : .OCX , .OCA, .VBX , .DLL − Conjunto de ficheros binarios necesarios para ejecutar la aplicación (runtime system) : vb40016.dll, vb40032.dll, etc. ENTORNO DE PROGRAMACIÓN VISUAL BASIC − Ventana de código accesible a través de la Ventana de proyecto + Ver código o clickeando dos veces sobre el objeto deseado. − En la ventana de código se usan las combinaciones de edición standard de Windows : Ctrl + c Copia texto seleccionado al portapapeles ; + v Pega el contenido del portapapeles en el lugar correspondiente; + x Cortar ; + z Deshace la última acción realizada ; + y Borra la linea actual. − Barra pequeña sobre el indicador de scroll vertical, nos permite dividir la pantalla en dos partes independientes de visualización de código. − Ctrl + F2 sobre un procedimiento, nos llevará directamente a esa parte de código. Para volver de esta llamada Ctrl + Shift + F2 2 − Browser de objetos y métodos −> F2 − Tabular una selección y destabular : <Tab> y Shift + <Tab> − Mediante la misma ventana nos podemos mover hacia cualquier objeto del mismo formulario. − Diversas opciones respecto a aspecto del entorno en Opciones. − Podremos escribir dos sentencias en la misma linea utilizando el carácter de separación `:' − Podremos cambiar de linea en una misma sentencia con el carácter `_' (separado de todo) , al final de la linea. OBSERVACIONES AL USO DE FICHEROS − Cuando se elimina un archivo, solo se elimina la inclusión en el proyecto, el archivo sigue estando fisicamente en el disco. − Cuando se incluye un archivo en el proyecto, se tiene que tener en cuenta que el archivo se liga al proyecto actual, pero que ese mismo archivo puede estar ligado a otros proyectos simultaneamente, por lo que debemos posteriormente Copiar Como .. en nuestro directorio o con otro nombre. USO DE LA COMPILACIÓN − F5 actúa del mismo modo que Play; con Ctrl + F5 iniciamos una compilación con comprobación sintáctica de código, depurando más los posibles errores tipográficos. − Teclas útiles para el Debug: Ctrl + F9; Shift + F9; Ctrl + F8; F8; F9; Ctrl + Shift + F9 Quitar todos los Breakpoints, etc − Con el Ctrl + G, activamos el uso de la ventana de depuración (que mediante el menú contextual del botón derecho del ratón, podemos tenerla siempre visible), en donde hay dos partes: 1 Nos visualiza en todo momento el nombre y valor de las variables que hemos añadido a la inspección (con Shift + F9 + Añadir o mediante el menú, opción Agregar Inspección), podemos posicionarnos sobre una y borrarla con Supr. 2 Podemos visualizar cualquier variable mediante: ? <nom_var> o ejecutar la mayoría de instrucciones escribiéndolas directamente y pulsando <Enter>. El formulario inicial, con el que se iniciará la aplicación, se indica en opciones de proyecto. NOTAS DE COMPILACIÓN − Permite distinguir entre entornos de 16 y 32 bits; Constantes WIN16 y WIN32; instrucción #If Then#Else − Permite forzar el valor de algunas constantes Win16 = TRUE TERMINOLOGÍA VISUAL BASIC Formularios : Ventana de Windows en donde depositaremos los controles para crear el interfaz con el usuario. Controles externos (fotos) e internos (listas). Propiedades : Definen la apariencia y el comportamiento de cada control : de diseño, de Ejecución y de diseño y ejecución. 3 Eventos : Son generados por parte del usuario / exterior a nuestra aplicación, aunque se puede producir eventos en cascada. Es la diferencia fundamental de Vb respecto al tipo de programación estructurada de DOS. Proyectos: Conjunto de Elementos que conforma el sistema que creamos en VB. Procedimientos : Tanto Subrutinas (no devolución de parámetros) como Funciones (devolución), contendrán todo nuestro código y se activarán por respuesta a eventos o por decisión nuestra. LENGUAJE Visual Basic 4.0 Respecto al libro de Fco. Charte : A ; Respecto al libro de 2ia: B Cualquier comentario debe ir precedido al principio de cada linea con: ` , sin posiblilidad de marcar todo un párrafo como comentario. B2 − B4 Tipos de Datos, Constantes y declaraciones : A73, B2 Las variables pueden contener hasta un máximo de 40 caracteres incluyendo `ñ' y acentos y siempre comenzando con una letra. Por herencia del Basic antiguo no se han de declarar las variables antes a no ser que al principio de cada módulo obliguemos con la clausula : Option Explicit; esto lo podemos hacer de forma automática con una opción del menú. Dim Ámbito local (Módulo o Sub) = Private a nivel de módulo Public Variable global a nivel de módulo. Si .BAS para todo el proyecto. Por compatibilidad VB3.0 se puede utilizar en .Bas `Global' Private Solo utilizada para ese módulo (se utiliza mejor en programación con clases) Static A nivel de Sub, cuando acaba la subrutina no se destruye su valor, sinó que permanece. Las variables de tipo string pueden tener un tamaño de caracteres definidos : Dim P as String * 20 Es posible declarar variables : Dim a,b,c As Integer , pero no recomendable para tipos de datos complejos ya que pueden dar problemas y además es más lento. Posibilidad de una línea: Dim a As Integer , B As Boolean Valores Iniciales : A750 Todas las variables numéricas (y currency), se inicializan con 0, las booleanas con FALSE y las variant con vacio (empty). Práctica 1 Variables del mismo tipo con mismo comienzo de nombre: A85 DefDate D−F,P : Sin no se dice lo contrario las variables que declaremos como Dim X* donde X pertenezca al rango anterior, serán de tipo DATE. Solo la primera letra disponible. 4 Matrices: Si no indicamos la clausula : Option Base 1, el primer índice de una matriz será el 0, en caso contrario será el 1. Dim Medidas(9) As Integer ` Declara una matriz de 9 elementos enteros. Dim Medidas(5 to 14) as Integer ` 9 elementos con el índice comenzando en 5 y acabando en 14 Límite inferior : LBound(Medidas); L. Superior : Ubound(Medidas) Dim N(1 to 10, 1 to 10) as Byte Matrices Dínamicas: Aquellas que que se pueden redimensionar Dim P() as Byte . ReDim P(9) Redimensionamos a 9 elementos ReDim P(10) Aumentamos a 1 elementos perdiendo lo que tenemos ReDim Preserve P(10) Aumentamos 1 elemento conservando lo que tenemos ReDim Preserve P(9) Hemos perdido irremediablemente un elemento Tipo de datos Variant : A103, B5,6 Puede contener cualquier tipo de datos definido excepto cadenas de longitud fija. Ocupa hasta 4 * la ocupación de memoria del tipo original. Hasta puede contener matrices. Se convierte automáticamente al asignarle un carácter o una cifra o se le suma otra cifra,etc Valores especiales: Empty(vacío o no inicializado), Error, Nothing (apuntando a nada, para objetos), Null (Nulo) TypeName y VarType nos devuelven los datos que contiene una variable. Tipos de Datos definidos por el usuario : Private / Public Type Persona Nombre as String*20 ` Tipos de datos standard Edad as Integer Dir as Direccion ` Tipo definido por el usuario End Type Llamada: Persona.Nombre =Pepe Martín Las intrucción WITH es util para ahorrarnos el principio de llamada a un tipo de datos o Registro de Base de Datos: 5 Persona.Nombre=Pepe : Persona.Edad = 24 ` Es equivalente a .. With Persona .Nombre = Pepe .Edad = 24 End With Indicadores de tipos : A78 / Conversión de Datos : A86 Operaciones comunes : A88,90,91 / Funciones Generales: A95,96 Para las operaciones booleanas contamos con pocas instrucciones y siempre debemos conocer el valor booleano con el que tratamos. Ejemplo : Dim A,B As Byte : A=3 (0..011) : B=1 (0..01) : A AND B (Da como resultado 0..01; Multi. de bits) Funciones con Cadenas : A98 / F. con Fechas A100 CONTROL DE FLUJO: B8 , A197 Subrutina : Call para llamadas a una Subrutina, pero no necesario si esta solo tiene un parámetro.Los parámetros separados por comas. No hace falta indicar los paréntesis : Call Sumar a,b,c Private / Public Sub(<param>).. End Sub, definen el comienzo y final. Private se utiliza para que la subrutina no se pueda utilizar fuera del ámbito establecido. Exit Sub : salida incondicional de la subrutina. Funciones: Private / Public Function (<param>) .. End Function Exit Function : salida incondicional de la función. La devolución del parámetro es al final de la función y el valor que hayamos introducido en una variable que se crea que es el propio nombre de la función. Común Sub y Function : End X lo pone directamente el editor de VB. Los parámetros : A As Integer , B As Byte. Por defecto los parámetros se pasan por valor, pero esto se puede cambiar mediante la clausula anterior al nombre ByVal (por valor) o ByRef (por referencia). 6 Para pasar matrices : Nombres() As Integer Posibilidad de incluir un parámetro opcional con : Optional B ; el tipo siempre debe ser Variant. Para comprobar si se nos ha pasado el parámetro, se utiliza la función IsMissing(<Nombre>) devolviendo True si no nos lo han pasado. Sub X ( ParamArray Cadena() ) , podemos recibir cualquier parámetro y de cualquier tipo. Procedimientos de Propiedades: Normalmente utilizados a nivel de formulario, son procedimientos que se ejecutan sin necesidad de Call y correspondientes al formulario actual. Son tratados como propiedades. Property Let : Private Property Let X(Nuevo as String) End Property Property Get: Private Property Get X() As String End Property Bifurcar : Sentencias arcaicas en programación: GoSub línea .. Return : Saltar a una subrutina desde un procedimiento, posteriormente devuelve el control. La Sub se encuenta fuera del procedimiento. GoTo línea : Saltar incondicionalmente a una linea On expresión GoSub listadestino On expresión GoTo listadestino Tratamiento de ERRORES: On Error GoTo línea : Activar tratamiento de errores, saltar a una línea cuando se produzca uno. On Error Resume Next : En caso de error, no se notifique y que pase el control a la siguiente linea. On Error Goto 0 : Desactiva el tratamiento de errores, volviendo al estado normal de Windows que producirá un error que puede parar la ejecución. En caso que en procedimiento que no controla errores, llamado dentro de otro que si que tiene, se produzca un error, se saltará a la etiqueta que se ha definido en el procedimiento que llama al segundo. Ver sección de objeto `Errr'. Estructuras de Control : A189 , B11,12 If <Cond> Then /1 línea/ Else /1 línea / ; Entendiendo línea como una sola instrucción o como varias separadas con el carácter `:'. Uso de ElseIf <Cond> Then . La primera condición que se cumpla, ejecutará el código que contiene. A = Iif(B=5,1,2) equivalente a If B=5 Then A= 1 Else A=2 7 A=Switch(B=1,5,B=2,7,B>3,4) equivalente a If B=1 Then A=5 ElseIf B =2 Then A=7 ElseIf B>3 Then A=4 End If ` El primero que lo cumpla, ejecutará sus sentencias posteriores. Exit Do y Exit For For Each X in Y Next: X es un elemento de la colección Y. Para utilizarlo como bucle For normal (p.ej. recorrido de una matriz), X debe ser de tipo variant. Salidas del código : A11 Exit Function , Exit Sub Exit Do : Sale de un bucle de tipo Do. Exit For : Sale de un bucle For. End : Finaliza la aplicación completamente Stop : Suspende la ejecución Si sentido aparente DoEvents : Hace una pausa permitiendo que el S.O. efectúe atenciones a otras aplicaciones. Con mucho sentido en VB3.0 y en Windows 3.11 peró no en Windows 95 con Multitarea. Recurrir a esta instrucción si vemos un error que no atiende a razones. DISEÑO : Si borramos un control con código dentro, este código no se borra, sino que si volvemos a crear un control con el mismo nombre(mejor si es del mismo tipo), que el que habíamos borrado, recuperaremos este código dentro de este control. Controles : Los controles (no formularios) del mismo tipo, pueden agruparse en familias de controles que contienen todos ellos unas propiedades comunes y otras que no, la principal diferencia es la propiedad .Index que indica el número de índice del elemento en la matriz. Se crea a través de copiar y pegar, que pregunta primero o indicando el mismo nombre para dos controles distintos pero del mismo tipo y con propiedad .Index diferente. Para recorrer una serie de elementos de una matriz, tenemos la posibilidad de : For Each B in Botones .. Next ; 8 en donde Botones es una matriz de buttons y B es una variable de tipo Button o Object (lo más frecuente para evitar concretar); Esto sería equivalente a For i=1 To Max .. B = Botones(i) .. Next, lo que implica saber el máximo, etc : Botones.Count # de botones y Botones.Ubound lím. Sup. / Botones.Lbound lím. Inf.. Propiedades comunes a * controles (también formularios) : Link* : Nada TabIndex : Número de orden en cuanto a recepción de foco. Este orden viene dado por el orden de inserción de los controles. Si eliminamos un control, esta propiedad no se ajusta, pero si ha un control le damos un TabIndex que ya existe, los demás TabIndex se mueven en una unidad. Name : Nombre del control Caption : Texto mostrado al usuario. Text : Texto que contiene el control (substituye al caption en algunos crls.) Left, Top, Height, Width : Margen Izquierdo y Superior respecto al formulario que lo contien; en caso de formulario se refieren respecto a la pantalla. Altura y Anchura del control. Todo medido en twips (+/− vigesima parte de un punto de impresión). Alignment : Alineación del texto escrito. TabStop : Si cuando le toque tener el orden de foco, lo coge o lo deja pasar al siguiente. Backcolor, Forecolor: Colores de fondo y de primera instancia respectivamente. BackStyle, BorderStyle : Estilos de apariencia. Dragicon, Dragmode : Icono al generarse D&D y modo de este. Enabled : Si el control permite interactuar con el usuario. Font : Fuente de la letra utilizada. Tag : Propiedad inutil que la podemos hacer servir para introducir texto para nuestros propósitos. Mousepointer,Mouseicon : Icono que tendrá el ratón cuando pase por encima del control, en caso que este valor sea 99 (custum), se cambiará al valor indicado en Mouseicon. Apparence : Tipo de apariencia (3D, etc) Visible : Si el control se muestra al usuario o no. No visible implica por supuesto no enabled. WhatThisHelpId : Identificador para mostrar ayuda cuando se lo selecciona con botón WhatThisHelp. DataField, DataSource : Respecto a BD, de donde leera / escr. la información que contiene. 9 UseMemonic : Establece si se puede acceder al control con una Hotkey (&) Comando Move coord X, coord Y, Ancho, Alto: En tiempo de ejecución mueve un control (no lo posiciona) Eventos comunes: Link* : Nada click : Apretar return o ratón ; dblclick : Doble pulsación de ratón ; mousemove : Mover el ratón por encima ; keypress : Apretar una tecla general (caracteres alfanumericos) keyup / mouseup : Cuando se libera tecla, con combinaciones de teclas (Ctrl, Shift, Alt, Fx, etc) keydown / mousedown : Cuando se pulsa una tecla, las mismas combinaciones. dragdrop / dragover : Correspondiente al procedimiento Drag & Drop (posteriormente explicado) gotfocus / lostfocus : Cuando se gana o pierde el foco o propiedad de ser el control activo del formulario Change : Cambia el contenido Tipos Especiales: Todos ellos son tratados como objetos, ya que en realidad se comportan como tales, propiedades y se pueden agrupar en familias. Si en tiempo de diseño definimos un control (Formulario, Form o Control propiamente dicho, Control), estos también son objetos que se pueden pasar como parámetros (en realidad apuntadores) con todas sus propieades, etc Forms : Colección de controles dentro de un formulario en forma de matriz. Forms.controls() Control : Para la creación de un control en tiempo de ejecución, debe darse la premisa que haya una matriz de controles. El nuevo elemento tendrá la propiedad de no visible y por supuesto recogerá como herencia la mayor parte de propiedades de la matriz que lo acoge : Load X(Y) ` Siendo X el nombre de la matriz de controles y siendo Y el índice superior nuevo; Error si ya existe el elemento Y. El nuevo elemento no está visible al crearlo. Para la destrucción o liberación tenemos la instrucción Unload X(max). Otro tipo es el Object. 10 Por último existen los tipos correspondiente a un control específico: Dim P As Textbox .Al que le podemos asignar que se haga una copia de otro igual, etc DIVERSOS CONTROLES El nombre de los controles, se separa del nombre de sus propiedades mediante un punto `.'. FORMULARIOS A209, B2 Eventos: Load: Se genera cuando se carga un formulario. En este proceso se considera que no están visibles los controles por ello no podemos hacer según que procedimientos con los controles, como darles el foco. Activate : Se activa el formulario, se pude producir en múltiples ocasiones antes que el formulario se descarge (cada vez que coja el foco). Deactivate: Lo contrario que el evento anterior. QueryUnload: Se genera inmediatamente antes de descargar el formulario, con posiblilidad de cancelarlo a través del evento Cancel a un valor diferente de 0. Unload : Se genera cuando irremediablemente se descarga el formulario Resize : Se redimensiona el tamaño del formulario. Inicialize, Terminate : Eventos correspondientes cuando se trata un formulario como un objeto que se inicilza una nueva instancia con (Dim a As New F1). Paint : Dibujar Propiedades : AutoreDraw, DrawMode, DrawStyle, DrawWhith, ClipControls, Fill* : Correspondientes a propiedades de dibujo. ControlBox : Combinación de tres botones de dimensión en una ventana normal de Windows (esquina superior derecha). Icon : Icono que se presentará en la esquina sup. Izquierda, que da paso al presionarlo al menu de redimensión típico y cuando se minimiza, abanderá la ventana minimizada en la barra de tareas. KeyPreview : Índica si las tecla presionadas desde cualquier control, las recibirá el formulario si no se hacen caso desde el control. FontTransparent : Ínidca la transparencia de la fuente. MaxButton, MinButton : Ínidica si el formulario tiene el botón de maximizar / minimizar. MDIChild : ¿Es un formulario hijo respecto al MDI? 11 NegotiateMenus : Ínclusión de menús de objetos dentro de la barra menús del formulario. Scale* : Las propiedades de tamaño y posición referidas en el tipo de medición indicado por ScaleMode. ShowInTaskBar : (W95), índica si se debe mostrar el formulario en la barra de tareas. WhatsThisButton : Índica si el botón de `Qué es esto ?' aparece en el formulario. WhatThisHelp : Ayuda correspondiente a la propiedad anterior. WindowsStat : Modo en que se mostrará primero el formulario (maximizado, min. o normal). LABEL A123, B5 Autosize : El tamaño del control aumenta según aumente el texto que contiene. WordWrap : Expander H o Verticalmente cuando el texto crezca y la prop. Autosize sea True. FontSize,FontBold,FontItalic,FontUnderline,FontStrikethru : Definen la fuente. TEXTBOX A125 , B5 MaxLength : Longitud máxima de introducción de texto; si 0 es ilimitado. Locked : Índica si se inhabilita la edición. No confundir con enabled. HideSelection = F : La selección seguirá visible aún cuando el control no este activo. PassWordChar : Carácter utilizado para tapar la introducción de texto. Usado para que los demás no vean los chars introducidos. Multiline : Índica si puede tener más de una linea de introducción de texto ScrollBars : Barras de scroll vertical, horizontal o ambas, para mover el texto contenido dentro del textbox. SelLength, SelStart y Seltext : Longitud, Carácter de comienzo y Texto seleccionado en tiempo de ejecución. Las dos primeras son de también de escritura. COMMANDBUTTON A133 , B5 Cancel : Establece que el botón sea el predeterminado para cancelar una acción. Activado al hacer click, return o Esc cuando tiene el foco; los demás botones de este tipo tendrán esta propiedad a False automáticamente (solo uno la tendrá True). Default : Automáticamente y si no se indica lo contrario se enfocará este control en primera instancia, cuando se muestre el formulario. CHECKBOX A137, B8 Indican uso de booleanos, pero en realidad son triestados Unchecked (No−marcado), Checked (Marcado), Grayed, si no contienen valor. 12 Value : Indica uno de los tres posibles valores del control. Estro perjudica la agilidad de programación porque no podemos tomarlo como un booleano (2 estados); pero para ello tenenemos los controles de la Sheridan (Sheridan 3D controls), que hemos de añadirlos a la caja de herramientas Ctrl + T. Las diferencias de los controles de la sheridan son basicamente de aspecto exterior, pero en check permiten solo tener dos estados, lo cual puede sernos útil para simplificar. OPTIONBUTTON (RadioButton) A , B8 Normalmente en parejas y también indican uso de booleanos. Solo uno de los de su ámbito tiene la propiedad Value = True, automáticamente se anulan los demás. Puede ser que al principio, ninguno tenga el valor = True. Value indica si esta activado o no. (T/F) Práctica 2 / 3 FRAME (Marco) A131 , B7 Actúa de contenedor de controles, aislándolos de forma lógica y física del resto. Para introducir un control dentro no podemos arrastrarlo, ya que quedaría debajo, debemos cortar y pegar o introducirlo en primer lugar dentro. Clipcontrols : Para métodos de dibujo CONTROLES `SHERIDAN 3D CONTROLS' (1ª Parte) Frames, checks y options con posibilidad de colores. Check con solo dos estados y apariencia de vacio o marcado (X). Botones con posibilidad de incluir además de un texto, la visualización de un icono en la propiedad Picture. También colores. PICTUREBOX e IMAGE: A , B2 Los utilizaremos simplemente como mostrar una imagen. La diferencia es que picturebox nos permite dibujar dentro y hacer de contenedor de otros controles; pero ocupa muchos más recursos. Picture : = LoadPicture (<path>) o directamente una propiedad picture de otro control Evento Resize : Redimensión del control. En Image la propiedad Stretch hace un ajuste automático del tamaño del control al tamaño de la imagen. Práctica 4 CÓDIGO RESPECTO A FORMULARIOS: Formulario que se carga en primer lugar viene determinado por el menú de opciones de proyecto. También podemos comenzar por una subrutina llamada Main (única y sin posibilidad de parámetros de llamada), 13 siempre situada en un módulo BAS. Para obtener los parámetros de llamada a la aplicación existe la función Command que nos devuelve en forma de string los comandos. Uso de la palabra reservada `Me' para substituir el formulario activo en ese momento. Los formularios se cargarán con la propiedad .Show seguida 0 o 1 si queremos un formulario no Modal (por defecto y correspondiente a un formulario que no coge el foco de forma exclusiva) o Modal (cogiendo el foco sin posibilidad de pasar a otro formulario de la misma aplicación). Primero se genera el evento .Load Seguido de .Activate. Existe propiedad instrucción Load <nombre form> pero solo util cuando queramos agilidad a la hora de E/S en memoria y no se muestra nada todavía, por tanto deberíamos hacer .Show después. Para descargarlo completamente tenemos la instrucción Unload <NomForm> Si no descargamos un formulario, este continuará siendo mostrado. Para ocultarlo tenemos la propiedad .Hide Para referirse a los controles situados en otro formulario, debemos añadir a la izquierda del nombre del control, el nombre del formulario en donde se sitúa, seguido de un punto (aunque se recomienda el carácter `!'). El texto de preguntar si se quiere seguir con la posibilidad de salir del form, se encuentra en el evento QueryUnload. INTRODUCCIÓN STANDARD DE INFORMACIÓN Y VISUALIZACIÓN DE AVISOS: Para el aviso de información tenemos la función Msgbox, en donde se le pasa el mensaje de aviso, una serie de valores sumados (en forma numérica o ctes.), que indican el icono, el modo, los botones, en definitiva la apariencia de la ventana; el título que va a presidir la ventanita de aviso y por último valores de ayuda. Nos puede devolver valores dependiendo de la opción que hayamos pulsado. Para la recepción de información, y con un modo demasiado simple tenemos Inputbox, que nos devuelve el valor (en forma de string), que hayan introducido, después de clickear el botón de Aceptar. En caso de clickear Cancelar, nos devuelve una cadena vacía, por lo que no hay forma de saber si han pulsado cancelar o no han introducido ningún carácter. Práctica 5 USO DE MENÚS EN LOS FORMULARIOS : A167, B3 Mediante el icono de editor de menus, opciones o el shortcut Ctrl + E, accedemos al editor de menus. Cualquier menú ha de distinguir dentro una serie de niveles; estos se definen mediante los botones de cursor o Siguiente, etc que nos mueven el caption de los elementos de menús que vamos añadiendo. El nivel 0 corresponde a los elementos que se visualizan de forma horizontal. los de nivel 1 estarán dentro del nivel 0 que le corresponda, etc.. Todos los elementos deben tener un nombre para poderse referir a ellos en tiempo de ejecución. Index : Poder hacer una matriz de elementos de menus. Con lo cual también podemos construir un nuevo elemento en tiempo de ejecución : Load P(X), etc HelpContextId : Identificador de ayuda Shorcut : Combinación de teclas para acceder al elemento directamente como si lo hubiéramos presionado. 14 Solo se permiten en un nivel terminal de grupo (último). Negotiateposition: Nada Diversas opciones check Checked : Equivalente a convertirlo en booleano, activado / no con una marca en forma de V cuando está activado. Ej.: Color V, indica que la opción color está activado. If f1.elem1.Checked Then Enabled : Si la opción se permite tocar WindowsList : Normalmente solo una vez en un menú, indica los formularios hijos abiertos dentro de un MDI. Visible : Índica si se permite visualizar el elmento. Si en caption ponemos un guión (−), esto representará una raya al abrir el menú (también podemos hacerlo invisible y no enabled). Para introducir código dentro del único evento posible de menús, evento click, lo podemos hacer directamente clickeando sobre el menú creado o a través de la ventana de código eligiendo el elemento que queramos. Podemos tener diferentes formularios con menus, pero normalmente este se encuentra en el principal o MDI. Para el uso de menús emergentes (caso de menús contextuales), debemos establecer un menú de nivel 0, invisible y dentro de él introducir todos los elementos necesarios y esta vez visibles. La instrucción que hace posible la visualización es: <Nombre Form>.PopUpMenu <Nombre menu>; lo normal es tenerlo en el evento MouseMove para cuando aprieten el boton de la derecha: If Button = 2 Then PopUpMenu F1.Pepe SHAPE (Forma): A153 , B7 Nos permite tener formas simples como (Shape) cuadrados, rectángulos, óvalos, circunferencias, etc.., así como controlar el color (FillColor) y el relleno (FillStyle). TIMER (Temporizador): Con este control, generaremos eventos periódicos. Propiedad Timer : Donde indicamos en milisegundos el periodo de eventos. Evento Timer : Donde pondremos código para que se ejecute cada vez que se haya cumplido el periodo establecido. El primer evento se producirá X milisegundos después de la carga del control, siendo X el valor de la propiedad Timer. 15 Ejemplo : Podemos fabricar un reloj con una Label y un Timer; la propiedad timer = 1000 y en el evento timer incluiremos: label1.Caption = Format(Time,HH:MM:SS); con lo que cada segundo actualizará la label. (Reloj analógico 155) Práctica 6 LINE (Línea): Principalmente como separador de información en un informe, pero también es un elemento de dibujo. Color (BorderColor), Estilo (punteado, continuo, etc) (BorderStyle), Ancho (BorderWith), Posición en forma de 4 puntos cartesianos (X1,X2,Y1,Y2). SCROLLBARS (H & V) : A150 Principalmente para dibujo, ya que su función más adecuada sería de mover texto, y esto ya lo tiene incorporado el textbox. LISTBOX & COMBOBOX: A141, B9 Casi todos los mismos metodos para las listas se aplican a las combos. Las listas, como su nombre indica, son listas de elementos en forma de string, que pretende siempre abiertas, nos permiten elegir 1 o varios elementos sin posibilidad de introducir texto, mientras que las combo pueden permanecer cerradas, pueden permitir la introducción de texto y solo permiten una elección. En general las listas y combos se comportan como una matriz de strings, con lo que podemos recorrerlas con For .. Next o For Each .. In Next Propiedades comunes: Additem X : Añadimos el elemento X a la lista RemoveItem (X) : Borramos el elemento X de la lista Clear : Borra todos los elementos ListCount : Número de elementos. Le restamos uno para obtener el último índice. ListIndex : Retorna el elemento elegido. En caso de −1 nos indica que no se ha elegido ninguno. Text : Nos proporciona el texto que hay en la combo, por si han introducido por teclado o han seleccionado en la lista. Listas: Columns: Índica el número de columnas en que se muestra. Sorted: La lista aparecerá ordenada en orden AlfaB., solo en tiempo de diseño. List : En tiempo de ejecución podemos introducirles datos fijos 16 List (X) : Devuelve el elemento de índice X. Multiselect : Índica el tipo de selección; None 1 ; Simple Varios con una pulsación de ratón; Extended Con Shift + ratón, etc Selected (X) : Nos indica como booleano si el elemento de índice X ha sido seleccionado. ItemData (X) : Índicamos un elemento Long asociado a cada elemento String. Útil para asociar un texto a un número de registro de la B.D. Combos: Style : Estilo de la combo : DropDownCombo : Podemos introducir texto SimpleCombo : Siempre abierta e intro. Texto. DropDownList : No se puede teclear info, solo desplegarla. Práctica 7 DRAG & DROP: A485 Procedimiento standard de Windows, que nos permite llevar a cabo procedimientos considerados a través de la acción de forma gráfica del usuario, llevando un elemento desde un control hasta otro; control origen y control destino respectivamente. DragIcon nos indica para cada control, el icono que va a substituir al puntero del ratón, en el momento que se inicie la acción de D&D y hasta que soltemos el botón pulsado (en otro control o donde sea). Podemos obtenerlo del disco (LoadPicture) o de otro control (X.Picture = Y.Picture). La acción ha realizar, siempre depende de nosotros y en ningún caso implica nada más que lo que establezcamos en el momento de detectarse el procedimiento o en el momento de finalización. Eventos Generados en cada control: Tienen 3 parámetros comunes Objeto origen en forma de control, posición x y posición y en donde se encuentra el control. DragOver se genera cada vez que pasa por encima y por tanto generado en múltiples ocasiones. Además de los anteriores parámetros tiene 1 entero que indica el estado : VbEnter Acaba de entrar en el control; VbOver El objeto se está moviendo por encima del control y VbLeave El objeto acaba de abandonar el perímetro del control. DragDrop se genera solo cuando se suelta el elemento encima de un control. INSTRUCCIONES DE MANEJO DE ESTRUCTURA DISCO: El elemento activo, ya sea directorio o unidad, es aquel que permanece y al que se refiere cuando sin especificar nada leemos o escribimos en disco. ChDrive : Cambia de unidad activa hacia la que digamos. ChDir : Cambia de Directorio activo. 17 CurDir : Nos informa del directorio actual. RmDir, MkDkir : Borramos y creamos un directorio Dir (<Path>) : Nos da el primer fichero que encuentra en el directorio especificado, si lo repetimos nos devolverá el siguiente y así hasta que nos devuelva Nulo, indicando que ya no hay más, por tanto podríamos obtener la lista de directorios, haciendo un bucle hasta que devuelva nulo. Dir (<Path + archivo>) : Nos devuelve nulo si no existe el archivo especificado. Su uso no es recomendable por su mal funcionamiento. Para saber si existe un fichero y como substituto bastante bueno, podríamos intentar abrir ese archivo en forma de lectura (como se verá más adelante)y si nos lo permite, sabremos que existe, en caso contrario nos provocará un error que debemos controlar. DRIVELISTBOX, DIRLISTBOX, FILELISTBOX: A375 Se comportan como 2 combos y una lista respectivamente, pero con funciones especificas para la visualización de información de unidades, directorios y ficheros. DriveListBox : Sabremos que unidad nos han elegido, a través de evento Click(), propiedades y métodos List, ListCount, ListIndex, etcDrive nos ofrece la unidad actual. DirListBox : Siempre referido a la unidad actual. Path nos devuelve el directorio actual. FileListBox : PropPattern = *.* o *.txt; *.bmp; *.lll; nos permite solo seleccionar el tipo de archivos que queramos. También existen las propiedades Archive; Normal; ReadOnly y System. Ejemplo de funcionamiento: Generación de eventos en cascada. (En unidades1) On Error Resume Next directorios1.Path = unidades1.Drive If Err Then ` Utilización como booleano, si no hay ningún error, la ` variable err = 0, con lo que ` la evaluación booleana da como resulatado False. MsgBox Fallo en la unidad elegida EndIf On Error Goto 0 ` Desactivamos detección errores Esto provoca evento en el control directorios1. (En Directorios) archivos1.Path = directorios1.Path CUADROS DE USO COMÚN(CommonDialog): A215 Los cuadros de diálogo común, son aquellos que en Windows nos permiten 5 funciones: Abrir / Guardar 18 Archivo, Elegir Color, Elegir Impresora y Elegir Tipo de Letra. (Ejemplo : Abrir Proyecto de Visual basic). El aspecto de estos cuadros, dependen de las versiones de Windows que tengamos, ya que nos permitirán hacer algunas funciones avanzadas o no. Respecto a los cuadros de Archivos, los podemos substituir por los controles FileListBox, DirListBox, etc.., pero su uso es más sencillo y las opciones que ofrecen son mejores, mientras que con la combinación de los 3 controles anteriores, nos permiten tener un mayor control sobre lo que permitimos ver. En la propiedad en tiempo de diseño de Personalizado (agrupación); encontramos una serie de opciones agrupadas. Filter : Filtro sobre el que visualizaremos los ficheros CancelError : True provocará un error detectable. Cuidado pq hemos de controlar el error. Action : Especificamos y lanzamos el tipo de dialogo que queremos FileName : Nos devuelve el nombre de fichero que han elegido Flags = &OOO Serie de opciones. Por ejemplo obligamos ha que el fichero elegido exista, etc (A218) FileTitle : Nos devuelve el nombre simple del archivo FilterIndex : # de filtro activo (1º = índice 1) ShowOpen ShowSave ShowPrinter ShowColor ShowFont : Diferentes formatos de CommonDialog Ejemplo : Dim filtro,fichero As String Dim cancelado as Boolean On Error Goto Errores filtro = BD (*.Mdb)|*.MDB|Todos|*.* While Not Salor dialogo1.Filter = filtro dialogo1.CancelError = Tue dialogo1.Action = 1 19 fichero = dialogo1.FileName If cancelado Then Exit Sub ` Han cancelado Salir = Not Isnull(Dir(fichero)) Wend Errores : If Error = X Then `X es el número de error cancelado = True ` Indicamos que se ha cancelado Resume Next Endif Práctica 8 CONTROL DE ERRORES: A233 Poseemos el objeto en Vb `Err' que nos permite controlar y conocer los errores que se han producido como los que se pueden producir. Number : Nos indica el número de error que se ha producido. Description : Nos devuelve un string indicando el error producido. Si es en versión castellana tanto Windows como Visual Basic, este error puede darse en castellano. Source : Cadena informativa de donde se ha producido el error, Subrutina o objeto generalmente. La función Error nos devuelve la descripción del error sin que este se produzca en realidad, como una matriz: h = Error (23) Métodos : Clear : Nos permite borrar cualquier referencia a un error producido y por tanto detectado en Err. Raise : Nos permite Provocar un error. Muy útil para conversación entre aplicaciones. Su uso es rellenar las 3 propiedades del objeto Err y posteriormente lanzarlo con `Err.Raise' o hacer esto último pasándo los 3 parámetros. USO DEL DEBUG : A249 <Recordar Uso Debug explicado anteriormente> Para la ventana de Debug (Ctrl + G) tenemos : Objeto Debug para nuestro uso. Print X : Nos permite imprimir en la ventana, el string X. Útil para pruebas de funcionamiento. Control + L Nos permite ver las llamadas que hemos estado realizando hasta el momento. Es la impresión de 20 las direcciones de retorno de la pila, en forma de nombre de procedimientos. En cualquier momento, podemos parar la ejecución normal del programa, con Ctrl + Pausa y entrar en modo Debug. FORMULARIO COMO COLECCIÓN: A209 Podemos acceder a los controles contenidos en un formulario, mediante la colección de controles dentro del formulario : Formulario1.Controls(X) donde X es el índice de control que es el orden en tiempo de diseño. Podemos saber el tipo de control, el nombre, etc, ya que lo que nos devuelve es un tipo Object. El número de controles lo indica propiedad Count : Formulario1.Count nos da el número de controles que existen en el formulario. Los índices comienzan en el 0. Podemos utilizar el método Move, para mover el formulario. FORMULARIO M.D.I.: A335 Se definen como Multiple Document Interface o Interfaz de documento múltiple. Son las ventanas `Padre absolutas', de ellas pueden depender las llamadas `Ventanas/formularios hijos'. Ejemplo claro : Ms−Word en donde podemos crear diferenentes documentos que serán ventanas hijas y siempre sujetas a la ventana padre MDI. Características: • Las hijas no pueden salir del ámbito del padre, siempre estarán dentro, por lo que si minimizamos quedarán en una esquina. • Solo puede haber un formulario MDI en cada aplicación. Las ventanas hijas se indican mediante la propiedad MDIChild = True. • Podemos crear cuantas ventanas hijas queramos en tiempo de ejecución (clónicas) a través de un modelo de hija. Podemos visualizar formularios dentro de un MDI y que no sean hijos suyos. • Los hijos no pueden mostrarse de forma modal (y por tanto dándoles el control de foco). • Podemos saber las hijas que tenemos abiertas, cambiar de una a otra y saber cual es la que está activada (con un Check), mediante el Editor de Menu con la opción de `WindowsList'. Formularios MDI: Se comportan igual que un formulario normal excepto : − Se crean desde el menú Insertar .. Formulario MDI. − No pueden tener fondo. − Solo pude tener controles que tengan propiedad `Align', solo PictureBox entre los standard. Podemos insertar uno diferente, a través de un PictureBox. − Si se descargan, se descargarán todos sus hijos. AutoShowChildren : Cuando se crea una ventana hija se muestra automáticamente esta. ActiveForm : Nombre del formulario hijo activo del padre. 21 ScrollBars : Barras de scroll. Arrange <Valor>: Ordenación de los formularios hijos. Valores VbCascade , VbTileHorizontal, VbTileVertical, VbArrangeIcons que significan respectivamente Cascada, MosaicoHorizontal, MosaicoVertical, Ordenar iconos minimizados. Formularios Hijos : Podemos crear un clónico de un modelo de formulario hijo, mediante: (existencia de formulario hijo con Name : Modelo) Dim NuevoHijo As Form Set NuevoHijo = New Modelo o equivalente : Dim NuevoHijo As New Modelo Si solo hacemos: Set NuevoHijo = Modelo, crearíamos una apuntador directo al formulario hijo modelo, por lo que todo lo que hiciéramos con NuevoHijo repercutiría en Modelo. Creando un nuevo formulario se crea NO−visible al incio si no se indica lo contrario en el padre con AutoShowChildren. Se heredan todos los atributos. El código de eventos será igual para todos. Como consecuencia no utilizar la palabra Me en vez de Name puesto que repercutirá en el formulario activo en ese momento. Cuando se maximiza un formulario hijo : el menú substituye al del padre y el caption del padre se concatena con el del hijo : Fpadre − [FHijo]. Podemos acceder a todos los formularios abiertos : Dim v as Form ` Temporal For Each v in Forms ` Recorrido total de la colección de formularios ` abiertos de la aplicación. If TypeName(v) <> `Principal' Then Unload v Next OBJETO SCREEN: A267 ActiveControl : Nos devuelve el CONTROL activo en ese momento, dentro de la pantalla Control activo del Formulario activo. ActiveForm : Nos devuelve el formulario activo. FontCount : # de fuentes disponibles. MousePointer : Establecemos o leemos el puntero del ratón, que será igual para TODA la pantalla. Útil si cada 22 control tiene su propio puntero y por tanto para poner reloj de espera deberíamos indicarlo control por control. Width, Height, etc : Tamaño de la pantalla. Práctica 9 MASKEDITBOX: A158 No es más que una textbox con una mascara o filtro de introducción, para evitar que nos introduzcan caracteres que no queremos. Su uso y su aspecto es idéntico al utilizado en Ms−Access. ClipMode : Si al cortar elegiremos los caracteres literales. Mask : Carácter indicador sobre el tipo de carácter que nos deben introducir. Debemos escribir uno para cada uno que esperamos. Diferentes tipos : # : número; ? : letra; A : dígito o letra; &: Cualquier carácter. Cualquier otro carácter, se tomará como un literal (/, (, ),etc) PromptChar : Carácter substituto del cursor. PromptInclude : Incluye literales en la propiedad .Text FormattedText : Texto con datos y máscara completa. ClipText : Texto sin literales Format : Formato de impresión en pantalla. AutoTab : Para cuando acabe que salte Evento `ValidateError' : Se produce cuando se intenta entrar un carácter no válido. Nos devuelve la posición y el string con el error incluido. FICHEROS Y ARCHIVOS : A353, B13 Dir : Ya explicado Kill <archivo> : Borramos el fichero. No avisa FileCopy <FichOrigen> <FichDestino> : Copia un fichero sobre otro. Si el destino existe, lo machacará. Name <FichOrigen> <NomDestino> : Cambia el nombre al indicado. Si existe ya un fichero con el mismo nombre, provocará error. Dim Atr as Long Atr = GetAttr (<Path>) ` Creamos máscara de atributos del archivo. If Atr And VbReadOnly ` Comprobación de la mascara con valores binarios en VbHidden ` forma de constante. VbReadOnly = 1 = 00..01, con VbSystem ` lo que si Atr = xx..101, Atr And VbReadOnly = 23 VbArchive ` x101 AND 0..01 el resultado el 0..1 con lo que la ` evaluación booleana es cierta y por tanto es de Lectura. Com SetAttr, establecemos los atributos de un archivo. FileDateTime(<Archivo>) : Leemos o establecemos la Fecha y Hora de creación del archivo. FileLen (<Archivo>) : Obtenemos la longitud del archivo. Creación y uso de archivos : Dim r A Integer ` Definimos una variable para utilizarla como canal r = FreeFile() ` Pedimos permiso de canal libre. No obligatorio Open <Nombre completo de archivo> For <Modo> As #r ` Tenemos 1511 canales disponibles ` Si no definimos nombre completo (path), lo creará en el CurrentDir. Para cerrar cualquier archivo, se utiliza : Close #canal : Cierra el canal Reset o Close : Cierra todos los canales abiertos FileAttr : Nos devuelve el modo de apertura de un fichero abierto con open EOF(#canal) : Indica si se ha llegado al fin de fichero. Lock,Unlock : Nos permite controlar el acceso a todo o parte de un archivo abierto. También podemos Bloquear el archivo directamente con la instrucción `Open'. Loc : Posición del puntero de un archivo abierto. 3 posibles modos de apertura : Texto (1); Registros (2) y Binarios (3) • OutPut Si no existe se crea. Modo de escritura. Machaca el contenido anterior. InPut Debe existir, si no provoca error. Este es un buen sustituto del Dir para saber si existe un fichero; lo intentamos abrir de este modo y si da error, lo detectamos y sabemos que no existe. Append Lectura / Escritura y los datos se añaden al final. No se machaca nada. Tab : Nos permite indicar posición de salida Para escribir : Print #<Canal> X Escribe en una linea diferente el str X Print #<Canal> X;M Escribe juntos X eY Print #<Canal> X ,M Escribe hasta el sig. pto. de tab. 24 ` Preferible para escribir solo texto. Write #<Canal> X [,Y] Escribe separando los elementos del fichero por comas.Cadenas entrecomilladas. Para leer: Input / LineInput #<Canal>,X,Z,Y La diferencia es que el primero cuando encuentra TAB o separación va metiendo los datos en las variables; el segundo solo admite carácter <Cr> o Chr(10) como separador • Los ficheros de registros son aquellos que tenemos guardados elementos de una longitud fija; normalmente de Tipos estructurados de datos (tuplas o types), pero podríamos tener un fichero dedicado a reales que indican valores obtenidos de la altura de personas, etc.. Open <> For Random As #1 Len = <# de bytes que ocupa el elemento> Si no conocemos la longitud de los elementos a guardar, la podemos obtener mediante : Len(variable del tipo elemento a guardar) Si no existe lo crea y si existe solo añade. Para escribir / leer : Put / Get <#canal>,[<#registro>], variable Si no se especifica el registro donde vamos a leer o escribir, se efectúa la operación sobre el registro activo. Para obtener el # de registros totales del fichero : Lof(#canal) / Len(variable del tipo elemento) Lof(#canal) Nos devuelve la longitud de un fichero abierto con Open Seek #Canal, #registro Posiciona el puntero en el registro indicado • Abrir un fichero binario, equivale a poder hacer lo que queramos con el fichero, siempre que sepamos entender lo que estamos leyendo, ya que la información presente son bytes, por lo tanto pueden contener caracteres, números o parte de otros tipos de datos. For Binary Si no existe crea el fichero Put / Get <#canal>, A, B A = #byte a partir del cual leeremos/escribiremos. B = variable que escribe o utiliza para leer. El número de bytes que lee/esc. Vendrán especificados por el tamaño de la variable que indicamos en B. InputB <#Bytes a leer>,<#canal> : Leemos un grupo de bytes y por tanto el puntero del fichero es el que indica la posición del archivo. Práctica 10 25 OBJETO PRINTER: A501 Dim P as Printer DriverName, DeviceName : Nombre del driver y dispositivo utilizado. Solo lectura. Orientation : VbPRORPortait Or. Vertical VbPRORLandScape Or. Horizontal o apaisada PaperBin : Alimentador PaperSize : Tamaño del papel definido Width / Height Tamaño del papel definido por nosotros en twips. Para otras unidades ScaleMode p.ej. VbMillimeters ScaleHeight y ScaleWidth nos dan los tamaños dependiendo de la unidad indicada anteriormente TwipsPerPixelX, TwipsPerPixelY : Twips por cada pto. físico Fonts : Matriz de tipos de letra (comienza en 0) = FontBold, FontItalic, FontUnderline, FontStrikethru, FontSize, FontName FontCount : # de fuentas ColorMode : VbPRCMColor, VBPRCMMonochrome ; indicamos posibilidad de color. PrintQuality : 75, 150, 300 puntos por pulgada (ppp) o también VbPRPQDraft, VbPRPQLow, VbPRQMedium, VbPRPQHigh Copies : # de copias ha imprimir. El modo de realización depende de la impresora (intercalado, una tras otra, etc) Zoom : Algunas impresoras ajustan el tamaño, las de tipo Postscript Colección de impresoras : Printers, por tanto es una matriz de Printer y se puede utiliar Ubound y Lbound. Solo podemos obtener información. .Count : # de impresoras dadas de alta en el sistema. Asignar una impresora por defecto : Set Printer = Printers(1) EndDoc : Finaliza el documento y manda a la cola de impresión lo que tenemos. Print S : Imprime el string S. Pset : Impresión de un punto. Line : Impresión de una linea. 26 Circle : Impresión de un círculo PaintPicture : Imprimir el gráfico a través de un picture de PictureBox o Formulario. CurrentX, CurrentY : Posición del cabezal de impresión. La 1ª vez o cuando se cambia de pagina, determinan la esquina izquierda de la página. Page : Solo de lectura, nos indica la página activa. NewPage : Implica una nueva página. KillDoc : Cancela el documento actual Si estamos debugando un programa que utiliza la impresora, y paramos la ejecución, todo lo que hayamos impreso hasta el momento, lo mandará a la cola de impresión. Puede ser que cada vez que cambiemos de impresora, no nos respeta las fuentes ni su tamaño. Para solucionarlo, deberemos inicializarlo o refrescarlo cada vez que cambie de página. Tendremos problemas si mezclamos el objeto Printer con mandar a la impresora secuencias de escape. ACCESO A LA API DE WINDOWS: A521 API = Conjunto de funciones y procedimientos standard que ofrece el sistema. Lo complicado es encontrar una función o procedimiento que se ajuste a nuestras necesidades. Tenemos una serie de documentos texto y ayuda en el directorio WinApi32 dentro del directorio donde se ha instalado Vb. Unicamente debemos declarar la función o procedimiento que vayamos a utilizar en la zona de declaraciones de un módulo Bas: Declare Sub/Function <Nombre> Lib <Nombre librería> ([<parametros si los hay>]) [As <tipo que devuelve>] Tenemos que tener en cuenta, si estas declaraciones necesitan un tipo de datos predeterminado o una serie de constantes, por lo que deberemos construirlo nosotros, simplemente copiándolo del archivo donde se indique. Cuidado con la versión castellana porque suelen traducir el nombre de las librerías. También debemos tener cuidado al elegir las sub/func que son de un tipo de Windows u otro (16 o 32 bits), con lo que podemos introducir una directiva : #If Win16 then Declare Type JOY End Type #Else Declare 27 #End If Win16 nos indica en que sistema estamos. En las opciones de compilación, podemos forzar el valor de Win16. Con #Const , declararemos constantes utilizadas solo en tiempo de compilación, no de ejecución. Práctica 11 (Explicar progressbar y gauge1º) DIVERSOS CONTROLES: SHERIDAN 3D CONTROLS (2): A610, B7,9,13 SSTab : Nos permite simular organizar controles en diferentes pestañas como si de una carpeta con separadores se tratara. Se asemeja a agrupar controles con un Frame. Su propiedad más importante es TabIndex, que nos indica la pestaña en la que estamos actualmente. SSRibbon: Boton o grupo de botones, de forma que cuando se presione, queda undido gráficamente para indicar que está activado y en la segunda pulsación, vuelve a su estado normal. En caso de un grupo de botones, podemos hacer que cuando se pulse uno, los demás queden liberados. SSPanel: Panel que puede actuar de forma versatil, simulando un gauge (asignando a la propiedad. floodpercent un porcentaje, automáticamente lo visualiza de forma gráfica y de cifra), Puede contener texto, diferentes formas gráficas (colores, esquinas, etc..). ANIMATTEDBUTTON : A587, B5 Un simple botón, que puede mostrar una imagen en movimiento o cambiar de imagen cuando se pulsa. GRID (Rejilla) : A297, B10 Muestra información en forma de filas y columnas que nos permiten leer y escribir de forma ordenada. TOOLBAR : B6 Nos permite hacer una barra de herramientas horizonal (barra de diferentes iconos), a los que asignar código. GRAPH : A285, B12 Gráficos estadísticos de diferentes formas. PROGRESSBAR : B3 Nos permite indicar gráficamente la progresión de una acción que se está realizando. Normalmente cálculos o lectura de registros. Solo hemos de aumentar la propiedad `Value'. GAUGE : A592, B12 Equivalente al anterior, pero podemos disponer de más opciones de aspecto: Forma vertical, horizontal, semicirculo, círculo, etc.. y también modificando la propiedad Value. MHSTATE: 28 Nos permite controlar y visualizar el estado de teclas especiales, como `Num Lock' , `Supr', etc.. COMUNICACIÓN SERIE (MSComm) : A563, B11 Control que mediante las propiedades correspondientes nos permite enviar y recibir información por el puerto serie. Propiedades corresponedientes ha : elegir el puerto serie, elegir parámetros (velocidad de transmisión en baudios, número de bits, etc..), definir si ha de haber evento cada vez que se envíe, definir tamaño buffer entrada y salida, etc.. Solo disponemos de un evento, el de recepción o envío. RICHTEXTBOX : B4 Equivale a una textbox, con la particularidad que le podemos asignar un archivo .RTF que puede contener tipos de letras diferentes, tamaños, colores, etc.. Con la propiedad `Acerca de ', podemos darle la forma deseada (Locked, Enabled, etc..). Solo disponible para la versión de 32 bits. SLIDER : B4 Mediante una forma gráfica el usuario puede darnos un valor a una variable que indique algo. Ejemplo de volumen. OUTLINE : A601, B15 Equivalente a las Listas normales pero introduciendo la posibilidad de presentar los elementos en forma jerárquica, donde cada elemento pertenece a un nivel. STATUSBAR : B5 Es la barra inferior de muchas aplicaciones, con nos ofrece información sobre lo que está activo en nuestra aplicación (May, Supr, etc..) o reloj, fecha, etc.. Son una serie de objetos panel que permite tener texto o imágenes. USO DEL PORTAPAPELES: A417 Se accede a él a través del objeto ClipBoard : . Seltext = <Texto> copia texto en el portapapeles . Seldata = X.picture ó Loadpicture(C:\...) para dibujos BMP o WMF Puede contener los dos tipos de datos a la vez. Para pegarlo en algún sitio, hemos de igualarlo a : .Gettext texto y .Getdata gráfico Getformat + | VbCFBitmap BMP / VbCFDib Gráfico BMP independ. VbCFText Texto / VbCFMetafile WMF VbCFPalette Paleta de color / VbCFLink Enlace DDE 29 • Devuelve True o False si el contenido del portapaeles es de ese tipo. .Clear limpia el portapapeles (graf + texto) ( algunas aplicaciones lo realizan automáticamente al hacer una copia al portapapeles. Ejemplo Word). DDE: A425 (Dynamic Data Exchange) Origen ) <Petición> (Destino Usaremos 3 controles : Textbox o Label texto y PictureBox Gráficos. . LinktopicNombre de la aplicación a establecer diálogo + `|' + tema (normalmente un archivo donde se encuentra la información). . LinkItem Donde se almacenarán los datos a transmitir. . LinkMode VbLinkNone No existe conversación VbLinkAutomatic Actualización auto. de datos. VbLinkManual Act. bajo petición destino VbLinkNotify Notificación de cambios origen y destino Normalmente Vb es destino, si actúa como origen; el nombre para contactar, será el nombre de nuestro ejecutable; el tema será el nombre de nuestro formulario (al no indicar lo contrario). En el formulario : .LinkMode = VbLinkSource .LinkTopic = Tema Ofrecer en el portapapeles información : Clipboard.Settext X | Y ! Z , VbCFLink X Nombre del proyecto o ejecutable sin extensión. Y Tema = Prop. Linktopic del formulario. Z Nombre del ctrl. Donde está la información ofrecida. Clipboard.Settext Y.Text Al Copiar al portapapeles con VbCFLink y desde una aplicación hacer Pegado Especial o Pegar Vínculo Automáticamente al cambiar al Ctrl. que hemos ofrecido, se cambiará al mismo tiempo. Activar el enlace automático con caja de texto (X). CadenaDDE = Clipboard.Gettext(VbCFLink) (Tema) X.LinkTopic = Left(CadenaDDE,Instr(CadenaDDE,!)−1) 30 (Elemento) X.LinkItem = Mid(CadenaDDE,Instr(CadenaDDE,!)+1) (Enlace auto.) X.LinkMode = VbLinkAutomatic Para terminar la conversaciónn DDE : X.LinkMode = VbLinkNone Otros Modos : • VbLinkNotify Generación de evento de notificación por parte del origen cada vez que se modifica. Nos avisará con el evento LinkNotify y si queremos actualizar LinkRequest. • VbLinkManual Actualización entre origen y destino se realiza bajo demanda. Para pedir la actualización, se hace con el método .LinkRequest para cada uno de ellos. Otros eventos: LinkOpen Al abrirse. LinkClose Al cerrarse. LinkError Al producirse un error en la conversación. LinkExecute Permite ejecutar macros y otras cosas. LinkPoke Actua al revés que el anterior. El Ctrl. origen se actualiza con lo que hay en el destino inmediatamente. Conversación vb como origen Cuando intenten establecer conversación recibiremos un evento : LinkOpen Form_LinkOpen Nos Ofrece el parametro Cancel que permite denegar el inicio de conversación. Evento de cierre de conversación : LinkClose. Cuando quieran hacernos ejecutar algo a nosotros Recibiremos el evento LinkExecute (1os. Parámetros = cadena con orden de ejecución + parámetros y 2º parámetro Cancel, indica si va a ser posible su ejecución; ya que nosotros seremos quien ejecutemos o no lo que nos piden. Si no queremos que establezcan comunicación, debemos dar Cancel = True en el evento LinkOpen o dar el valor VbLinkNone a la prop. LinkMode. Si durante el diseño asignamos a `LinkMode' el `VbLinkSource' podremos en diseño cambiarlo, sin embargo si no, en tiempo de ejecución no podremos alterarlo. Ejemplos en página 441. ARCHIVOS DE RECURSOS 31 Almacenan texto, títulos o gráficos fijos en nuestra aplicación que se agrega al ejecutable pero no se carga en memoria como se haría en el caso normal. Solo se cargan en memoria los necesarios. No es posible crearlos desde VB, la mayoría de compiladores de C y C++ tienen un editor de recursos que a cada recurso (elemento) le asigna un identificador numérico. Archivo normal : .RC pasa a texto normal. Archivo compilado : .RES Texto normal a compilado Para añadir estos archivos al proyecto, debemos hacer: Add File ; Solo se puede añadir un archivo de recursos por proyecto. Funciones : LoadResString(1) / LoadResPicture(2) / LoadResData(3) 1.− Dándole el indentificador; nos devuelve un texto. 2.− Parámetros: Id. De recurso ; VbResBitmap Bmp VbResIcon Icono VbResCursor Cursor 3.− Para cualquier otro tipo. Los archivos de recursos son bastante útiles para la traducción de una aplicación hacia otros idiomas. MANEJO DE BASES DE DATOS: A617 Visual Basic, utiliza el mismo motor de Access para manejar las bases de datos, Ms MotorJet 2.0 y por tanto hereda las mismas características que access para algunas acciones, como el dialecto de SQL utilizado(Access−SQL). El manejo se hace a través de dos sistemas, los DataControls o controles de datos, que actúan de intermediario entre los controles de la aplicación que están ligados a ella y la Base de datos. El otro sistema es actuar mediante DAO (Data Access Object) que simplemente es un conjunto de sentencias y procedimientos para poder trabajar con los datos. La ventaja de utilizar DataControls es su facilidad de ahorrar trabajo cuando hay cantidades grandes de información, ya que con una rejilla de datos, podemos cambiar lo que queramos del registro que queramos, mientras que con DAO debemos mostrar en cada momento el que vamos a agregar, borrar, etc. Los DataControls dan muchos problemas. A partir de ahora definiremos Recordset como el conjunto de registros con el que vamos a trabajar, ya sea de una misma tabla o de varias. DATACONTROLS Los metodos que definamos ahora, se aplican igual para DAO pero mediante código, no por ventanas. Al igual que lo que definamos después, con la particularidad de actuar sobre el objeto Recordset contenido en ellos. 32 Lo que en más utilizaremos de un DataControl es el objeto Recordset (una parte de él), con lo que estamos trabajando con un tipo de datos similar al que utilizaremos en DAO y por tanto con los mismos métodos y propiedades. Los marcados con ** no son extrapolables a D.A.O.. *** DababaseName : Nombre completo de la base de datos o directorio donde se encuentran los múltiples fichero (Ej. Dbase *.DBF, *.NDX, etc) RecordSource : Tabla o consulta almacenada en la base de datos o sentencia SQL tipo `SELECT'. RecordsetType : (1) VbRsTypeTable Datos procedentes de una tabla • VbRsTypeDynaset De 1 o más tablas actualizables • VbRsTypeSnapshot De 1 o más tablas no actualizables. 1 solo datos de una tabla, por tanto no se permite una sentencia SQL en RecordSource. Tipo 2 y 3 si que lo permiten. 1 carga en memoria el registro actual. 3 carga todos los datos en memoria. 2 carga referencia a cada registro y en memoria solo existe el actual. A consecuencia de lo anterior, un SnapShot no se da cuenta de las modificaciones que le pueden estar produciendo en una BD desde otra máquina que comparta la BD. Refresh : Hace que todos los cambios que se han realizado, se materialicen. CollatingOrder : Secuencia de ordenación de la Base de Datos. Updatable : Lectura / Lectura y Escritura Connect : Tipo de B.D. Version : Da la versión del tipo de la BD Propiedad Options : (Para DAO a la hora de definir un RecordSet) dbDenyWrite : Denegar Escritura a otros usuarios. dbDenyRead : Denegar Lectura dbReadOnly : Los datos no pueden ser modificados dbAppendOnly : Solo es posible añadir datos dbInconsistent : Permite añadir incluso con inconsistencias en la relación entre datos dbConsistent : Permitir añadir solo si no hay inconsistencias. dbForwardOnly : Solo es posible moverse al siguiente registro no al anterior. dbSeeChanges : Generar error si otro usuario intenta editar un registro. 33 Cada vez que vayamos a construir un recordset debemos pensar quer requisitos realmente necesitamos, ya que si restringimos algunos usos superfluos para nosotros, podremos aumentar la velocidad de trabajo del código. Un claro ejemplo es un recorrido por una tabla que lo podemos hacer perfectamente desde el primero hasta el último solo avanzando y por tanto utilizar dbForwardOnly y así el código ganará en velocidad. *** EOFaction VbEOFAction | MoveLast Permanecer en la última fila. EOF Posicionarse después de la última fila. AddNew Añadir una nueva fila y posicionarse en ella. BookMark : Marca de la posición en la RecordSet. Se considera como una marca de lectura de un libro. Se asigna a un string. DEFINIR RECORDSETS MEDIANTE DAO Para definir uno, debemos establecer primero sobre que BD estamos trabajando. Definir un área de trabajo de la BD (no obligatorio y por defecto ya se asigna). Esto es útil para que posteriormente nos de información, usuarios que la utilizan, passwords, etc Por defecto se utiliza el WorkSpaces(0) Dim Db As DataBase Set Db = [WorkSpaces(0).]OpenDataBase (<Path>, [opciones diversas]) Definimos un RecordSet : Dim R as RecordSet Set R = Db.OpenRecordset ( A , B, C) A = <nombre tabla> o Sentencia SQL (cuidado con el tipo de recordset después) B = dbOpenTable / dbOpenDynaSet / dbOpenSnapShot C = [dbForwardOnly y demás opciones vistas anteriormente] Propiedades del RecordSet : .RecordCount : # de Registros contenidos dentro. Esta propiedad no va muy bien y para asegurarse su correcto uso, deberíamos estar situados sobre el último registro. AddNew : Comienzo de proceso de añadir nueva fila o registro. Edit : Edita el registro actual para modificarlo. Update : Realiza las modificaciones o da de alta un registro (complemento de Edit o AddNew) 34 CancelUpdate : Cancelar últimas modificaciones (antes de hacer Update). Delete : Borra registro actual. Después es recomendable reposicionarse en algún registro, para saber donde estamos exactamente. [Solo para Dynaset ?? y snapshot] FindFirst : Posicionarse en un registro si ha encontrado la primera coincidencia en forma de string. Ej. : X.FindFirst Sueldo = 130000 FindNext : la siguente coincidencia . FindPrevious : la anterior coincidencia. FindLast : la última coincidencia. [Solo para Table] Index : Define el nombre de un índice para buscar. En Access la PrimaryKey tiene el nombre de `PrimaryKey'. Ej.: X.Index = PrimaryKey Seek : Complemento del anterior.Inicia la busqueda de un registro por comparación (=,>,<,etc..) de un valor. Ej.: X.Seek =, Valor1 [,Valor2, etc..]. En caso que busquemos por una clave primaria compuesta, hemos de tener en cuenta que IMPORTA el orden en que pongamos las claves. En Acces este orden viene impuesto por la posición de arriba a abajo dentro de la tabla de índices. Para saber si se ha encontrado lo buscado tenemos el método que nos devuelve un booleano indicando si NO LO HA Encontrado : NoMatch [Movimiento de forma secuencial] MoveFirst : Moverse a la 1er. registro de todo el conjunto. MoveNext : Moverse al siguiente registro del conjunto. MovePrevious :.. al anterior... MoveLast : ..al último Hemos de tener en cuenta que debemos controlar en cada momento que no nos pasemos del último registro, no retrocedamos demasiado y sobre todo que siempre tengamos un registro activo si vamos a hacer algo. Para huir del error NocurrentRecord, conoceremos si hay al menos un registro activo con .Recordcount (al menos 1 significa <> 0, aunque el valor real lo conoceremos si nos movemos al último registro). 35 .Requery : Procesar de nuevo la selección de datos. .Close : Cerramos el recordset Para utilizar la información contenida en un Recordset: X!Nombre : nos devuleve la información contenida en el campo nombre del recordset X. También podemos acceder a la información a través de la colección Fields que está contenida en él: X.Fields(0) : no devuelve el contenido que hay en el primer campo en orden. En caso que tengamos muchos recordsets (normalmente ocurre con los DataControls), nos puede producir errores de ambigüedad desde el Motor Jet, con lo cual en algunos casos desambigüaremos mediante la observación concreta de la tabla a utilizar: X.Fields(Personas!Nombre) Para ello, es muy útil la sentencia With que nos ahorra trabajo a la hora de no repetir el nombre del recordset. SENTENCIAS SQL (Devoluciónes y acciónes): A646 Podemos ejecutar directamente sentencias del lenguaje SQL con dos condiciones; siempre ateniéndose al modo de la variante o dialecto del SQL `Acces Sql' que es el utilizado por el Motor Jet (Motor de Base de datos utilizado por Visual Basic) y que la sentencia no devuelva ningún registro o valor (Ejemplos más claros son las sentencias UPDATE [Actualizar] o DELETE [Borrar]): Sobre el objeto DataBase, que no sea a través de ODBC : Execute <String conteniendo la sentencia SQL> Mediante ODBC: ExecuteSql <String> Para obtener valores concretos como el máximo, mínimo, etc.., podemos obtenerlo a través de un RecordSet : Dim A As Recordset Sql = SELECT MAX(Sueldo) AS Maximo FROM Personas Set A = Db.OpenRecordset(Sql,dbOpenDynaset) ` Se pude obviar el tipo de recordset SueldoMax = A!Maximo Práctica 12 (1ª Parte) TRANSACCIONES : A646 Para controlar mejor las acciones ha realizar, tenemos el control de transacciones, que nos permiten comenzar y finalizar un bloque de transacción, con lo que si por alguna razón queremos invalidar todas las acciones realizadas desde el comienzo de una transacción, podemos efectuarlo o por el contrario dar el visto bueno. 36 Todo esto es posible ya que las operaciones se registran de forma temporal. Las transacciones se inician a traves del método `.BeginTrans' del objeto Workspace , por ello la transacción afectará a todas las operaciones con bases de datos realizadas en ese área de trabajo que estamos utilizando. Para finalizar una transacción CANCELANDO todo lo realizado hasta el momento se utiliza el método `RollBack' y en caso de querer efectuar los cambios `CommitTrans' COLECCIÓN TABLEDEFS Y FIELDS: A627 Para obtener información referente al contenido de una Base de Datos, principalmente las tablas, tenemos la colección `TableDefs' perteneciente al objeto base de datos, que está contenida por elementos `TableDef', con lo que podemos recorrerla: Dim t as TableDef For Each t In Bd.TableDefs `Dependiente del objeto Database `Bd' .. Next Name : Nombre de la tabla DateCreated / LastUpdated : Fechas de creación y actualización Attributes : Tipos de tabla. Una tabla no es solamente las tablas de datos, en algunas BD, podemos tener guardadas como tablas consultas SQL, Formularios, etc (Como es el caso de MS−Access). Si no tiene ningún atributo especial, se considera que es una tabla normal (de datos). dbSystemObject : Tabla de Sistema dbHiddenObject : Oculta dbAttachExclusive : Modo Exclusivo dbAttachedODBC : Bd. ODBC SourceTableName : Nombre de la tabla origen. Por si es una tabla resultado de un consulta. RecordCount : Número de registros que posee. Updatable : Equivalente al del objeto Database. ValidationRule; ValidationText : Reglas de validación definidas por el usuario. COLECCIÓN FIELDS DE TABLEDEF Enumeración de campos (columnas), existentes en una tabla Dim Col as Field 37 For Each Col In Bd.TableDefs.Fields . Next o también : Set Col = Bd.Tabledefs(Alumnos).Fields(Nombre) Name : Nombre . SourceField : Origen de la columna, por si es el resultado de una consulta. Type : Tipo de datos. dbBoolean : Booleano db* .. : Idem que en Visual Basic dbLongBinary : Objeto OLE dbMemo : Texto hasta de 1,2 Gb dbText : Texto de hasta 255 chars. Size : Tamaño del campo Attributes : Combinación de 1 o más atributos : dbAutoIncrField : Autoincremento. dbDescending : Orden descendente. dbFixedField : LongitudfFija. dbUpdatableField : Campo modificable. DbVariableField : Longitud variable. AllowZeroLength : False = La columna necesita un valor DefaultValue : Valor por defecto que se introduce en el campo si en este se deja NULL. Required: Se debe obligatoriamente, introducir un valor no nulo. ValidationRule : Regla de validación que se consulta a cada introducción de datos. ValidationText : Texto que se muestra en caso de violarse la regla anterior. ValidationOnSet : Activa la regla de validación anterior. CONTROL DB*: A623 Existen un trio de controles standar de VisualBasic, DbGrid, DbCombo, DbList, que son equivalentes a los controles Grid, ComboBox y ListBox respectivamente, y nos permiten obtener/escribirlos datos directamente 38 de un DataControl. Los DbCombos y lo DbList son efectivos solo cuando se utilizan para obtener los datos de un DataControl (aunque solo nos ahorra un bucle de recorrido), de otra manera ofrecen demasiados problemas; para ello se ofrecen multiples versiones externas de Sheridan o GreenTree. Con el DbGrid pasa algo equivalente, tenemos mejoradas versiones de Sheridan o GreenTree, pero podemos utilizar la que tenemos: AllowAddNew : Permitir añadir. AllowDelete : Permitir Borrar. AllowUpdate : Permitir Actualizar. AllowRowSzing : Permitir redimensionar el tamaño de las columnas. ColumnHeader : Visualización o no del título de la columna. HeadFont : Fuente para los títulos de las columnas. HeadLines : # de líneas de los títulos. RecordSelectors : Aparición / no de columna indicadora de estado (editando, selección, etc..) RowHeight : Altura de las filas de la rejilla. RowDividerStyle : Tipo de línea para separar filas. Colección Columns : Nos representa el total de columnas de la rejilla. Métodos generales para trabajo con controles ligados a datos. `Reposition' en los datacontrol indica que han cambiado de registro, por lo que debemos actualizar la dbgrid. `Closeup' en los dbcombo, han cerrado y por tanto han elegido un elemento y debemos igualar los Bookmarks de la combo como el del control (.bookmark) Propiedades en los Db* controls que al cargar elementos, podemos ver que valor contiene una columna no visible y actulizarla con otro valor.Ejemplo un booleano que indique el actual por una flecha indicativa `'. Práctica 12(2ª Parte) CREACIÓN SERVIDOR OLE Y LIBRERIAS DLL OLE: A449 La creación de DLL's solo se pueden hacer a través de VB versión 32 bits. La creación de estas herramientas se efectúa a través de técnicas de Orientación a Objetos pero de una forma parcial. Crearemos un ejemplo que podemos hacer como DLL y como Servidor OLE, pero este ejemplo es para un Servidor OLE: [P1.Vbp] 39 CLASE: Sumas.cls Declaraciones: Public tot as Double Public Sub Sumar(x as Integer) tot = tot + x End Sub Public Function VerSuma() As Double VerSuma = tot End Function En Inicialize / Terminate Poner el código que se quiera. Propiedades: Instancing: 2−Creatable Multiuse (Para que se le puedan hacer múltiples llamadas) Name: Sumas Public: True (Para que se le puedan llamar) Subrutina Main () necesaria aunque esté vacia !! para que arranque el Servidor. Crear un archivo .EXE normal; esta es la diferencia con un archivo DLL, ya que los servidores OLE se pueden ejecutar directamente mientras que las DLL solo se pueden invocar. Automáticamente se da de alta en el registro de sistema el nombre de la clase y así poderlo utilizar para lo que queramos. Llamada al Servidor ` Sin especificar referencia a clase, en referencias del proyecto: Dim p As Object Set p = CreateObject (Sumar.Sumas) ` Sumar = Nombre del servidor OLE. ` Sumar = Nombre de la clase que ofrece. Este sistema es un 50% más lento que el siguente : 40 ` Crear objeto de la clase Sumas que ya está en referencias en la librería, en opciones de proyecto !! Dim p as New Sumar ` Creamos una nueva instancia del objeto `Sumar' ` Común a las dos maneras de declaraciones: P.Sumar(1) P.Sumar(5) MsgBox p.VerSuma Notas : • Se puede incluir llamadas a formularios (Interficies) • Cuidado al hacer instalaciones de Servidores OLE mediante diskettes de instalación. • Cuidado con RE−Instalar Servidor OLE; porque las llamadas pueden quedar antiquadas: Puede que no esté incluido en las referencias; Puede que haya que reiniciar VB para obtener las referencias actualizadas; Raro sería que haya que reiniciar Windows; Avisará que no existe la referencia = X Falta : Sumar Desactivarlo Aceptar Volver a activarlo (X Sumar) Aceptar • Normalmente Vb incluye las referencias del sistema. • Los formularios que se cogen mediante Servidores OLE son independientes, por lo que los hemos de descargar aparate!! • A la hora de instalarlo mediante diskette, normalmente lo hace en el directorio c:\Windows\System\Olesrv\x.exe • Cuidado si los formularios interactivos del s. OLE son modales • Si creamos oleserv llamado X y una dll llamada x en las referencias nos podemos equivocar; distinguirlos por el path que posee debajo. • Si el Main() del OLESRV ponemos código, porque lo utilizamos de EXE normalmente, también se ejecutará cuanda hagamos : ` Dim p As New X' DIVERSAS SENTENCIAS DE UTILIDAD : En el formulario actual : Print Str escribe un string ; Cls Borra el fondo. Randomize inicializa el generador ; Rnd : Da un número aleatorio entre 0..1. Cint(Rnd*49+1) E [1..49] RGB(r,g,b) Ofrece un color combinación de Rojo, Verde y Azul. Los tres valores deben estar entre 0 y 255. LoadPicture(<Path>) Asignado en tiempo de ejecución a la propiedad Picture de un control permite cargar una imagen. DIBUJO : Pset(x,y) Dibuja un punto en las coordenadas indicadas Print ; Circle, Line Circulo y linea 41 PaintPicture PRÁCTICAS • Definir variable `Dim Contador As Integer', que se incremento, en tres ámbitos : Formulario, Módulo y Subrutina y mostrar el contenido a través de una etiqueta desde el evento Click() de un botón : l.caption = contador; se ve la diferencia entre : Contador, Form1.Contador (o Form1!Contador) y Modulo1.Contador • Un formulario en blanco, introducir 2 options Hombre / Mujer, compilar y posteriormente introducir Casado / Soltero, observar que no puede darse a la vez las dos condiciones. Solución : Introducción de control Frame. • Minieditor : Un textbox de introducción de texto; cuatro botones : Seleccionar, Copiar, Copiar y Pegar; 2 textbox de introducción de número de caracteres a seleccionar y otro para el número de carácter desde el que marcar; una label como destino de lo que hagamos. • Formulario con todos los elementos visuales (Iconos, ControlBox, etc..), que mediante un botón cambie el dibujo de fondo del formulario así como el contenido de un ImageBox (con Loadpicture), con una imagen externa que se indicará con un path completo dentro de un TextBox. En caso de no encontrar la imagen, detectar el error dándo un mensaje en una label. • 2 formularios. 1 de password de entrada al segundo formulario. Password es una constante string de 4 char. Al tercer intento fallido sale de la aplicación sino entrada. No se permite visualización del password, colores, avisos, iconos, tamaño, sensible a mayúsculas y minúsculas ( operador `= ` o StrCmp para comparar password con cte.). Preguntar antes de salir de la aplicación. 2º consiste en una calculadora con : teclas de número de 0−9, operaciones: +, −, /, * y tecla de `='; 2 label para operador1 y operador2 y otra para el resultado. Aprovechar la potencia de matrices de controles para el código. Utilización de botones de Sheridan, detectar el error de overflow. Posibilidad de hacer una calculadora de tiempo. Dado dos fechas, que haga calculos de resta en días, semanas, etcObtener el día de la semana correspondiente a un día antiguo, etc • Una label que vaya moviéndose en horizontal de un lado a otro cada vez que el timer lo indique y con un incremento de posición definido por una constante. Cuando se pulse un botón, el movimiento debe ser en vertical. . Utilización del evento MouseMove sobre el formulario, si pulsan boton derecho del ratón sale un menú popup que nos permite dos cambios : cambiar el sentido de movimiento de la label (derecha izquierda o arriba abajo, según donde esté) y otra que nos permita cambiar de tipo de movimiento (horizontal vertical). Ha de haber un menú superior en forma de Checked que nos indique y nos permita que la etiqueta se visualice. Utilización de variables de tipo static, controlar el margen (Top y Left), etc • Elección de diversos productos: Al entrar pregunte por el número de elementos (Redim Mat). Bucle hasta detectar un `Cancelar' con un InputBox entrando par de elementos Descripción−Precio (Hacer un tipo desc−precio y una matriz de él o simplemente asignando a cada uno en la propiedad itemdata un long y por tanto controlar el preio máximo). Formulario con una Combo con las descripciones pedidas y cada vez que apriete una salga el total sumado en una label y en una lista salgan todas las descripciones. Botón que nos permita borrar los elementos (+ de uno), que hemos seleccionado de la lista y por tanto actualize el precio final. Deberemos entrar a través de Submain. 42 La variante será entrar el número de elementos mediante la linea de comandos desde `Ejecutar'. • Mediante los 3 controles normales de manejo de archivos o directorios o mediante un commondialog, debemos elegir un archivo de imagen (solo ficheros .Wmf, .Ico, .Dib), para cargarlo en un ImageBox. También deberemos cambiar el color de fondo de un formulario, a través de un CommonDialog de tipo elección de color. • Formulario MDI que mediante una opción de menú cree formularios hijos modelos, en cada uno tendremos la caption indicando el nombre del formulario y un textbox donde podemos escribir; en cada uno un mousepointer diferente (controlar el posible error). En el formulario padre hacer menú con opciones de ordenar los formularios hijos. Utilizar un formulario hijo como portada, con caption `Bienvenido'. Una opción de menú que nos permita cambiar entre formularios hijos. • Fichero de Registros de un tipo Personas : Hacer un tipo Persona con : Nombre str(15); Apellidos str(25); Dirección str(30); Teléfono str(14) Casado/Soltero Bool; Hombre/Mujer Bool; Edad Byte; Altura single Profesión str(10) Se deberá elegir de una combobox (tiempo diseño). Botones de : Siguiente registro, Anterior, Primero, Último, Validar Actual y buscar el número de registro que indiquen. Se debe controlar todos los posibles errores, así como la longitud del fichero y el registro actual. • (A597) [Se supone sobre W95 o WNT]Construir un formulario con un Gauge o ProgressBar que indique el porcentaje de memoria virtual que tenemos disponible a cada segundo en nuestro sistema. Para ello tenemos una Subrutina de la API de 32 bits: GlobalMemoryStatus(X), siendo X un tipo de datos donde se introduce la información. Control Timer que a cada segundo actualice el gaude llamando a la función. Se debe controlar que estemos en 32 bits (#If Win16..) ` Si NoWin16 [Dar esta información] Private Type MEMORYSTATUS dwLength As Long dwMemoryLoad As long dwTotalPhys As Long dwAvailPhys As Long dwTotalPageFile As Long dwAvailPageFile As Long 43 dwTotalVirtual As Long dwAvailVirtual As Long End Type Private Declare Sub GlobalMemoryStatus Lib Kernel32 (lpmstMemStat As MEMORYSTATUS) ` Si no Win16 y en evento timer [Dar esta información] Dim Bloque As MEMORYSTATUS Bloque.DwLength = 32 GlobalMemoryStatus Bloque `Llamada a la sub Total = (Bloque.dwTotalPhys + Bloque.dwTotalPageFile) * 256 / 1024 ` Definimos el total que tenemos en Kb; antes definido en páginas Libre = (Bloque.dwAvailPhys + Bloque.dwAvailPageFile) * 256 / 1024 ` Definimos lo que tenemos libre en Kb; definido antes en pág. ` End if not Win16 Gauge.Max = Total Gauge.Value = Libre • 1ª Parte : Formulario de agenda Posibilidad de uso de SSTAB. Opciones de Alta, Baja, Actualización y Consulta. Alta debe borrar todo y dejar introducir datos; Hasta que no se de al Edit, no se debe permitir actualizar los datos contenidos. Consulta debe abrir un formulario pequeño que de opción a buscar por la clave o por el nombre (por tanto utilización de búsquedas). Observaciones : Posibilidad de hacerlo mediante ControlData o con DAO. Controlar longitud máxima de campos (MaxLength) y matriz de controles para mejor control. Profesiones escogidad de una tabla profesiones. Cuidado con los checks. BD global. Formulario de sentencias SQL : Elección de borrar un registro dado la clave y/o actualizar sueldo pidiendo el porcentaje de aumento. Todo ello más un botón `Ahora'. Hacer una tabla paralela con referencia de integridad referencial : Categoria IdPersona + Tipo (124 Empleado) Personas IdPersona + etc(124..) 44 Exigir integridad referencial entre las dos tablas sobre el campo IdPersona (más `On Delete Cascade' y `On Update Cascade'). 2ª Parte : Formulario hijo que dado una base de datos existente, nos devuelva toda la información posible sobre la estructura. • Hacer una librería DLL con una función que pasándole un número entero lo imprima en una etiqueta de un formulario y muestre este formulario. Probar a mostrar este formulario en la subrutina Main(). • REFERENCIAS (A) Colores 121 ; Tipos de Letras 118 ; Punteros ratón 123 ; Gráficos 253; Gráficos Puntuales 264; Grid 297 Sheridan 3D controls 610 ScrollBars 148 Ayuda en las aplicaciones 523 (B) Sheridan 3D controls 7,9,13 Notas: Reposition en los datacontrol indica que han cambiado de registro, por lo que debemos actualizar la dbgrid. Closeup en los dbcombobox, han cerrado y por tanto han elegido un elemento y debemos igualar los Bookmarks de la combo como el del control (.bookmark) Propiedades en los Db* controls que al cargar elementos, podemos ver que valor contiene una columna no visible y actulizarla con otro valor. 49 45