Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Mtodos
Los mtodos son un conjunto de procedimientos que permiten que un objeto ejecute una
accin o tarea sobre s mismo. Por ejemplo, para un formulario tenemos el mtodo Hide que
har que el formulario se oculte; o el mtodo Show que har que el formulario se vuelva a
mostrar.
Eventos
Un evento es una accin que es reconocida por el objeto. Un evento ocurre (se dispara) como
resultado de la interaccin del usuario con el objeto. Tambin puede dispararse debido a la
ejecucin de cdigo (sentencias) o como resultado de la interaccin de otro objeto con el
objeto de poseedor del evento. Para un formulario tenemos por ejemplo; el evento Load que
se dispara cuando se carga el formulario; o el evento Click para un botn de comando, se
dispara cuando se hace clic sobre l.
Qu papel cumplen las propiedades, mtodos y eventos?
Toda aplicacin necesita una interfaz de usuario, la parte visual a travs de la cual el usuario
interacta con la aplicacin. Los bloques bsicos de construccin de una interfaz de usuario son
los formularios y los controles. Visual Basic utiliza tcnicas de programacin visual para
disear las aplicaciones.
Para disear esta ventana (Formulario), del conjunto de objetos de Visual Basic seleccionamos
un objeto tipo Formulario (Form). Luego a la propiedad Nombre (Name) le asignamos el
valor frmEntrada; a la propiedad Ttulo le asignamos el valor Bienvenidos a Gestin y
Sistemas.
Dentro del formulario se colocan los controles. Para que el usuario pueda ingresar un dato (por
ejemplo, la contrasea) colocamos en la ventana un control tipo Cuadro de Texto (TextBox);
a continuacin establecemos su propiedad Nombre en txtContrasea, y su propiedad
PasswordChar es un * (asterisco) para que el dato ingresado sea reemplazado por asteriscos
slo en la pantalla, para que no se pueda visualizar.
Para obtener el botn Ingresar seleccionamos un control tipo Botn de Comando
(CommandButton), y lo colocamos en la ventana. Luego cambiamos sus propiedades; a la
propiedad Nombre le asignamos cmdIngresar, y a la propiedad Ttulo le asignamos
Ingresar.
Se desea que cuando el usuario haga clic en el botn Limpiar, se borre cualquier dato que el
usuario haya ingresado en los Cuadros de Texto, y que el punto de insercin se ubique en el
cuadro txtUsuario. Para que esto ocurra debemos programar el evento Hacer_Click del
botn de comando cmdLimpiar.
El evento debe ejecutar dos sentenciar para cambiar la propiedad Texto de cada uno de los
cuadros de texto, y luego invocar al mtodo EstablecerEnfoque() del cuadro de texto
txtUsuario.
Cuando se inicia Visual Basic, se crea un proyecto nuevo con un formulario. El IDE de Visual
Basic consta de los siguientes elementos:
1. Barra de Mens
Presenta los comandos que se usan para trabajar con Visual Basic. Adems de los mens
estndar Archivo, Edicin, Ver, Ventana y Ayuda, contiene otros mens para tener acceso
a funciones especficas de programacin, como Proyecto, Formato o Depuracin.
2. Barra de Herramientas
Permite un acceso directo (solo un clic) a muchas de las operaciones ms frecuentes utilizadas
durante el desarrollo de aplicaciones.
3. Cuadro de Herramientas
Contiene todos los objetos y controles que se pueden aadir a los formularios para crear
aplicaciones.
4. Diseador de Formularios
Funciona como una ventana en la que se puede personalizar el diseo de la interfaz de usuario
(ventana) de una aplicacin.
5. Explorador de Proyectos
Lista de los archivos (formularios, mdulos, etc.) del proyecto actual. Un Proyecto es una
coleccin de archivos que utiliza para construir una aplicacin.
6. Ventana de Propiedades
Lista los valores de las propiedades del formulario o control seleccionado que pueden ser
modificados durante el diseo del formulario o control.
7. Ventana de Cdigo
Funciona como un editor para escribir el cdigo (sentencias) de la aplicacin.
Obtencin de Ayuda del Sistema
Visual Basic proporciona una variedad de recursos para ayudarle a encontrar la informacin
que necesite cuando se encuentre trabajando dentro del entorno de desarrollo.
Ayuda en lnea
Visual Basic proporciona una amplia ayuda en lnea. El archivo de Ayuda contiene mucho
cdigo de ejemplo que se puede copiar directamente a una aplicacin.
La ayuda de Visual Basic es sensible al contexto. Para emplear la ayuda sensible al contexto en
la ventana de cdigo, escriba la palabra para la cual desea informacin, y luego presione F1.
Por ejemplo, si desea informacin acerca de la sentencia Open, escriba Open y presione F1.
Libros en Pantalla
Adems de la ayuda sensible al contexto, el CD-ROM de Visual Basic incluye una versin en
lnea de la documentacin impresa para Visual Basic. Para acceder a los Libros en Pantalla,
haga clic en Libros en Pantalla dentro del men Ayuda de Visual Basic.
La Ventana de Cdigo
La ventana o editor de cdigo de Visual Basic proporciona de manera automtica informacin
relevante a medida que se ingresa cdigo. Por ejemplo, si se escribe el nombre de un control,
seguido de un punto, las propiedades y mtodos para ese control sern mostrados
automticamente en un cuadro de lista. Luego se puede escoger la propiedad o mtodo
deseado para completar la sentencia.
Cuando se ingresa el nombre de una funcin en la ventana de cdigo, Visual Basic
automticamente proporciona el formato o sintaxis de la funcin.
Cmo se aaden controles al formulario?
Para aadir controles a un formulario tenemos dos mtodos:
Mtodo 1
Teniendo el cuadro de Herramientas o un Formulario visible, haga doble clic en el control que
desea aadir en el Cuadro de Herramientas, los controles se ubican en el centro del formulario,
uno encima de otro, luego hay que moverlos a la posicin deseada dentro del formulario.
Mtodo 2
1. Haga clic sobre el control en el Cuadro de Herramientas.
2. Ubique el puntero del Mouse (una cruz) sobre el formulario en la esquina superior izquierda
donde desea colocar el control.
3. Realice un clic sostenido mientras arrastra el puntero a la esquina superior derecha donde
colocar el control.
4. Suelte el botn del Mouse.
Estos cuatro pasos se repiten con cada control que desea aadir al formulario.
Terminologa de Visual Basic
Conforme trabaje con Visual Basic, necesitar estar familiarizado con los siguientes trminos:
Trmino
Tiempo de diseo
Definicin
Es el momento en el que se construye la aplicacin.
Tiempo de ejecucin
Formulario
Trmino
Controles
Definicin
Representacin grfica de objetos tales como botones, cuadros de
lista, cuadros de edicin, etc., con los que el usuario interacta
para proporcionar informacin a la aplicacin.
Objetos
Propiedades
Mtodos
Eventos
Programacin controlada
por eventos
Qu es un proyecto?
Cuando desarrolla una aplicacin, Visual Basic crea un archivo especial llamado Archivo de
Proyecto para administrar todos los dems archivos de la aplicacin.
El Archivo de Proyecto es simplemente una lista de todos los archivos y objetos asociados
con el proyecto, as como informacin sobre las opciones del entorno. Esta informacin se
actualiza cada vez que se guarda el proyecto. Todos los archivos y objetos tambin se pueden
compartir con otros proyectos. Un proyecto est compuesto por los siguientes archivos:
Tipo de archivo
Proyecto
Extensin
.vbp
Descripcin
Realiza el seguimiento de todos los componentes de la
aplicacin.
Formulario
.frm .frx
Mdulo estndar
.bas
Tipo de archivo
Controles
Personalizados
Extensin
.ocx
Controles
adicionales
a
los
controles
estndar
proporcionados
por
Microsoft
u
otras
empresas.
(opcional)
Mdulo de clase
.cls
Recursos
.res
Descripcin
Cuando ha completado todos los archivos del proyecto puede convertir el proyecto en un
archivo ejecutable (.exe).
Nota: Con las ediciones Profesional y Empresarial de Visual Basic tambin puede crear otro
tipo de archivos ejecutables, como archivos .ocx y .dll.
Pasos para crear una aplicacin
El proceso de creacin de una aplicacin Visual Basic puede descomponer en una serie de siete
pasos.
1. Crear la interfaz de usuario
Usted crea una interfaz dibujando controles y objetos sobre un formulario. A fin de hacer que
su cdigo sea ms fcil de leer y depurar, debe luego asignar nombres a los objetos usando
convenciones de nombres estndar.
2. Establecer las propiedades de los objetos de la interfaz
Luego de aadir objetos al formulario, se establece las propiedades de los objetos. Puede
establecer valores iniciales ya sea usando la ventana de propiedades en tiempo de diseo o
escribiendo cdigo para modificar las propiedades en tiempo de ejecucin.
3. Escribir cdigo para los eventos
Luego de establecer las propiedades iniciales para el formulario y cada objeto, aada el cdigo
que se ejecutar en respuesta a los eventos. Los eventos ocurren cuando diferentes acciones
ocurren sobre un control u objeto. Por ejemplo, clic es un evento que puede ocurrir para un
botn de comando.
4. Guardar el proyecto
Cuando crea el proyecto, asegrese de darle un nombre usando el comando Guardar
Proyecto como del men Archivo. Guarde su proyecto frecuentemente conforme aada
cdigo. Al guardar un proyecto se guardan cada formulario y mdulo de cdigo en el proyecto.
5. Probar y depurar la aplicacin
Conforme aada cdigo al proyecto, puede usar el comando Iniciar en la Barra de
Herramientas para ejecutar su aplicacin y ver su comportamiento. Tambin puede usar las
herramientas de depuracin para verificar errores y modificar cdigo.
6. Crear un archivo ejecutable
Al completar su proyecto, crear un archivo ejecutable usando el comando Generar
Xxxxxxx.exe del men Archivo.
7. Crear una aplicacin de instalacin
Debido a que su archivo ejecutable depende de otros archivos, tales como el archivo en tiempo
de ejecucin de Visual Basic (Vbrun50032.dll), algunos archivos OCX y archivos DLL
adicionales requeridos por la aplicacin o por los controles ActiveX.
Cuando se usa esta convencin de nombres, todos los miembros de un grupo de mens
determinado se muestran uno junto a otro en la ventana Propiedades de Visual Basic. Adems,
los nombres del control de men documentan claramente los elementos del men a los que
estn adjuntos.
Formularios
Con los controles, los usuarios pueden operar y obtener los resultados de una aplicacin.
Puede aadir controles a un formulario seleccionando la herramienta adecuada del Cuadro de
Herramientas. Entre los controles ms comunes a utilizar en una aplicacin tenemos:
Etiqueta (Label), Cuadro de Texto (TextBox) y Botn de Comando (CommandButton).
10
Mtodos
SetFocus
Estableciendo Propiedades
Al disear la interfase de usuario de una aplicacin Visual Basic, se deben establecer la
propiedades para los controles (objetos) creados.
Estableciendo Propiedades en Tiempo de Diseo
Algunas propiedades pueden ser establecidas en tiempo de diseo. Para establecer estas
propiedades se emplea la ventana de propiedades. Para acceder a la ventana de
propiedades, oprima en botn secundario del ratn sobre un objeto, y luego haga clic
en Propiedades. Tambin se puede obtener el mismo resultado seleccionado el
objeto y luego presionando F4.
Si selecciona varios objetos a la vez y accede a la ventana de propiedades, slo se mostrarn
las propiedades que son comunes para todos los controles seleccionados. Cualquier cambio
que se haga a una propiedad ser aplicada a todos los controles.
Estableciendo Propiedades en Tiempo de Ejecucin
En tiempo de ejecucin, se puede escribir cdigo para establecer u obtener el valor de una
propiedad. La siguiente lnea de cdigo establece a negrita la fuente de un cuadro de texto
llamado txtData.
txtData.Font.Bold = True ' Establece el texto a negrita
Este cdigo establece la propiedad Text del cuadro de texto txtData
txtData.Text = "Hola mundo" 'Establece el valor del texto
Si se omite el nombre de la propiedad, se establece la propiedad predeterminada del control.
La propiedad predeterminada de un cuadro de texto es la propiedad Text. La propiedad
predeterminada de una etiqueta es la propiedad Caption. Las siguientes lneas de cdigo
establecen las propiedades predeterminadas text y caption de un cuadro de texto y de una
etiqueta.
txtData = Se establece la propiedad Text del cuadro de texto
lblData = Se establece la propiedad Caption de la etiqueta
Obteniendo Propiedades en Tiempo de Ejecucin
Puede emplear el siguiente cdigo para obtener el valor de una propiedad en tiempo de
ejecucin.
11
12
13
14
Formato
MsgBox( prompt [, buttons] [, title ] [, helpfile, context] )
EL formato de la funcin MsgBox consta de los siguientes argumentos:
Parte
Prompt
Buttons
Title
Descripcin
Helpfile
Context
15
Valores
El argumento buttons puede asumir los siguientes valores:
16
Funcin InpuBox()
Formato
InputBox( prompt [, title] [, default] [, xpos] [,ypos] [, helpfile, context] )
El formato de la funcin InpuBox consta de los siguientes argumentos con nombre:
Parte
Prompt
Descripcin
Requerido. Expresin de cadena que se muestra como mensaje en el cuadro
de dilogo. La longitud mxima de prompt es de aproximadamente de 1024
caracteres, segn el ancho de los caracteres utilizados. Si prompt consta de
ms de una lnea, puede separarlos utilizando un carcter de retorno de
carro (Chr(13)), un carcter de avancede lnea (Chr(10)) o una combinacin
de los caracteres de retorno de carro avance de lnea (Chr(13) y (Chr(10))
entre cada lnea y la siguiente.
17
Title
Default
Xpos
Ypos
Helpfile
Context
Comentarios
Si el usuario hace clic en Cancelar, la funcin devuelve una cadena de caracteres de
longitud cero ().
Nota: Si desea omitir algunos argumentos, debe incluir el delimitador de coma
correspondiente o utilizar argumentos con nombre.
Constantes Predefinidas
Visual Basic reconoce cierta cantidad de constantes predefinidas que pueden se usadas en
cualquier parte de su cdigo en lugar de valores numricos. Puede hacer que su cdigo sea
ms fcil de leer y escribir mediante el uso de estas constantes. Adems, los valores de
estas constantes pueden cambiar en versiones posteriores de Visual Basic, su uso
permitir que su cdigo sea compatible. Por ejemplo, la propiedad WindowState de un
formulario puede aceptar las siguientes constantes:
18
Mtodo Show
Muestra un formulario. Si el formulario no est cargado al momento de ejecutar el mtodo
Show, Visual Basic lo cargar automticamente.
Formato
NombreDelFormulario.Show
Ejemplo
FrmEntrada.Show
Sentencia Load
Carga un formulario a la memoria, pero no lo muestra.
Formato
Load NombreDelFormulario
Ejemplo
Load FrmEntrada
Evento Load
El evento Load ocurre cuando el formulario es cargado en la memoria. Esto sucede cuando
se usa la sentencia Load, o cuando se invoca el mtodo Show y el formulario an no est
cargado en memoria. Normalmente, este evento se utiliza para establecer algunas
propiedades del formulario, los controles que se encuentran en l, o variables a nivel del
formulario.
Ejemplos:
Mtodo Hide
Oculta un formulario, pero no lo descarga de memoria.
Formato
NombreDelFormulario.Hide
Ejemplo:
frmIngreso.Hide
Sentencia Unload
Descarga un formulario de memoria
Formato
Unload NombreDelFormulario
Comentarios
La descarga de un formulario puede ser necesario o conveniente en aquellos casos en los
que la memoria utilizada se necesite para alguna otra tarea o cuando sea necesario
restablecer las propiedades a sus valores originales.
19
El Editor de mens
Esta herramienta permite crear mens personalizados para la aplicacin y definir sus
propiedades. Para ingresar, estando en tiempo de diseo, haga clic en el men
20
21
El control ToolBar
Un control Toolbar contiene una coleccin de objetos Button utilizados para crear una
barra de herramientas asociada a una aplicacin.
Comentarios
22
El Control ImageList
Un control ImageList contiene una coleccin de objetos ListImage, a cada uno de los
cuales se puede hacer referencia mediante su ndice o su clave. El control ImageList no
est concebido para utilizarlo en solitario, sino como punto de almacenamiento central para
proporcionar cmodamente imgenes a otros controles.
Comentarios
Puede usar el control ImageList con cualquier control que asigne un objeto Picture a una
propiedad Picture.
Es posible agregar imgenes de diferentes tamaos al control ImageList, pero todas se
ajustan al mismo tamao. El tamao de los objetos de ListImage est determinado por
uno de los siguientes valores:
El valor de las propiedades ImageWidth y ImageHeight antes de agregar alguna
imagen.
Las dimensiones de la primera imagen agregada.
No hay ninguna limitacin en cuanto al tamao de la imagen, pero el nmero total de
imgenes que se puede cargar est limitado por la cantidad de memoria disponible.
Durante el diseo del programa puede agregar imgenes mediante la ficha General del
cuadro de dilogo Propiedades del control ImageList. En tiempo de ejecucin puede
agregar imgenes mediante el mtodo Add para la coleccin ListImages.
Nota: Los controles Toolbar e ImageList forman parte del grupo de controles ActiveX
adicionales Microsoft Windows Common Controls 5.0 (archivo COMCTL32.OCX). Para
usarlos en su aplicacin debe agregar el archivo COMCTL32.OCX al proyecto. Cuando
distribuya su aplicacin, instale el archivo COMCTL32.OCX en la carpeta System o
System32 (en plataformas con Windows NT) de Microsoft Windows del usuario.
Interfaz de Mltiples Documentos (MDI Multiple Document Interfase)
El Objeto MDIForm
Un formulario MDI es una ventana que acta como fondo de una aplicacin y es el
contenedor de formularios que tienen su propiedad MDIChild establecida a True. Para crear
un objeto MDIForm, elija Agregar formulario MDI en el men Proyecto, luego de
agregarlo tenga en cuenta lo siguiente:
Una aplicacin slo puede tener un objeto MDIForm, pero varios formularios
secundarios MDI.
23
Tipos de Datos
Un tipo de dato determina la naturaleza del dominio de valores que puede tomar una
variable, las operaciones en que puede participar y el espacio de memoria que necesita. La
tabla siguiente muestra los tipos de datos, incluyendo el tamao de almacenamiento y el
intervalo.
24
Tipo de Dato
Byte
Boolean
Integer
Long
(entero largo)
Single
(coma
flotante/
precisin
simple)
Double
(coma
flotante/
precisin doble)
Currency
(entero
a
escala)
Decimal
Date
Object
String
(longitud
variable)
String
(longitud fija)
Variant
(con nmeros)
Variant
(con
caracteres)
Definido por el
usuario
(utilizando
Type)
Tamao
de
Almacenamient
o
1 byte
2 bytes
2 bytes
4 bytes
Rango
4 bytes
-3,402823E38
a
-1,401298E-45
para
valores
negativos; 1,401298E-45 a 3,402823E38 para valores
positivos
8 bytes
-1,79769313486232E308 a -4,94065645841247E-324
para valores negativos; 4,94065645841247E-324 a
1,79769313486232E308 para valores positivos
8 bytes
-922.337.203.685.477,5808
922.337.203.685.477,5807
14 bytes
8 bytes
4 bytes
10 bytes +
longitud de la
cadena
Longitud de la
cadena
16 bytes
0 a 255
True o False
-32.768 a 32.767
-2.147.483.648 a 2.147.483.647
22 bytes +
longitud de la
cadena
Nmero
El intervalo de cada elemento es el mismo que el
requerido por los intervalo de su tipo de datos
elementos
Nota: Las matrices de cualquier tipo de datos requieren 20 bytes de memoria ms cuatro
bytes para cada dimensin de matriz, ms el nmero de bytes que ocupan los propios
datos. Por ejemplo, los datos de una matriz unidimensional que constan de cuatro
elementos de datos tipo Integer de dos bytes cada uno, ocupan ocho bytes. Los ocho
bytes que requieren los datos ms los 24 bytes necesarios para la matriz suman un
requisito total de memoria de 32 bytes para dicha matriz. Un tipo Variant que contiene una
matriz requiere 12 bytes ms que la matriz por s sola.
Convertir tipos de datos
25
Visual Basic proporciona varias funciones de conversin que puede utilizar para convertir
valores de tipos de datos especficos. Por ejemplo, para convertir un valor a Currency,
utilice la funcin Ccur:
PagoPorSemana = Ccur (horas * PagoPorHora)
La siguiente tabla muestra las funciones de conversin:
Nota: Los valores que se pasan a una funcin de conversin deben ser vlidos para el tipo
de dato de destino o se producir un error. Por ejemplo, si intenta convertir un tipo Long
en un Integer, el tipo de Long debe de estar en el intervalo vlido del tipo de dato
Integer.
Variables
Las variables se utilizan para almacenar valores temporalmente durante la ejecucin de
una aplicacin. Las variables tienen un nombre (la palabra que utiliza para referirse al valor
que contiene la variable) y un tipo de dato (que determina la clase de dato que la variable
puede almacenar).
Almacenamiento y recuperacin de datos en variables
Utilice una sentencia de asignacin para realizar clculos y asignar el resultado a una
variable:
ManzanaVendidas = 10
Se pasa el valor 10 a la variable
ManzanasVendidas = ManzanasVendidas + 1
Observe que el signo igual del ejemplo es un operador de asignacin, no un operador de
igualdad; el valor 10 se asigna a la variable ManzanasVendidas.
Declaracin de Variables
Declarar una variable es decirle al programa algo de antemano. Se declara una variable
mediante la instruccin Dim, proporcionando un nombre a la variable, segn la siguiente
sintaxis:
Dim nombre-variable [As tipo]
Las variables que se declaran en un procedimiento mediante la sentencia Dim slo existen
mientras se ejecuta el procedimiento. Cuando termina el procedimiento, desaparece el
valor de la variable. Adems, el valor de una variable de un procedimiento es local a dicho
procedimiento; es decir, no puede tener acceso a una variable de un procedimiento desde
otro procedimiento. Estas caractersticas le permiten utilizar los mismos nombres de
variables en distintos procedimientos sin preocuparse por posibles conflictos o
modificaciones accidentales.
El nombre de una variable debe cumplir con los siguientes requisitos:
Debe comenzar con una letra.
26
Declaracin Implcita
No tiene por qu declarar una variable antes de utilizarla. Por ejemplo, podra escribir una
funcin donde no hiciera falta declarar TempVal antes de utilizarla:
Visual Basic crea automticamente una variable con ese nombre, que puede utilizar como
si la hubiera declarado explcitamente. Aunque es cmodo, puede provocar errores sutiles
en el cdigo si se equivoca de nombre de variable. Por ejemplo, suponga que ha escrito
esta funcin:
A primera vista, parece igual. Pero como se ha escrito errneamente la variable TempVal
en la tercera lnea, la funcin devolver siempre cero. Cuando Visual Basic encuentra un
nombre nuevo, no puede averiguar si realmente desea declarar una variable nueva o
simplemente ha escrito de forma errnea una variable existente, por lo que crea una
variable nueva con ese nombre.
Declaracin Explcita
Para evitar problemas al equivocarse de nombre en las variables, puede configurar Visual
Basic para que le avise siempre que encuentre un nombre que no se haya declarado
explcitamente como una variable.
Para declarar variables de forma explcita:
Incluya esta sentencia en la seccin Declaraciones Generales del mdulo de clase, de
formulario o estndar:
Option Explicit
o bien
En el men Herramientas, elija Opciones, haga clic en la ficha Editor y active la
opcin Declaracin de variables requerida. Esto inserta automticamente la
sentencia Option Explicit en los mdulos nuevos, pero no en los ya creados, por lo
que tendr que agregar manualmente Option Explicit a los mdulos existentes en el
proyecto.
Parte 3: Tipos de datos, constantes y variables - Danny A. Matta Gonzales
27
Los valores de variables locales declaradas con Static existen mientras se ejecuta la
aplicacin, mientras que las variables declaradas con Dim slo existen mientras se ejecuta
el procedimiento.
Variables utilizadas en un mdulo
De forma predeterminada, una variable al nivel de mdulo est disponible para todos los
procedimientos del mdulo, pero no para el cdigo de otros mdulos. Cree variables al
nivel de mdulo declarndolas con la palabra clave Private en la seccin Declaraciones
Generales al principio del mdulo. Por ejemplo:
Private intTemp As Integer
Al nivel de mdulo, no hay diferencia entre Private y Dim, pero es preferible usar
Private porque contrasta con Public y hace que el cdigo sea ms fcil de comprender.
Variables utilizadas por todos los mdulos
28
Para hacer que una variable al nivel de mdulo est disponible para otros mdulos, utilice
la palabra clave Public para declararlas. Los valores de las variables pblicas estn
disponibles para todos los procedimientos de la aplicacin. Al igual que todas las variables
al nivel del mdulo, las variables pblicas se declaran en la seccin Declaraciones
Generales al principio del mdulo. Por ejemplo:
Public intTemp As Integer
Nota: No puede declarar variables pblicas en un procedimiento, slo en la seccin
Declaraciones Generales de un mdulo.
Constantes
A menudo ver que el cdigo contiene valores constantes que reaparecen una y otra vez.
O puede que el cdigo dependa de ciertos nmeros que resulten difciles de recordar
(nmeros que, por s mismos, no tienen un significado obvio).
En estos casos, puede mejorar mucho la legibilidad del cdigo y facilitar su mantenimiento
si utiliza constantes. Una constante es un nombre significativo que sustituye a un nmero
o una cadena que no vara. Aunque una constante recuerda ligeramente a una variable, no
puede modificar una constante o asignarle un valor nuevo como ocurre con una variable.
Hay dos orgenes para las constantes:
Constantes intrnsecas o definidas por el sistema proporcionadas por Visual Basic.
Las constantes simblicas o definidas por el usuario se declaran mediante la
instruccin Const.
Creacin de sus propias constantes
La sintaxis para declarar una constante es la siguiente:
[Public|Private] Const nombre_constante [As tipo] = expresin
El argumento nombre_constante es un nombre simblico vlido (las reglas son las mismas
que para crear nombres de variable) y expresin est compuesta por constantes y
operadores de cadena o numricos; sin embargo, no puede utilizar llamadas a funciones en
expresin. Una instruccin Const puede representar una cantidad matemtica o de fecha y
hora:
Const conPi = 3.14159265358979
Public Const conMaxPlanetas As Integer = 9
Const conFechaSalida = #1/1/95#
Se puede utilizar tambin la instruccin Const para definir constantes de cadena:
Public Const conVersion = 07.10.A
Const conNombreClave = Enigma
Puede colocar ms de una declaracin de constante en una nica lnea si las separa con
comas:
Public Const conPi=3.14, conMaxPlanetas=9, conPobMundial=6E+09
A menudo, la expresin del lado derecho del signo igual ( = ) es un nmero o cadena
literal, pero tambin puede ser una expresin que d como resultado un nmero o una
cadena (aunque la expresin no puede contener llamadas a funciones). Puede incluso
definir constantes en trminos de constantes previamente definidas:
Const conPi2 = conPi * 2
Una vez que defina las constantes, puede colocarlas en el cdigo para hacerlo ms legible.
Por ejemplo:
Parte 3: Tipos de datos, constantes y variables - Danny A. Matta Gonzales
29
Para crear una constante que slo exista en un procedimiento, declrela dentro del
procedimiento.
Para crear una constante disponible para todos los procedimientos de un mdulo, pero
no para el cdigo que est fuera del mdulo, declrela en la seccin Declaraciones
Generales del mdulo.
Si se produce un ciclo, Visual Basic generar un error cuando intente ejecutar la aplicacin.
No puede ejecutar el cdigo hasta que resuelva la referencia circular. Para evitar la
creacin de un ciclo, restrinja todas las constantes pblicas a un nico mdulo o, al menos,
al menor nmero posible de mdulos.
Convenciones para Nombres de Constantes y Variables
Las variables se deben definir siempre con el menor alcance posible. Las variables globales
(pblicas) pueden hacer lgica de una aplicacin muy difcil de entender. Las variables
globales tambin hacen ms difcil mantener y volver a usar el cdigo.
En Visual Basic las variables pueden tener el alcance siguiente:
En una aplicacin de Visual Basic, las variables globales se deben usar slo cuando no
exista ninguna otra forma cmoda de compartir datos entre formularios. Cuando haya que
usar variables globales, es conveniente declararlas todas en un nico mdulo agrupadas
por funciones y dar al mdulo un nombre significativo que indique su finalidad, como
Pblicas.
Parte 3: Tipos de datos, constantes y variables - Danny A. Matta Gonzales
30
Una prctica de codificacin correcta es escribir cdigo modular siempre que sea posible.
Por ejemplo, si la aplicacin muestra un cuadro de dilogo, coloque todos los controles y el
cdigo necesario para ejecutar la tarea del dilogo en un nico formulario. Esto ayuda a
tener cdigo de la aplicacin organizado en componentes tiles y minimiza la sobrecarga
en tiempo de ejecucin.
A excepcin de las variables globales ( que no se deberan pasar), los procedimientos y
funciones deben operar slo sobre los objetos que se les pasan.
Prefijos de alcance de variables
A medida que aumenta el tamao del proyecto, tambin aumenta la utilidad de reconocer
rpidamente el alcance de las variables. Esto se consigue escribiendo un prefijo de alcance
de una letra delante del prefijo de tipo, sin aumentar demasiado la longitud del nombre de
las variables.
Una variable tiene alcance global si se declara como Public en un mdulo estndar o en un
mdulo de formulario. Una variable tiene alcance de nivel de mdulo si se declara como
Private en un mdulo estndar o en un mdulo de formulario, respectivamente.
Nota: La coherencia es crucial para usar esta tcnica de forma productiva; el corrector de
sintaxis de Visual Basic no interceptar las variables de nivel de mdulo que comience con
p.
Constantes
El nombre de las constantes se debe escribir en maysculas y minsculas, con la letra
inicial de cada palabra en maysculas. Aunque las constantes estndar de Visual Basic no
incluyen informacin de tipo de datos y el alcance de una constante. Para los nombres de
constantes, se deben seguir las mismas normas que para las variables. Por ejemplo:
Variables
Declarar todas las variables ahorra tiempo de programacin porque reduce el nmero de
errores debidos a nombres de variables errados (por ejemplo, aNombreUsuarioTmp frente
a sNombreUsuarioTmp frente a sNombreUsuarioTemp). En la ficha Editor del cuadro de
dilogo Opciones, active la opcin Declaracin de variables requerida. La instruccin
Option Explicit requiere que declare todas las variables del programa de Visual Basic.
Las variables deben llevar un prefijo para indicar su tipo de datos. Opcionalmente, y en
especial para programas largos, el prefijo se puede ampliar para indicar el alcance de la
variable.
Tipos de datos de variables
Use los siguientes prefijos para indicar el tipo de datos de una variable.
31
Ejemplo
32
Arreglo de Variables
Un arreglo es una coleccin de elementos del mismo tipo con un nombre comn. Los
elementos son identificados por el nombre comn y un ndice.
Sintaxis
Dim NombreDelArreglo( Dimensin1, Dimensin2, ... ) As TipoDeDato
Visual Basic soporta hasta 60 dimensiones. Al declarar las dimensiones se puede indicar un
solo nmero, en cuyo caso se entiende que dicha dimensin va de cero hasta el nmero
indicado. Tambin es posible indicar explcitamente el inicio y trmino de la dimensin.
Ejemplo
Arreglos Dinmicos
Hay situaciones en las cuales se desea usar un arreglo, pero al momento del diseo no se
sabe sus dimensiones. Para este tipo de situaciones Visual Basic permite declaraciones de
arreglos del siguiente modo:
Dim x ( ) As Integer
...
...
Redim x (lstLista.ListCount)
Cuando se redimensiona un arreglo, los valores almacenados anteriormente se pierden,
porque cada elemento es reinicializado con cero o null dependiendo del tipo de dato del
elemento. Si se desea preservar los valores debemos usar la palabra clave Preserve en la
sentencia de redimensionamiento.
Redim Preserve x ( intNmeroDeElementos )
OPERADORES
Aritmticos
^
Exponenciacin
*
Multiplicacin
/
Divisin
Divisin entera
Mod
Residuo entero (Ejm: A Mod B)
+
Suma
Resta
&
Concatenacin de cadenas
Comparacin
=
Igual
<>
Distinto
Menor que
<=
Menor o igual
>=
Mayor o igual
Like
Compara dos cadenas
*
Cero o ms caracteres (Ejm: cad Like ma*)
?
Cualquier carcter
#
Cualquier dgito (0-9)
[lista] cualquier carcter en lista
[lista] cualquier carcter que no esta en lista
Is
Usado para comparar dos variables de referencia a objetos
Parte 3: Tipos de datos, constantes y variables - Danny A. Matta Gonzales
33
Lgicos
And
Or
Xor
Not
Y lgico
O lgico
O Exclusivo
Negacin
34
Condicin normalmente es una comparacin, pero puede ser cualquier expresin que d
como resultado un valor numrico. Visual Basic interpreta este valor como True o False;
un valor numrico cero es False y se considera True cualquier valor numrico distinto de
cero. Si condicin es True, Visual Basic ejecuta todas las sentencias que siguen a la
palabra clave Then. Puede utilizar sintaxis de una lnea o de varias lneas para ejecutar
una sentencia basada en una condicin, los siguientes dos ejemplos son equivalentes:
Observe que el formato de una nica lnea de If...Then no utiliza la instruccin End If. Si
se desea ejecutar ms de una lnea de cdigo cuando condicin sea True, debe utilizar la
sintaxis de bloque de varias lneas If...Then...End If.
If...Then...Else
Utilice un bloque If...The...Else para definir varios bloques de sentencias, uno de los
cuales se ejecutar:
If condicin1 Then
[bloque de sentencias 1]
35
Observe que siempre puede agregar ms clusulas ElseIf a la estructura If...Then. Sin
embargo, esta sintaxis puede resultar tediosa de escribir cuando cada ElseIf compara la
misma expresin con un valor distinto. Para estas situaciones, puede utilizar la estructura
de decisin Select Case.
Select Case
Visual Basic proporciona la estructura Select Case como alternativa a If...Then...Else
para ejecutar selectivamente un bloque de sentencias entre varios bloques. La sentencia
36
Select Case ofrece posibilidades similares a la instruccin If...Then...Else, pero hace que
el cdigo sea ms legible cuando hay varias opciones.
La estructura Select Case funciona con una nica expresin de prueba que se evala una
vez solamente, al principio de la estructura. Visual Basic compara el resultado de esta
expresin con los valores de cada Case de la estructura. Si hay una coincidencia, ejecuta
el bloque de sentencias asociado a ese Case:
37
Observe que la estructura Select Case evala una expresin cada vez que al principio de
la estructura. Por el contrario, la estructura If...Then...Else puede evaluar una expresin
diferente en cada sentencia ElseIf. Slo puede sustituir una esructura If...Then...Else con
una estructura Select Case si la intruccin If y cada instruccin ElseIf evala la misma
expresin.
38
Otros Ejemplos
Estrucuras de Repeticin
Las estructuras de repeticin o bucle le permiten ejecutar una o ms lneas de cdigo
repetidamente. Las estructuras de repeticin que acepta Visual Basic son:
Do...Loop
For...Next
For Each...Next
Do...Loop
Utilice el bucle Do para ejecutar un bloque de sentencias un nmero indefinido de veces.
Hay algunas variantes en la sentencia Do...Loop, pero cada una evala una condicin
numrica para determinar si contina la ejecucin. Como ocurre con If...Then, la
condicin debe ser un valor o una expresin que d como resultado False (cero) o True
(distinto de cero).
En el siguiente ejemplo de Do...Loop, las sentencias se ejecutan siempre y cuando
condicin sea True:
Do While condicin
Sentencias
Loop
Cuando Visual Basic ejecuta este bucle Do, primero evala condicin. Si condicin es
False (cero), se salta todas las sentencias. Si es True (distinto de cero) Visual Basic
ejecuta las sentencias, vuelve a la instruccin Do While y prueba la condicin de nuevo.
Por tanto, el bucle se puede ejecutar cualquier nmero de veces, siempre y cuando
condicin sea distinta de cero o True. Nunca se ejecutan las sentencias si condicin es
False inicialmente. Por ejemplo, este procedimiento cuenta las veces que se repite una
cadena destino dentro de otra cadena repitiendo el bucle tantas veces como se encuentre
la cadena de destino:
39
For...Next
Los bucles Do funcionan bien cuando no se sabe cuntas veces se necesitar ejecutar las
sentencias del bucle. Sin embargo, cuando se sabe que se va a ejecutar las sentencias
un nmero determinado de veces, es mejor elegir el bucle For...Next. A diferencia del
bucle Do, el bucle For utiliza una variable llamada contador que incrementa o reduce su
valor en cada repeticin del bucle. La sintaxis es la siguiente:
For contador = iniciar To finalizar [Step incremento]
Sentencias
Next [contador]
Los argumentos contador, iniciar, finalizar e incremento son todos numricos.
Nota: El argumento incremento puede ser positivo o negativo. Si incremento es
positivo, iniciar debe ser menor o igual que finalizar o no se ejecutarn las sentencias
del bucle. Si incremento es negativo, iniciar debe ser mayor o igual que finalizar para
que se ejecute el cuerpo del bucle. Si no se establece Step, el valor predeterminado de
incremento es 1. Al ejecutar el bucle For, Visual Basic:
1. Establece contador al mismo valor que iniciar.
2. Comprueba si contador es mayor que finalizar. Si lo es, Visual Basic sale del bucle.
(Si incremento es negativo, Visual Basic comprueba si contador es menor que
finalizar.)
3. Ejecuta las sentencias.
4. Incrementa contador en 1 o en incremento, si se especific.
5. Repite los pasos 2 a 4.
Este cdigo imprime los nombres de todas las fuentes de pantalla disponibles:
For Each...Next
40
El bucle For Each...Next es similar al bucle For...Next, pero repite un grupo de sentencia
por cada elemento de una coleccin de objetos o de una matriz en vez de repetir las
sentencias un nmero especificado de veces. Esto resulta especialmente til si no se sabe
cuntos elementos hay en la coleccin. He aqu la sintaxis del bucle For Each...Next:
For Each elemento In grupo
Sentencias
Next elemento
Por ejemplo, el siguiente procedimiento Sub abre la base de datos Biblio.mdb y agrega el
nombre de cada tabla a un cuadro de lista.
41
Exit For y Exit Do son muy tiles ya que, algunas veces, resulta apropiado salir
inmediatamente de un bucle sin realizar ms iteraciones o sentencias dentro del bucle.
Cuando utilice la instruccin Exit para salir de un bucle, el valor de la variable contador
difiere, dependiendo de cmo haya salido del bucle:
Cuando termina un bucle, la variable contador contiene el valor del lmite superior
ms el paso.
Cuando sale de un bucle prematuramente, la variable contador conserva su valor
segn las reglas usuales del alcance.
Cuando sale antes del final de una coleccin, la variable contador contiene Nothing si
se trata de un tipo de dato Object y Empty si es un tipo de dato Variant.
Parte 5: Controles Estndar Adicionales y Procedimientos
Visible
1 Checked (Marcado)
2 Grayed (Gris, Indefinido)
Determina si la casilla est visible o no.
Eventos
Click
Arreglo de Controles
Cuando creamos un arreglo de controles, todos los controles que forman el arreglo deben
tener el mismo nombre (Propiedad Name), la propiedad Index establece el ndice de cada
control en el arreglo, esta propiedad comienza desde 0.
Un arreglo de controles es un grupo de controles que comparten el mismo:
Tipo de objeto
Nombre del control
Procedimientos de evento
Cdigo ms fcil de escribir y mantener
43
Los arreglos de controles hace que el cdigo sea ms fcil de escribir y mantener debido a
que solo escribe un solo procedimiento de evento para todos los controles pertenecientes
al arreglo, el parmetro Index del procedimiento de evento determina desde que control
ocurri el evento.
Cdigo ms eficiente
Los arreglos de controles hacen que el cdigo sea ms eficiente y mejoran el rendimiento
de la aplicacin debido a que usa menos recursos del sistema que los controles
individuales.
Cmo se crea un arreglo de controles?
Luego de crear y establecer el nombre del primer control, tiene dos alternativas:
Mtodo 1
1. Copiar el primer control al portapapeles.
2. Luego pegar el control de portapapeles en el formulario. Visual Basic le
preguntar si desea crear un arreglo de controles.
3. Repita el paso 2 hasta completar el arreglo.
Mtodo 2
1. Dibuje el siguiente control y establezca su nombre igual al del primer control.
Visual Basic le preguntar si desea crear un arreglo de controles.
2. Repita el paso 1 hasta completar el arreglo.
Ejemplo
La interfaz mostrada tiene un arreglo de controles para seleccionar el reporte, el
procedimiento de evento es el mismo para cualquier elemento del arreglo.
44
Propiedades
Enabled
List
ListCount
ListIndex
MultiSelect
Name
NewIndex
45
Selected
Sorted
Style
Text
Arreglo de valores lgicos paralelo y del mismo tamao al arreglo list, indica
que elementos han sido seleccionados (True) de la lista. Se utiliza en lugar
de ListIndex cuando establecemos la propiedad Multiselect en 1 2.
True/False. Establece los elementos se ordenan alfabticamente.
Establece el comportamiento del control.
Devuelve el elemento seleccionado en el cuadro de lista; el valor de retorno
es siempre equivalente al que devuelve la expresin List(ListIndex). Es de
slo lectura en tiempo de diseo y es de slo lectura en tiempo de ejecucin.
Mtodos
AddItem
Permite aadir nuevos elementos a la lista.
RemoveItem Permite eliminar elementos de la lista.
Eventos
Click
Ejemplos
Muestra en el Cuadro de Texto txtGaseosa el elemento seleccionado
Private Sub lstGaseosas_Click()
txtGaseosa.Text = lstGaseosas.Text
End Sub
Aade un nuevo elemento al Cuadro de Lista lstGaseosas
NewIndex
Sorted
Style
Text
Mtodos
AddItem
Permite aadir nuevos elementos a la lista.
RemoveItem Permite eliminar elementos de la lista.
Eventos
Click
Change
Propiedad Style
Esta propiedad establece el comportamiento del control ComboBox, y puede tomar los
siguientes valores:
Ejemplo
En la siguiente interfaz se ilustra el uso del control ComboBox y la propiedad Style.
47
el
usuario
modifica
el
control
seleccionado
del
control
Procedimientos
Existen dos tipos de procedimientos con los que se trabaja en Visual Basic: los
procedimientos de evento y los procedimientos generales.
Procedimientos de Evento
Visual Basic invoca automticamente procedimientos de evento en respuesta a acciones
del teclado, del ratn o del sistema. Por ejemplo, los botones de comando tienen un
procedimiento de evento Click. El cdigo que se escriba en el procedimiento de evento
Click es ejecutado cuando el usuario haga clic en un botn de comando.
Cada control tiene un conjunto fijo de procedimientos de evento. Los procedimientos de
evento para cada control son mostrados en un cuadro de lista despegable en la ventana de
cdigo.
Procedimientos Generales
Los procedimientos generales son procedimientos Sub o Function que son creados para
que lleven a cabo tareas especficas, estos deben ser invocados de manera explcita.
Para crear un procedimiento general, se debe abrir la ventana de cdigo y hacer clic en la
orden Agregar procedimiento del men Herramientas. Tambin se puede crear un
nuevo procedimiento escribiendo el encabezado de procedimiento Sub, seguido por el
nombre del procedimiento, en una lnea en blanco dentro de la ventana de cdigo.
Si se tiene cdigo duplicado en varios procedimientos de evento, se puede colocar el
cdigo en un procedimiento general y luego invocar al procedimiento general desde los
procedimiento de evento.
Procedimientos Sub
Los procedimientos Sub no retornan valores. Por ejemplo:
Los procedimientos Sub son invocados especificando slo el nombre del procedimiento, o
empleando la instruccin Call con el nombre del procedimiento. Por ejemplo:
Call Seleccionar(Text1)
Si se emplea la instruccin Call, se debe encerrar la lista de argumentos entre parntesis.
Si se omite Call, tambin se deben omitir los parntesis alrededor de la lista de
argumentos.
Procedimientos Function
48
49
Para visualizar una lista de los valores ASCII, busque ASCII en la ayuda de Visual Basic.
Validacin de Informacin a Nivel de Formulario
Adems de emplear tcnicas a nivel de campo para validar los datos mientras son
ingresados, se puede escribir cdigo que valide los datos en todos los campos de un
formulario al mismo tiempo. En esta parte del curso se vern las tcnicas de validacin a
nivel de formulario soportadas por Visual Basic.
Habilitando el Botn Aceptar
Una forma de validar la informacin del formulario sera la de asegurar que un usuario ha
ingresado los datos en todos los campos en un formulario antes de que se le permita
continuar. Esto puede llevarse a cabo deshabilitando el botn Aceptar en un formulario
hasta que el usuario haya llenado todos los campos, como se muestra a continuacin.
51
52
Notas:
Cuando se cierra un objeto MDIForm, el evento QueryUnload ocurre primero para el
formulario MDI principal y despus en todos los formularios secundarios MDI. Si
ningn formulario cancela el evento QueryUnload, ocurre el evento Unload primero
en todos los dems formularios y despus en un formulario MDI principal. Cuando un
formulario secundario o un objeto Form se cierra, el evento QueryUnload de ese
formulario ocurre antes que el evento Unload del formulario.
Cuando una aplicacin se cierra, puede utilizar los procedimientos de evento
QueryUnload o Unload para establecer la propiedad Cancel a True, deteniendo el
proceso de cierre. Sin embargo, el evento QueryUnload ocurre en todos los
53
54
Descripcin
Regresa a la instruccin que gener el error. Emplee Resume para
repetir una operacin luego de corregir el error.
Instruccin
Descripcin
Resume Next
Regresa a la instruccin inmediatamente siguiente a la que gener el
error.
Resume lnea
La ejecucin contina en la lnea especificada en el argumento
obligatorio
lnea.
Nota:
Si utiliza una instruccin Resume en otro sitio que no sea una rutina de manipulacin
de errores, ocurre un error.
Deshabilitando la Manipulacin de Errores
Puede ser difcil depurar cdigo que tiene habilitada la manipulacin de errores. Visual
Basic puede ejecutar el cdigo de manipulacin de errores cuando se quiera ingresar al
modo de Interrupcin y depurar la aplicacin.
Visual Basic proporciona opciones para deshabilitar la manipulacin de errores en el
momento de la depuracin.
Para cambiar como sern manipulados los errores:
1. En el men Herramientas, haga clic en Opciones.
2. En la ficha General, debajo de Interceptacin de errores, haga clic en la opcin
deseada y luego en Aceptar.
La siguiente tabla describe las opciones de manipulacin de errores disponibles debajo de
Interceptacin de errores en la ficha General.
55
Adems del archivo ejecutable, se debe de proporcionar diversas DLL's y otros archivos
a los usuarios. Se debera crear un programa de instalacin que instale la aplicacin en
la computadora del usuario.
El Asistente para instalar aplicaciones de Visual Basic hace sencilla la tarea de
crear discos o una carpeta de distribucin para una aplicacin. Los usuarios pueden
luego ejecutar el programa de instalacin en sus computadoras para instalar y registrar
los archivos apropiados.
Parte 7: Controles Estndar Avanzados y Acceso a Datos
para ajustarse al control o viceversa. Aunque puede colocar un control Image dentro de
un contenedor, un control Image no puede actuar como contenedor.
Funcin LoadPicture()
Carga un grfico en un objeto Picture, un control PictureBox o un control Image.
Formato:
LoadPicture(NombreDeArchivoGrfico)
Tambin se puede usar la funcin LoadPicture() para asignar un icono a un formulario o
al puntero del ratn mostrado en pantalla.
Ejemplos de la funcin LoadPicture():
'Establece el icono del formulario
Set Form1.Icon = LoadPicture("MIICONO.ICO")
'Establece el puntero del ratn
Screen.MouseIcon = LoadPicture("MIICONO.ICO")
Screen.MousePointer = 99
Creacin de un visor de imgenes
58
fondo. No existe ningn lmite prctico en cuanto al nmero de controles Timer activos
que se puede tener en Visual Basic 5.0 ejecutndose en Windows 95 o en Windows NT.
Propiedades
Enabled True/False. Activa o desactiva el control. Si se desactiva el control Timer,
estableciendo Enabled a False, se cancelar la cuenta atrs establecida por la
propiedad Interval del control.
Interval Devuelve o establece el nmero de milisegundos entre las llamadas al evento
Timer de un control Timer. Los valores admitidos para milisegundos son 0, que
desactiva el control Timer, o de 1 a 65535. El mximo, 65535 milisegundos,
equivale a poco ms de un minuto.
Eventos
Timer
59
60
61
La Clave Principal
Cada tabla debe de tener una clave principal, que es un campo (o una combinacin de
campos) que es nico para cada registro en la tabla. Por ejemplo, el campo IdEmpleado es
la clave principal para la tabla Empleados.
Una tabla puede tambin tener claves forneas, que son campos que hacen referencia a
una clave principal de otra tabla. Por ejemplo, en la base de datos Neptuno, la tabla
Pedidos tiene un campo llamado IdCliente. Este campo es una clave fornea porque hace
referencia a un cliente de la tabla Clientes. En vez de duplicar toda la informacin del
cliente por cada pedido, slo se ingresa la clave principal del cliente a quien pertenece el
pedido, como la clave principal es nica por cada cliente, hay un solo cliente por cada
62
pedido, y un cliente puede tener muchos pedidos. En trminos de una base de datos, la
relacin entre la tabla Clientes y la tabla Pedidos es una relacin del tipo uno-a-varios.
Registros
Un registro contiene informacin acerca de un solo ingreso en una tabla. Generalmente, no
se desea que dos registros en una tabla tengan los mismos datos. Por ejemplo, un registro
en la tabla Empleados contiene informacin acerca de un nico empleado.
Campos
Cada campo en una tabla contiene una parte de la informacin. Por ejemplo, la tabla
Empleados incluye campos para el Id del empleado, Apellidos, Nombre, etc.
Indices
Los ndices de una tabla de una base de datos son listas ordenadas que son ms rpidas
para las bsquedas que las tablas en s. Para habilitar un acceso ms rpido a una base de
datos, la mayora de bases de datos emplean uno o ms ndices. Por ejemplo, la tabla
Empleados tiene un ndice para la columna IdEmpleado.
Trabajando con el Control Data
El control Data de Visual Basic permite escribir aplicaciones de bases de datos muy
eficaces con muy poco cdigo.
En esta parte se aprender a generar aplicaciones de bases de datos con el control Data y
el objeto Recordset asociado. Tambin se aprender como el Asistente para Formularios
de Datos puede construir una aplicacin que incluye el control Data.
Tener Acceso a Datos con el Control Data
El control Data implementa el acceso a datos mediante el motor de base de datos
Microsoft Jet. Esta tecnologa proporciona acceso a muchos formatos de base de datos y
permite crear aplicaciones que manejan datos sin necesidad de escribir cdigo.
Para crear una aplicacin de base de datos que emplee el control Data, se siguen los
siguientes pasos:
1. Aadir el control Data al formulario y establecer las propiedades para especificar la
base de datos y la tabla desde la cual se obtendrn los datos.
2. Aadir controles enlazados a datos al formulario, y establecer las propiedades para
enlazar los controles al control Data para que los datos puedan ser mostrados.
Uso de Controles Enlazados a Datos
Cuando un control que ha colocado en un formulario se enlaza a datos, se muestran
automticamente los datos de la base de datos en el control enlazado. Si un usuario
cambia los datos de un control enlazado, dichos cambios se actualizarn automticamente
en la base de datos en cuanto el usuario se desplace a otro registro. Muchos controles
intrnsecos o estndar de Visual Basic permiten ser enlazados a datos, como es el caso de
los controles CheckBox, Image, Label, PictureBox, TextBox, ListBox, ComboBox y
los contenedores OLE.
La siguiente ilustracin es un ejemplo de un formulario que contiene un control Data y dos
controles enlazados.
63
64
El Objeto Recordset
En una aplicacin de base de datos, los usuarios trabajan con el control Data para
desplazarse entre registros dentro de la base de datos. Los usuarios pueden hacer clic en
los botones del control Data para avanzar o retroceder registro a registro o para ir
directamente al primer o al ltimo registro.
Qu es un Recordset?
Todo el conjunto de registros al que hace referencia un control Data se denomina conjunto
de registros o Recordset. El Recordset se almacena en la memoria, transfirindose al
disco si es necesario.
Para manipular el Recordset, se emplea la propiedad Recordset del control Data. El
Recordset contiene el registro actual. La informacin del registro actual es mostrada por
los controles enlazados. Se puede cambiar la posicin del registro actual haciendo clic en el
control Data o escribiendo cdigo que emplee mtodos del objeto Recordset.
Determinar los lmites de un Recordset
Si utiliza cdigo para cambiar la posicin del registro actual, debe comprobar las
propiedades EOF y BOF del objeto Recordset para determinar el inicio y el final del
mismo. Cuando se desplace al registro EOF o al BOF, se ejecutar la accin indicada por el
valor de la propiedad BOFAction o EOFAction.
Por ejemplo, se puede establecer la propiedad EOFAction para aadir un nuevo registro
automticamente. Si se establece la propiedad EOFAction a EOF, ninguna accin ser
tomada cuando se desplace al registro EOF. Cuando se desplace pasando un registro los
registros BOF o EOF, se producir un error en tiempo de ejecucin.
En la siguiente ilustracin se muestra cmo las propiedades BOF y EOF determinan los
lmites del objeto Recordset.
65
66
El control Data proporciona tres eventos que puede utilizar para mejorar la aplicacin de
base de datos: Validate, Error y Reposition. Dichos eventos permiten omitir parte del
comportamiento predeterminado del control Data.
Usar el Evento Validate
Utilice el evento Validate para comprobar los datos antes de guardar un registro en la base
de datos. Este evento se produce justo antes de que Visual Basic escriba en la base de
datos los cambios procedentes de los controles enlazados y de que vuelva a colocar el
puntero del registro actual en otro registro de la base de datos. Puede utilizar el evento
Validate para pedir al usuario que confirme los cambios realizados.
Sintaxis
El evento Validate tiene la siguiente sintaxis:
Private Sub Data1_Validate (index As Integer, action As Integer, save As Integer)
El Argumento Action
El argumento action indica la operacin que provoc el evento Validate. El evento Validate
se produce como resultado de realizar las operaciones siguientes:
Para ver el nmero del registro actual, utilice la propiedad AbsolutePosition del objeto
Recordset. El nmero de registro es relativo a cero, por lo que el primer registro es el 0.
El siguiente cdigo muestra como visualizar el nmero del registro actual.
Private Sub Data1_Reposition()
Data1.Caption = "Registro N" & Data1.Recordset.AbsolutePosition + 1
End Sub
Tratar los cambios al desplazarse a un nuevo registro
Cuando un usuario se desplaza a un nuevo registro mediante el control Data, puede que
los datos del formulario tengan que presentarse de una forma distinta en el caso del nuevo
registro.
Por ejemplo, es posible que en un formulario que muestre registros de empleados haya
distintas opciones dependiendo de s los empleados son fijos, temporales o si trabajan por
horas. Cada registro mostrar la informacin sobre un empleado distinto, cuyas opciones
pueden no ser las mismas para todos los registros. Para que se seleccione la opcin
correcta para cada registro, escriba cdigo en el evento Reposition.
El cdigo siguiente utiliza el evento Reposition para modificar la apariencia de un
formulario.
68
70
Por ejemplo, para combinar las celdas en la tabla Detalles de pedidos, aada el siguiente
cdigo al formulario donde se encuentra el control MSFlexGrid.
Private Sub Form_Load()
MSFlexGrid1.MergeCells = flexMergeFree
MSFlexGrid1.MergeCol(0) = True
End Sub
71
representacin en la ventana. Son por ejemplo, los objetos de acceso a datos que veremos
profusamente ms adelante.
Todos los objetos de Visual Basic tienen Propiedades. (Por ejemplo, el nombre de ese
objeto es una de sus propiedades). Los objetos que tienen parte grfica tienen adems
Eventos. Y muchos de ellos tienen tambin Mtodos
Propiedades, Eventos, Procedimientos y Mtodos
Tpica pregunta de examen de VB elemental. Veamos que es cada una de estas cosas.
Las propiedades son aquellas caractersticas de un objeto que lo define "fsicamente", bien
por su forma o color, por su contenido, por la forma en la que va a trabajar
Las
propiedades pueden modificarse cuando estamos diseando la interface grfica, mediante
lo que llamamos caja de propiedades, o durante la ejecucin del programa. En este caso
hay que hacerlo con cdigo escrito en el propio programa. Veamos ya dos definiciones que
se repetirn profusamente a lo largo del curso
-
al ejecutarse esa lnea, se cambiar el color del control de nombre MiControl. Hemos
cambiado la propiedad BackColor de ese control en tiempo de ejecucin.
Las propiedades pueden ser de lectura y escritura, (se puede cambiar y se puede leer el
valor de la propiedad), slo de lectura (solamente se puede leer el valor de la propiedad)
solo de escritura (hay muy pocas de este tipo). Puede que una propiedad, que es de
lectura y escritura en tiempo de diseo, sea slo de lectura en tiempo de ejecucin (esto
es lo que le pasa por ejemplo, a la propiedad Name - Nombre)
Un evento es todo aquello que le puede ocurrir a un objeto con parte grfica (Control o
Formulario) Por ejemplo, es un evento el hecho de hacer click sobre ese control, el hecho
de pasar el ratn por encima de l, el hecho de que un control cambie de tamao. Los
controles tienen muchos eventos, unos de ellos comunes a casi todos los controles (Evento
click, por ejemplo) y otros exclusivos de un determinado control (El evento Timer
solamente lo tiene el control Timer) Puede ver los eventos de un control haciendo doble
click sobre ese control en tiempo de diseo. Le aparecer la ventana de cdigo.
72
MouseUp, que se ejecuta cuando levantamos el botn del ratn (tambin existe el evento
MouseDown), pasa los siguientes parmetros: Nmero del botn que se ha pulsado,
(1=Izdo, 2=Dcho, 3=Central), si est pulsada la tecla maysculas (Shift, 1 si est pulsada,
0 si no est pulsada) y los valores X e Y de la posicin del cursor del ratn. Podemos ver
los parmetros que pasa en la propia definicin del procedimiento, que nos da Visual Basic
Private Sub Command1_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As
Single)
End Sub
Observe que los parmetros estn entre parntesis, y que queda definido el tipo de
variable que es cada uno de ellos. Podemos usar ese valor dentro del cdigo del
procedimiento como un dato ms.
Un Mtodo es una operacin que la realiza Visual Basic sin necesidad de escribir cdigo
para realizarla. Por ejemplo, si queremos dibujar una lnea en un formulario o en la
impresora utilizaremos el mtodo Line. Si queremos dibujar una circunferencia usaremos el
mtodo Circle. Si queremos escribir texto, utilizaremos el mtodo Print. No necesitamos
decirle como lo tiene que haver, puesto que eso ya lo sabe hacer VB sin necesidad de que
se lo expliquemos. A los mtodos les tenemos que pasar datos. A eso le llamamos tambin
pasarle parmetros. Los mtodos solo permiten introducir los parmetros que necesita el
mtodo para ejecutarse. (En el caso de una lnea, el punto inicial y el final, en el caso del
circulo, el radio y las coordenadas del centro. Pueden pedir parmetros optativos, como el
puede ser el color de la lnea o circulo.
Espero que le quede claro cada una de estas definiciones. Tendr tiempo suficiente a lo
largo del curso para verlas, y dentro de muy poco tiempo le sern muy familiares estos
conceptos.
EL FORMULARIO
El primer objeto Visual Basic con que nos encontramos es el FORMULARIO. De hecho, cada
vez que iniciamos Visual Basic (VB) nos presenta en pantalla un nuevo formulario, que
tiene por defecto el nombre de Form1
El Formulario es un objeto, que sirve de soporte de otros objetos. El nombre de
FORMULARIO lo toma precisamente porque, al igual que un formulario de papel contiene
textos escritos, lugares donde podemos escribir, figuras, cajas donde podemos elegir una u
otra opcin, etc., en este cuadro grfico que llamamos formulario, podemos introducir
textos escritos, lugares donde podemos escribir, figuras, cajas donde podemos elegir una u
otra opcin ....
En realidad un formulario es lo que normalmente conocemos por VENTANA. El nombre de
formulario le viene muy bien cuando ese formulario es una ventana donde vamos a
introducir datos alfanumricos. Cuando en vez de introducir datos, lo que tenemos es, por
ejemplo, una ventana donde se reproducen exactamente los controles de operacin de una
mquina, parece en principio que sera mas correcto el nombre de "ventana". De alguna
forma lo hay que llamar, y esa forma es FORMULARIO. Posiblemente a lo largo de estos
apuntes nos referiremos al formulario con el nombre de ventana, o incluso, pantalla.
Procuraremos usar el nombre apropiado: FORMULARIO.
74
Fig. 2.3 Un formulario que parece un equipo de radio (Programa realizado por el autor)
Ejemplo de un formulario para una aplicacin industrial. Este formulario reproduce el panel
de control de un transmisor - receptor de radio. En este caso, parece que el nombre de
ventana le viene mejor que el de formulario. Observe que dentro del formulario existen
gran cantidad de objetos. Botones, que hacen la misma funcin que el botn real en el
equipo de radio, y un par de displays, que muestran un texto, en este caso las frecuencias
de transmisin y recepcin.
Como cualquier objeto Visual Basic, un formulario tiene propiedades, procedimientos y
mtodos.
Vamos a ver las propiedades del formulario, pero solo veremos las que son especficas para
un formulario. El resto las podr ver al final del captulo. Aqu haremos referencia a esas
propiedades con un asterisco (*) que significa que esa propiedad no tiene una notacin
especial para los formularios. Seguiremos esta norma con todos los controles.
PROPIEDADES.
Name
Nombre
75
Caption
Ttulo
Es el texto que aparecer en la barra de Ttulo cada vez que aparezca en pantalla este
formulario. No tiene otra funcin dentro del programa. El programa no accede a este
formulario por el ttulo, sino por el nombre. Puede cambiarse en tiempo de ejecucin.
NOTA.- No confundir Nombre (Name) con Ttulo (Caption)
Control Box Men de Control en la parte sup. Izda.
Propiedad Booleana que admite los valores de true (verdadero) o False (Falso). Si esta
propiedad es True, aparecer en la esquina superior izquierda el icono (el "menos" en W3.11) para desplegar el men de control de este formulario. Si esta propiedad se pone
como False, no aparece dicho icono y por tanto no se puede desplegar dicho men.
MinButton
MaxButton
Botones de minimizar
booleanas, que admiten
correspondiente. Si estn
otra forma, dependiendo
ejecucin.
y
el
en
si
Nota.
En los formularios MDI child, es necesario poner a true las propiedades
ControlBox, MinButton y MaxButton para poder maximizar el formulario hijo. De no
ponerlas a true, s se pretende maximizar el formulario hijo, (Propiedad WindowState=2)
el formulario no aparece.
BorderStyle Tipo de borde
Define el tipo de borde que tendr el formulario durante la ejecucin. No se puede cambiar
en tiempo de ejecucin. Admite los siguientes valores:
0 - None
1 - Fixed Single
El formulario tendr un borde fino, y no podr cambiarse su tamao
durante el tiempo de ejecucin. Con este valor, el formulario puede
tener un men de control, barra de ttulo y botones de maximizar y
minimizar. Solo podr cambiarse de tamao utilizando estos botones.
2-Sizable
El formulario tendr borde grueso, y se podr cambiar su tamao en
tiempo de ejecucin mediante los botones de maximizar y minimizar,
y mediante el arrastre de uno de los bordes con el ratn.
3 - Fixed Dialog
El formulario tendr borde grueso, y no se podr redimensionar
durante la ejecucin. No puede tener los botones de maximizar ni
minimizar.
4 - Fixed ToolWindow
En las versiones de 16 bits de Windows y Windows NT 3.51 y
anteriores se comporta como Fixed Single. No puede cambiar de
tamao. En Windows 95 muestra el botn Cerrar, y el texto de la
barra de titulo aparece con un tamao de fuente reducido. El
formulario no aparece en la barra de tareas de W95.
76
5 - Sizable ToolWindow
En las versiones de 16 bits se comporta como Sizable. En W95
muestra el botn Cerrar y el texto de la barra de titulo aparece con
un tamao de fuente reducido. El formulario no aparece en la barra
de tareas de W95.
Valor por defecto: 2 . Sizable
Nota: Al cambiar a determinados valores, las propiedades MaxButton
y MinButton se ponen a False. Pueden cambiarse a True
posteriormente.
Appearance Apariencia
Valor por defecto: 3D
Admite los valores 0 (=Flat, plano) y 1 (=3D) Si tiene el valor 1 (3D), el formulario
aparecer con cierto efecto tridimensional, y los controles que le introduzcamos a este
formulario aparecern como esculpidos dentro de l. Con valor 0 (Flat) en esta propiedad,
el formulario aparecer durante la ejecucin como una superficie plana. El color de fondo
se ve afectado al cambiar esta propiedad. Si se cambia a 3D, el fondo (Backcolor) toma el
color definido en Windows en el Panel de Control. Si se cambia a Flat, toma el color blanco
Autoredraw
Valor por defecto: False
Propiedad Booleana. Esta propiedad, estando en True, permite actualizar el contenido del
formulario y de sus controles incluso cuando no estn visibles. Imaginemos que en este
formulario existe un texto, que se haya cambiado por programa mientras este formulario
no estaba visible. Si esta propiedad Autoredraw est en False, al hacer visible este
formulario, aparecer sin reflejar ese cambio. Si esta propiedad est en True, aparecer
actualizado.
Backcolor
Color del fondo
Establece el color del fondo del formulario. Puede cambiarse en tiempo de ejecucin.
Valor por defecto: El establecido en el Panel de Control de Windows.
ClipControls
Valor por defecto: False
Propiedad Booleana. Establece si un evento Paint vuelve a dibujar el objeto entero (True) o
si solamente dibujan las partes que han sufrido cambios (False)
DrawMode
Establece un valor que determina el aspecto de la salida de un mtodo grfico o el aspecto
de un control Shape o Line. Ver mas adelante los efectos de esta propiedad.
DrawStile
(*)
Valor por defecto : 0
DrawWidth (*)
Valor por defecto: 1
Enabled
(*)
ForeColor
Valor por defecto: Negro
Establece el color del primer plano del formulario. Es el color que tendrn las letras si
escribimos en l, o los dibujos, si lo que hacemos es dibujar. En tiempo de diseo,
determina el color de la rejilla,.
FillStyle
FillColor
Font
Tipo de relleno
(*)
Color del relleno
(*)
Tipo de letra Valor por defecto: El determinado en la personalizacin.
truco para utilizar en todos los controles una determinada fuente sin tener que teclearla
para cada control.
FontTranparent
Texto Transparente
Valor por defecto: True
Establece si el texto o grfico de fondo del formulario se muestra (True) o no se muestra
entre los caracteres de texto escritos en el propio formulario.
FontSize
Tamao de letra
(*)
FontBold, FontItalic, FontStrikethru, FontUnderline
(*)
Height
Altura
(*)
HelpContextID
Identificador de contexto de la Ayuda (*)
Icon
Icono
Esta propiedad define el icono que va a representar a este formulario cuando est
minimizado. Si el formulario es el formulario padre o formulario de inicio de una aplicacin,
este icono es el que toma el Asistente de Instalacin para colocarlo como icono de apertura
del programa en el grupo de programas Windows correspondiente. Como valor de esta
propiedad se le puede asignar directamente el icono o el nombre de un archivo (con su
path correspondiente) que lo contiene, hacindolo directamente sobre la caja de
propiedades.
Valor por defecto: el icono que se le haya programado en la personalizacin.
KeyPreview
Propiedad Booleana. Cuando un formulario tiene dentro de s varios controles, uno de ellos
es el que est activo. En estas condiciones, si se pulsa una tecla, esa pulsacin la recibe
en primer lugar el control que est activo, y si ste no la procesa, pasa esa pulsacin al
formulario. Para hacer que esa pulsacin pase previamente por formulario, debe ponerse
esta propiedad en True. Esta propiedad la usar frecuentemente cuando quiera realizar
alguna funcin pulsando una letra. Pone KeyPreview a True, y puede conocer que tecla se
ha pulsado en el procedimiento KeyPress del formulario. Si la tiene a False, ese
procedimiento no se ejecuta ya que la pulsacin no pasa por el formulario.
Left
Indica la posicin del borde izquierdo del formulario respecto a la parte izquierda de la
pantalla. (Lo ver mas adelante, la pantalla ser para VB el objeto Screen). Normalmente
no se introduce como valor numrico, sino que lo toma automticamente de la posicin
que tenga el formulario en el tiempo de diseo. Puede cambiarse en tiempo de ejecucin,
para mover el formulario.
LinkMode
Valor por defecto: 0
Permite que una aplicacin destino inicie una conversacin DDE con el formulario (origen
de datos). Puede tomar los siguientes valores:
0 - No hay interaccin DDE
1 - Source. Indica que este Formulario es origen de una comunicacin DDE. El dato
que se va a traspasar en esa comunicacin DDE estar en un TextBox, en un Label
o en un PictureBox de este Formulario.
LinkTopic
Establece el tema al que este formulario va a responder a una conversacin DDE, cuando
funciona como origen. Es por este tema por el que se debe llamar a este formulario cuando
acta de origen en una conversacin DDE
MDIChild
Valor por defecto: False
Establece que este formulario es un formulario Hijo dentro de un formulario MDI. No se
puede cambiar en tiempo de ejecucin. Es una propiedad Booleana
78
(*)
False =No lo es
(*)
Valor por defecto: flecha
Grfico
Mediante esta propiedad podemos poner un grfico como fondo del formulario. El grfico
puede ser un bit-map o un fichero .ICO
ScaleHeight, ScaleWidth, ScaleMode,
Indican la unidad de medida de dimensin de altura y anchura del Formulario. ScaleMode
indica en qu unidades de medida se van a medir esas dimensiones. Acepta Twips (1),
Point(2), Pixel (3), Character (4), Pulgadas (Inch) (5), Milmetros (6), Centmetros (7). Si
colocamos la propiedad ScaleMode en cualquiera de estos valores, las propiedades
ScaleHeight y ScaleWidth nos vendrn dadas automticamente dependiendo del ancho
del Formulario, y no se extrae si encuentra para estas propiedades valores tan peregrinos
como 4815 y 7423. Al haber elegido la unidad de medida, los valores de ancho
(ScaleWidth) y alto (ScaleHeight) sern los que tengan que ser, medidos en la unidad
que hemos elegido. Podemos elegir una cifra para el ancho y el alto del Formulario de
forma que podamos controlar mejor las distintas posiciones que van a ocupar en l los
controles, los textos o los dibujos. Podemos poner, por ejemplo, que el Formulario mida
400 de ancho (ScaleWidth = 400) y 300 de alto (ScaleHeight = 300) forzndole estas
propiedades, bien en tiempo de diseo en la caja de propiedades, o en tiempo de ejecucin
mediante cdigo. Entonces sabemos que el formulario, independientemente de las
dimensiones fsicas que tenga sobre la pantalla, medir 400 de ancho y 300 de alto, y si en
estas condiciones queremos colocar un control o un dibujo justo en el medio del
Formulario, sabemos que tenemos que colocarle en las coordenadas 200, 150. Que
unidad de medida estaremos utilizando entonces en el Formulario ? Unas definidas por el
usuario (distintas para el ancho y el alto) que sern las necesarias para que el Formulario
mida de ancho lo que le hayamos puesto en la propiedad ScaleWidth y de alto lo que le
hayamos puesto en la propiedad ScaleHeight. Observe que la propiedad ScaleMode se
ha cambiado automticamente a User (0) al introducir las dimensiones de ancho y alto
que nosotros queremos.
Estas unidades de medida afectarn a los controles que metamos en este Formulario. Se
medirn en su ancho y alto con la unidad de medida definida para el ancho y alto del
Formulario. Lgicamente tambin afectar a las propiedades Left y Top de los controles,
pero estas propiedades se vern afectadas adems por las propiedades ScaleLeft y
ScaleTop del Formulario que se vern a continuacin.
ScaleLeft, ScaleTop
Estas propiedades, medidas en la unidad de medida elegida para el ancho y alto mediante
las propiedades ScaleMode, ScaleWidth y ScaleHeight anteriores, expresan las
coordenadas iniciales de la parte izquierda y de la parte superior respectivamente del
Formulario. Estas propiedades no afectan a la posicin del Formulario en la pantalla (Si
est maximizado seguir ocupando toda la pantalla, si est en Normal ocupar el mismo
sitio que se dio en tiempo de diseo).
Supongamos que se le asigna a un Formulario, las propiedades
ScaleWidth = 400, y ScaleHeight = 300.
Si colocamos un control justamente en el centro del Formulario tendr sus propiedades
Top =150 y Left=200.
Si ponemos ahora las propiedades del Formulario
ScaleLeft a 30 y ScaleTop a 10,
ese control, para seguir en el centro del Formulario deber tener sus propiedades
Top a 160 (150 + 10) y Left a 230 (200 + 30).
79
Recuerde que las medidas de un formulario crecen, desde la esquina superior izquierda,
segn avanzamos hacia abajo y hacia la derecha.
Como aclaracin de las relaciones entre distintas unidades de medida, puede ver en la
siguiente table la correspondencia entre cada una de ellas y la unidad imaginaria Twip.
1 Point=20 Twips ; 1Pixel=15 Twips : 1 Charecter=240 Twips ; 1 Inch (pulgada) =1440
Twips 1mm=56,52 Twips 1 cm=566 Twips
Tag
(*)
Top
Posicin del borde superior
Esta propiedad establece la posicin del borde superior del formulario respecto a la parte
superior de la pantalla (Objeto Screen). Normalmente no se introduce como valor
numrico sino que lo toma automticamente de la posicin que tenga el Formulario
durante el tiempo de diseo Este valor puede cambiarse durante la ejecucin para,
conjuntamente con Left, variar la posicin del Formulario. Los valores de Top y Left
definen la esquina superior izquierda del Formulario.
Visible
Width
Ancho
(*)
(*)
WindowState
Establece el estado en el que aparecer el formulario cuando se activa y presenta en
pantalla. Admite tres opciones:
0 - Normal El formulario recupera la posicin y tamao que tena en el tiempo de
diseo.
1 - Minimizado El formulario aparece minimizado, representado por su icono.
2 - Maximizado El formulario aparece maximizado, ocupando toda la pantalla.
EVENTOS DEL FORMULARIO
Se explican a continuacin los eventos de un formulario. Recuerde que un evento es lo que
le puede ocurrir a un formulario o control (p.e. Evento Click) y un procedimiento es el
cdigo escrito en ese evento, que se ejecutar cuando ocurra el evento.
Evento Activate
Activacin
Este evento se ejecuta al convertirse el formulario en formulario activo. Esto sucede
mltiples veces cuando tenemos en el programa mas de un formulario. Slo uno de ellos
puede ser el formulario activo. Este procedimiento no pasa parmetros. No debe
emplearse para los parmetros iniciales del formulario. sese para este fin el evento Load
o el Initialize.
Evento Click
Click
Este evento se ejecuta cuando hacemos Click (con cualquier botn del ratn) en una parte
del formulario que no est ocupada por un control. Para que se ejecute el evento Click es
necesario que no se ejecute el procedimiento MouseDown. (Que no tenga cdigo escrito en
el evento MouseDown). Existe una diferencia entre el evento click del formulario y el de
cualquier control : en el formulario se ejecuta con cualquiera de los botones del ratn, y en
los controles, solamente con el botn izquierdo. Este evento no pasa parmetros.
Evento DblClick
Doble click
Este evento se ejecuta cuando hacemos doble click con cualquier botn del ratn sobre
una parte del formulario que no est ocupada por un control. Este evento no se ejecuta si
tenemos escrito cdigo en el procedimiento Click. No pasa parmetros.
80
Evento GotFocus
(*)
(*)
Este evento ocurre cuando el formulario toma el foco. Cosa un poco difcil, ya que para que
el formulario tome el foco debe ocurrir, o que no tenga ningn control capaz de tomar el
foco, o que todos los controles existentes en el formulario y que puedan tomar el foco,
estn desactivados. No se suele usar este procedimiento.
Evento Initialize
Se produce al cargar por primera vez el formulario. Esto significa que si en una aplicacin
cargamos ese formulario una vez (la primera) se realiza este evento, pero si descargamos
el formulario (con Unload Formxx) y luego lo volvemos a cargar (con Formxx.Show), esta
segunda vez (y sucesivas) no se produce este evento
Evento KeyDown
Evento KeyPress
Evento KeyUp
81
Estos tres procedimientos ocurren cuando el formulario forma parte de un enlace DDE. Vea
el captulo del DDE para mas detalles.
Evento Load
Cargar el formulario
1
2
vbAppTaskManager
cerrando la
vbFormMDIForm
BOTON DE COMANDO
El Command Button es un objeto que sirve para introducir datos a travs de la pantalla. El
Botn de Comando tiene la siguiente forma:
El botn de comando puede usarse para la entrada de datos con el ratn, o para validar
cualquier operacin. El tamao puede cambiarse a voluntad, pero la forma siempre es
rectangular. En la figura anterior vemos dos botones de comando, uno de ellos (el
Command2) marcado con unos puntos en su contorno. Estos puntos nos permiten variar
su tamao en tiempo de diseo. Tambin puede cambiarse su tamao y posicin en tiempo
de ejecucin.
(Las propiedades marcadas con (*) no varan de la descripcin general, hecha al final del
captulo)
PROPIEDADES
Name
Nombre
(*)
Caption
Ttulo (*)
Es el texto que aparece en el botn. Puede cambiarse en tiempo de ejecucin. No tiene
otra funcin dentro del programa.
Appearance Apariencia
(*)
Backcolor
Color de fondo
(*)
Esta propiedad permite cambiar el color del botn cuando la propiedad Style est puesta a
Graphycal. Si la propiedad Style esta puesta a Standars, esta propiedad solamente
controla el color de un pequeo cuadrado que aparece rodeando el ttulo. Puede cambiarse
en tiempo de ejecucin.
Cancel
Establece un valor que indica si un botn de comando es el botn Cancelar de un
formulario. Es una propiedad booleana, y admite los valores True o False. Puede utilizar la
propiedad Cancel para dar al usuario la opcin de cancelar los cambios que no se han
84
(*)
(*)
(*)
(*)
(*)
DragDrop
KeyPress
MouseMove
DragOver
KeyUp
MouseUp
GotFocus
LostFocus
86
LABEL
ETIQUETA
Una etiqueta es un control que nos permite presentar un texto. La etiqueta debe usarse en
aquellos casos en los que exista una informacin esttica o dinmica que no deba ser
cambiada por el operador.
Puede adoptar estas formas: con borde tridimensional, borde plano o sin borde, y el texto
justificado a la izquierda, a la derecha o centrado.
Se ha incluido la trama para poder observar los lmites de la etiqueta sin borde.
PROPIEDADES
Alignment Justificacin
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta.
Appearance Apariencia
Plana o tridimensional.
(*)
Autosize
Si est a True, el tamao de la etiqueta se ajusta al tamao del texto de su
propiedad Caption
Backcolor
Color de fondo
(*)
BackStyle
Tipo de fondo
Opaco o transparente.
Cuando se selecciona transparente, se ve solamente el texto de la etiqueta, dejando ver
como fondo entre las letras, el color o Picture del formulario. Cuando se selecciona opaco,
este texto se v sobre un fondo gris.
BorderStyle Tipo de borde
Sin borde o con borde. En caso de haber elegido en la propiedad Appearance el modo
tridimensional, y eligiendo con borde en esta propiedad, el aspecto adopta una forma como
incrustada en el formulario.
Caption
Ttulo
(*)
DataSource DataField
Establecen el control data asociado y el campo de la base de datos que se presentar en la
propiedad Caption. Estas propiedades permiten presentar los datos de una Base de Datos
mediante un procedimiento muy sencillo, con la ayuda de un control Data (Se ver mas
adelante)
DragIcon
DragMode
Enabled
Font
Index
Left
(*)
LinkItem LinkMode LinkTimeout LinkTopic
ForeColor
Height
Estas propiedades establecen la forma en que debe llevarse a cabo una conexin DDE con
otra aplicacin. Se vern con mas detalle al estudiar los enlaces DDE
MouseIcon
MousePointer
Name
TabIndex
Tag
ToolTipText
Top
(*)
UseMneumonic
Es una propiedad Booleana. Devuelve o establece un valor que indica si al incluir el signo
(&) en el texto de la propiedad Caption del control Label se define una tecla de acceso.
Los valores que puede tomar son True o False.
87
DbClick
LinkError
DragDrop
LinkNotify
TEXT BOX
CAJA DE TEXTO
Las cajas de texto son los controles en los que Visual Basic presenta o introduce textos. Es
por tanto un control bidireccional. Normalmente se usan para introducin de textos, o
para la presentacin de aquellos que el operador pueda cambiar. Para cambiar o escribir un
texto en una caja de texto, basta con conseguir que esa caja de texto tenga el foco y
teclear el texto en el teclado. Esto se puede lograr, bien haciendo click con el ratn en esa
caja de texto, bien con la tecla TAB, bien por programa.
La caja de texto no se debe usar nunca para presentar textos que el operador de la
aplicacin no deba cambiar. sese para ello la etiqueta, control no bidireccional, que
adems tiene la ventaja de ocupar menos memoria de programa.
Las cajas de texto pueden tener una o varias lneas, segn est la propiedad Multiline. La
capacidad mxima de una caja de textos es de 64 Kbytes.
La forma de una caja de texto es la siguiente, dependiendo de las propiedades BorderStyle
y Appearance:
88
PROPIEDADES
Alignment Justificacin
Establece si el texto se justifica a la izquierda, a la derecha, o se centra sobre la etiqueta.
Esta propiedad solamente tiene efecto cuando la propiedad Multiline est a True,
ignorndose en caso contrario. Es decir, permite colocar el texto justificado a la derecha
cuando ese texto puede ser de varias lneas. Si la propiedad Multiline est a False, se
justifica siempre a la izquierda.
Esta propiedad no puede cambiarse en tiempo de ejecucin, pero s puede leerse en que
condicin est.
Appearance Backcolor
(*)
BorderStyle Tipo de borde
Sin borde o con borde. En caso de haber elegido en la propiedad Appearance el modo
tridimensional, y eligiendo con borde en esta propiedad, el aspecto adopta una forma como
incrustada en el formulario.
DataField
Nombre de un Campo
DataSource Nombre de un control Data
Establecen el control Data y el campo donde est el texto que se llevar a la propiedad
Text. Estas propiedades permiten presentar de una forma muy sencilla datos de una Base
de Datos. Se vern cuando se estudie el control Data y el motor de bases de datos
DragIcon
DragMode
(*)
Enabled
Habilitado
Propiedad Booleana que habilita o deshabilita la etiqueta Cuando est deshabilitado
(Enabled = False), no tienen efecto los eventos que se produzcan sobre el TextBox. No se
puede escribir el l ni pasarle el foco, pero s se le puede cambiar el texto mediante el
programa. Puede ser una buena alternativa para impedir que el usuario pueda cambiar un
determinado texto. Esta propiedad puede variarse en tiempo de ejecucin.
Font
ForeColor
Height
HelpContextID
Index Left
(*)
LinkItem LinkMode LinkTimeout LinkTopic
Estas propiedades establecen la forma en que debe llevarse a cabo una conexin DDE con
otra aplicacin. Se vern con mas detalle al estudiar los enlaces DDE
Locked
Establece si el texto se puede editar, es decir, cambiar. Cuando se pone esta propiedad a
True, el texto existente en la caja puede resaltarse con el ratn, e incluso copiarlo al
portapapeles, pero no puede variarse tecleando un nuevo texto. Se puede cambiar por
programa, cambiando la propiedad Text.
Si est en False, puede cambiarse el texto mediante teclado.
MaxLenght
Indica, si se establece, la longitud mxima del texto. Si no se establece o si se pone valor
0, permite cualquier longitud de texto.
MouseIcon Puntero del ratn personalizado
(*)
MousePointer
Puntero ratn
Lo tpico para esta propiedad es el I-Beam (barra vertical)
Name
Nombre
(*)
PasswordChar
En ocasiones, es conveniente que no se pueda leer lo que se escribe en la caja de texto,
caso por ejemplo de la entrada de un password o palabra de paso. Esta propiedad nos
permite indicar un carcter que sustituye a cualquier carcter que tenga la caja de texto.
(Tpicos el * o ?). El texto que tenga en la propiedad Text no cambia por el hecho de
presentar en pantalla un carcter distinto. Esta propiedad puede cambiarse en tiempo de
ejecucin. Para quitar el PasswordChar basta con forzarlo al carcter nulo :
Text1.PasswordChar =
89
Visible
WhatsThisHelpID
Width
DragOver
(*)
GotFocus
FRAME
RECUADRO
Se obtiene directamente de la caja de herramientas
que solo aparecern en el programa cuando se cumpla una determinada condicin. Cuando
esa condicin se cumpla, se pone la propiedad Visible del Frame a True y se vern todos
los controles que tiene dentro. Si no se cumple esa condicin, se pone la propiedad Visible
del Frame a False y no se ver ni el Frame, ni los controles que contiene.
PROPIEDADES
Las sealadas con (*) no presentan novedades respecto a las ya
comentadas para los controles precedentes.
Appearance
Backcolor
Caption
(*).
ClipControls
Si esta propiedad est a True, los mtodos grficos en eventos Paint vuelven a dibujar el
objeto entero. Antes del evento Paint se crea una zona de recorte alrededor de los
controles no grficos del formulario. Si esta propiedad est a False dibujarn solamente
las reas ltimamente expuestas. En tiempo de ejecucin, esta propiedad es de slo
lectura.
DragIcon
Enabled
Cuando esta
Frame como
est a True,
DragMode
(*)
Font
(*)
ForeColor
Color de las letras del ttulo del Frame.
Height
HelpContextID
Index
Left MouseIcon
MousePointer
Name
TabIndex
Tag
Top
(*)
Visible
Cuando un Frame est con la propiedad Visible = False, tanto el propio Frame como
todos los controles interiores a el sern invisibles.
WhatsThisHelpID Width
(*)
PROCEDIMIENTOS DEL FRAME
Click
MouseMove
DblClick
MouseUp
DragDrop
DragOver
MouseDown
91
Un control OptionButton muestra una opcin que se puede activar o desactivar, pero con
dependencia del estado de otros controles OptionButton que existan en el formulario.
Generalmente, los controles OptionButton se utilizan en un grupo de opciones para
mostrar opciones de las cuales el usuario slo puede seleccionar una. Los controles
OptionButton se agrupan dibujndolos dentro de un contenedor como un control Frame,
un control PictureBox o un formulario. Para agrupar controles OptionButton en un
Frame o PictureBox, dibuje en primer lugar el Frame o PictureBox y, a continuacin,
dibuje dentro los controles OptionButton. Todos los controles OptionButton que estn
dentro del mismo contenedor actan como un solo grupo, e independientes de los
controles OptionButton de otros grupos distintos.
Aunque puede parecer que los controles OptionButton y CheckBox funcionan de forma
similar, hay una diferencia importante: Cuando un usuario selecciona un OptionButton,
los otros controles del mismo grupo OptionButton dejan de estas disponibles
automticamente. Por contraste, se puede seleccionar cualquier nmero de controles
CheckBox.
92
Caption
(*).
DataField DataSource
Propiedades del CheckBox solamente.
Establecen el control Data asociado y el campo donde estn los datos (True / False) que se
llevarn a la propiedad Value . Al igual que en los controles Label y TextBox esta
propiedad nos permite visualizar datos de una base de datos de una forma muy sencilla.
En este caso, el CheckBox solamente permite presentar (logicamente) datos de tipo
Booleano.
DragIcon
DragMode
Enabled
Font
ForeColor
(*)
Height
Comn a ambos controles.
La altura del control solamente afecta a la colocacin del Titulo (Puede ponerse un ttulo
largo en varias lneas), no al tamao del botn, que es invariable.
HelpContextID
Name
TabIndex
Index
TabStop
Left
Tag
Top
MouseIcon
MousePointer
(*)
Value
Comn a ambos controles
El valor de esta propiedad indica si el control est seleccionado (Value = 1) o no
seleccionado (Value = 0 Value = False). Esta propiedad puede cambiarse en tiempo de
ejecucin. Mediante esta propiedad, podemos tanto forzar el valor como leerlo.
Atencin. Presenta una diferencia entre uno y otro control respecto a la forma de
expresarse respecto a su valor cuando est seleccionado. Para forzar que el control NO
est seleccionado, o para leer el Value cuando no est seleccionado, podemos utilizar
tanto Value = 0 como Value = False. Sin embargo, cuando lo que se quiere es poner la
propiedad a True hay una diferencia entre ambos controles.
Para el OptionButton podemos utilizar indistintamente las siguiente formas :
Option1.Value = True
Option1.Value = 1
Visible
WhatsThisHelpID
Width
(*)
PROCEDIMIENTOS
Click
KeyDown
94
DragOver
GotFocus
Un control ListBox muestra una lista de elementos en la que el usuario puede seleccionar
uno o ms. Si el nmero de elementos supera el nmero que puede mostrarse, se
agregar automticamente una barra de desplazamiento al control ListBox.
Un control ComboBox combina las caractersticas de un control TextBox y un control
ListBox. Los usuarios pueden introducir informacin en la parte del cuadro de texto y
seleccionar un elemento en la parte de cuadro de lista del control. En resumen, un
ComboBox es la combinacin de un ListBox, que se comporta como si de un ListBox se
tratase, y de un TextBox, con comportamiento anlogo a un TextBox sencillo, con la
particularidad aqu de que el texto se le puede introducir por teclado, o elegir uno de los
que figuran en la parte ListBox del Combo.
Estos controles toman la siguiente forma :
95
Backcolor
(*)
Columns
Height
NombreDeLaLista.ItemData(ndice) [= nmero]
NombreDeLaLista
ndice
nmero
La propiedad ItemData es una matriz de valores enteros largos cuyo nmero de elementos
es el valor de la propiedad ListCount del control. Los nmeros asociados con cada
elemento se pueden usar para cualquier fin. Por ejemplo, se puede usar en la confeccin
de una lista de telfonos, el nmero de identificacin de un empleado, etc. Cuando se
rellena el ListBox, tambin se rellena los elementos correspondientes de la matriz
ItemData con los nmeros correspondientes.
La propiedad ItemData se usa a menudo como ndice de una matriz de estructuras de
datos asociados con los elementos de un control ListBox.
Nota Cuando se inserta un elemento en una lista con el mtodo AddItem, el elemento
tambin se inserta automticamente en la matriz ItemData. Sin embargo, el valor no se
reinicializa a cero; retiene el valor que estaba en esa posicin antes agregar el elemento a
la lista. Cuando se usa la propiedad ItemData, asegrese de establecer su valor al agregar
nuevos elementos a la lista.
Left
(*)
List
Es el contenido de la lista.
Si la lista de elementos es corta e invariable, pueden introducirse los elementos en el
cuadro de propiedades durante el diseo.
MouseIcon
MousePointer
Name
(*)
Sorted
Establece o devuelve un valor que indica si los elementos de un ListBox o
ComboBox se colocan automticamente en orden alfabtico. Los valores que
puede adoptar son True o False.
True Los elementos de la lista se ordenan alfabticamente (sin distinguir entre
maysculas y minsculas).
False (Predeterminado) Los elementos de la lista no se ordenan alfabticamente.
Cuando esta propiedad tiene el valor True, Visual Basic se encarga de casi todo el
procesamiento de cadenas necesario para mantener el orden alfabtico, incluyendo
el cambio de los nmeros de ndice cuando se agregan o eliminan elementos.
Nota
El uso del mtodo AddItem para agregar un elemento en una posicin
especfica de la lista puede romper el orden alfabtico, y los elementos agregados
con posterioridad pueden no ordenarse correctamente.
TabIndex
TabStop
Width (*)
Tag
Top
Visible
PROCEDIMIENTOS
98
WhatsThisHelpID
Click
Change (Solo ComboBox) DblClick
DragDrop
DragOver
DropDown (Solo ComboBox)
GotFocus
KeyDown
KeyPress
KeyUp
LostFocus
MouseDown (Solo ListBox) MouseMove (Solo ListBox)
MouseUp (Solo ListBox)
NOTA MUY IMPORTANTE
El procedimiento Change del ComboBox solamente se efecta cuando el cambio se
produce mediante la entrada de un texto DESDE EL TECLADO, no por un cambio en la
parte Text de este control, producido al llevar un elemento desde la parte List a la parte
Text.
CONTROLES HScrollBar y VScrollBar
Son dos controles similares, para introducir un dato cuasi-analgico en una aplicacin. Se
toman directamente de la caja de herramientas, y tienen un aspecto parecido al de un
control de volumen de un equipo de msica. El HScrollBar est en posicin horizontal, y el
VScrollBar en posicin vertical.
Mediante estos controles se pueden introducir datos variando la posicin del cursor.
PROPIEDADES de HScrollBar y VScrollBar
Las sealadas con (*) son comunes a ambos controles y no presentan novedades respecto
a las ya comentadas para los controles precedentes.
DragIcon
DragMode
Index
(*)
Enabled
Height
HelpContextID
LargeChange
Esta propiedad establece la variacin de la propiedad Value cada vez que se hace click en
el interior de la barra de desplazamiento, en la parte por donde pasa el cursor.
Left
(*)
Max
Esta propiedad establece el valor mximo para la propiedad Value, es decir, el valor de
esta propiedad cuando el cursor est en su parte mxima. (Recuerde que el cursor est en
el mximo, cuando est mas a la derecha, caso del HScrollBar, o cuando est en la parte
mas baja, caso del HScrollBar.
99
Min
Esta propiedad establece el valor mnimo para la propiedad Value, es decir, el valor de
esta propiedad cuando el cursor est en su parte mnima. (Recuerde que el cursor est en
el mnimo, cuando est mas a la izquierda, caso del HScrollBar, o cuando est en la parte
mas alta, caso del HScrollBar.
MouseIcon
MousePointer
Name
(*)
SmallChange
Esta propiedad establece la variacin de la propiedad Value cada vez que se hace click en
las flechas superior o inferior de la barra de desplazamiento.
TabIndex
TabStop
Tag
Top
(*)
Value
Esta propiedad lee o establece el valor dado por la posicin del cursor. Este valor tiene un
mnimo, establecido por Min y un mximo, establecido por Max. Esta propiedad es la que
se debe leer para conocer la posicin del cursor.
Visible
WhatsThisHelpID
Width
(*)
DragDrop
LostFocus
DragOver
Scroll
GotFocus
KeyDown
KeyPress
TEMPORIZADOR
Este objeto permite establecer temporizaciones. Presenta una novedad respecto a los
controles estudiados hasta ahora. El control Timer solamente se ve durante el tiempo de
diseo. En tiempo de ejecucin, el control permanece invisible.
La temporizacin producida por el Timer es independiente de la velocidad de trabajo del
ordenador. (Casi independiente. El timer no es un reloj exacto, pero se le parece)
Se toma directamente de la caja de herramientas, y tiene el aspecto siguiente :
PROPIEDADES
Enabled
Index
(*)
Interval
100
El valor de esta propiedad nos dar el intervalo de tiempo (en milisegundos) en que se
producir un evento Timer y consecuentemente, realizar el procedimiento asociado a
este evento. Si el valor de la propiedad Interval est a 0 (Predeterminado), no se produce
el evento Timer. (El control Timer est deshabilitado cuando la propiedad Interval =
0)
Left
Name
Tag
Top
(*)
PROCEDIMIENTOS
Timer
Se produce cada vez que se cumple un intervalo completo.
CONTROL
SHAPE
Shape es un control grfico que se muestra como un rectngulo, un cuadrado, una elipse,
un crculo, un rectngulo redondeado o un cuadrado redondeado.
Un control Shape no acta como contenedor de controles. (Esto quiere decir que un
control Shape nunca le servir, por ejemplo, para albergar varios OptionButton y
pretender que sean independientes de otros controles OptionButton que se encuentren
fuera del control Shape.
Este control no tiene Procedimientos. En realidad, solamente sirve para mostrar un
determinado grfico, envolver grficamente a otros controles, pero no tiene ninguna
aplicacin en cuanto a programa. Es un adorno para sus aplicaciones.
PROPIEDADES
Backcolor
(*)
BackStyle
Esta propiedad establece si Shape permite ver a su travs (Transparent) o n lo permite
(Opaque)
BorderColor
Establece el color del borde.
BorderStyle
Establece el tipo de borde. Puede ser : Transparent, (No se ve el borde), Solid, (Borde de
lnea continua),Dash, (lnea a rayas), Dot, (lnea a puntos), Dash-Dot, (lnea de raya punto), dash-Dot-Dot, (lnea de raya - punto - punto), InsideSolid, (raya continua)
El efecto de establecer la propiedad BorderStyle depende del valor de la propiedad
101
FillColor
FillStyle
Height
Index Left
Name (*)
Shape
Establece la forma del control. Puede ser : Rectangular, cuadrado, redondo, ovalado,
cuadrado con esquinas redondeadas y rectangular con esquinas redondeadas.
Tag
Top
Visible
PROCEDIMIENTOS
Width
(*)
No tiene.
CONTROL LINE
Se toma directamente de la caja de herramientas
Line, al igual que Shape, es un control grfico que solamente sirve para poner una lnea en
un formulario. Del mismo modo, no tiene procedimientos, por lo que no sirve para aportar
cdigo al programa. Solo sirve para aportar una caracterstica grfica, es un adorno.
PROPIEDADES
BorderColor
Establece el color de la lnea.
BorderStyle
Establece el tipo de lnea : Puede ser : Transparent, (No se ve la lnea), Solid, (Lnea
continua),Dash, (lnea a rayas), Dot, (lnea a puntos), Dash-Dot, (lnea de raya - punto),
dash-Dot-Dot, (lnea de raya - punto - punto), InsideSolid, (raya continua)
BorderWidth
Establece el ancho de la lnea.
DrawMode
X1, X2
Index
Y1, Y2
Left
Name
Tag
Visible
(*)
Establece las coordenadas y del inicio y final
PROCEDIMIENTOS No tiene.
102
Eligiendo el elemento Componentes de este men desplegado nos muestra todos los
componentes existentes en el disco, que podremos sacar a nuestra caja de herramientas
para poder utilizarlos.
existentes en el PC del autor. Puede observarse que est seleccionado el control Calendar,
y en la parte de abajo puede verse la ubicacin y nombre del fichero que contiene ese
control (MSCAL.OCX). No todos los controles son de Microsoft. Observe que hasta Kodak
realiza (o le realizan) controles. Existen muchas empresas que venden controles, unas con
mejor calidad que otras. En este tema debe tener especial precaucin con los controles que
se distribuyen de forma gratuita por Internet. No utilice nunca un control adquirido por
este procedimiento si no tiene plena confianza en el origen del mismo y lo ha probado
103
Obviamente estos
Estos controles que adquiere con posterioridad a la instalacin del Visual Basic hay que
registrarlos. No se asuste. No se trata de registrarlos ante el fabricante para poder
utilizarlos. Se trata de introducirlos en el registro de Windows. Con ello Windows conoce el
CLSID de ese control, su ubicacin en el disco duro (los controles suelen estar en
C:\Windows\System, pero pueden estar en cualquir otra carpeta). Windows necesita
registrarlos para poder encontrarlos. Para registrar un control se utiliza el programa
Regsvr32.exe. Para registrar un control basta con ejecutar este programa, pasandole como
parmetro el nombre y ubicacin del control a registrar. Esto se hace en Inicio | Ejecutar.
Por ejemplo, para registrar el conjunto de controles VB_GuiaEst.Ocx introduciramos ese
fichero Ocx en C:\Windows\System y a continuacin ejecutamos:
regsvr32 c:\windows\system\ VB_GuiaEst.Ocx
104
105
Puede usar este cdigo para bloquear todos los TextBox de un formulario. Se mete en un
procedimiento llamado Bloquear (p.e.) y cada vez que queramos bloquear todos los
TextBox del formulario basta con citar a este procedimiento. Un cdigo similar sera
Dim I As Integer
For I = 0 To Controls.Count - 1
If TypeOf Controls(I) Is TextBox Then
Controls(I).Locked = True
End If
Next
(Observe que en la segunda versin, trabajamos directamente sobre los elementos de la
coleccin, que se distinguen unos de otros mediante el Indice colocado entre
parntesis. En este caso, la variable I que tomar los valores entre 0 y n-1)
106
Ttulo
Es el texto del control o lo que figura en la barra de men del formulario. Puede cambiarse
en tiempo de ejecucin.
DragMode
Modo de iniciar una operacin de Drag & Drop
Establece un valor que determina si se usa el modo de arrastre manual o automtico en
una operacin de arrastrar y colocar. Los valores posibles de esta propiedad son:
0
1
DrawStile
Manual
Automtico
Estilo de dibujo
Activado
Tipo de relleno
FillColor
0
1
2
3
4
5
6
7
Continuo
Transparente
Lnea Horizontal
Lnea Vertical
Diagonal hacia arriba
Diagonal hacia abajo
Cruzado
Diagonal cruzada
Color de relleno
ejecucin.
FontSize
Tamao de letra
Establece el tamao de la letra que se usar en ese formulario o control (U otro objeto VB,
p.e. el Printer). Esta propiedad puede variarse en tiempo de ejecucin. El tamao debe
expresarse en puntos. Mximo, 2160 puntos.
FontBold, FontItalic, FontStrikethru, FontUnderline
Permiten, en tiempo de ejecucin, cambiar un texto a negrita, cursiva, tachado y
subrayado. Son propiedades Booleanas True / False
Height
Altura
Nmero de Contexto
Establece un nmero de contexto asociado para este formulario. Este nmero se aplica
para determinar la ayuda interactiva asociada a este formulario o control. Vea mas
adelante, el tema Ayuda de Windows.
Puede tomar los siguientes valores :
0 - No se especifica nmero de contexto
>0 Un entero que especifique un contexto
vlido.
Index
Indice
En el caso de que se tengan varios controles que realicen una funcin similar (Las teclas
numricas de una calculadora, p.e.) puede hacerse un array con estos controles. Todos
tendrn el mismo nombre, y se diferencian por un ndice. La propiedad Index de ese
control toma el nmero de ese ndice.
Left
Establece un icono personalizado para el puntero del ratn cuando est encima del
Formulario o control. Este icono puede ser un Bitmap de los existentes en el directorio
Icons de Visual Basic o cualquiera que tengamos. Si se pone 99 como valor de la propiedad
MousePointer (siguiente), cada vez que el puntero del ratn pase por este Formulario o
control, cambiar su forma y adoptar la del icono elegido.
MousePointer
Determina la forma del puntero del ratn cuando se coloca encima del formulario o control.
Puede elegirse uno de los punteros preestablecidos (15 en total) o el personalizado visto
108
en la propiedad anterior. Para elegir ese icono personalizado, debemos poner en esta
propiedad el valor 99.
TabIndex
Propiedad Booleana. Cuando esta propiedad est a False, el botn no tomar el foco
cuando se pulse la tecla del Tabulador. Sin embargo sigue manteniendo el ndice de la
propiedad TabIndex descrita anteriormente. Puede cambiarse en tiempo de ejecucin.
Esto nos permite descartar algn botn de tomar el foco, cuando por facilidad para el
usuario, sea conveniente en determinados puntos del programa.
Tag
Valor auxiliar
Indica la coordenada de la parte superior del control. Puede variarse durante el tiempo de
ejecucin. Esta propiedad, juntamente con Left definen la esquina superior izquierda del
botn de comando. Normalmente esta propiedad no se introduce numricamente, sino que
la toma automticamente de la posicin que se le den al botn en tiempo de diseo. Puede
cambiarse, cambiando el valor a esta propiedad, en tiempo de ejecucin.
Visible
Propiedad Booleana. Asignndole el valor True al control o formulario, ser visible, y
asignndole el valor False, no se ver. Este valor puede cambiarse durante el tiempo de
ejecucin para ocultar y hacer visible el formulario o control correspondiente.
WhatsThisHelpID
Ancho
109
Evento Click
Lo tienen casi todos los controles y el formulario. Es el evento habitual para introducir el
cdigo que queremos que realice el programa al hacer click sobre un determinado control.
No es el nico evento donde podemos hacerlo, pues tambin tenemos otros muy parecidos
(MouseDown, MouseUp), pero que funcionan de distinta forma. El evento Click en el
formulario se efecta cada vez que pulsamos uno de los botones del ratn. En los
controles, slo con el botn izquierdo.
Si un control tiene el foco, se ejecutar su evento Click al pulsar ENTER o la barra
espaciadora.
El evento Click no pasa parmetros
Evento DragDrop Accin de Soltar durante el Drag & Drop
Se produce cuando se suelta el ratn sobre un formulario o control, durante una
operacin de Drag & Drop. Pasa los parmetros Source As Control, X As Single, Y As
Single, donde Source es el control donde se origin el Drag & Drop, y X e Y las
coordenadas del puntero del ratn en el momento de soltar. Vea el captulo de Drag & Drop
Evento DragOver Arrastrar por encima
Ocurre cuando se pasa por encima de un formulario o control durante la operacin de Drag
& Drop. Pasa los parmetros Source As Control, X As Single, Y As Single, State As
Integer. Los parmetros son los mismos que en el procedimiento anterior. State es un
entero que indica el estado de transicin del puntero sobre el formulario. Toma los
siguientes valores :
0 = Entra (El puntero del ratn est entrando al formulario o control).
1 = Deja (El puntero del ratn est saliendo del formulario o control).
2 = Sobre (El puntero del ratn se desplaza de una posicin a otra dentro del
formulario o
control). Vea el captulo de Drag & Drop
Evento GotFocus
Tomar el Foco
Ocurre este evento cuando el control toma el foco. Tomar el foco significa que se acaba de
convertir en el control activo. (por ejemplo, cuando llevamos el cursor y hacemos click
sobre un Text Box. Hay algunos controles que no tienen procedimiento GotFocus porque
nunca toman el foco (Label, p.e.)
Evento KeyDown Pulsar una tecla (Ocurre cuando el control tiene el foco)
Se produce sobre el control que tiene el foco al pulsar una tecla, justo en el instante que
llega a su posicin inferior. Pasa como parmetros el KeyCode As Integer y el Shift As
110
Integer. El KeyCode es el cdigo de la tecla (no confundir con Keyascii, que es el cdigo de
la letra. Hay teclas que no tienen Keyascii y s tienen KeyCode F1, F2, ...Insert, ) Shift es
la posicin de la tecla Maysculas (1=pulsada, 0=levantada)
Evento KeyPress
Este evento se produce despus del KeyDown, y pasa como parmetro el KeyAscii As
Integer, que es el cdigo Ascii de la letra cuya tecla se ha pulsado.
Evento KeyUp
Ocurre al levantar la tecla, despus del KeyPress. Pasa como parmetros los mismos que
KeyDown, KeyCode As Integer, Shift As Integer
Estos tres eventos se producen tambin en el formulario (y antes que en el control), si el
formulario tiene la propiedad KeyPreview = True
LinkClose
LinkError
LinkNotify
LinkOpen
Son eventos relacionados con el DDE (Intercambio Dinmico de Datos). Ocurren
respectivamente cuando se cierra el enlace DDE, cuando ocurre un error en el enlace,
cuando han cambiado los datos en origen y en destino se ha establecido la propiedad
LinkMode a Notify, y cuando se inicia una conversacin DDE. Vea el captulo dedicado al
DDE para mas detalles.
LostFocus
Ocurre cuando el control pierde el foco. Este evento es muy importante, por ejemplo en un
Text Box, para dar el formato adecuado al texto contenido en ese Text Box, o para
comprobar que es correcto, etc.
MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)
Se ejecuta en el instante de apretar el botn de mouse, cuando est el puntero encima del
formulario o control correspondiente. Pasa como parmetros el botn pulsado (1=
izquierdo, 2 = derecho, 3 = centro), la tecla maysculas (Shift=1 significa pulsada, =0 no
pulsada) y las coordenadas X e Y del puntero del ratn.
MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Se ejecuta cuando pasa por encima del formulario o0 control el puntero del ratn
MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
111
CommonDialog
Este control no se presenta en tiempo de diseo mas que con un simple icono :
Abrir Ficheros
Guardar Ficheros
Elegir colores
Seleccionar Impresora
Seleccionar Fuentes
112
CommonDialog mostrando la funcin Abrir. Ntese el icono para crear nueva carpeta,
objeto del comentario siguiente.
En realidad el cuadro de dilogo permite conocer datos con los cuales, y mediante el
cdigo adecuado, abriremos o guardaremos ficheros, elegiremos colores o seleccionaremos
fuentes. Es decir, el CommonDialog NO realiza mas funciones que mostrar ficheros
existentes, fuentes disponibles, colores, para que, mediante cdigo, abramos esos ficheros
o usemos una determinada fuente.
La expresin anterior se ha recuadrado porque ya no es completamente cierta. El
CommonDialog no es un control propio de Visual Basic, sino de Windows. Y la versin de
este control que Windows pone en W98 permite que pueda crear una nueva carpeta. Ya
hace algo directamente. No se extrae que el CommonDialog empleado en su aplicacin
pueda crear una nueva carpeta sin que Vd. lo haya diseado para eso. Al introducir el
control en la aplicacin est introduciendo la versin ms moderna del mismo.
Dependiendo de la aplicacin para la que vaya a usarse se deber activar de distintas
formas. Si el cuadro de dilogo se va a usar para seleccionar la impresora y para
otras aplicaciones, es recomendable usar uno exclusivamente para seleccionar la
impresora.
Esta ltima recomendacin se debe a que, para el control de la impresora, el
CommonDialog SI realiza las funciones de seleccin de impresora predeterminada. Esta
diferencia operativa hace que si usamos el mismo CommonDialog para seleccionar
impresora y abrir ficheros, por ejemplo, se cuelgue el CommonDialog.
El control CommonDialog es un control personalizado (Microsoft CommonDialog Control
COMDLG32.OCX), y como casi todos los controles personalizados presenta un asistente de
propiedades propio. Puede accederse a las propiedades mediante el cuadro de propiedades
tpico de otros controles, o mediante el asistente, pulsando el botn derecho del ratn con
el puntero colocado encima del icono del cuadro de dilogo.
Analizando las propiedades, vemos que tiene gran cantidad de ellas. Esto es porque agrupa
todas las propiedades correspondientes a la cinco funciones que puede desarrollar. Se
detalla a continuacin la forma de usar el CommonDialog para cada aplicacin.
Se entiende que el nombre - Name - que se ha puesto para el cuadro de dilogo en todos
los ejemplos es CD1)
113
114
115
(Si la parte derecha del cuadro no sale, se saca haciendo click en Definir colores
personalizados.)
El nmero correspondiente al color elegido se puede conocer analizando la propiedad color
de cuadro de dilogo. En nuestro ejemplo, lo obtendramos con
Variablecolor = CD1.Color
donde Variablecolor contendr un nmero correspondiente al color elegido. Variablecolor
debe declararse como tipo Long
Programa de ejemplo. Mediante un CommonDialog elegimos el color de fondo de un
TextBox (TbPrueba).
Private Sub BColores_Click()
CD1.Flags = 2
'Hace que el cuadro de dilogo se muestre completo
CD1.ShowColor
TbPrueba.BackColor = CD1.Color
End Sub
Nota acerca del nmero del color.
Para establecer un color por medio de cdigo, se pondr un valor de color a la propiedad
correspondiente de ese objeto. El valor del color puede establecerse de tres formas que se
116
comentan a continuacin.
Colores en Visual Basic.
Visual Basic acepta para especificar un color, tres procedimientos: Mediante el nmero de
color, mediante la sentencia RGB ( rojo, verde, azul ) o mediante la funcin QBColor.
Por nmero
El nmero que representa el color en VB est formado por la suma de la componente roja,
la componente verde y la componente azul. Podramos verlo muy bien en numeracin
Hexadecimal:
Color = Hex
XX YY ZZ
Donde ZZ es un nmero Hexadecimal que representa la cantidad del color rojo. El mnimo
estara en 0 (H00) y el mximo en 255 (HFF)
YY representara la cantidad de color verde y XX la de color azul, ambos con los mismos
lmites explicados para el rojo.
Por ejemplo: el rojo puro sera:
Hex(0000FF) = 255
el verde puro sera: Hex(00FF00) = 652280
el azul puro sera:
Hex(FF0000) = 16711680
Una mezcla de un poco de rojo (HB1), otro poco de verde (H56) y otro poco de azul (H1F)
dara el siguiente nmero:
Hex(1F56B1) = 2053809
El nmero de color puede estar comprendido entre 0 (correspondiente al negro) y el
16777215 (correspondiente al blanco. Observe que esa cantidad, 16.777.215 (FFFFFF en
hexadecimal) corresponde a los famosos 16 millones de colores de las tarjetas grficas.
Si queremos poner el color de fondo a un control Label, usaremos la propiedad Backcolor.
Si el Label se llama Label1, pondramos la instruccin
Label1.Backcolor = 12345678
Por la sentencia RGB
Se puede expresar el color, poniendo simplemente RGB (rojo, verde, azul), donde rojo es
un nmero entre 0 y 255 que indica la cantidad de color rojo que se aporta al color, verde
un nmero comprendido entre 0 y 255 indicando la cantidad de verde, y lo mismo para
azul.
Esta es la forma mas sencilla de poner la propiedad color, y con la que mejor
controlaremos el mismo.
Si queremos poner al Label anterior un color mediante la sentencia RGB, ejecutaramos la
sentencia :
Label1.Backcolor = RGB (128, 30, 100)
Mediante la Funcin
compatibilidad)
QBColor
Esta funcin se ha puesto en Visual Basic para compatibilidad con los colores que se usan
117
Objeto.QBColor(color)
Color
Negro
Azul
Verde
Aguamarina
Rojo
Fucsia
Amarillo
Blanco
Nmero
8
9
10
11
12
13
14
15
Color
Gris
Azul claro
Verde claro
Aguamarina claro
Rojo claro
Fucsia claro
Amarillo claro
Blanco brillante
118
119
pero antes deber introducir el filtro o filtros de archivos que necesite. Ojo, ANTES !
Un filtro sirve para que en el cuadro de dilogo se presenten solamente los ficheros de
nuestro inters. Se pueden seleccionar por el nombre, la extensin o las dos cosas. La
sintaxis para introducir un filtro es la siguiente:
CD1.Filter = "Descripcin del fichero|nombre.extensin"
donde "nombre" puede ser un nombre o usar caracteres comodn. Lo mismo para
"extensin"
Por ejemplo, para buscar archivos ejecutables, con cualquier nombre y extensin .EXE
CD1.Filter = "Ficheros ejecutables |*.exe"
Observe el carcter separador entre la descripcin de los ficheros (Ficheros ejecutables) y
el parmetro de busca (*.EXE). No ponga ningn espacio entre el separador y los
caracteres de busca. El separador es el carcter ASCII 124.
Puede buscar varios tipos de ficheros, separando los caracteres de busca por medio del
carcter punto y coma (;)
CD1.Filter = "Ficheros ejecutables |*.EXE;*.COM;*.BAT"
Puede tambin introducir dos filtros, separados por el separador | (En una lnea
solamente).
CD1.Filter=Ficheros de un tipo |*.EXE |Ficheros de otro |*.COM |Otros ficheros |*.BAT
Por ejemplo : CD1.Filter = "Ficheros Word |*.DOC|Ficheros Write |*.WRI"
No se pueden poner dos lneas con filtros, se quedara solamente con la ltima !
En este caso, cuando se presente el cuadro de dilogo, solamente presentar uno de los
filtros, y deber seleccionar manualmente el otro en un cuadro situado en la parte inferior
izquierda del cuadro de dilogo. Para predeterminar cul de los dos filtros saldr sin tener
que seleccionarlo, deber ejecutar esta instruccin, ANTES de invocar el cuadro de dilogo
CD1.FilterIndex = 2
En este caso, aparecer por defecto el filtro escrito en segundo lugar. El orden de los filtros
comienza por 1.
El cuadro de dilogo deber presentar un directorio. Este directorio con el que, por defecto,
aparece el cuadro de dilogo, se puede introducir mediante la propiedad InitDir, que
deber contener el nombre del directorio y su path. Si no se especifica, comenzar por el
directorio actual.
Para conocer el nombre del fichero elegido, se emplea la propiedad FileName :
Nombrefichero= CD1.filename
El nombre del fichero, Nombrefichero en la sentencia anterior, viene con su path, es decir,
nombre y direccin completa, por lo que puede emplearse directamente la salida del
CommonDialog para abrir un fichero.
El cuadro de dilogo de abrir o cerrar tiene esta forma :
120
El cuadro de guardar es similar. Observe que en este caso hemos desplegado la segunda
opcin de filtro de ficheros :
Como ve ambos cuadros son prcticamente iguales. Solamente se difieren en que uno
pone Abrir y el otro Guardar como en su barra de ttulo. Tambin en que el cuadro
Guardar como presenta los nombres de los ficheros con un tono apagado. Funcionalmente
difieren. Por ejemplo, si quiere guardar un fichero con un nombre ya existente, y
dependiendo de la propiedad Flags que ver mas adelante, le aparecer la siguiente
advertencia :
121
PRESENTAR AYUDAS
Mediante el CommonDialog se puede presentar un fichero de ayuda. (Ficheros del tipo
.HLP de Windows)
Pese a que se pueden presentar estos ficheros basndonos en el CommonDialog,
es preferible usar directamente el programa WinHelp.Exe, que puede ejecutarlo
mediante la funcin Shell :
VariableID = Shell (WinHelp.Exe FicheroAyuda.hlp,1)
Para mostrar el fichero de ayuda debe poner el nombre (y Path) del fichero de ayuda en la
propiedad HelpFile del CommonDialog
CD1.HelpFile = "C:\MiCarpeta\MiFicheroAyuda.HLP"
Puede mostrar el ndice, o una pgina concreta de ese fichero. Para ello debe jugar con la
propiedad HelpCommand, que le va a indicar al CommonDialog qu ayuda debe mostrar.
122
CD1.HelpCommand =Valor
Las opciones para valor son:
1
2
3
3
4
5
5
8
9
257
258
261
&H1 cdlContext
Muestra la Ayuda de un contexto determinado. Cuando se usa esta valor, tambin
se debe especificar un contexto con la propiedad HelpContext.
&H2 cdlQuit
Notifica a la aplicacin Ayuda que el archivo de Ayuda especificado ya no se est
utilizando.
&H3 cdlContents
Muestra el tema de contenido de ayuda, definido con la opcin Contents de la
seccin [OPTION] del archivo .HPJ.
&H3 cdlIndex
Muestra el ndice del archivo de Ayuda especificado. Las aplicaciones slo deben
utilizar este valor para un archivo de Ayuda con ndice nico.
&H4 cdlHelpOnHelp
Muestra la Ayuda para utilizar la propia aplicacin Ayuda.
&H5 cdlSetContents
Determina el tema de contenido a mostrar cuando el usuario presiona la tecla F1.
&H5 cdlSetIndex
Establece el contexto especificado en la propiedad HelpContext como ndice actual
para el archivo especificado en la propiedad HelpFile. Este ndice seguir siendo el
actual hasta que el usuario acceda a un archivo de Ayuda distinto. Utilice este valor
slo para los archivos de Ayuda con ms de un ndice.
&H8 cdlContextPopup
Muestra en una ventana emergente un tema de Ayuda determinado, identificado
por un nmero de contexto definido en la seccin [MAP] del archivo .HPJ.
&H9 cdlForceFile
Asegura que WinHelp muestre el archivo de Ayuda correcto. Si se muestra el
archivo correcto, no sucede nada. Si se muestra un archivo incorrecto, WinHelp
abrir el correcto.
&H101
cdlKey
Muestra la Ayuda sobre una palabra reservada determinada. Al usar esta opcin,
deber especificar tambin una palabra reservada con la propiedad HelpKey.
&H102
cdlCommand
Ejecuta una macro de Ayuda.
&H105
cdlPartialKey
Muestra el tema de la lista de palabras claves que coincide con la palabra pasada en
el parmetro dwData, si slo se encuentra uno. Si se encuentra ms de uno,
aparecer el cuadro de dilogo Buscar mostrando los temas encontrados en el
cuadro de lista Ir a. Si no se encuentra ninguno, se mostrar el cuadro de dilogo
Buscar. Para que aparezca el cuadro de dilogo Buscar sin pasar una palabra
reservada, utilice un puntero largo a una cadena vaca.
123
(En
124
Nombre.Action [= valor]
Valor
Descripcin
0
1
2
3
4
5
6
Ninguna accin.
Muestra el cuadro de dilogo
Muestra el cuadro de dilogo
Muestra el cuadro de dilogo
Muestra el cuadro de dilogo
Muestra el cuadro de dilogo
Ejecuta WINHELP.EXE.
Abrir.
Guardar como.
Color.
Fuente.
Impresora.
Se genera un error.
(Predeterminado) No se genera ningn error.
en el
color. Puede introducirse como RGB o numricamente, como se explic mas atrs.
Para que aparezca este color predeterminado, debe poner la propiedad Flags a 1.
De lectura : Entrega el color elegido, bien en el cuadro de eleccin de color, bien
cuadro de eleccin de fuente.
Copies
Establece el valor predeterminado para nmero de copias que aparecer en el CD
cuando se abra para elegir impresora.
125
DefaultExt
Devuelve o establece la extensin de archivo predeterminada para el cuadro de
dilogo.
Sintaxis
objeto.DefaultExt [= cadena]
Nombre.DialogTitle [= ttulo]
CD1.FilterIndex [= nmero]
126
CD1.Flags [= valor]
&H1& cdlRGBInit
Establece como valor de color inicial para el cuadro de dilogo el indicado en su
propiedad Color.
&H2& cdlFullOpen
Hace que el cuadro de dilogo se muestre completo al crearlo, incluyendo la seccin
que permite al usuario crear colores personalizados. Sin esta opcin, el usuario
debe elegir el botn de comando Definir colores personalizados para mostrar tal
seccin.
&H4& cdlPreventFullOpen
Desactiva el botn de comando Definir colores
usuario defina colores.
&H8& cdlShowHelp
Hace que el cuadro de dilogo muestre un botn Ayuda.
Se pueden poner varias de estas condiciones, poniendo como valor Flags la suma de los
valores de cada una de las condiciones a poner.
Para los cuadros Abrir y Guardar
Las opciones para valor son:
1
4
8
16
256
&H1& cdlReadOnly
Hace que la casilla de verificacin Slo lectura aparezca marcada inicialmente al
crear el cuadro de dilogo. Este indicador tambin seala el estado de la casilla Slo
lectura cuando el cuadro de dilogo est cerrado.
&H2& cdlOverwritePrompt
Hace que el cuadro de dilogo Guardar como genere un cuadro de mensaje si el
archivo seleccionado ya existe. El usuario deber confirmar que desea sobrescribir
el archivo.
&H4& cdlHideReadOnly
Oculta la casilla de verificacin Slo lectura.
&H8& cdlNoChangeDir
Hace que el cuadro de dilogo restablezca como directorio actual el que lo era en el
momento de abrirse.
&H10&
cdlShowHelp
Hace que el cuadro de dilogo muestre el botn Ayuda.
&H100&
cdlNoValidate
127
&H1& cdlScreenFonts
Hace que el cuadro de dilogo muestre solamente las fuentes de pantalla que
admite el sistema.
&H2& cdlPrinterFonts
Hace que el cuadro de dilogo muestre solamente las fuentes que admite la
impresora, especificadas por la propiedad hDC.
&H3& cdlBoth
Hace que el cuadro de dilogo muestre las fuentes de impresora y de pantalla
128
&H0& cdlAllPages
Devuelve o establece el estado del botn de opcin Todas las pginas.
&H1& cdlSelection
Devuelve o establece el estado del botn de opcin Seleccin. Si no se
129
2
4
8
16
32
64
128
256
&H100&
cdlReturnDC
Devuelve un contexto de dispositivo para la impresora seleccionada en el
cuadro de dilogo. El contexto se devuelve en la propiedad hDC del cuadro
de dilogo.
512 &H200&
cdlReturnIC
Devuelve un contexto de informacin para la impresora seleccionada en el
cuadro de dilogo. Un contexto de informacin proporciona un mtodo
rpido de obtener informacin sobre el dispositivo sin crear un contexto de
dispositivo. El contexto de informacin se devuelve en la propiedad hDC del
cuadro de dilogo.
2048 &H800&
cdlShowHelp
Hace que el cuadro de dilogo muestre el botn Ayuda
262144
&H40000& cdlUseDevModeCopies
Si un controlador de impresora no admite copias mltiples, al establecer este
indicador se desactiva el control de edicin de nmero de copias. Si el
controlador s admite mltiples copias, al establecer este indicador el cuadro
de dilogo almacenar el nmero de copias solicitado en la propiedad
Copies.
524288
1048576
&H80000& cdlDisablePrintToFile
Desactiva la casilla de verificacin Imprimir a un archivo.
&H100000& cdlHidePrintToFile
Oculta la casilla de verificacin Imprimir a un archivo.
Variable = CD1.FontBold
130
FontItalic
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Cursiva.
Sintaxis
FontStrikethru
Propiedad Booleana que establece o devuelve que el tipo de letra usado es Tachada.
Sintaxis
Variable = CD1.FontUnderline
FontName
Devuelve el nombre de la fuente elegida. Es una variable tipo String
Sintaxis
Variable = CD1.FontName
(Variable toma el valor del nombre de la fuente. Por ejemplo, Variable = Arial
En general, deber modificar FontName antes de establecer los atributos de
tamao y estilo con las propiedades FontSize, FontBold, FontItalic,
FontStrikethru y FontUnderline.
Nota
En tiempo de ejecucin puede obtener informacin sobre las fuentes
disponibles a travs de las propiedades FontCount y Fonts. Lo ver mas adelante
FontSize
Devuelve de la fuente elegida. Debe ser una variable tipo Integer o Long
Sintaxis
Variable = CD1.FontSize
131
donde Variable ser una expresin numrica que especifica el tamao de fuente a
utilizar, en puntos.
Nota
Las fuentes disponibles en Visual Basic varan dependiendo de la
configuracin del sistema y de los dispositivos de presentacin e impresin. En las
propiedades relacionadas con las fuentes slo pueden establecerse valores para los
que exista una fuente.
En general, deber modificar FontName antes de establecer los atributos de
tamao y estilo con las propiedades FontSize, FontBold, FontItalic,
FontStrikethru y FontUnderline. Sin embargo, cuando especifique un tamao
inferior a 8 puntos para una fuente TrueType, primero deber establecer el tamao
en puntos con la propiedad FontSize, luego especificar la propiedad FontName y
despus establecer de nuevo el tamao con FontSize. El entorno operativo
Microsoft Windows utiliza una fuente distinta para las fuentes TrueType con un
tamao inferior a 8 puntos.
Index
Igual que el ya estudiado para otros controles.
InitDir
Devuelve o establece el directorio de archivos inicial.
Sintaxis
objeto.InitDir [= cadena]
control CommonDialog.
Sintaxis
objeto.MaxFileSize [= valor]
PrinterDefault
Devuelve o establece una opcin que determina si la configuracin elegida por el
usuario en el cuadro de dilogo Imprimir se utiliza para modificar la configuracin
predeterminada de impresora del sistema.
Sintaxis
True Las opciones que elija el usuario en el apartado Configurar del cuadro de
dilogo Imprimir (seleccin de la impresora, orientacin, etctera) se utilizan para
modificar la configuracin de impresora almacenada en el Registro).
False Las opciones que elija el usuario no se utilizan para modificar la
configuracin de impresora predeterminada del sistema.
Tag
Utilice esta propiedad, que por defecto est a True, para poner o no poner como
impresora predeterminada, la impresora seleccionada con el CommonDialog. Puede
por ejemplo, querer imprimir un texto en una impresora determinada, pero solo ese
texto, y no quiere cambiar la impresora predeterminada por el hecho de haber
seleccionado en este momento otra impresora. Ponga esta propiedad a False
(recuerde que por defecto est a True) para que la impresora seleccionada no se
quede como impresora por defecto.
Lo mismo que se ha explicado para otros controles.
133
determinadas necesidades s son muy prcticos. Estdieselos con el mismo entusiasmo que
si no existiese el CommonDialog.
Al tratarse de controles tipo Lista, le recomiendo que lea el captulo correspondiente al
ListBox. Le aclarar sobre todo los trminos empleados para definir los elementos de la
lista, que en este caso, son los ficheros de una carpeta, las carpetas de un disco o los
discos visibles desde la mquina.
Tal como indica su nombre, estos controles son listas. Repase el control ListBox para
recordar sus propiedades.
DriveListBox
Este control permite elegir una unidad de disco vlida en tiempo de ejecucin. Utilice este
control para mostrar una lista de todas las unidades vlidas del sistema de un usuario.
Puede crear cuadros de dilogo que permitan al usuario abrir un archivo de una lista en
cualquier unidad disponible.
Posee las propiedades tpicas de cualquier control VB respecto a su geometra y color. Las
propiedades mas destacables de este control son : Drive, List, ListCount y ListIndex
Drive devuelve el nombre de la unidad de disco seleccionada :
134
Variable = List1.Drive
Variable = a :
( c :[MS-DOS_6]
D)
Este control se trata de una lista como su nombre indica, y posee las propiedades List,
ListCount y ListIndex para permitir al usuario tener acceso a elementos de la lista.
List (n) devuelve el texto que define a la unidad colocada en el lugar n. El nmero n
comienza por 0. Por ejemplo, en la figura anterior, List1.list(1) devolver c :[MS-DOS_6]
ListCount proporciona informacin acerca del nmero de unidades de disco disponibles
(En el ejemplo, List1.ListCount ser 3, que corresponde a los tres discos disponibles disco C :, disco A : y disco D : )
ListIndex devuelve el ndice del disco seleccionado en la lista (0 para el primero, n-1 para
el ltimo)
Utilizando el control DriveListBox en combinacin con DirListBox y FileListBox, podr
realizar un explorador de ficheros en cualquier disco de su ordenador.
DirListBox.
Presenta un cuadro de la siguiente forma:
Nombre.Path [= pathname]
donde
Nombre
es el nombre del DirListBox
pathname Una expresin de cadena que evala en el nombre de va de acceso del
directorio por defecto del DirListBox..
El valor de la propiedad Path es una cadena que indica una ruta de acceso, como
C:\WINDOWS\SYSTEM. El valor predeterminado es la ruta de acceso actual
Cuando se cambia la propiedad Path en tiempo de ejecucin se genera un evento Change.
135
Nota
El valor que devuelve Path es distinto del de List (ListIndex). Path devuelve
siempre un mismo camino, bien el que se le haya impuesto mediante esta misma
propiedad Path, y si no se le ha impuesto con anterioridad, el que tenga por defecto. List
(ListIndex) devuelve el camino completo del directorio seleccionado, y, como era de
esperar, cambia cada vez que cambiamos la seleccin del directorio.
List, ListCount y ListIndex
Al igual que cualquier lista, el DirListBox tiene las propiedades List, ListCount y
ListIndex.
ListIndex devuelve el valor del ndice del directorio seleccionado. El valor devuelto es cero
cuando est seleccionado el primer directorio de los situados al final del rbol, 1 para el
siguiente, etc. Toma el valor -1 cuando se selecciona el directorio inmediatamente
superior al ltimo nivel, el valor -2 cuando se selecciona el directorio situado 2 niveles
jerrquicos por encima del ltimo nivel, etc.
ListCount devuelve un valor numrico igual al nmero de directorios existentes en el
ltimo nivel, independientemente de los directorios que tuviesen por arriba.
List (n) devuelve una cadena de caracteres con el camino completo del elemento cuyo
orden sea el sealado entre parntesis. Si en vez de n colocamos el ListIndex nos
devolver, logicamente, el camino del elemento seleccionado.
FileListBox
Esta lista nos presenta los ficheros existentes en un directorio.
Como se puede apreciar, cuando el nmero de ficheros supera el nmero que puede
presentar, aparecen automticamente las flechas de scroll verticales.
Esta lista de ficheros tiene las siguientes propiedades destacables :
Path
Devuelve o establece la ruta de acceso de su directorio actual. No est disponible en
tiempo de diseo. Este directorio puede ser el que se le haya impuesto mediante esta
propiedad Path, o el que tenga por defecto. (El directorio por defecto sera el del
ejecutable de la aplicacin)
Si le ponemos el nombre por defecto, List1, para todos los ejemplos :
variable = List1.Path
(p. e.)
ListCount
Devuelve el nmero total de ficheros que hay en ese directorio.
136
Variable = List1.ListCount
Variable = 19
(p. e.)
ListIndex
Devuelve un nmero con el ndice del elemento seleccionado. Como todas las listas,
devuelve -1 si no hay ningn elemento seleccionado. El primer elemento de una lista tiene
el ndice = 0.
Filename
Devuelve el nombre del fichero seleccionado.
List (n)
Devuelve el nombre del fichero que ocupa el lugar n en la lista.
Variable = List1.List (5)
la lista.
obtendremos
el
nombre
del
fichero
objeto.Pattern [= valor]
137
[= booleano]
[= booleano]
[= booleano]
[= booleano]
Las sintaxis de la propiedades Archive, Hidden, Normal y System tiene la siguiente partes:
objeto :Nombre del FileListBox
booleano :Una expresin booleana (True / False) que especifica el tipo de archivos
presentados.
El valor booleano puede presentar los siguientes valores :
True :(Predeterminado para Archive y Normal) Presenta archivos con el atributo de la
propiedad en el control FileListBox.
False : (Predeterminado para Hidden y System) Presenta archivos sin el atributo de la
propiedad en el control FileListBox.
Use estas propiedades para especificar el tipo de archivos a presentar en un control
FileListBox, basndose en los atributos de archivos estndar usados en el entorno
operativo. La definicin de estas propiedades en el cdigo en tiempo de ejecucin hace que
el control FileListBox presente slo aquellos archivos con los atributos especificados.
Por ejemplo, en una operacin de buscar y reemplazar se podran presentar solamente
archivos del sistema estableciendo la propiedad System a True y las dems propiedades a
False. Tambin, como parte del procedimiento de copia de seguridad, se podra establecer
la propiedad Archive a True para relacionar solamente aquellos archivos modificados a
partir de la ltima copia de seguridad.
PROCEDIMIENTOS del FileListBox
Click
KeyDown
Change
KeyPress
DragDrop
KeyUp
DragOver
GotFocus
138
El directorio por defecto es el ltimo que se ha seleccionado por algn procedimiento. Por
ejemplo, al arrancar una aplicacin, el directorio por defecto ser el mismo donde se
encuentra el ejecutable. Pero si a lo largo de la aplicacin cambiamos el directorio,
seleccionando otro mediante un CommonDialog, ese directorio es el que queda por
defecto. Asegrese en sus aplicaciones que siempre elige la propiedad Path antes de
presentar ficheros o directorios a travs de los controles anteriores, para evitar que pueda
mostrarle ficheros de un directorio no deseado.
Puede comprobar cual es el directorio actual. La funcin CurDir nos devuelve el directorio
actual.
Ejemplo : Introduzca una lnea de cdigo con la siguiente sentencia
Variable = CurDir
(p. e.)
Puede darse el caso de que desee conocer el directorio actual de varias unidades de disco.
Por ejemplo, puede estar trabajando en el directorio C:\CursoVB\Ejemplos y ser este el
directorio actual en el disco C :, y tener un disquete en la unidad A : en el que la ltima
vez que trabaj fue en el directorio A :\ApVB\Tema1 y ese es su directorio por defecto en
el disco A. Para conocer el directorio actual del disco C : no necesit especificar la unidad,
ya que era precisamente la unidad C la unidad actual. Para conocer el directorio actual de
la unidad A empleara la expresin :
Variable = CurDir (A)
Variable = A :\ApVB\Tema1
Decamos que el disco C era la unidad actual. Tambin podemos cambiar la unidad actual,
mediante la sentencia ChDrive seguida de una letra (entre comillas dobles)
Ejemplo
ChDrive A
si
Tambin podemos forzar a que un directorio sea el directorio por defecto. La sentencia que
tendremos que usar en ChDir.
Ejemplo : ChDir C :\Windows\System cambiara el directorio actual al especificado.
Podemos incluso crear un directorio. Usaremos para ello la sentencia MkDir. Esta
sentencia crea el directorio con el nombre indicado, sobre el directorio actual.
Si el directorio actual es el C:\VB\Icons y ejecutamos la sentencia :
MkDir Varios
crearamos el directorio
C:\VB\Icons\Varios
139
existentes, guardarla en un fichero, etc., tenemos una forma que facilita esta labor. Igual
que en DOS. La funcin Dir
A esta funcin le debemos aadir como parmetro el criterio de bsqueda, criterio formado
por los caracteres o comodines que deseemos. Dir devuelve solamente el nombre de un
fichero, por lo que tendremos que repetirla tantas veces como ficheros tenga el directorio.
Pero solamente tendremos que introducir el criterio de bsqueda la primera vez.
En el siguiente ejemplo, sacaremos por impresora los nombres de los ficheros existentes
en el directorio actual : (Este cdigo lo meteremos en el procedimiento click de un botn
de comando)
fichero = Dir("*.*")
Do Until fichero = ""
Printer.Print fichero
fichero = Dir
Loop
Printer.EndDoc
Ya sabemos sacar el directorio. Vamos a ver que otras cosas se pueden hacer con ficheros.
Funcin Kill. A poco Ingls que sepa se habr dado cuenta que esta funcin sirve para
quitarse algo de enmedio. Esta funcin borra un fichero del disco.
Kill C:\CursoVB\Ejemplos\Ejemplo1.txt
borra el fichero
CursoVB\Ejemplos
Ejemplo1.txt,
que
se
encuentra
en
el
disco
C,
directorio
140
141
Para conocer los atributos de un fichero, utilizaremos la funcin GetAttr. Esta funcin
devuelve un nmero, que representa la suma de los atributos de un archivo, directorio o
carpeta o una etiqueta de volumen.
Sintaxis
Donde nombreruta es una expresin de cadena que especifica un nombre de archivo, con
su Path y unidad de disco.
El valor devuelto por GetAttr es un nmero, igual a la suma de los siguientes valores de
atributos:
Valor
Constante
Descripcin
0
1
2
4
16
32
copia
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Slo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado despus de efectuar la ltima
de seguridad.
Donde nombreruta es una expresin de cadena que especifica un nombre de archivo, con
su Path y unidad de disco, y atributos es una o varias de las constantes o valores
anteriores, cuya suma especifica los atributos de archivo.
Dado que el valor 16 indica que lo expresado en nombreruta es un directorio, no puede
pretenderse darle a ese directorio atributos que solamente se pueden aplicar a un fichero,
ni puede pretender darle a un fichero un valor en el que entre el 16 como sumando. Estos
casos le producirn un error en tiempo de ejecucin.
Si pretende establecer los atributos de un archivo abierto, se producir un error en tiempo
de ejecucin.
Existe una funcin, que no tiene nada que ver con la anterior, aunque puede parecerlo por
su parecido semntico y que tambin devuelve atributos, pero de otro tipo. Esta funcin es
FileAttr
Funcin FileAttr
Devuelve el modo de apertura de un archivo. Logicamente debe referirse a un archivo
abierto en el momento de ejecutar esta funcin. Vea para mas detalles la sentencia Open.
Sintaxis
142
Valor
1
2
4
8
32
Entrada
Salida
Aleatorio
Aadir
Binario
La Ayuda de VB dice que tipoinformacin puede ser =2 para que FileAttr devuelva
informacin sobre el selector de archivos del sistema operativo. Algunas veces la
informacin de ayuda de VB promete cosas que, sin dudar de que sean ciertas, son difciles
de comprobar.
Esta funcin no tiene una gran aplicacin prctica, ya que comprueba la forma en la que
hemos abierto un archivo. Informacin que conocemos desde el mismo momento de
abrirlo.
Visual Basic - Gua del Estudiante Cap. 4
CONTROLES PARA MOSTRAR IMGENES
CREAR CONTROLES EN TIEMPO DE EJECUCIN
EL EXAMINADOR DE OBJETOS
_________________________________________________________________
Una imagen representa una figura, bien natural (tipo fotografa) o sinttica. Para presentar
una imagen es necesario hacerlo sobre un objeto que la admita. Los objetos que admiten
una imagen son:
Formularios
PictureBox
Image
Existen mas controles grficos que se irn viendo a lo largo del curso. Estos tres son los
mas usados y con los que comenzaremos a trabajar.
Para mostrar una imagen en cualquiera de estos objetos, es necesario especificarlo en su
propiedad Picture. La forma de especificarle al objeto la imagen que debe presentar
puede hacerse de dos formas:
Por ejemplo, si tenemos un formulario llamado Form1 y queremos rellenarlo con una
imagen contenida en el fichero de Windows metafile DOLLAR.WMF que se encuentra en el
directorio C:\VB\METAFILE\BUSINESS, deberemos ejecutar la instruccin:
Form1.Picture = LoadPicture (C:\VB\METAFILE\BUSINESS\DOLLAR.WMF)
Para "descargar" esa imagen de ese formulario, basta con ejecutar la misma instruccin sin
fichero alguno:
Form1.Picture = LoadPicture ( )
143
un
Puede tambin meter una imagen en una variable, y luego poner en uno de los controles
citados anteriormente la imagen guardada en la variable. Este mtodo es muy rpido, ya
que no necesita acceder al disco para buscar una imagen, pero emplea mucha memoria
RAM, ya que la variable )o variables conteniendo la(s) imgenes estn en la RAM.
Para ello debemos declarar una o varias variables tipo Picture, y meter en ellas una
imagen mediante el mtodo LoadPicture. Vea en el capitulo 7 (Mtodos Grficos - Mtodo
LoadPicture) un ejemplo muy ilustrativo.
EL FORMULARIO
Ya hemos visto lo que es el Formulario. Simplemente podemos aadir a lo ya dicho, que un
formulario tiene la propiedad Picture, con lo que podemos poner como fondo un bit-map,
un fichero de icono ( .ICO) o un Metarchivo (.WMF). Un fondo grfico sobre el Formulario
puede convertir una aplicacin de buena a excelente. No intente nunca mejorar una
aplicacin mediocre con un fondo artstico en un Formulario.
Adems de presentar imgenes, se puede escribir texto en un formulario. Para ello se
utiliza el mtodo grfico Print que veremos en el captulo de mtodos grficos
CONTROL PICTURE BOX
Este objeto se encuentra en la caja de herramientas estndar:
Este objeto permite presentar todo tipo de ficheros grficos (.BMP, WMF, .ICO, .CUR)
Las dimensiones del PictureBox se establecen en el diseo o mediante programa, variando
las propiedades Height y Width. Tambin puede cambiarse su posicin mediante las
propiedades Top y Left. Dispone de una propiedad, Align que permite colocarlo adosado
en la parte superior. Inferior o a uno de los lados del formulario que lo contiene.
El Control PictureBox puede ser destino de los datos de un enlace DDE. (Los datos sern,
lgicamente, grficos. Por ello, tiene las propiedades LinkMode, LinkItem, LinkTimeout
y LinkTopic.
Tambin puede tomar el dato del grfico de una Base de Datos. (A travs de un control
Data o un objeto Recordset o rdoResultset)
Las propiedades de un PictureBox son:
Align
Appearance Autoredraw Autosize
Backcolor
BorderStyle
ClipControls DataField
DataSource DragIcon
DragMode
DrawStile
DrawWidth
Enabled
FillColor
FiilStyle
Font
Fontransparent
ForeColor
Height
HelpContextID
Index
Left
LinkItem
LinkMode
LinkTimeout LinkTopic
MouseIcon MousePointer
Name
Negotiate
Picture
ScaleHeight ScaleLeft
ScaleMode ScaleTop
ScaleWidth
TabIndex
TabStop
Tag
Top
Visible
144
WhatThisHelp
Width
Change
KeyPress
DblClick
DragDrop
DragOver
GotFocus
CONTROL IMAGE
Este control se encuentra en la caja de herramientas estndar:
Este control permite presentar todo tipo de ficheros grficos (.BMP, WMF, .ICO, .CUR)
El control Image no puede ser destino de una comunicacin DDE. Puede tomar la imagen
de una base de datos, bien a travs de un control Data o a travs de un objeto Recordset.
El control Image utiliza menos recursos del sistema y repinta con ms rapidez que un
control PictureBox, pero slo admite una parte de las propiedades, los eventos y los
mtodos de PictureBox. Use la propiedad Stretch para determinar si el grfico se escala
para que se ajuste al control o viceversa. Poniendo esta propiedad a True el grfico se
adaptar a las dimensiones del control Image. Si se pone a False, el control Image tomar
las medidas del grfico que contenga. Si el grfico es un bit-map (Fichero .BMP), con la
propiedad Stretch a True podemos variar el tamao del bit-map, variando las propiedades
Width y Height del control Image, propiedades que se pueden cambiar en tiempo de
ejecucin. Si esta propiedad est a False, el tamao del bit-map no cambiar,
presentndose solamente una porcin del bit-map, caso que el control Image sea menor
que el tamao del bit-map, o sobrar espacio en el control, en caso contrario.
Un Image es transparente, es decir, deja ver el fondo del formulario en las partes no
ocupadas por su grfico. Por lo tanto, no tendran sentido en este control propiedades como
Backcolor, FillColor, o FillStyle.
Las propiedades de un Image son:
Appearance BorderStyle Datafield
DataSource DragIcon
DragMode
Enabled
Height
Index
Left
MouseIcon
MousePointer Name
Picture
Stretch
Top
Visible
WhatThisHelp
Width
145
Tag
DragOver
GotFocus
MouseDown
(PictureBox solamente)
Permite colocar el control en el borde superior (Align Top), en el inferior (Align
Bottom), en el izquierdo (Align Left) o en el derecho (Align Right) del
formulario que lo contiene. Para no alinearlo con ningn borde basta con poner
la propiedad Align a 0-None.
Cuando se adosa a uno de los bordes, el tamao del control se ajusta
automticamente a la anchura o altura del formulario.
Sintaxis
NombrePictureBox.Align [= nmero]
nmero
0-None
MDI).
asignada en
1-Top
control
igual
igual
igual a
146
Negotiate
(PictureBox solamente)
Esta propiedad le permite mostrar o no mostrar el PictureBox dentro de un
formulario donde tiene una barra de herramientas. No est disponible en tiempo
de
ejecucin.
Esta propiedad no es muy usual, por lo que omitimos una mayor explicacin.
Recurra a la ayuda para obtener mas detalles
(PictureBox solamente)
(PictureBox solamente)
Color de fondo. Igual que otros controles
BorderStyle
(PictureBox e Image)
(PictureBox solamente)
(PictureBox e Image)
(PictureBox e Image)
Ver con mas detalles estas propiedades cuando estudie los Objetos enlazados a
Datos. Le van a permitir presentar una imagen desde una base de datos. Le
permitir tambin introducirla de una forma muy sencilla en la base de datos.
DragIcon
DragMode
(PictureBox e Image)
DrawMode
DrawStyle
DrawWidth
(PictureBox solamente)
(PictureBox solamente)
(PictureBox solamente)
147
(PictureBox solamente)
(PictureBox solamente)
(PictureBox e Image)
(PictureBox solamente)
(PictureBox e Image)
donde :
objeto
Nombre del objeto PictureBox o Image
ruta
Expresin de cadena que especifica la ruta y el nombre del archivo
que contiene el icono personalizado. As podemos cargar un icono de los
existentes
en
el
disco.
Ej.
Image1.MouseIcon
=
LoadPicture("C:\vb\icons\computer\disk05.ico")
imagen Propiedad Picture de un objeto Form, de un control PictureBox o de un
control Image, o nombre de una variable tipo Picture. De esta forma podemos
cargar como un icono el grfico que tengamos en otro objeto o en una variable
tipo Picture.
Ej. Image1.MouseIcon = Picture1.picture
La propiedad MouseIcon proporciona un icono de mouse personalizado que se
utiliza cuando el valor de la propiedad MousePointer es 99.
MousePointer. Establece el tipo de puntero de mouse que aparece cuando se
pasa el puntero del ratn por encima de un objeto en tiempo de ejecucin.
148
Sintaxis
objeto.MousePointer [= valor]
objeto
Nombre del objeto PictureBox o Image
valor
Nmero entero que especifica el tipo de puntero de mouse que
aparece, segn se describe mas adelante.
Las opciones para valor son:
0 (Predeterminado) Forma que determine el objeto.
1 Flecha.
2 Cruz (puntero en forma de cruz).
3 Forma de I.
4 Icono (pequeo cuadrado dentro de otro cuadrado).
5 Tamao (flecha de cuatro puntas: norte, sur, este y oeste).
6 Tamao NE SO (flecha doble apuntando al nordeste y al sudoeste).
7 Tamao N S (flecha doble apuntando al norte y al sur).
8 Tamao NO SE (flecha doble apuntando al noroeste y al sudeste).
9 Tamao O E (flecha doble apuntando al oeste y al este).
10 Flecha hacia arriba.
11 Reloj de arena (espera).
12 No soltar.
13 Flecha y reloj de arena.
14 Flecha e interrogacin.
15 Tamao de todo (personalizable en Microsoft Windows NT 3.51)
99 Icono personalizado especificado en la propiedad MouseIcon explicada
anteriormente.
Name
(PictureBox e Image)
Picture
(PictureBox e Image)
objeto.ScaleHeight [= valor]
objeto.ScaleWidth [= valor]
objeto
valor
Nota
Las propiedades ScaleHeight y ScaleWidth son distintas de las
propiedades Height y Width.
149
ScaleLeft,
ScaleTop
Devuelven o establecen las coordenadas horizontal (ScaleLeft) y vertical
(ScaleTop) de los bordes izquierdo y superior de un objeto al utilizar mtodos
grficos o al situar controles. Estas coordenadas estn medidas de acuerdo con
la unidad de medida establecida en las propiedades ScaleHeight y ScaleWidth
ScaleMode
Devuelve o establece un valor que indica la unidad de medida de las
coordenadas de un objeto al utilizar mtodos grficos, o al situar controles.
Sintaxis
objeto.ScaleMode [= valor]
objeto.Stretch [= lgico]
objeto
Nombre del control Image
lgico
Expresin booleana que especifica si el grfico adapta su tamao,
segn se describe a continuacin.
True
False
grfico.
151
IMAGE LIST
Lo ver mucho mas ampliamente en un captulo posterior. Se incluye en este captulo para
que lo pueda ir usando.
Este control no est normalmente en la caja de herramientas. Hay que introducirlo
mediante los Proyecto | Componentes y pertenece al grupo Microsoft Windows
Common Controls (COMCTL32.OCX) (Vea Nota 1)
Este control nos permite almacenar varias imgenes. Es, tal como indica su nombre, como
un ListBox pero que en vez de contener textos, contiene imgenes.
La utilidad de este control es para almacenar en l distintas imgenes, y servirlas desde l
a otro control, un PictureBox o un control Image, sin necesidad de tener que acceder a
leerlas en el disco, que conllevara una importante prdida de tiempo si el cambio de
imgenes debe ser rpido.
Este control es necesario para almacenar las imgenes que se mostrarn en los iconos de la
barra de herramientas. Ver mas adelante como se realiza una barra de herramientas (La
barra de herramientas solo est disponible para la versin de 32 Bits)
Un ImageList permite tener varias imgenes dentro de l, pero este control no las
presenta. Solamente sirve de almacn para pasarlas rpidamente a otro control
(PictureBox, p.e.) que ser el que las presenta en pantalla.
En la siguiente figura, pueden verse las propiedades de un ImageList con varias imgenes
cargadas.
152
153
pepe = pepe + 1
If pepe > ImageList1.ListImages.Count Then pepe = 1
Set Picture1.Picture = ImageList1.ListImages(pepe).Picture
Una de las mayores aplicaciones del ImageList es proporcionar imgenes para otros
controles. Entre ellos el TOOLBAR
Barra de Herramientas. Control Toolbar
Este control permite realizar una barra de herramientas. La barra de herramientas es,
como ya conocer, una barra donde existen varios iconos. Estos iconos realizan una
determinada funcin. Normalmente se ponen en la barra de herramientas los iconos que
representan las acciones mas frecuentes de una aplicacin. Esto facilita la operacin al no
tener que desplegar mens para buscar la operacin a realizar.
Como el espacio que ocupan los iconos es grande, es tambin bastante normal que no
estn representados en la barra de herramientas todas las funciones posibles de la
aplicacin, sino como decamos, solamente las mas frecuentes. Pero ocurre que la funcin
que para un usuario es muy frecuente, para otro no lo es, por lo que tambin es habitual
poder programar los iconos que aparecen en la barra de herramientas.
Todo ello lo puede hacer el control Toolbar.
Para introducir el Toolbar es necesario que est presente en la caja de herramientas el
control personalizado Microsoft Windows Common Controls (COMCTL32.OCX).
El control Toolbar es un contenedor de un array de iconos. Estos iconos forman botones
sobre los que se puede insertar cdigo en sus procedimientos. A cada botn se le
denomina Button y a la coleccin de botones se le denomina Buttons. Cada Button es un
elemento de la coleccin Buttons y por lo tanto podemos referirnos a cada uno de ellos
por el ndice que tiene dentro de la coleccin.
Los iconos de cada uno de los botones del Toolbar debe introducirse previamente en un
control ImageList. Como se recordar, un control ImageList es un almacn de
imgenes, que podemos usar en cualquier parte de la aplicacin. Una de esas partes es la
confeccin de la barra de herramientas. Por lo tanto, es necesario introducir un control
ImageList en cualquier aplicacin que use un control Toolbar. Todas las imgenes del
Toolbar deben estar en un nico ImageList. Y este ImageList debe estar en el mismo
formulario que el Toolbar
La barra de herramientas puede realizarse en tiempo de diseo (este sera el caso para
cuando no existiese variacin ni eleccin de botones a lo largo de la ejecucin de la
aplicacin)
o en tiempo de ejecucin (caso que correspondera con una aplicacin que tuviese una
barra de men programable o que variase esta barra de men dependiendo de cada
operacin que se est ejecutando en la aplicacin).
Para realizar la barra de herramientas en tiempo de diseo, basta con visualizar el cuadro
de propiedades que aparece pulsando el botn derecho del ratn sobre el control Toolbar.
Aparecer un cuadro de dilogo como este :
154
Para insertar un nuevo botn hay que hacer click sobre Insertar botn e insertar un nuevo
botn inmediatamente despus del que figura en la propiedad Index (en la figura del
ejemplo, lo insertara en segundo lugar, no en el ltimo lugar como podra creerse).
Tambin podemos eliminar un botn haciendo click sobre Eliminar botn.
155
El Caption (opcional) es la palabra que figurar debajo del icono del botn.
Un botn se identifica por su ndice. ( Toolbar1.buttons(1) )
La propiedad Key es un nombre que se puede aadir a cada botn. Esta propiedad sirve
para identificar el botn que se ha pulsado, pero no para nombrar al botn.
La propiedad Value es el valor por defecto, con el que aparecer el botn al comienzo de
la aplicacin. (Unpressed, no pulsado, Pressed, pulsado).
La propiedad Style define el tipo de botn :
click)
0 - Default
1 - Check
2 - Button Group
Solo uno de los botones del grupo puede estar pulsado. Esta
propiedad lleva implcito que los botones que forman un grupo
son biestables. Pueden hacerse varios grupos independientes
introduciendo un botn que no pertenezca a un grupo (tipos 0,
1, 3 4) entre los dos grupos que se independientes que se
pretenden formar
El botn se convierte en un separador de anchura fija.
El botn se convierte en un separador de anchura
3 - Separator
4 - PlaceHolder
variable.
ToolTipText es el texto que aparecer al lado del botn cada vez que se ponga el cursor
del ratn sobre el botn. Para que aparezca debe estar habilitada la propiedad ShowTips.
Image es el nmero de la imagen en el ImageList.
El control Toolbar tambin puede realizarse en tiempo de ejecucin. Para introducir u botn
en el Toolbar hay que crear el botn y aadirlo a la coleccin Buttons de Toolbar. Podemos
hacerlo en una sola instruccin :
Set NombreBotn = NombreToolbar.Buttons.add ( [Indice], [Key], [Caption], [Style],
[Imagen])
NombreBotn puede ser cualquier nombre (es el nombre del objeto botn)
NombreToolbar es el nombre del Toolbar
Indice es el nmero de orden de ese botn dentro del Toolbar
Key es el valor de la propiedad Key del botn. Este valor debe ser nico para cada botn.
Style es un nmero del 0 al 4 con el tipo de botn. Vea lista mas arriba
Imagen es el nmero de la imagen para ese botn, dentro del ImageList que las contiene.
Los botones pueden habilitarse y deshabilitarse usando la propiedad Enabled (True /
False). Recuerde que los botones se identifican por su ndice :
Toolbar1.Buttons(Indice).Enabled = False
Para saber que botn se ha pulsado, puede leerse la propiedad Key :
Text1.Text = Button.Key
Con la lectura de la propiedad Key, y la sentencia Case o If ... Then podemos iniciar la
parte de la aplicacin asociada a cada botn.
156
157
LA BARRA DE ESTADO
Este control es muy parecido a la barra de herramientas, y suele usarse, colocndolo en la
parte inferior de la ventana, para indicar el proceso que est en curso en la aplicacin. La
barra de estado, control StatusBar se introduce en la caja de herramientas al mismo
tiempo que el control Toolbar, mediante el control personalizado mltiple Microsoft
Windows Common Controls (COMCTL32.OCX).
La barra de estado puede albergar hasta 16 paneles, que pueden contener texto o grficos.
Tambin pueden contener informacin del Hardware, tal como el estado de la tecla
Bloqueo de Maysculas, Bloqueo del teclado numrico, tecla Insert activada, tecla
Scroll Lock activada, o mostrar la fecha y la hora
La barra de estado puede configurarse como de un solo panel o de mltiples paneles.
(Propiedad Style. 0=mltiples paneles, 1= panel nico)
Las dimensiones de cada panel pueden configurarse como fijas o ajustadas al tamao del
texto o imagen que presentan.
Las propiedades pueden establecerse en tiempo de diseo, mediante el siguiente cuadro.
Donde PanelNuevo es el nombre con el que se va a conocer ese panel que acabamos de
crear. PanelNuevo debe declararse como variable objeto Panel donde sea necesario segn el
mbito que le queramos dar. De esta forma, una vez creado, nos podremos referir a ese
panel simplemente citndolo por su nombre (En este caso, PanelNuevo)
Los trminos
[ndice],[key],[Text],[estilo],[grfico]
la sintaxis de creacin del panel se explican a continuacin.
Set PanelNuevo = statusbar1.Panels.Add(pepe, "Contenido del Key " & Str(pepe), "Texto "
& Str(pepe), , LoadPicture("C:\vb\icons\comm\net09a.ico"))
Estos son los controles grficos mas importantes. Ver a lo largo del curso que existen
otros, y ms que podr encontrar entre diferentes suministradores de controles, ya que VB
ha dejado una puerta abierta para realizar controles a medida. Existen varias empresas de
software dedicadas a la fabricacin de controles personalizados, y en el aspecto de
controles grficos, podr encontrar una amplia gama de fabricantes y controles. Puede
obtener muchos controles en el CD-ROM que acompaa a varias revistas especializadas en
programacin VB, y a travs de Internet.
159
en s mismos materia
Desde mis comienzos en la actividad educativa de esta asignatura, los alumnos siempre
me preguntaron por la posibilidad de crear controles en tiempo de ejecucin. Supongo
que exista alguna razn que yo desconozco para ello. Y digo esto porque no he tenido la
necesidad de ello en ninguno de mis proyectos, y no han sido precisamente pocos.
Quiero decir con esto que la creacin de controles en tiempo de ejecucin es algo muy
llamativo, pero de escaso sentido prctico. Sean los alumnos los que busquen utilidad a
ello, y yo me limito a mi obligacin de enserselo.
En anteriores versiones de VB era un proceso un poco tedioso. Haba que crear una matriz
de controles y aadir en tiempo de ejecucin tantos controles nuevos a esa matriz como
necesitemos. Era complicado. Haba que meter un control y ponerle Index = 0. Se le pone
la propiedad Visible = False y ya tenemos una matriz de controles. Una matriz de un solo
control, pero al tener la propiedad Index = 0 ya era una matriz. Ya en ejecucin, se
utilizada el mtodo Load para crear los controles que necesitamos. Los nuevos elementos
de la matriz tendrn todas las propiedades del elemento inicial, es decir, las del elemnto
que tienen indice 0. Al ser una matriz, todos los controles comparten el cdigo de sus
procedimientos.
Para crear por ejejmplo, varios botones de comando, introduciremos primero uno con
Index = 0 cmdBotonInicial(0) y cuando queramos crear un botn nuevo, invocamos el
mtodo Load. Recuerde que el nuevo botn tendr las mismas propiedades que el objeto
inicial, por lo tanto sus mismas propiedades Left y Top. Resultado: el nuevo botn queda
completamente solapado con el inicial, por lo que habr que cambiarle de posicin y
coocarlo en las coordenadas deseadas.
Una de las propiedades que no se pasan al nuevo control es la propiedad Visible. Esta
siempre comienza a False. Por lo tanto tambin hay que ponerla a True para que veamos el
nuevo control. Este podra ser un cdigo para crear un botn de comando
Load cmdBotonInicial(1)
cmdBotonInicial(1).Visible = True
cmdBotonInicial(1).Left = cmdBotonInicial(0).Left + 1000
160
Es un poco complicado. Se suele hacer esto para que aparezca un control justamente
donde hacemos clic con el ratn sobre el formulario. Dejo al alumno la posibilidad de jugar
con este mtodo.
Veamos un mtodo ms sencillo.
Add (Mtodo de la coleccin Controls)
Agrega un control a la coleccin Controls y devuelve una referencia al mismo.
Sintaxis
Set NombredelControl = NombredelFormulario.Controls.Add (progID, name, container)
Donde:
NombredelControl
Es la referencia del nuevo control devuelta por el mtodo Add. Debe
ser
una variable tipo Control declarada previamente. Le
recomiendo que esta
variable tipo objeto tenga el mismo nombre que
le va a dar al control en su
parmetro Name. Le ahorrar muchas
confusiones.
NombredelFormulario
ser Me)
ProgID
biblioteca
en el citado
Name
Es el nombre que va a tener el control. Le repito lo de ms atrs.
Ponga aqu la misma cadena que en NombredelControl.
Container
Es el nombre del contenedor de ese control si es que se quiere meter
dentro de un contenedor que a su vez est dentro del
formulario. Un
contenedor de controles puede ser un
PictureBox o un Frame. Aqu se
pondra el nombre del ese
contenedor que debe existir en el formulario.
Vamos a ver como se puede declarar una variable tipo Control. Puede hacerlo segn estos
tres ejemplos, en el primero se declara que NuevoBoton es un control,
(declaracin
161
Ya
162
163
Este es el analizador de objetos. Puede ver que tienen varias partes. Comencemos por
arriba.
El desplegable donde pone Todas sirve para elegir una parte de todo lo que nos puede
mostrar. En este caso est mostrando todo lo que tienen el proyecto. Si observa la figura
de la pgina siguiente ver que est desplegado, mostrando todas las referencias y
controles que tienen en ese momento. Puede ver que tienen el MSCommDlg, porque a ese
proyecto le habamos introducido el CommonDialog. Si seleccionamos ese control, nos
aparecen en la ventana Classes todas las colecciones que tiene el CommonDialog, entre
ellas el propio control, que si lo seleccionamos, en la ventana de la derecha, (Miembros)
aparecern todas la propiedades, los mtodos, y los eventos (Claro que un CommonDialog
no tienen eventos, pero s aparecern si mostramos cualquier otro control)
Si le aadimos ahora una referencia (El acceso a una base de datos mediante DAO, por
ejemplo) aparecer esa referencia en la lista desplegable.
Los controles bsicos aparecen en la referencia VB. Aparecen concretamente los controles
que figuran en la barra de herramientas al abrir un nuevo proyecto.
Si aadimos ms
componentes (Haciendo clic en la barra de men Proyecto | Componentes) veremos que
aparecen nuevos controles en el desplegable.
164
165
El objeto Clipboard se usa para manipular el texto y los grficos del Portapapeles. Este
objeto puede usarse para permitir que el usuario corte, copie y pegue texto y grficos en la
aplicacin.
El objeto Clipboard puede contener varias unidades de datos siempre y cuando cada una
tenga un formato diferente. Por ejemplo, se puede usar el mtodo SetData para poner un
mapa de bits en el Clipboard con el formato CF_BITMAP y despus usar el mtodo
SetText con el formato CF_TEXT para poner texto en el Clipboard. Despus se puede
usar el mtodo GetText para recuperar el texto o el mtodo GetData para recuperar el
grfico. Los datos del Clipboard se pierden cuando se colocan otros datos con el mismo
formato en el Clipboard desde el cdigo o mediante un comando de men.
SetText
Pone una cadena de texto en el objeto Clipboard usando el formato del objeto Clipboard
especificado. No acepta argumentos con nombre.
Sintaxis
Valor
Descripcin
vbCFLink
vbCFRTF
vbCFText
&HBF00
&HBF01
1
datos
formato
del
Valor
vbCFBitmap 2
vbCFMetafile 3
Descripcin
Mapa de bits (archivos .BMP)
Metarchivo (archivos .WMF)
166
vbCFDIB
vbCFPalette
8
9
Clipboard.GetData (formato)
formato
Opcional. Una constante o valor que especifica el formato grfico de Clipboard,
como se describe mas adelante. La constante o valor debe ir entre parntesis. Si
formato es 0 o se omite, GetData usa automticamente el formato apropiado.
Los valores de formato son:
Constante
Valor
Descripcin
vbCFBitmap
vbCFMetafile
vbCFDIB
vbCFPalette
2
3
8
9
GetText
Devuelve una cadena de texto del objeto Clipboard. No acepta argumentos con
nombre.
Sintaxis
Clipboard.GetText (formato)
formato
Opcional. Un valor o constante que especifica el formato del objeto Clipboard, como
se describe mas adelante. La constante o valor debe ir entre parntesis.
Los valores de formato son:
Constante
Valor
Descripcin
vbCFLink
vbCFText
&HBF00
1
167
objeto.Paste
VariableBooleana = objeto.PasteOK
Objeto es el nombre del contenedor OLE donde se quiere pegar el contenido del
portapapeles.
168
formato
Requerido. Un valor o constante que especifica el formato del objeto Clipboard,
como se describe mas adelante. La constante o valor debe ir entre parntesis.
Los valores de formato son:
Constante
Valor
Descripcin
vbCFLink
vbCFText
vbCFBitmap
vbCFMetafile
vbCFDIB
vbCFPalette
HBF00
1
2
3
8
9
El mtodo GetFormat devuelve True si algn elemento del objeto Clipboard coincide
con el formato especificado. Si no, devuelve False.
Para los formatos vbCFDIB y vbCFBitmap, la paleta de colores que se encuentre en
el Clipboard se usa para presentar el grfico.
Clear
Borra el contenido del Portapapeles del sistema.
Sintaxis
Clipboard.Clear
objeto.Copy
169
End Select
Label1.Caption = Msg ' Muestra el mensaje.
End Sub
Private Sub Command3_Click()
Clipboard.Clear
End Sub
Private Sub Command4_Click()
Clipboard.SetText Label2.Caption
End Sub
Private Sub Command5_Click()
Label3.Caption = Clipboard.GetText
End Sub
Private Sub Command6_Click()
Picture2.Picture = Clipboard.GetData()
End Sub
Private Sub Command7_Click()
Picture2.Picture = LoadPicture
End Sub
Private Sub Command8_Click()
Text1.Text = Trim(Text1.Text)
If UCase(Right(Text1.Text, 3)) = "BMP" Then
Check1.Value = 1
Else
Check1.Value = 0
End If
If Check1.Value = 1 Then
Clipboard.SetData LoadPicture(Text1.Text), 8
Else
Clipboard.SetData LoadPicture(Text1.Text)
End If
End Sub
171
172
173
Para un control, la propiedad LinkMode le permite que inicie una conversacin DDE con
una aplicacin servidor, (origen), y cmo iniciarla. Tiene 4 valores posibles :
0=None.
2=Manual
(destino),
3=Notify
NombredelFormulario.LinkTopic [= tema]
NombredelControl.LinkTopic [= aplicacionorigen|tema]
174
El nombre de la aplicacin origen ser el nombre del de proyecto de Visual Basic sin la
extensin .VBP (si la aplicacin se est ejecutando en el entorno de desarrollo de Visual
Basic), o el nombre de la aplicacin de Visual Basic sin la extensin .EXE (si se ejecuta
como un archivo ejecutable independiente).
El tema ser el mismo al que responde el formulario donde se encuentra el control que
contiene la informacin a traspasar.
(DDE es una utilidad de Windows. Windows establece que el estndar de un vinculo DDE
es Aplicacin | Tema | elemento. Vase para mas detalles el manual de Windows, enlaces
DDE)
Propiedad LinkItem
La propiedad LinkItem solamente la tiene el control destino de la informacin. No la tiene
el formulario origen. En esta propiedad deber expresarse el nombre del control origen
de la informacin.
Esta propiedad es de lectura y escritura, es decir, tanto sirve para saber el nombre del
control origen de los datos, como para establecerlo en tiempo de ejecucin.
Sintaxis
objeto.LinkItem = cadena
donde cadena es el nombre del control origen que tiene los datos y objeto es el nombre del
control al que le estamos poniendo la propiedad LinkItem.
Propiedad LinkTimeout
Devuelve o establece la cantidad de tiempo que un control espera una respuesta a un
mensaje DDE.
Sintaxis
objeto.LinkTimeout = nmero
donde nmero es una expresin numrica que especifica el tiempo de espera en dcimas
de segundo.
El tiempo de respuesta DDE desde aplicaciones origen vara. Use esta propiedad para
ajustar el tiempo que un control destino espera la respuesta de una aplicacin origen. Si se
usa LinkTimeout de forma correcta se puede evitar la generacin de un error por Visual
Basic si una aplicacin origen tarda mucho en responder.
Nota
La plazo mayor de tiempo que un control puede esperar es 65.535 dcimas de
segundo, es decir, sobre 1 hora y 49 minutos. Al establecer LinkTimeout a 1 se indica al
control que espere la respuesta en una conversacin DDE durante el mayor plazo de
tiempo. El usuario puede forzar que el control deje de esperar presionando la tecla ESC..
Evento LinkNotify
Ocurre cuando el origen ha cambiado el dato definido por el vnculo DDE si la propiedad
LinkMode del control destino est establecido a 3 (Notificar).
Private Sub objeto_LinkNotify([ndice As Integer])
End Sub
175
objeto.LinkRequest
Mtodo LinkSend
Transfiere el contenido de un control PictureBox a la aplicacin destino de una conversacin
DDE.
Sintaxis
objeto.LinkSend
Objeto debe ser un control PictureBox de un objeto Form que sea origen de una
conversacin DDE.
Cuando otras aplicaciones establecen vnculos automticos con un objeto Form de su
aplicacin, Visual Basic las notifica cuando el contenido de un control TextBox o Label
origen cambia. Sin embargo, Visual Basic no notifica automticamente a una aplicacin
destino DDE cuando el valor de la propiedad Picture de un control PictureBox origen
cambia. Como la cantidad de datos de un grfico pueden ser muy grande y como no tiene
sentido actualizar la aplicacin destino por cada cambio de pxel de la imagen, Visual Basic
requiere el uso del mtodo LinkSend para notificar explcitamente a las aplicaciones
destino DDE cundo cambia el contenido de un control PictureBox.
Mtodo LinkPoke
176
objeto.LinkPoke
177
178
(Arrastrar y Soltar)
El Drag & Drop es una forma visual de representar el movimiento de algo. Para ello se
toma algo de una parte de la interface grfica, mediante la operacin de colocar el puntero
del ratn y pulsar su botn izquierdo sobre ese algo que se quiere tomar. Sin dejar de
pulsar el botn izquierdo del ratn se desliza (se arrastra) el puntero del ratn hasta el
punto de la interface grfica donde lo queremos dejar. Ese punto puede ser un control o un
formulario. Una vez en el punto de destino se suelta el botn del ratn y se deja caer lo
que habamos tomado en el punto de origen. El efecto de tomar algo de un control le
denominaremos Drag. Si durante la operacin de arrastre pasamos por encima de un
control, se producir en ese control el evento DragOver Al efecto de dejar caer le
denominaremos DragDrop.
El Drag & Drop tiene un efecto visual muy didctico. Pero NO HACE otra cosa. Es decir,
no toma nada del control origen ni lo suelta al llegar a destino. Esa accin de tomar algo
en el origen o soltarlo al llegar al destino debemos realizarla mediante cdigo en los
eventos adecuados (MouseDown, DragOver , DragDrop), dando los valores adecuados
a las propiedades DragMode y DragIcon, y utilizando el mtodo Drag.
Propiedad DragMode
Es una propiedad de lectura y escritura. Devuelve o establece un valor que determina si se
usa el modo de arrastre manual o automtico en una operacin de arrastrar y soltar.
Sintaxis
NombreControlOrigen.DragMode = nmero
NombreControlOrigen.DragIcon = icono
desplazamiento se expresa mediante un rectngulo del tamao del control origen, cosa
que resulta bastante desagradable en cualquier aplicacin. Debe ponerse por lo tanto un
icono en esta propiedad.
El valor de esta propiedad puede establecerse en tiempo de diseo, eligiendo el icono en el
cuadro de Propiedades del control origen, o en tiempo de ejecucin. En este caso, la
referencia a un icono vlido puede darse igualando el valor de esta propiedad a un icono ya
existente en la aplicacin (NCO.DragIcon = Form1.Icon pondra como icono el del
formulario Form1, NCO.DragIcon = Text1.DragIcon pondra el mismo icono de Text1 para
esta propiedad), o cargndolo mediante la funcin LoadPicture :
(NCO.DragIcon = LoadPicture (C :\Iconos\Icono1.ICO)
El archivo que se cargue debe tener la extensin .ICO y formato de icono.
Para Nota. Cuando quiera colocar un icono animado en la propiedad DragIcon (una hoja
de papel que oscila al moverse, una hoja de papel que se destruye - ejemplos tomados de
W95-), debe usar varios iconos en secuencia. Por lo tanto debe cambiar la propiedad
DragIcon a lo largo del tiempo que dura el arrastre. Puede utilizar para ello un
temporizador (control Timer) o basarse en las coordenadas del formulario por donde se
mueve (para eso introducen en el evento DragOver del Formulario). Dado que el cambio
debe ser rpido, no es conveniente acceder al disco (mediante la funcin LoadPicture) cada
vez que tiene que cambiar la imagen del icono. Como para simular un movimiento tan
sencillo son suficientes pocas imgenes, (8 por ejemplo) puede crear otras tantas variables
tipo Picture, cargar las imgenes al comienzo de la aplicacin (con la funcin LoadPicture)
y cuando necesite el movimiento animado del icono, cargar las 8 imgenes
secuencialmente desde esas variables, para simular el movimiento
NCO.DragIcon = Variable1
NCO.DragIcon = Variable2
......
NCO.DragIcon = Variable8
Esto le ocupar mas memoria. Es el precio a pagar por la rapidez y la buena presentacin
de una aplicacin.
Mtodo Drag
Inicia, termina o cancela una operacin de arrastre de cualquier objeto excepto los
controles Line, Menu, Shape o Timer.
Sintaxis
NombreControlOrigen.Drag TipoAccin
NombreControlOrigen es el nombre del control donde se inici la operacin Drag & Drop.
TipoAccin es un valor o una constante que especifica la accin a realizar, segn se
describe a continuacin :
Constante
Valor
vbCancel
0
vbBeginDrag 1
vbEndDrag
2
Descripcin
Cancela la operacin de arrastre.
Inicia el arrastre del objeto.
Termina el arrastre y suelta el objeto.
180
El uso del mtodo Drag para controlar una operacin de arrastrar y soltar slo se requiere
cuando la propiedad DragMode del control origen tiene el valor Manual (0). Sin embargo,
Drag puede usarse con objetos cuya propiedad DragMode tenga el valor 1
(o
vbAutomatic).
En versiones anteriores de Visual Basic, Drag era un mtodo asncrono y las instrucciones
siguientes se ejecutaban incluso aunque la accin de arrastre no hubiera terminado. En
Visual Basic versin 4.0, Drag es un mtodo sncrono y las instrucciones siguientes no se
ejecutan hasta que la accin de arrastre no haya terminado.
Usando el mtodo Drag puede controlar exactamente cuando quiere que se produzca el
inicio del Drag & Drop y el final. El autor de esta Gua del Estudiante vuelve a recomendar
que ponga la propiedad DragMode = 0 (Manual). Entre otras razones por la siguiente :
Cuando tenemos la propiedad DragMode de un TextBox a 1 (automtico) ese TextBox no
podr coger el foco, (al menos de forma fcil) y si lo consigue no puede seleccionar el
texto que tiene actualmente, ya que VB no puede saber si lo que est ocurriendo es que
queremos seleccionar el texto o si deseamos iniciar la operacin D & D.
Como decamos al principio, el Drag & Drop solamente es una manifestacin visual de algo
que se est produciendo, pero ese algo deberemos programarlo. Por ejemplo, es muy
tpico llevar un dato de una casilla a otra (de un TextBox a otro p.e.) mediante una
operacin D & D.
El dato debemos llevarlo a una variable que nos permita, al final de la operacin, introducir
ese dato en el TextBox final. (No olvide declarar la variable en el lugar correspondiente
para que sea vlida en ambos controles). La accin de llevar el dato a la variable debemos
hacerla en el procedimiento mas adecuado. Puede ser por ejemplo, el procedimiento
MouseDown del control origen, ya que cualquier operacin de D & D comienza haciendo
click en el control origen. Si tiene la propiedad DragMode de ese control en Manual, en el
momento de hacer Click, ese control toma el foco y, caso de un TextBox, puede arrastrar
con el ratn para cambiar el texto, cosa que no podra hacer si pone DragMode=1.
Evento DragOver
Cuando una operacin de arrastrar y soltar est en progreso y el cursor del ratn pasa por
encima de un control o un formulario, se produce el evento DragOver de ese control o
formulario.
Dependiendo si se trata de un Formulario convencional, un Formulario MDI o un control, el
procedimiento DragOver captura distintos parmetros :
Private Sub Form_DragOver(origen As Control, x As Single, y As Single, estado As
Integer)
Private Sub MDIForm_DragOver(origen As Control, x As Single, y As Single, estado As
Integer)
Private Sub Control_DragOver([ndice As Integer,]origen As Control, x As Single, y As
Single, estado As Integer)
Donde :
origen = Control que se est arrastrando. O dicho de forma mas ortodoxa, control en el
que se inici la operacin de Drag & Drop. Dentro de este procedimiento puede hacer
referencia a sus propiedades y mtodos con este argumento. Por ejemplo, Source.Visible
= False. Caso de que el Control Origen fuese parte de un array de controles, el Index de
ese control se tiene en ndice
181
x, y
Nmero que especifica la posicin horizontal (x) y vertical (y) actual del puntero del
mouse dentro del control o formulario destino. Estas coordenadas se expresan siempre en
trminos del sistema de coordenadas del destino tal y como se establece en las
propiedades ScaleHeight, ScaleWidth, ScaleLeft y ScaleTop.
estado
Entero que nos indica el estado de transicin del control que se est
arrastrando en relacin al formulario o control destino:
0 = Entra. Este valor se produce en el instante en el que entra el cursor del ratn
a
se
En General - Declaraciones
Dim pepe as string
Dim icono1 As Picture, Icono2 As Picture, Icono3 As Picture
Dim Icono4 As Picture, Icono5 As Picture, Icono6 As Picture
El Form1.Load se cargan los valores de estas variables con seis iconos existentes en el
disco. El icono asignado al control origen (Text1) es Icono4.
Set icono1 = LoadPicture("C:\vb\icons\dragdrop\drag1pg.ico")
Set Icono2 = LoadPicture("C:\vb\icons\dragdrop\drag2pg.ico")
Set Icono3 = LoadPicture("C:\vb\icons\dragdrop\drag3pg.ico")
Set Icono4 = LoadPicture("C:\vb\icons\dragdrop\drop1pg.ico")
Set Icono5 = LoadPicture("C:\vb\icons\dragdrop\dragfldr.ico")
Set Icono6 = LoadPicture("C:\vb\icons\dragdrop\dropfldr.ico")
Text1.DragIcon = Icono4
182
algo
parecido:
OLECompleteDrag,
OLEDragDrop,
OLEDragOver,
183
utilizando la misma interfase grfica para ver el movimiento de los datos. Lo mismo
ocurre en sentido contrario. Desde una aplicacin nuestra podemos llevar texto o imgenes
a Word. A ese mecanismo se le denomina OLE Drag & Drop. Parece como si el OLE Drag &
Drop reuniera las dos ventajas de DDE y de Drag & Drop. Esa fue la idea con la que
Microsoft creo esta herramienta.
Mediante el OLE Drag & Drop ya podemos enlazar nuestras aplicaciones a las aplicaciones
compradas.
Pero piense que lo que va a conseguir con el OLE Drag & Drop ya lo tiene
objeto es un objeto tipo DataObjet. Este objeto no es necesario declararlo, ya que aparece
en todos los procedimientos donde es posible introducir o sacar datos del DataObject.
Por ejemplo, en el mtodo OLEStartDrag se pasa como parmetro un objeto DataObject
llamado Data.
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
184
objeto.GetData (formato)
Valor
1
2
3
14
8
9
15
-16639
Descripcin
Texto (archivos .txt)
Mapa de bits (Archivos .bmp)
Metaarchivo (archivos .wmf)
Metarchivo mejorado (archivos .emf)
Mapa de bits independiente del dispositivo (DIB)
Paleta de colores
Lista de archivos
Formato de texto enriquecido (archivos .rtf)
Mtodo Clear
Elimina el contenido del objeto DataObject.
Sintaxis
objeto.Clear
185
Puede ejecutar este mtodo antes de introducir nuevos datos en el DataObject para
asegurarse que ha borrado los datos existentes
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
Data.Clear
Data.SetData Text1.Text
End Sub
Este mtodo slo est disponible para los orgenes de operaciones de arrastre de
componentes. Si se invoca Clear desde un destino de la operacin de colocacin de
componentes, se producir un error.
Mtodo GetFormat
Devuelve un valor booleano que indica si un elemento del objeto DataObject coincide con
un formato especificado.
Sintaxis
objeto.GetFormat formato
Ejemplo
Puede asegurarse que el formato contenido en el DataObject es el deseado
antes de proceder a colocarlo en un control en la operacin de Drop:
Private Sub RTB1_OLEDragDrop(Data As RichTextLib.DataObject, Effect As Long, Button As
Integer, Shift As Integer, x As Single, y As Single)
If Data.GetFormat(vbCFText) = True Then
RTB1.SelText = Data.GetData(vbCFText)
End If
End Sub
Propiedades del DataObject
Deberamos decir mejor, propiedad, ya que solamente tiene una:
Propiedad Files
Devuelve una coleccin DataObjectFiles, que a su vez contiene una lista con todos los
nombres de archivo utilizados por un objeto DataObject (por ejemplo los nombres de los
archivos que un usuario arrastra hacia o desde el Explorador de archivos de Windows).
Sintaxis
NombredelObjetoDataObject.Files(ndice)
La coleccin Files slo se puebla con nombres de archivo cuando el objeto DataObject
contiene datos de tipo vbCFFiles. La coleccin Files puede rellenarse para permitir a las
aplicaciones de Visual Basic actuar como origen de operaciones de arrastre de una lista de
archivos.
Coleccin DataObjectFiles
Es la coleccin de cadenas con los nombres de ficheros de la propiedad Files del objeto
DataObject.
Sintaxis
NombredelObjetoDataObject.DataObjectFiles
186
Volvamos sobre las propiedades y mtodos de los controles involucrados en un OLE Drag &
Drop
Propiedad OleDragMode
Esta propiedad establece la forma en la que comienza a realizarse la operacin de Drag. Si
est en Automtico basta con seleccionar el texto o la imagen a pasar a otra aplicacin y
una vez seleccionado, al volver a marcarlo con el ratn, se inicia el Drag. En ese instante
se ejecuta el procedimiento OLEStartDrag donde deberemos colocar el cdigo para que VB
haga lo que nosotros queramos. Ya se ver al estudiar este procedimiento.
A diferencia del Drag & Drop estudiado anteriormente, donde recomendbamos poner la
propiedad similar a manual, en este caso es mucho ms prctico ponerlo en automtico y
adems no es molesto, ya que el Drag no se inicia si no se ha seleccionado previamente
parte del texto o la imagen a enviar a la otra aplicacin.
La propiedad DragMode de ese control debe estar ahora a Manual, ya que si est en
automtico se genera antes el Drag & Drop ordinario y no se producir el OLE Drag &
Drop.
Si se pone esta propiedad a Manual es necesario iniciar el drag mediante el mtodo
OLEDrag, que ejecuta el procedimiento OLEStartDrag, y colocar en este el cdigo
correspondiente. No es prctico, pero cada aplicacin y cada programador es una caso
distinto.
Propiedad OLEDropMode
187
Esta propiedad va a determinar la forma en la que el componente destino toma los datos
transportados medainte OLE Drag & Drop. Acepta tres valores:
0
vbOLEDropNone
El componente no acepta operaciones de Drop. Cuando pasa
el
cursor del ratn sobre l durante una operacin de OLE
Drag &
Drop, muestra el icono de No Colocar
1
vbOLEDropManual Manual. El componente de destino desencadena los eventos
OLE de colocar, (Evento OLEDragDrop) lo que permite
al
programador controlar la operacin en el cdigo.
2
vbOLEDropAutomatic
Automtico. El componente de destino acepta
automticamente
las operaciones OLE de colocar si el
objeto DataObject
contiene datos en un formato que
reconoce. En este caso, en el
destino no se producen los
eventos del mouse ni eventos OLE
de arrastrar y colocar.
Es normal poner esta propiedad a manual, para poder controlar lo que ocurre con la
informacin tanto en destino como en origen. Estando en Automtico, la informacin en el
origen se mueve al destino, es decir, desaparece del origen al tiempo que se pone en el
destino. Esto puede que no sea lo deseado por el programador. Si pone esta propiedad en
Manual, puede controlar lo que hace la informacin tanto en destino como en origen.
Eventos relacionados con el OLE Drag & Drop.
Una cosa que podemos advertir en todos los eventos relacionados con el OLE Drag & Drop
es la ausencia del parmetro Source que tenamos en los eventos DragDrop y DragOver
del Drag&Drop convencional. Parece normal, ya que no tenemos porque saber el nombre
del control origen si ste es de una aplicacin externa (Word por ejemplo). Ese parmetro
Source lo emplebamos para saber si un control poda recibir o no la informacin,
dependiendo del origen de la misma. En el OLE Drag & Drop solamente podemos basarnos
para eso en el tipo de informacin que transporta el DataObject, tipo que podemos
determinar mediante el mtodo GetFormat.
Evento OLEStartDrag
Se produce cuando se ejecuta el mtodo OLEDrag de un componente o cuando un
componente inicia una operacin OLE de arrastrar y colocar, y su propiedad
OLEDragMode est establecida a Automatic.
Sintaxis
Private Sub objeto_OLEStartDrag(datos As DataObject, efectosPermitidos As Long)
Vemos que pasa como parmetro el objeto datos que es del tipo DataObject. Por lo tanto
podemos realizar sobre este objeto el mtodo SetData visto anteriormente, para introducir
en l los datos deseados. Veamos un ejemplo:
Private Sub Text1_OLEStartDrag(Data As DataObject, AllowedEffects As Long)
Data.Clear
Data.SetData Text1.Text
AllowedEffects = 1
End Sub
188
Evento OLEDragOver
Se produce cuando el puntero del ratn pasa por encima de un control durante una
operacin de OLE Drag & Drop.
Sintaxis
Private Sub nombredelcontrol_OLEDragOver(datos As DataObject, efecto As Long,
botn As Integer, maysculas As Integer, x As Single, y As Single, estado As
Integer)
Este evento solamente ocurre cuando la propiedad OLEDropMode est en manual
nombredelcontrol
se
Nombre del control sobre el que pasa el puntero del ratn, en el que
produce el evento OLEDragOver.
datos
Objeto tipo DataObject que transporta los datos
efecto
Este parmetro es similar al AllowedEffects del evento OLEStartDrag
y
tiene los mismos valores.
boton
Indica el botn que se est pulsando: 1 = izdo. 2 = Dcho. 4 =
Central.
Si est pulsado ms de uno, ser la suma de los
valores de cada uno.
mayusculas
Indica el estado de pulsacin de las teclas MAYUSCULAS, CTRL y ALT
1 = MAY, 2 = CTRL, 4 = ALT. Si hay ms de una tecla pulsada, ser
la suma de los valores de cada una.
x, y
Posicin del puntero del ratn dentro del control destino, medidas en
las
unidades de medida del formulario.
estado
Valor que indica uno de los tres estados siguientes:
0
1
2
vbEnter
vbLeave
vbOver
Evento OLEDragDrop
Se produce cuando se termina la operacin de OLEDrag&Drop sobre el control. Para que se
pueda terminar la operacin de OLEDrag&Drop el componente destino tienen que
permitirlo.
Nota Este evento slo se produce cuando OLEDropMode est establecido a 1 (Manual).
Sintaxis
Private Sub objeto_OLEDragDrop(datos As DataObject, efecto As Long, botn As
Integer, maysculas As Integer, x As Single, y As Single)
189
En este evento podemos escribir el cdigo necesario para que el dato se coloque de la
forma deseada (por ejemplo, puede analizar el tipo de dato y proceder de acuerdo al
contenido del DataObject).
Los parmetros pasados por este evento son iguales al del evento anterior.
Evento OLECompleteDrag
Se produce en el origen cuando se ha completado la operacin de arrastre (cuando se
levanta el botn del ratn), e informa al componente de origen de que se ha completado o
cancelado dicha operacin.
Sintaxis
En este captulo hemos visto tres formas de transvasar informacin, bien de una aplicacin
a otra, bien dentro de la misma aplicacin.
Es posible que le haya llamado la atencin estas herramientas. Y posiblemente piense en
un enorme nmero de posibilidades de aplicacin. La realidad le va a demostrar que se
aplican muy pocas veces. Exceptuando el OLEDrag&Drop, que le permite exportar texto
190
a / desde Word, y eso le vienen muy bien al usuario porque le ahorra tiempo de teclear,
los dems no se usan con la profusin que se debera, vistas a priori las ventajas que
tienen.
Como siempre en programacin, lo bueno es lo que acepta y le gusta al usuario. Y el
realizar un arrastre con el ratn es una operacin que no todos terminan con xito. Quizs
sea esa la razn de no usarlo tan profusamente.
EL EDITOR DE MENUS
El Men o Barra de Men es la segunda lnea de cualquier ventana Windows, donde pueden
verse distintos nombres. La Barra de Men es un componente de un Formulario.
La Barra de Men puede tener tantas palabras como se desee, y sobre cada palabra, puede
desplegarse un Men desplegable con mas palabras. Sobre cada una de estas puede a su
vez desplegarse otro conjunto de palabras, etc. con lo que se puede conseguir una
cantidad de palabras tan grande como necesitemos.
Para cada palabra se produce el evento click. Cada palabra de la Barra de Men lleva anexo
un nico procedimiento, que se ejecutar al hacer click sobre la palabra. Pero en las
palabras que sirven para desplegar un men no tiene sentido que se ponga ningn cdigo
en su procedimiento, ya que estn ah justamente para desplegar otras palabras. Ser en
las palabras finales donde se colocar el cdigo correspondiente.
En las figuras anteriores pueden verse tres formas distintas de ver el mismo Men. En la
primera figura el Men est sin desplegar. En la segunda figura puede verse un rbol de
Men largo, desplegado en su totalidad. En la tercera puede verse el Men desplegable de
la palabra Archivo de la Barra de Men. Puede apreciarse en este men desplegable una
lnea que separa las palabras Guardar Como y SALIR. Esta lnea separadora es muy
prctica para separar dos temas distintos dentro de un Men desplegable. Tan distintos
191
como las operaciones de Abrir y Guardar respecto a la ltima orden del men desplegable
que es SALIR de la aplicacin.
Para crear un men debe usarse el Editor de Men, que se encuentra en la Barra de Men
de VB en Herramientas | Editor de mens. Le aparecer el siguiente cuadro. (En
principio vaco)
Cada palabra del men tiene su Caption (La palabra que aparece en el men), su Name
(Nombre), y puede tener Index (si existen varias palabras con el mismo Name). Para
introducir estas propiedades basta con teclearlas directamente en cada una de las casillas
al efecto del cuadro del editor de mens. Para colocar el cursor de escritura en una u otra
casilla, puede hacerse bien con el cursor del ratn, bien con el tabulador. Para pasar a la
siguiente lnea de edicin (crear una nueva palabra), basta con pulsar ENTER.
Existen otras propiedades aparte del Caption y Name que se introducen directamente en
las casillas al efecto.
HelpContextID
Igual que esta propiedad en el resto de los controles, permite
introducir un nmero de contexto para la ayuda de Windows.
Enabled.
Habilitado. Si se quita la marca de esa casilla, esa palabra aparecer por
defecto deshabilitada. Esta propiedad puede leerse y cambiarse en tiempo de ejecucin,
por lo que esta propiedad puede usarse para deshabilitar ciertas funciones de la aplicacin,
dependiendo de la evolucin de la propia aplicacin. La presentacin en el men cuando
est deshabilitada es con color plido.
Visible.
Como su nombre indica, que sea visible o no lo sea. Puede cambiarse
en tiempo de ejecucin.
WindowList Indica si esa palabra es la que va a mostrar todos los formularios abiertos en
una aplicacin de documentos mltiples (MDI). Al hacer click sobre esta palabra, se
desplegar un submen con todos los Caption de los Formularios hijo abiertos en ese
192
momento. Solamente puede existir una palabra en un men con esta propiedad activada.
Esta propiedad no puede variarse en tiempo de ejecucin.
Para cambiar una de estas propiedades en tiempo de ejecucin, basta con citar por su
nombre a esa palabra (por su Name, no por su Caption), e igualar a True o False su valor :
nmuDocumentos.Visible = False
El nombre usado para nombrar a una de las palabras del men puede ser cualquiera. Sin
embargo es prudente usar un nombre que nos pueda identificar, por una parte, que ese
nombre corresponde a una de las palabras del men, y por otra, a que palabra se refiere.
La solucin puede ser cualquiera. El autor de estos apuntes propone poner las letras mnu
(o menu - recomiendo no usar acentos e los Names de VB), seguido del Caption de esa
palabra.
Otras propiedades
Shortcut
Atajo. Esta propiedad admite varias combinaciones de teclas para acceder al
procedimiento click de esa palabra sin necesidad de usar el ratn. Las combinaciones de
teclas posibles se muestran haciendo click en la flecha hacia abajo que tiene esa casilla. Se
desplegar una lista con todas ellas. Para elegir una de estas combinaciones, basta con
hacer click sobre la lnea que la contiene. Esta combinacin de teclas aparecer en el
men, al lado de la palabra (Vase figura siguiente, SALIR Ctrl + X)
NegotiatePosition. Establece un valor que determina si los controles Menu de nivel
superior se muestran en la barra de mens mientras un objeto vinculado o incrustado de
un formulario est activo y mostrando sus mens. No est disponible en tiempo de
ejecucin. Puede tener los valores 0 (Predeterminado) Ninguno. El men no se muestra en
la barra de mens cuando el objeto est activo.
1 Izquierda. El men se muestra a la izquierda de la barra de mens cuando el objeto est
activo.
2 Medio. El men se muestra en medio de la barra de mens cuando el objeto est activo.
3 Derecha. El men se muestra a la derecha de la barra de mens cuando el objeto est
activo.
El men editado con los datos de la figura anterior tendr esta forma en tiempo de
ejecucin :
Observe que tiene cuatro palabras en la lnea superior, y que colgando de la primera
aparece un men desplegable. Para conseguir un men desplegable fjese en la figura del
Editor, en la parte de abajo donde estn todos los Caption de las palabras del men.
Observar que algunas de ellas (&Edicion, Documentos, Ayuda - Hay otra que no se v,
&Archivo) estn completamente a la izquierda de la ventana, y las dems estn separadas
193
de la parte izquierda por unos guiones. Las palabras que estn completamente a la
izquierda son las que figurarn en la barra de men de forma permanente. Las que estn
separadas (tabuladas) corresponden a las que aparecern en los mens desplegables.
Como es lgico, un men desplegable debe colgar de una palabra de las de la barra de
men. La palabra de la que cuelga el submen es la palabra sin tabular inmediatamente
anterior.
Para tabular las palabras, hay que hacer click en el botn en forma de flecha a la derecha
que est sobre la ventana de edicin:
Situandonos sobre una de las lneas ya editadas, y haciendo click sobre el botn con flecha
hacia la izquierda, quitamos la tabulacin.
Los botones con flecha hacia arriba o abajo nos permiten variar el orden de las lneas ya
editadas.
Podemos hacer varios niveles de submens a base de introducir varias tabulaciones. Al
comienzo de este captulo puede ver un ejemplo de ello.
Quedan un par de cosas. Una de ellas es el carcter & que est delante de los Caption de
Archivo y Edicin. Este carcter nos permite acceder al procedimiento click de esa palabra
pulsando la tecla Alt + la tecla correspondiente a la letra que est detrs del carcter &.
Justamente la letra que est subrayada en la palabra del men.
El carcter & no tiene porqu ir precisamente al comienzo de la palabra. Puede ir en el
medio de la palabra. De esta forma se subrayar una letra intermedia.
Otra cosa. Puede verse en el men desplegado de la figura anterior una lnea entre
Guardar Como y SALIR. Esta lnea, que solamente tiene efectos estticos, se logra
introduciendo como Caption un guin ( - ). El editor de mens solamente le permite el
guin en una palabra de men desplegable (Tabulada). No se olvide de poner el Name
incluso para este guin.
NOTA MUY IMPORTANTE
Siempre se recomienda poner la orden de SALIR en la primera palabra de la barra de
Men. Bien que esa primera palabra sea Salir o que est en el men desplegable de la
primera palabra de la Barra de Men, en este ltimo caso, separada mediante una lnea
separadora. (Vea The Windows Interface Guidelines for Software Design, pg.124)
POPUP MENS
Un PopUpMen o Men Emergente es un men que despliega en cualquier punto de un
Formulario (MDI o normal) con varias opciones. Es normal en los procesadores de texto
que se obtenga un men emergente pulsando el botn derecho del ratn, donde aparecen
las tres palabras mgicas de Copiar, Cortar y Pegar.
Para crear un men emergente o PopUpMenu es necesario tener en el men de ese
formulario una palabra de la que se despliegue un submen con las mismas palabras que
queremos que aparezcan en el PopUpMenu.
194
Por ejemplo, en el men que hemos editado como ejemplo anteriormente, exista una
palabra Edicin, de la que se desplegaba el Submen Copiar, Cortar y Pegar. Si analizamos
la edicin realizada, las palabras tenan el siguiente Caption y Name :
Caption
Name
Tabulada
Edicin
Copiar
Cortar
Pegar
mnuEdicion
mnuCopiar
mnuCortar
mnuPegar
NO
SI
SI
SI
Recuerde que las palabras del men que estaban tabuladas son las que aparecan en el
men desplegable. Esas mismas sern las que aparezcan en el PopUpMenu.
Para ello utilizaremos el Mtodo PopupMenu. Este mtodo pesenta un men emergente
en un objeto MDIForm o Form en la posicin actual del mouse o en las coordenadas
especificadas.
La sintaxis de este mtodo es la siguiente :
NombreFormulario.PopupMenu nombremen, indics, x, y, negrita
Donde NombreFormulario
PopUpMenu. Puede omitirse.
es
el
nombre
del
formulario
donde
presentamos
el
Valor
vbPopupMenuLeftAlign 0
Descripcin
vbPopupMenuCenterAlign
vbPopupMenuRightAlign 8
Constante (comportamiento)
Valor
Descripcin
vbPopupMenuLeftButton
vbPopupMenuRightButton
emergente
se
Para combinar la los valores de indics de posicin y comportamiento basta con sumar los
valores.
195
Nota
El parmetro indics no tiene efecto en las aplicaciones que se ejecuten bajo
Microsoft Windows versin 3.0 o anteriores.
X, y Parmetro(s) opcionales que especifican las coordenadas x e y donde va a aparecer el
men emergente. Si no se especifican, aparecer donde est el puntero del mouse. Las
unidades de medida de las coordenadas x e y se definen mediante la propiedad ScaleMode.
negrita. Parmetro opcional que especifica el nombre de un control men del men
emergente para presentar su ttulo en negrita. Si se omite, ningn control del men
aparece en negrita.
Nota. Este argumento funciona solamente en las aplicaciones que se ejecuten bajo
Windows 95. La aplicacin ignora este argumento cuando se ejecute bajo versiones de 16
bits de Windows o Windows NT 3.51 y anteriores.
La forma mas habitual de presentar un men emergente es mediante el botn derecho del
ratn. Concretamente en el editor Word que estoy utilizando para escribir estos apuntes
ocurre cuando se levanta el botn derecho del ratn. Es decir, en el evento MouseUp, con
la condicin de que Button=2.
Imaginemos que queremos presentar en un men
emergente las palabras Cortar, Copiar y Pegar del ejemplo anterior, que colgaban en el
men de la palabra Edicin. (Vea mas atrs). Queremos tambin que la palabra Copiar
salga resaltada en negrita.
Iramos al procedimiento MouseUp del Formulario y
escribiramos :
Private Sub Form_MouseUp(Button As Integer, Shift As Integer, X As Single, Y As Single)
If Button = 2 Then
PopupMenu mnuEdicion, , , , mnuCopiar
End If
End Sub
Observe que se ha omitido el nombre del Formulario (Opcional), el parmetro indics, y las
coordenadas x e y (el men emergente aparecer donde est situado el cursor del ratn).
Observe tambin que las comas separadoras de los parmetros hay que colocarlas.
Cuando se presenta un men emergente, el cdigo que sigue a la llamada al mtodo
PopupMenu no se ejecuta hasta que el usuario elige un comando del men (en cuyo caso
se ejecuta antes el cdigo del procedimiento de evento Click) o cancela el men. Adems,
slo puede presentarse un men emergente al mismo tiempo; por lo tanto, las llamadas a
este mtodo se ignoran si el men emergente est presentado actualmente o si un men
desplegable est abierto.
Si queremos presentar un men emergente es necesario tener ese men en el men del
formulario. El problema puede ser que no queramos que est en la barra de men. No es
problema. Ponga la propiedad Visible del elemento del men desde el que se va a
desplegar el submen a False. No se ver ya en la barra de men ni esa palabra ni el
submen que de ella se despliega. Eso s, las palabras del submen deben tener la
propiedad Visible = True. Si les pone esa propiedad a False, no se vern en el men
emergente. Puede aprovechar esta circunstancia para hacer mens emergentes con mas o
menos elementos, segn las necesidades de su aplicacin. Tambin puede poner la
propiedad Enabled a False si as lo precisa. No puede activar la propiedad WindowList en
un elemento que forma parte de un men emergente.
Ejercicio propuesto: un editor de texto, con un men que diga Copiar | Cortar | Pegar
donde pueda utilizar el portapapeles. Ahora es posible que le cueste un poco de trabajo.
196
Pero este ejercicio lo va a repetir con casi todas las aplicaciones que realice en su vida
profesional.
Visual Basic - Gua del Estudiante Cap. 6
FICHEROS EN VISUAL BASIC
Existen tres tipos de ficheros donde podremos almacenar y leer datos:
- Secuenciales
- Aleatorios (Random)
- Binarios
Cada uno de ellos tiene sus aplicaciones y particularidades.
FICHEROS SECUENCIALES
Este tipo de ficheros nos permite guardar informacin de cualquier longitud. En este tipo
de ficheros, la informacin se guarda colocando un carcter tras otro. La forma de leerlos
es, igualmente, carcter tras carcter. (Byte tras byte). Son los mas sencillos de manejar,
y los utilizados para guardar texto en ASCII. Permiten guardar datos en un fichero con un
determinado nombre, "machacando" la informacin de otro posible fichero que ya
estuviese en el disco con el mismo nombre, o aadir la informacin nueva a continuacin
de la ya existente.
Para abrir un fichero secuencial para guardar informacin, debemos ejecutar la siguiente
instruccin:
Open
Write Nos
Print
Introduce la informacin de forma secuencial, byte tras byte tal como se
coment. Sirve para guardar textos. Por ejemplo si deseamos guardar en ese
fichero el contenido de una caja de texto llamada Text1, basta con ejecutar
la siguiente instruccin:
197
un
leeremos el fichero de una nica vez. Este procedimiento puede ahorrarle cierto tiempo a
la hora de la lectura. (Por lo dicho anteriormente, este procedimiento de leer todo el
fichero de un golpe solamente se podr hacer si la longitud del fichero (LOF(1)) es inferior
a 65.534 bytes. Tenga esto presente cuando vaya a leer un fichero que no sabe que
longitud tiene. Para curarse en salud, le recomiendo que lea los ficheros secuenciales
carcter a carcter. Input(1,#X) pues tarda poco mas que leyndolo de un golpe. Claro
que para leer un fichero carcter a carcter debe poner un bucle en el que se van leyendo
los caracteres hasta que llaga al final del fichero..
La forma de hacer este bucle es la siguiente:
Dim A As String
del fichero.
Dim MiVariable as String
todo el
Do Until EOF(1)
El programa ejecutar este bucle hasta que se cumpla que
EOF(1) sea
True.
EOF(NumerodeCanal) es una propiedad de los
ficheros cuando
estn abiertos, que es True cuando la posicin
del puntero de lectura
apunta al carcter Fin De Fichero (End Of
File) que es el carcter siguiente
al ltimo carcter de texto de ese
fichero.
198
Close #1
Cierra el fichero
Slo se utilizar la instruccin Input con archivos abiertos en modo Input o Binary. (Los
Binary Se vern a continuacin) A diferencia de la instruccin Input #, (la veremos a
continuacin, pues es la instruccin que deber utilizar para leer archivos escritos con la
instruccin Write ), Input devuelve todos los caracteres que lee, incluyendo puntos y
coma, retornos de carro, avances de lnea, comillas y espacios iniciales.
Existe una instruccin, Input$ , que asume que el dato a leer es un String. (Cadena de
caracteres). Puede ahorrar un poco de memoria usando esta instruccin en lugar de
Input.
Nota Se proporciona otra funcin (InputB) para su uso con datos de byte incluidos en
archivos de texto. En lugar de especificar el nmero de caracteres a devolver, nmero
especifica el nmero de bytes.
INSTRUCCION LINE INPUT
La instruccin Line Input se utiliza para extraer una lnea completa. Tiene la
siguiente sintaxis:
Line Input # Nmero de canal, VariableString
Mediante esta instruccin se extrae una lnea completa (los caracteres delimitados entre
dos retornos de carro), y se le asigna esa cadena a VariableString
Una lnea es un trozo de texto delimitado por los caracteres 13 (Retorno de carro) y 10
(Avance de lnea) La instruccin Line Input # lee un carcter cada vez en un archivo
hasta que encuentra un retorno de carro (Chr(13)) o una secuencia retorno de carro avance de lnea (Chr(13) + Chr(10)). Las secuencias de retorno de carro - avance de lnea
no se tienen en cuenta y no se aaden a la cadena de caracteres extrada mediante esta
instruccin. Cuando lea un archivo mediante Line Input # y lo quiere presentar en un
TextBox o en el Printer, deber introducirlos para evitar que le salga todo el texto en una
nica lnea.
Con lo que se ha explicado, ya puede realizar un pequeo edito de textos. Este sencillo
editor tiene un TextBox llamado TBTexto, donde podemos escribir el texto que queramos
(con la propiedad MultiLine = True y ScrollBars = Vertical), tres botones llamados BAbrir
(1), (2 a y b) y (3), para abrir el fichero y poner su contenido en TBTexto, y dos
BGuardar para guardar, uno abriendo el fichero For Append y el otro abrindolo For
Output. En este ltimo, al guardar el texto borramos el contenido que del fichero, si ya
existiera. En el primero, lo anexamos al final del mismo . Para conocer el nombre del
199
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
PRECIO = LIBRETBPREC.Text
EXISTENCIAS = LIBRETBEX.Text
Donde LIBRETBTITULO, LIBRETBAUTOR, Etc. son los nombres de los TextBox
Ha ledo los datos de los TextBox. Ya estn el las variables TITULO, AUTOR, Etc.
Ahora los metemos en el fichero con la instruccin Write. El nombre del fichero ser el
que hayamos puesto en el TextBox LIBRETBFICHERO, y lo guardar en el directorio
C :\cursoVB
Open TBNombreFichero.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, PRECIO, EXISTENCIAS
Close #1
End Sub
Si introduce los datos del ejemplo anterior, se crear un fichero que tiene esta apariencia:
Luis Surez, VisualBasic - Gua del estudiante,Editorial XX,3200,51
Si realizamos otra introduccin de datos, con la segunda lnea del ejemplo anterior, los
datos existentes en ese fichero no se borrarn, dado que lo hemos abierto con Append.
Quedar de la siguiente forma:
Luis Surez, VisualBasic - Gua del estudiante,Editorial XX,3200,51
Miguel de Cervantes,El Qijote,Editorial YY,5000,27
Que pasara si leemos este fichero con la instruccin Input o Line Input # vista
anteriormente ? Pues simplemente que lo leeramos tal como est, con sus comas y
comillas dobles. No sera la forma mas adecuada, ya que lo que queremos es obtener
sucesivos datos de autores, ttulos, editoriales, precios y existencias.
Para sacar estos datos debemos leerlos con la instruccin Input #. Esta instruccin saca
los datos que hemos metido, es decir, elimina las comillas y la coma que servan de
separadores.
En nuestro ejemplo, podramos hacerlo de esta forma, aprovechando los mismos TextBox:
Private Sub Command2_Click()
' Limpiamos los TextBox
LIBRETBTITULO.Text = "" : LIBRETBAUTOR.Text = "" : LIBRETBEDITORIAL.Text = ""
LIBRETBPREC.Text = "" : LIBRETBEX.Text = ""
'Abrimos el fichero
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
' Introducimos una parada para poder leer datos
DETENERSE = True
Input #1, TIT, AUT, NED, PRE, EXS
LIBRETBTITULO.Text = TIT
LIBRETBAUTOR.Text = AUT
LIBRETBEDITORIAL.Text = NED
LIBRETBPREC.Text = PRE
202
LIBRETBEX.Text = EXS
' Refrescamos los TextBox
Refresh
' Esto produce una pequea parada
Do While DETENERSE = True
A=A+1
If A = 100000 Then DETENERSE = False: A = 0
Loop
' termin la parada y vuelve a leer datos
Loop
Close #1
End Sub
Observe que los nombre de las variables en el proceso de lectura tienen distintos nombres
a los utilizados durante la escritura. Como en el fichero no se guarda ninguna referencia al
respecto, lo nico que importa es que el nmero de variables para la lectura sea igual al
nmero de variables que se utiliz para la escritura, y que el orden de las variables sea
correcto. Si por ejemplo, el nmero de variables usadas en la introduccin de datos fuese
distinto al nmero de variables usado en la lectura, Visual Basic nos dara un error.
Observe tambin que se ha introducido un temporizador. Sirve para ver los sucesivos
ttulos que tenemos en nuestra base de datos tan sui generis. Se ha pretendido presentar
unos datos de esta pequea base de datos sin complicarnos mucho la vida. Mas adelante
veremos como presentarlos de una forma correcta. Este tipo de ficheros no es el mas
adecuado para construir bases de datos, es complicado manejar ficheros de mas de unas
pocas lneas, por lo que para tener muchos datos, este tipo de ficheros no es
recomendable. No es aconsejable ni para muchos datos ni para pocos datos. Pero es
obligacin del autor explicarlo y de advertirlo.
En esta pequea aplicacin mostrbamos las informaciones sucesivamente segn las
bamos leyendo del fichero. Interrumpamos momentneamente la lectura para presentar
cada informacin durante un instante, ya que como tenemos cinco datos distintos en cada
registro y cinco TextBox para presentarlos, deberemos presentar una informacin tras otra.
Esto no parece en principio una solucin prctica para una base de datos, donde lo que
interesa es disponer de todos los datos para usarlos cuando sea necesario. Esto nos lleva a
crear una matriz para albergar todos los datos de la base, ya que los ficheros secuenciales
se leen y se les tiene que extraer toda la informacin de un golpe, ya que no permiten ir a
leer hacia atrs. Por lo tanto, si deseamos disponer de todos los datos, deberemos
guardarlos en la memoria, en una matriz. Imagnese que estamos tratando datos de varios
miles de libros en el ejemplo anterior. Si la informacin de cada campo es medianamente
extensa, no tendramos memoria RAM suficiente en el ordenador para albergarlos. Esto nos
lleva a pensar en otro tipo de archivo que veremos a continuacin, los Random
(aleatorios), que permiten leer solamente los registros que nos interesan.
Pero volvamos a nuestra aplicacin de librera, donde hemos hecho una variacin, los
campos PRECIO y EXISTENCIAS los vamos a tratar ahora como nmeros (Integer).
Tambin se ha introducido otro campo tipo texto, para introducir la edicin. El fichero
creado tras introducir varios libros qued de la siguiente forma :
"EL RODABALLO","GUNTER GRASS","PLANETA",1995,2000,12
" VisualBasic - Gua del Estudiante ","LUIS SUAREZ","CEU",PRIMERA,1000,21
"EL NOMBRE DE LA ROSA","UMBERTO ECO","AGUILAR",28,1000,21
"ENCICLOPEDIA DEL VB","CEBALLOS","RAMA",CUARTA,1200,23
"LA GRANJA ANIMAL","ORWELL","DESTINO",45,12000,78
203
El programa necesita que le introduzcamos el nombre del fichero que alberga la base de
datos. Por sencillez no se ha usado ningn CommonDialog y se introduce directamente el
nombre de este fichero en un TextBox llamado TBNombreFichero
El fichero anterior podemos leerlo tal y como indicbamos antes :
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
Input #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Donde las variables TITULO, AUTOR, EDITORIAL y EDICION sern del tipo String y PRECIO
y EXISTENCIAS sern de tipo numrico. Podemos saberlo, ya que en una lnea cualquiera
del fichero anterior :
" VisualBasic - Gua del Estudiante ","LUIS SUAREZ","CEU",PRIMERA,1000,21
los cuatro primeros parmetros van entre comillas dobles, ya que son datos tipo texto, y
los dos ltimos van sin comillas, como corresponde a datos numricos.
204
Pero existe otra forma mejor (al menos un poco mas complicada) para leer estos datos, y
evitar el problema que tenamos antes de tener que hacer un temporizador para poder ver,
aunque solo sea un momento, los datos. Podemos meter los datos a una matriz que tenga
tantas columnas como datos (campos) (en el ejemplo 6, cuatro String y dos numricos), y
tantas filas como apuntes (registros) tengamos.
Para ello, antes de nada debemos definir un tipo de variable, mediante la instruccin Type.
Parece que no nos basta con los tipos de variable que trae VB (Long, String, Integer ...) y
es cierto. La variable que necesitamos no es de ningn tipo de esos. Est compuesta por
varias secciones, y cada una de ellas puede ser de un tipo distinto. Este tipo de
definiciones debe hacerse en un mdulo (Vase instruccin Type en la ayuda de VB), por
lo que se ha creado un mdulo llamado LIBREMD2.BAS, con el siguiente cdigo :
Type REGISTROLIBRO
AUTOR As String
TITULO As String
EDITORIAL As String
EDICION As String
PRECIO As Integer
EXISTENCIAS As Integer
End Type
Esto es lo que se llama DEFINIR una variable. Es como hacerse un traje a medida. Y dese
cuenta de que es un tipo de variable (REGISTROLIBRO) formado por varias partes (AUTOR,
TITULO, Etc.) Observe que DEFINIR una variable NO es lo mismo que DECLARAR
En el apartado de Declaraciones del General del formulario declaramos las variables, entre
ellas una variable, REGISTROLIBROS, de la cual decimos que va a ser una matriz mediante
los parntesis que la acompaan, y adems declaramos que va a se similar a
REGISTROLIBRO ya definida en el mdulo.
Dim NR As Integer
Dim REGISTROLIBROS() As REGISTROLIBRO
Dim NRP As Integer
Observe que al usar parntesis al declarar la variable REGISTROLIBROS le estamos
diciendo a VB que esa variable ser un Array, y adems que es una variable del tipo
REGISTROLIBRO, tipo de variable que ya conoce, puesto que se la hemos definido en un
mdulo.
En el ejemplo preparado podemos escribir y leer datos. Veamos de nuevo como se escriben
El cdigo del procedimiento click del botn BIntroducir1 es :
Private Sub BIntroducir1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
EDICION = LIBRETBEDICION.Text
PRECIO = Val(LIBRETBPREC.Text)
EXISTENCIAS = Val(LIBRETBEX.Text)
autor
editorial
edicin
precio
existencias
(Observe que para introducir el precio y las existencias se transform el contenido del
TextBox a un valor numrico mediante la instruccin Val.)
Open "C:\cursoVB\" + LIBRETBFICHERO.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Close #1
205
End Sub
Tras reiteradas entradas, el fichero de la BD qued como se vio anteriormente.
Al leer los datos, lo primero es que no conocemos el nmero de registros existentes. Como
cada registro va en una lnea del fichero, si contamos el nmero de retornos de carro
(Chr(13)) obtendremos el nmero de registros. Esta operacin es la primera que se realiza
en el procedimiento click del botn LEER :
Private Sub Command2_Click()
LIBRETBTITULO.Text = ""
Pone todos los TextBox en blanco
LIBRETBAUTOR.Text = ""
LIBRETBEDITORIAL.Text = ""
LIBRETBEDICION.Text = ""
LIBRETBPREC.Text = ""
LIBRETBEX.Text = ""
NR = 0
NR=nmero de registros
Abre el fichero, lo lee entero y cuenta el nmero de retornos de carro. Existirn tantos
apuntes (registros) como retornos de carro existan, ya que cada registro ocupa una lnea.
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
A = Input(1, #1)
If A = Chr(13) Then NR = NR + 1
Loop
Close #1
Presenta en LNumFich el nmero de registros
LNumFich.Caption = Str(NR) + " Registros)"
'Redimensionamos la matriz de REGISTROLIBROS a NR elementos..
ReDim REGISTROLIBROS(1 To NR)
Volvemos a abrir el fichero
Open TBNombreFichero.Text For Input As #1
Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando a los
elementos que componen la matriz.
For I = 1 To NR
Input #1, REGISTROLIBROS(I).TITULO
Input #1, REGISTROLIBROS(I).AUTOR
Input #1, REGISTROLIBROS(I).EDITORIAL
Input #1, REGISTROLIBROS(I).EDICION
Input #1, REGISTROLIBROS(I).PRECIO
Input #1, REGISTROLIBROS(I).EXISTENCIAS
Next I
Close #1
NOTA.- Estas lneas podramos heberlas puesto en una lnea nica :
Input#1,REGISTROLIBROS(I).TITULO,REGISTROLIBROS(I).AUTOR,_
REGISTROLIBROS(I).EDITORIAL,REGISTROLIBROS(I).EDICION,_
REGISTROLIBROS(I).PRECIO, REGISTROLIBROS(I).EXISTENCIAS
206
207
No solamente hemos visto una forma de crear una base de datos, sino que hemos visto
como movernos a lo largo de los registros. Ver esto con mucho mas detalle cuando demos
bases de datos. Este tipo de bases de datos son la Tipo Texto que ver mas adelante.
Propiedades de los ficheros Secuenciales:
EOF
Indica el fin del fichero (End Of File). EOF ser False hasta que encuentre el final
del fichero secuencial. Habr observado instrucciones tales como:
Do until EOF(1) (Hazlo hasta que encuentres el EOF del canal 1)
Do While Not EOF(1)
(Hazlo mientras EOF del canal 1 sea False)
Estas expresiones se usan en un bucle, para ir extrayendo con la instruccin Input
o Line Input los caracteres de un fichero hasta que se encuentre la marca de final
de fichero (EOF)
LOC
Devuelve la posicin de lectura/escritura actual en un archivo abierto.
La sintaxis de esta propiedad es: LOC (Numero de canal)
la informacin devuelta para un archivo secuencial es la posicin de byte actual en
el archivo, dividida por 128.
LOF
LOF(numeroarchivo)
Ejemplo
Observaciones
funcin
SEEK
Seek(nmeroArchivo)
Observe la diferencia de esta definicin con la que hacamos en los ficheros secuenciales.
209
Estudiante///////////Lus
Surez
Bernaldo//////////Ediciones
donde se ha sustituido el carcter nulo por una barra ( / ) con el fin de hacerlo visible en el
texto. Si se molesta en contar los caracteres que tiene el registro observar que son 88,
que es la suma de 30 + 30 + 15 + 6 + 4 + 3 que son los caracteres asignados a cada uno
de las partes que forman el registro (Ttulo, Autor, etc.) Para hablar con propiedad, a esas
partes que componen el registro lea vamos a llamar CAMPOS. Un Registro est formado
por varios Campos, y cada Campo contiene una informacin.
Imagnese que introducimos otro libro. El primer campo de ese nuevo registro se colocar
en el fichero inmediatamente despus del ltimo campo existente, sin ningn tipo de
separacin. No hace falta esa separacin, pues VB conoce donde finaliza un registro y
comienza otro, ya que la longitud total del registro se le ha introducido en la instruccin
para abrir el fichero, que repetimos aqu por comodidad :
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
(Si se omite el dato LongitudRegistro VB colocar la longitud por defecto, 128 caracteres)
LongitudRegistro deber ser igual o mayor que la suma de caracteres de cada uno de los
campos declarados en la instruccin Type, que tambin reproducimos :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edicin As String * 6
Precio As String * 4
Existencias As String * 3
End Type
210
Deber ser igual o mayor, o estrictamente igual ? La respuesta es igual o mayor. Pero si
declaramos en la instruccin Open que el registro es mayor que la suma de los caracteres
de todos los campos que lo componen, estaremos perdiendo espacio de disco duro, tanto
como la diferencia entre lo declarado en la instruccin Open menos la suma de los
caracteres de cada uno de los campos. Y esa cifra, multiplicada por el nmero de registros
existentes. Por lo tanto debe declararse en la instruccin Open exactamente la suma de los
caracteres de todos los campos. En el ejemplo anterior era bastante fcil, ya que todos los
campos eran del tipo String (cadena de caracteres) y cada carcter ocupa un byte. La cosa
se complica si uno o varios de los campos son de tipo numrico, porque nos obligar a
recordar cuantos bytes ocupa un integer, un Long, etc. Si hubisemos declarado en la
instruccin Type Precio as Long, Existencias as Integer deberamos tener en cuenta que un
Long (nmero entero entre -2.147.483.648 y 2.147.483.647, inclusive) ocupa 4 bytes y un
integer
(nmero entero entre -32.768 y 32.767) ocupa 2 bytes. Se reproduce a
continuacin la longitud en Bytes de cada uno de los tipos de datos. No se moleste en
aprendrsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como
Resumen de tipos de datos. Pero fjese en algo tan curioso como que un dato tipo
Boolean que solamente puede tomar 2 valores (S / No) ocupa 2 bytes frente a un dato
tipo Byte, que puede tomar 256 valores y ocupa solamente un Byte.
Tipo de Dato
Byte
Boolean
Integer
Long(entero largo)
Single(coma flotante Simple precisin)
Double(coma flotante Doble Precisin)
Currency
Date
Object
String (longitud variable)
String (longitud fija)
Variant (con nmeros)
Variant (con caracteres)
Ocupa
1 byte
2 bytes
2 bytes
4 bytes
4 bytes
8 bytes
8 bytes
8 bytes
4 bytes
10 bytes + longitud de cadena
longitud declarada de la cadena
16 bytes
22 bytes + longitud de cadena
Ya le estoy viendo tomando buena nota de cuanto ocupa cada variable. Y echando nmeros
para saber la longitud exacta de la variable y no perder ningn byte del disco duro
desaprovechndolo sin informacin. No habr algo que nos lo facilite ? S, lgicamente.
La instruccin LEN
LEN nos da la longitud de un texto (Var=Len (Hola que tal), o de una variable
Var=Len(Variable)
Podemos usarla para conocer la longitud total de la variable MiVariable
LongitudRegistro = Len (MiVariable)
Pero si quiere reducir mas la cosa, abra el fichero de esta forma :
Open Nombrefichero For Random As # Numerocanal Len = Len (MiVariable)
Ni que decir tiene que si se abre ese fichero en varias partes del programa con distintas
instrucciones Open el valor de LongitudRegistro debe ser igual en todas ellas.
La declaracin del registro mediante la instruccin Type debe hacerse en la seccin de
211
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edicin As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Luego REGLIBROS tendr 6 campos (Titulo, Autor, Editorial, Edicin, Precio y Existencias),
cada uno de una longitud determinada, la definida en la instruccin Type.
Antes de introducir REGLIBROS en el fichero habr que decir que valor tiene. Pero cada
campo que lo compone tendr un valor. Podramos hacer una aplicacin en la que, a
travs de varios TextBox, le introdujsemos los valores de los campos, y el nmero de
212
registro en el cual queremos escribir. El nombre de cada uno de los TextBox para cada uno
de los datos es el siguiente :
Campo Ttulo :
TBTITULO
TBEDITORIAL
Campo Edicin :TBEDICION
TBEXISTENCIAS
Campo Autor :
Campo
Precio :
TBAUTOR
TBPRECIO
Campo Editorial :
Campo
Existencias :
La aplicacin deber introducir en cada campo el valor (string) existente en cada uno de
esos TextBox. El valor de la variable REGLIBROS lo compondremos de la siguiente forma :
REGLIBROS.Titulo = TBTITULO.Text
REGLIBROS.Autor = TBAUTOR.Text
REGLIBROS.Editorial = TBEDITORIAL.Text
REGLIBROS.Edicion = TBEDICION.Text
REGLIBROS.Precio = TBPRECIO.Text
REGLIBROS.Existencias = TBEXISTENCIAS.Text
(Si se hubiese omitido alguna de estas igualdades, el campo correspondiente contendra el
valor nulo)
De esta forma, REGLIBROS ya tiene un valor que se puede escribir en el fichero mediante
la instruccin Put.
213
Observe que ya se le han introducido otros controles (TextBox para introducir el nombre
del fichero, otro para el nmero de registro, botones para leer, escribir, abrir el fichero
(EXAMINAR), un par de botones para subir o bajar el nmero de registro y un botn para
salir de la aplicacin. El TextBox para introducir el nombre del fichero se llama
TBNOMBREFICHERO y en el que debemos introducir el nmero de registro a leer o escribir
TBLEERESCR.
El Botn EXAMINAR cierra cualquier fichero que pudiese estar abierto, abre el fichero
indicado en TBNOMBREFICHERO, calcula el nmero de registros y escribe este nmero en
el Label con nombre LNUMFICH. El cdigo de su procedimiento Click es el siguiente :
Private Sub BEXAMINAR_Click()
Close
Cierra cualquier fichero abierto
Open TBNOMBREFICHERO For Random As #1 Len = 88 Abre el fichero deseado
LONGITUDFICH = LOF(1)
Obtiene su longitud
NUMREGS = LONGITUDFICH / 88
Calcula el N. de registros
LNUMFICH.Caption = NUMREGS
Pone ese N. en el Label
End Sub
Veamos como se escribe un registro. Analicemos el cdigo del procedimiento click del
botn ESCRIBIR
Private Sub BESCRIBIR_Click()
REGISTROLIBRO.Titulo = TBTITULO.Text
REGISTROLIBRO.Autor = TBAUTOR.Text
REGISTROLIBRO.Editorial = TBEDITORIAL.Text
REGISTROLIBRO.Edicin = TBEDICION.Text
REGISTROLIBRO.Precio = TBPRECIO.Text
REGISTROLIBRO.Existencias = TBEXISTENCIAS.Text
Put #1, Val(TBLEERESCR), REGISTROLIBRO
End Sub
Se escribe el registro
214
Para leer los datos de un fichero Random utilizaremos la instruccin Get. Su sintaxis es la
siguiente :
Get # Numerocanal , NumeroRegistro, Variable
Puede omitirse NumeroRegistro. En este caso, el nmero de registro que se leer ser el
siguiente al ltimo registro ledo.
La Instruccin Get leer un registro completo. Ese registro contendr varios campos, y
seguramente nos interesar conocer el valor de cada campo dentro de ese registro.
Variable es una variable que contendr todos los campos. En nuestra aplicacin de
biblioteca, Variable tiene por nombre REGISTROLIBRO (El mismo que tena para la
instruccin Put de escribir. Es pura comodidad del programador. Puede tener cualquier otro
nombre)
Para obtener el contenido de cada campo, realizaremos un proceso similar al empleado
para la escritura, pero al revs. En nuestra aplicacin, pretendemos poner el contenido de
cada campo en los mismos TextBox que se utilizaron para escribirlos. Veamos el contenido
del procedimiento click del botn LEER
Private Sub BLEER_Click()
Get #1, Val(TBLEERESCR), REGISTROLIBRO
Lee el registro completo
TBTITULO.Text = REGISTROLIBRO.Titulo
Obtiene el valor del campo Titulo
TBAUTOR.Text = REGISTROLIBRO.Autor
Autor, Editorial, Edicin, Precio
TBEDITORIAL.Text = REGISTROLIBRO.Editorial y Existencias y los pone en los
TBEDICION.Text = REGISTROLIBRO.Edicin
TextBox correspondientes a cada
TBPRECIO.Text = REGISTROLIBRO.Precio
dato
TBEXISTENCIAS.Text = REGISTROLIBRO.Existencias
End Sub
Funciones e instrucciones aplicables a los ficheros Random.
Funciones Seek y Loc.
En los ficheros Random tienen especial importancia las funciones Seek y Loc.
Mediante la Funcin Loc podemos conocer la el ltimo registro manipulado, bien por
lectura, escritura. Si abrimos el fichero y no se ha hecho ninguna lectura o escritura de
registros, el nmero devuelto por la funcin Loc es 0.
La sintaxis de la funcin Loc es :
Variable = Loc (Numerocanal)
Variable tomar un valor igual al nmero del registro escrito o ledo por ltima vez.
Mediante la Funcin Seek podemos conocer el prximo registro que ser manipulado en
una operacin de lectura o escritura. Si abrimos el fichero y no se ha hecho an ninguna
operacin de lectura o escritura, Seek devuelve el valor 1.
Seek puede ser una funcin (lee un Dato) o una instruccin (fuerza un
dato) ! ! !
Instruccin Seek
La instruccin Seek establece el prximo registro a leer o escribir en un fichero Random.
Sintaxis
Seek (Numerocanal), posicin
posicin es el nmero de registro que se va a leer o escribir en la siguiente operacin. No
acepta el 0 como nmero de registro, el mas bajo debe ser el 1. Si se intenta forzar a la
posicin 0 dar un error.
Funciones de los ficheros Random:
EOF
Devuelve un valor que indica si se ha llegado al final de un archivo.
Sintaxis
EOF(Numerocanal)
En archivos Random, EOF devuelve False hasta que se haya ejecutado una instruccin Get
y no haya podido leer el registro completo, en cuyo caso devolver True.
La funcin EOF no suele emplearse en ficheros Random, ya que en estos nos movemos a
base de registros, y es muy fcil controlar cuantos registros existen en el fichero y en que
registro nos encontramos o nos vamos a mover, mediante las funciones LOF, LOC y SEEK
LOF
( Lenght Of File )
Devuelve la longitud de un fichero .
Sintaxis
Variable = LOF(Numerocanal)
216
FICHEROS BINARIOS
Un fichero binario es una sucesin de bytes, uno tras otro, que puede almacenar cualquier
tipo de informacin. Cuando se explicaban los ficheros secuenciales, decamos que eran
los mas adecuados para introducir informacin de un texto, con los Random podamos
realizar una base de datos de forma sencilla, a base de controlar los registros y sus
campos. Con un fichero binario podemos almacenar cualquier informacin. (texto y
cualquier tipo de datos) .
Para abrir un fichero secuencial se abre utilizando la instruccin :
Open Nombrefichero For Binary As # Numerocanal
Como siempre en VB, Numerocanal puede ser un nmero comprendido entre 1 y 255, que
define ea fichero. No pueden existir al mismo tiempo 2 ficheros abiertos con el mismo
Numero de canal.
Nombrefichero es el nombre completo del fichero, con su Path.
Una vez abierto un fichero se binario, podemos leer o escribir datos en l.
Para escribir uno o varios caracteres en un fichero binario, usaremos la instruccin Put.
Put # Numerocanal, Posicin, Variable
Donde Posicin es el Byte donde comenzar la escritura, y Variable es el nombre de la
variable que contiene el dato a escribir. Este dato puede ser un byte o varios bytes.
Para escribir varios bytes podemos hacerlo de dos formas :
- Si se puede conocer de antemano el nmero de bytes a escribir, puede declararse
Variable como un string de ese nmero de caracteres mediante la instruccin Dim, por
ejemplo :
Dim Variable As String * numero de bytes
y en este caso siempre escribir el nmero de bytes declarado. Cuidado ! Si los datos a
introducir sobrepasan el nmero de bytes declarados para Variable, los datos sobrantes no
se escribirn en el fichero. Si los datos a escribir en el fichero fuesen menos que los
declarados para Variable, la diferencia se rellenar con el byte nulo ( 0 ).
- Si no se conoce de antemano el nmero de bytes a escribir, podemos declarar la variable
sin especificar el nmero de bytes que tiene, y de esta forma se escribirn todos los bytes
que componen la variable :
Dim Variable As String
Pero en este caso debemos volver a decir Cuidado !, si no conocemos el nmero de
bytes que vamos a escribir, puede que machaquemos parte de la informacin que ya
tenemos en el fichero, pues la instruccin Put va a colocar los bytes que componen
Variable en la posicin especificada por Posicin y siguientes, hasta que quepa toda la
cadena de bytes que le queremos introducir. Si la posicin en la que introducimos esos
bytes es una posicin intermedia, y no controlamos bien el nmero de bytes a introducir y
las informaciones que ya existen en el fichero en las posiciones colindantes con las que
vamos a introducir los datos, es muy probable que perdamos esa informacin al introducir
la nueva.
217
218
Seek (1), 48
Variable = Input (35, #1)
Variable contendr ahora los 35 bytes deseados.
Al igual que se hizo para los ficheros secuenciales y Random, vamos a ver con un ejemplo
prctico como se manejan los ficheros binarios.
El formulario del ejemplo tiene esta forma :
Con el botn ABRIR se abre el fichero deseado. Si no existe en el disco, lo crea, ya que la
instruccin
Open Nombrefichero For Binary As # Numerocanal
intenta abrir un fichero existente llamado Nombrefichero, y si este no existe, lo crea. Si
existe el fichero, presenta todo su contenido en el TextBox inferior, para poder tener una
referencia de que lugar ocupan los distintos caracteres (un fichero binario puede guardar
cualquier byte, por lo que si abre un fichero generado con cualquier programa puede ser
que muchos de los bytes no contengan informacin de un carcter, por lo que le
recomendamos haga esta prctica con un fichero creado por la misma prctica)
El botn CERRAR cierra el fichero. SALIR sale de la aplicacin. El TextBox superior
(variable) sirve para introducir la variable a escribir en el fichero, o para presentar la
variable leda en caso de lectura . El TextBox posicin sirve para indicar la posicin del
primer byte. Posicin por defecto presenta la posicin que se extrae mediante la funcin
Seek cada vez que se hace una lectura o escritura en el fichero. Longitud de la variable
permite introducir esa longitud, para leer mediante la instruccin Input.
El botn ESCRIBIR escribe el dato Variable en el fichero, LEER (GET) lee un nico byte, y
LEER (INPUT) lee una cadena de caracteres, de longitud la especificada en el TextBox
Longitud de la variable.
Se enumera a continuacin el cdigo de cada uno, dejando para las explicaciones del
profesor en clase, o el estudio del alumno, la interpretacin de cada una de susu partes.
FORMULARIO.
DECLARACIONES
219
Option Explicit
Dim LONGVAR As Integer
Dim COMIENZA As Long
Dim TESTO As String
Dim pospordef As Long
BOTON ABRIR
Private Sub BABRIR_Click()
CD1.ShowOpen
CD1 es un CommonDialog para buscar el fichero
Open CD1.filename For Binary As #1
Abre el fichero indicado en CD1
TESTO = Input(LOF(1), #1) Lee de un golpe el fichero y lo mete en la variable TESTO
TBFICHERO.Text = TESTO Presenta el fichero en el TextBox TBFICHERO
End Sub
BOTON CERRAR
Private Sub BCERRAR_Click()
Close
End Sub
BOTON ESCRIBIR
Private Sub BESCRIBIR_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
Pone el TB long. De la variable en rojo
Dim escribe As String
Declara la variable escribe como string, sin
limitacin
escribe = TBVAR1.Text
Pasa el contenido de TBVAR a la variable
escribe
Put #1, Val(TBVAR3), escribe
Instruccin Put. Val(TBVAR3) es la posicin del
1er byte
pospordef = Seek(1)
Analiza donde qued el puntero del fichero
Lvar5 = Str(pospordef)
y pone este valor en la etiqueta Lvar5
End Sub
BOTON LEER (GET)
Private Sub BLEER_Click()
TBVAR2.BackColor = RGB(255, 0,
variable)
TBVAR2.Text = "1"
If Seek(1) >= LOF(1) Then
Seek #1, 1
End If
Dim TEXTO As String * 1
If TBVAR3.Text <> "" Then
COMIENZA = Val(TBVAR3.Text)
TBVAR3
ElseIf Lvar5.Caption <> "" Then
COMIENZA = Val(Lvar5.Caption)
Else
COMIENZA = Seek(1)
End If
Get #1, COMIENZA, TEXTO
TBVAR1.Text = TEXTO
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
0)
BOTON SALIR
Private Sub BSALIR_Click()
End
End Sub
Sale de la aplicacin.
Dir[(nombreruta[, atributos])]
nombreruta
Valor
Descripcin
vbNormal
vbHidden
vbSystem
vbVolume
vbDirectory
0
2
4
8
16
Normal.
Oculto.
Sistema
Etiqueta de volumen; si se especifica se ignoran todos los atributos
Directorio o carpeta.
En Microsoft Windows, Dir permite el empleo de los caracteres comodn '*' (mltiples
caracteres) y '?' (un solo carcter) para especificar varios archivos.
La primera vez que se llama a la funcin Dir se debe especificar el nombreruta, de lo
contrario se produce un error. Si adems se especifican atributos de archivo, se debe
221
incluir el nombreruta.
Dir devuelve el primer nombre de archivo que coincide con el nombreruta. Para obtener
ms nombres de archivo que coincidan con el nombreruta, se debe volver a llamar a Dir
sin argumentos.
Cuando no hay ms nombres de archivo coincidentes, Dir devuelve una cadena de
caracteres de longitud cero. Cuando se devuelve una cadena de longitud cero, en las
siguientes llamadas se debe especificar nombreruta o se producir un error. Se puede
cambiar el nombreruta sin haber obtenido todos los nombres de archivo que coinciden con
el nombreruta actual. Sin embargo, no se puede llamar a la funcin Dir.
FILECOPY
Copia un archivo.
Sintaxis
Variable = FileDateTime(nombreRuta)
Variable = GetAttr(nombreRuta)
Constante
Descripcin
0
1
2
4
16
32
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Slo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado despus de efectuar la ltima copia de
seguridad.
SETATTR
Establece los atributos de un archivo.
Sintaxis
nombreRuta
el
atributos
SetAttr nombreRuta;atributos
Las constantes y valores de atributos son los mismos que para la instruccin GetAttr
Si se trata de establecer los atributos de un archivo abierto, se producir un error en
tiempo de
ejecucin.
FREEFILE
Devuelve el siguiente nmero de archivo disponible para ser usado con la instruccin
Open.
Sintaxis
FreeFile[(nmerodeintervalo)]
Write Nos
Print
Introduce la informacin de forma secuencial, byte tras byte tal como se
coment. Sirve para guardar textos. Por ejemplo si deseamos guardar en ese
fichero el contenido de una caja de texto llamada Text1, basta con ejecutar
la siguiente instruccin:
Print #NumerodeCanal, Text1.Text
El texto queda en el fichero en caracteres ASCII, que se pueden leer con el
Bloc de Notas.
Cuando los datos se han introducido con la instruccin Print, la forma de acceder a ese
texto es muy sencilla:
Se abre el archivo con la instruccin Open
224
un
leeremos el fichero de una nica vez. Este procedimiento puede ahorrarle cierto tiempo a
la hora de la lectura. (Por lo dicho anteriormente, este procedimiento de leer todo el
fichero de un golpe solamente se podr hacer si la longitud del fichero (LOF(1)) es inferior
a 65.534 bytes. Tenga esto presente cuando vaya a leer un fichero que no sabe que
longitud tiene. Para curarse en salud, le recomiendo que lea los ficheros secuenciales
carcter a carcter. Input(1,#X) pues tarda poco mas que leyndolo de un golpe. Claro
que para leer un fichero carcter a carcter debe poner un bucle en el que se van leyendo
los caracteres hasta que llaga al final del fichero..
La forma de hacer este bucle es la siguiente:
Dim A As String
del fichero.
Dim MiVariable as String
todo el
Do Until EOF(1)
El programa ejecutar este bucle hasta que se cumpla que
EOF(1) sea
True.
EOF(NumerodeCanal) es una propiedad de los
ficheros cuando
estn abiertos, que es True cuando la posicin
del puntero de lectura
apunta al carcter Fin De Fichero (End Of
File) que es el carcter siguiente
al ltimo carcter de texto de ese
fichero.
A = Input (1, #1)
Estrae un carcter del fichero abierto por el canal nmero 1. Al
leer este
carcter,
el
puntero
de
lectura
avanza
automticamente tantos caracteres
como haya ledo, colocndose
sobre el primer carcter no ledo.
MiVariable = MiVariable & A Con esta lnea vamos anexando el carcter ledo a la variable
MiVariable. En vez de utilizar una variable, podramos
poner ese
texto sobre un TextoBox o un RichTextBox (RTB) (Lo
ver
proximamente). Si lo ponemos en un RTB esta lnea
sera:
RTB.SelText = A
225
Loop
Close #1
Cierra el fichero
Slo se utilizar la instruccin Input con archivos abiertos en modo Input o Binary. (Los
Binary Se vern a continuacin) A diferencia de la instruccin Input #, (la veremos a
continuacin, pues es la instruccin que deber utilizar para leer archivos escritos con la
instruccin Write ), Input devuelve todos los caracteres que lee, incluyendo puntos y
coma, retornos de carro, avances de lnea, comillas y espacios iniciales.
Existe una instruccin, Input$ , que asume que el dato a leer es un String. (Cadena de
caracteres). Puede ahorrar un poco de memoria usando esta instruccin en lugar de
Input.
Nota Se proporciona otra funcin (InputB) para su uso con datos de byte incluidos en
archivos de texto. En lugar de especificar el nmero de caracteres a devolver, nmero
especifica el nmero de bytes.
INSTRUCCION LINE INPUT
La instruccin Line Input se utiliza para extraer una lnea completa. Tiene la
siguiente sintaxis:
Line Input # Nmero de canal, VariableString
Mediante esta instruccin se extrae una lnea completa (los caracteres delimitados entre
dos retornos de carro), y se le asigna esa cadena a VariableString
Una lnea es un trozo de texto delimitado por los caracteres 13 (Retorno de carro) y 10
(Avance de lnea) La instruccin Line Input # lee un carcter cada vez en un archivo
hasta que encuentra un retorno de carro (Chr(13)) o una secuencia retorno de carro avance de lnea (Chr(13) + Chr(10)). Las secuencias de retorno de carro - avance de lnea
no se tienen en cuenta y no se aaden a la cadena de caracteres extrada mediante esta
instruccin. Cuando lea un archivo mediante Line Input # y lo quiere presentar en un
TextBox o en el Printer, deber introducirlos para evitar que le salga todo el texto en una
nica lnea.
Con lo que se ha explicado, ya puede realizar un pequeo edito de textos. Este sencillo
editor tiene un TextBox llamado TBTexto, donde podemos escribir el texto que queramos
(con la propiedad MultiLine = True y ScrollBars = Vertical), tres botones llamados BAbrir
(1), (2 a y b) y (3), para abrir el fichero y poner su contenido en TBTexto, y dos
BGuardar para guardar, uno abriendo el fichero For Append y el otro abrindolo For
Output. En este ltimo, al guardar el texto borramos el contenido que del fichero, si ya
existiera. En el primero, lo anexamos al final del mismo . Para conocer el nombre del
fichero, ponemos un CommonDialog llamado CD1, con un filtro CD1.Filter = Ficheros de
Texto |*.txt
Para abrir el fichero, y depositar su contenido en TBTexto pondremos este cdigo en
BAbrir :
Private Sub BAbrir1_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
VarTexto = Input(LOF(1), #1)
'leemos todo el fichero de un golpe
Close #1
226
TBTexto = VarTexto
End Sub
Cuando el fichero es mayor de 64 kilobytes, el leerlo de un golpe puede dar problemas.
Mejor dicho, no funciona. Deberemos leerlo en ese caso, carcter a carcter o lnea a lnea.
Para leer carcter a carcter :
Private Sub BAbrir_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
Hacemos un bucle de lectura hasta que encontremos EOF(1)
Vea mas adelante la Propiedad EOF en Propiedades de los ficheros Secuenciales
VarTexto = Input(1, #1)
'leemos el fichero carcter a carcter
TBTexto = TBTexto & VarTexto
'vamos aadiendo los caracteres ledos a TBTexto
Loop
Close #1
End Sub
(NOTA.- Lo expuesto funciona perfectamente, pero el hecho de meter en un TextBox
carcter a carcter eterniza la aplicacin. - Meter un texto en un TextBox o en un Label es
una operacin que tarda cierto tiempo. Si esa operacin hay que hacerla una vez por
carcter, puede tardar mucho tiempo. Para evitar esto, cuando vaya a leer un fichero
carcter a carcter, mtalo primero en una variable y luego realice un volcado nico de esa
variable al TextBox o Label)
Y podemos hacerlo tambin leyendo lnea a lnea con Line Input
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowOpen
Open CD1.filename For Input As #1
Do Until EOF(1)
Line Input #1, VarTexto
'leemos el fichero Lnea a Lnea
TBTexto = TBTexto & VarTexto & vbCrLf
'vamos aadiendo las lneas ledas a TBTexto
'(Hay que introducir un retorno + avance de lnea con cada lnea (vbCrLf), ya que VarTexto
no
contiene los retornos ni avances de lnea.
Loop
Close #1
Los Botones de Guardar tienen el cdigo :
Private Sub BGuardar_Click()
Dim VarTexto As String
CD1.Filter = "Ficheros de Texto |*.txt"
CD1.ShowSave
Open CD1.filename For Output As #1
Print #1, TBTexto.Text
Close #1
End Sub
O para el caso de abrir con For Append
Private Sub BGuardar2_Click()
227
End Sub
Observe que los nombre de las variables en el proceso de lectura tienen distintos nombres
a los utilizados durante la escritura. Como en el fichero no se guarda ninguna referencia al
respecto, lo nico que importa es que el nmero de variables para la lectura sea igual al
nmero de variables que se utiliz para la escritura, y que el orden de las variables sea
correcto. Si por ejemplo, el nmero de variables usadas en la introduccin de datos fuese
distinto al nmero de variables usado en la lectura, Visual Basic nos dara un error.
Observe tambin que se ha introducido un temporizador. Sirve para ver los sucesivos
ttulos que tenemos en nuestra base de datos tan sui generis. Se ha pretendido presentar
unos datos de esta pequea base de datos sin complicarnos mucho la vida. Mas adelante
veremos como presentarlos de una forma correcta. Este tipo de ficheros no es el mas
adecuado para construir bases de datos, es complicado manejar ficheros de mas de unas
pocas lneas, por lo que para tener muchos datos, este tipo de ficheros no es
recomendable. No es aconsejable ni para muchos datos ni para pocos datos. Pero es
obligacin del autor explicarlo y de advertirlo.
En esta pequea aplicacin mostrbamos las informaciones sucesivamente segn las
bamos leyendo del fichero. Interrumpamos momentneamente la lectura para presentar
cada informacin durante un instante, ya que como tenemos cinco datos distintos en cada
registro y cinco TextBox para presentarlos, deberemos presentar una informacin tras otra.
Esto no parece en principio una solucin prctica para una base de datos, donde lo que
interesa es disponer de todos los datos para usarlos cuando sea necesario. Esto nos lleva a
crear una matriz para albergar todos los datos de la base, ya que los ficheros secuenciales
se leen y se les tiene que extraer toda la informacin de un golpe, ya que no permiten ir a
leer hacia atrs. Por lo tanto, si deseamos disponer de todos los datos, deberemos
guardarlos en la memoria, en una matriz. Imagnese que estamos tratando datos de varios
miles de libros en el ejemplo anterior. Si la informacin de cada campo es medianamente
extensa, no tendramos memoria RAM suficiente en el ordenador para albergarlos. Esto nos
lleva a pensar en otro tipo de archivo que veremos a continuacin, los Random
(aleatorios), que permiten leer solamente los registros que nos interesan.
Pero volvamos a nuestra aplicacin de librera, donde hemos hecho una variacin, los
campos PRECIO y EXISTENCIAS los vamos a tratar ahora como nmeros (Integer).
Tambin se ha introducido otro campo tipo texto, para introducir la edicin. El fichero
creado tras introducir varios libros qued de la siguiente forma :
"EL RODABALLO","GUNTER GRASS","PLANETA",1995,2000,12
" VisualBasic - Gua del Estudiante ","LUIS SUAREZ","CEU",PRIMERA,1000,21
"EL NOMBRE DE LA ROSA","UMBERTO ECO","AGUILAR",28,1000,21
"ENCICLOPEDIA DEL VB","CEBALLOS","RAMA",CUARTA,1200,23
"LA GRANJA ANIMAL","ORWELL","DESTINO",45,12000,78
"LA PASION TURCA","ANTONIO GALA","PLANETA",SEGUNDA,2500,25
"LA METAMORFOSIS","KAFKA","PLAZA&JANES", 4,3400,101
"VB4 PARA WINDOWS95","GARY CORNELL","MCGRAWHILL",1,6500,25
Observe que los dos ltimos campos (correspondientes a PRECIO y EXISTENCIAS) no
estn entre comillas, pues no se trata de texto, sino de nmeros.
(Observe tambin la gran ventaja de tener una base de datos con datos completamente
legibles)
Se han introducido alguna variaciones en el programa. Entre ellas, se crea una matriz de
variables de 5 x n (n=nmero de registros). Tambin se le aaden unos botones para
poder recorre toda la base de datos.
230
El programa necesita que le introduzcamos el nombre del fichero que alberga la base de
datos. Por sencillez no se ha usado ningn CommonDialog y se introduce directamente el
nombre de este fichero en un TextBox llamado TBNombreFichero
El fichero anterior podemos leerlo tal y como indicbamos antes :
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
Input #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Donde las variables TITULO, AUTOR, EDITORIAL y EDICION sern del tipo String y PRECIO
y EXISTENCIAS sern de tipo numrico. Podemos saberlo, ya que en una lnea cualquiera
del fichero anterior :
" VisualBasic - Gua del Estudiante ","LUIS SUAREZ","CEU",PRIMERA,1000,21
los cuatro primeros parmetros van entre comillas dobles, ya que son datos tipo texto, y
los dos ltimos van sin comillas, como corresponde a datos numricos.
Pero existe otra forma mejor (al menos un poco mas complicada) para leer estos datos, y
evitar el problema que tenamos antes de tener que hacer un temporizador para poder ver,
aunque solo sea un momento, los datos. Podemos meter los datos a una matriz que tenga
tantas columnas como datos (campos) (en el ejemplo 6, cuatro String y dos numricos), y
tantas filas como apuntes (registros) tengamos.
Para ello, antes de nada debemos definir un tipo de variable, mediante la instruccin Type.
Parece que no nos basta con los tipos de variable que trae VB (Long, String, Integer ...) y
es cierto. La variable que necesitamos no es de ningn tipo de esos. Est compuesta por
varias secciones, y cada una de ellas puede ser de un tipo distinto. Este tipo de
definiciones debe hacerse en un mdulo (Vase instruccin Type en la ayuda de VB), por
lo que se ha creado un mdulo llamado LIBREMD2.BAS, con el siguiente cdigo :
231
Type REGISTROLIBRO
AUTOR As String
TITULO As String
EDITORIAL As String
EDICION As String
PRECIO As Integer
EXISTENCIAS As Integer
End Type
Esto es lo que se llama DEFINIR una variable. Es como hacerse un traje a medida. Y dese
cuenta de que es un tipo de variable (REGISTROLIBRO) formado por varias partes (AUTOR,
TITULO, Etc.) Observe que DEFINIR una variable NO es lo mismo que DECLARAR
En el apartado de Declaraciones del General del formulario declaramos las variables, entre
ellas una variable, REGISTROLIBROS, de la cual decimos que va a ser una matriz mediante
los parntesis que la acompaan, y adems declaramos que va a se similar a
REGISTROLIBRO ya definida en el mdulo.
Dim NR As Integer
Dim REGISTROLIBROS() As REGISTROLIBRO
Dim NRP As Integer
Observe que al usar parntesis al declarar la variable REGISTROLIBROS le estamos
diciendo a VB que esa variable ser un Array, y adems que es una variable del tipo
REGISTROLIBRO, tipo de variable que ya conoce, puesto que se la hemos definido en un
mdulo.
En el ejemplo preparado podemos escribir y leer datos. Veamos de nuevo como se escriben
El cdigo del procedimiento click del botn BIntroducir1 es :
Private Sub BIntroducir1_Click()
TITULO = LIBRETBTITULO.Text
AUTOR = LIBRETBAUTOR.Text
EDITORIAL = LIBRETBEDITORIAL.Text
EDICION = LIBRETBEDICION.Text
PRECIO = Val(LIBRETBPREC.Text)
EXISTENCIAS = Val(LIBRETBEX.Text)
autor
editorial
edicin
precio
existencias
(Observe que para introducir el precio y las existencias se transform el contenido del
TextBox a un valor numrico mediante la instruccin Val.)
Open "C:\cursoVB\" + LIBRETBFICHERO.Text For Append As #1
Write #1, TITULO, AUTOR, EDITORIAL, EDICION, PRECIO, EXISTENCIAS
Close #1
End Sub
Tras reiteradas entradas, el fichero de la BD qued como se vio anteriormente.
Al leer los datos, lo primero es que no conocemos el nmero de registros existentes. Como
cada registro va en una lnea del fichero, si contamos el nmero de retornos de carro
(Chr(13)) obtendremos el nmero de registros. Esta operacin es la primera que se realiza
en el procedimiento click del botn LEER :
Private Sub Command2_Click()
LIBRETBTITULO.Text = ""
LIBRETBAUTOR.Text = ""
232
LIBRETBEDITORIAL.Text = ""
LIBRETBEDICION.Text = ""
LIBRETBPREC.Text = ""
LIBRETBEX.Text = ""
NR = 0
NR=nmero de registros
Abre el fichero, lo lee entero y cuenta el nmero de retornos de carro. Existirn tantos
apuntes (registros) como retornos de carro existan, ya que cada registro ocupa una lnea.
Open TBNombreFichero.Text For Input As #1
Do Until EOF(1)
A = Input(1, #1)
If A = Chr(13) Then NR = NR + 1
Loop
Close #1
Presenta en LNumFich el nmero de registros
LNumFich.Caption = Str(NR) + " Registros)"
'Redimensionamos la matriz de REGISTROLIBROS a NR elementos..
ReDim REGISTROLIBROS(1 To NR)
Volvemos a abrir el fichero
Open TBNombreFichero.Text For Input As #1
Leemos los registros del 1 al NR, y cada campo del fichero lo vamos asignando a los
elementos que componen la matriz.
For I = 1 To NR
Input #1, REGISTROLIBROS(I).TITULO
Input #1, REGISTROLIBROS(I).AUTOR
Input #1, REGISTROLIBROS(I).EDITORIAL
Input #1, REGISTROLIBROS(I).EDICION
Input #1, REGISTROLIBROS(I).PRECIO
Input #1, REGISTROLIBROS(I).EXISTENCIAS
Next I
Close #1
NOTA.- Estas lneas podramos heberlas puesto en una lnea nica :
Input#1,REGISTROLIBROS(I).TITULO,REGISTROLIBROS(I).AUTOR,_
REGISTROLIBROS(I).EDITORIAL,REGISTROLIBROS(I).EDICION,_
REGISTROLIBROS(I).PRECIO, REGISTROLIBROS(I).EXISTENCIAS
NRP = Nmero del Registro Presentado. Lo hacemos igual a 1 para presentar, de
momento, el nmero 1
NRP = 1
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
233
End Sub
Copiamos este cdigo de presentacin de datos y lo llevamos a las flechas de incrementar
o disminuir el nmero del registro a presentar.
Private Sub BMas1_Click()
NRP = NRP + 1
If NRP > NR Then
protegemos que salga error de NRP fuera de intervalo
MsgBox "No existen mas registros en esta direccin"
NRP = NR
Else
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End If
End Sub
Esta es la de incrementar. La de disminuir es igual, pero restando 1 a NRP
Las flechas dobles llevan al registro 1 y al ltimo. Tienen este cdigo
Private Sub BMas2_Click()
NRP = NR
LIBRETBTITULO.Text = REGISTROLIBROS(NRP).TITULO
LIBRETBAUTOR.Text = REGISTROLIBROS(NRP).AUTOR
LIBRETBEDITORIAL.Text = REGISTROLIBROS(NRP).EDITORIAL
LIBRETBEDICION.Text = REGISTROLIBROS(NRP).EDICION
LIBRETBPREC.Text = REGISTROLIBROS(NRP).PRECIO
LIBRETBEX.Text = REGISTROLIBROS(NRP).EXISTENCIAS
End Sub
Observe que es muy sencillo trabajar con ficheros secuenciales para bases de datos. El
inconveniente es la cantidad de memoria necesaria para la matriz de datos. Tambin tienen
un gran inconveniente: solamente se pueden leer de hacia adelante. Un fichero secuencial
hay que leerlo de una sola vez. Esto que no es ningn inconveniente para un fichero de
texto, o incluso para un fichero de datos que leemos una nica vez, es un problema
cuando leemos un dato situado en un punto de ese fichero, y luego tenemos que leer un
dato colocado en una posicin anterior. En este caso, deberemos terminar de leerlo, y
volver a comenzar por el principio. Este es un gran inconveniente para hacer bases de
datos con ficheros secuenciales.
No solamente hemos visto una forma de crear una base de datos, sino que hemos visto
como movernos a lo largo de los registros. Ver esto con mucho mas detalle cuando demos
bases de datos. Este tipo de bases de datos son la Tipo Texto que ver mas adelante.
Propiedades de los ficheros Secuenciales:
EOF
Indica el fin del fichero (End Of File). EOF ser False hasta que encuentre el final
del fichero secuencial. Habr observado instrucciones tales como:
Do until EOF(1) (Hazlo hasta que encuentres el EOF del canal 1)
Do While Not EOF(1)
(Hazlo mientras EOF del canal 1 sea False)
234
LOF
Devuelve la longitud de un fichero (Lenght Of File) abierto mediante Open.
Sintaxis
LOF(numeroarchivo)
Ejemplo
Observaciones
funcin
SEEK
Devuelve la posicin actual de lectura/escritura de un archivo abierto con la
instruccin Open.
Sintaxis
Seek(nmeroArchivo)
a cualquier nmero de libros, y para leerla no es necesario leer todo el fichero, sino
simplemente acceder a los registros que nos interesen. Tambin permite realizar el cambio
de un registro de una forma sencilla, sin alterar los dems.
Todo esto tiene un precio: En los archivos secuenciales, podamos introducir informaciones
de cualquier longitud. En los archivos aleatorios cada dato tiene una longitud asignada,
longitud que no se puede sobrepasar, y si la informacin que debemos almacenar tiene
menos que la longitud preestablecida, perderemos esa capacidad sobrante.
Para abrir un fichero aleatorio debemos emplear la expresin:
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
Nombrefichero es el nombre que queremos dar al fichero
Numerocanal es el nmero del canal (nmero de fichero) que puede ser de 1 a 255
LogitudRegistro es la longitud total del registro.
Un fichero aleatorio (Random), una vez abierto, puede utilizarse para leer o escribir datos.
Para escribir datos en un fichero aleatorio, primero debemos definir el registro, es decir, en
el caso de los libros visto anteriormente, un registro va almacenar los datos del titulo,
autor, editorial, etc. Para "saber" como se colocan estos datos dentro del registro ser
necesario definirlo.
En realidad lo que vamos a hacer es definir una variable de las denominadas Definidas por
el usuario Con esto lo que hacemos es crear un nuevo tipo de variable, en el ejemplo, la
variable tipo Registro. Se debbe hacer en la seccin de declaraciones de un mdulo o de
un formulario, y siempre antes de declarar una variable como variable de ese tipo. (La
definicin de la variable debe hacerse en la seccin de declaraciones del mdulo o
formulario con mbito suficiente para que sea vlida en todas las partes de la aplicacin
donde se necesite esa variable)
Podemos hacerlo con la instruccin Type:
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edicin As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Observe la diferencia de esta definicin con la que hacamos en los ficheros secuenciales.
En aquellos no ponamos la longitud de cada seccin. Aqu es necesario, ya que la longitud
de un registro (y tambin de cada campo) es fija.
Ya una vez definido como es Registro, podemos decir que una variable es del tipo definido
para Registro, es decir :
Dim MiVariable as Registro
Entonces MiVariable ya puede almacenar los datos de Titulo, Autor, Editorial, Edicin,
Precio y Existencias, colocando un dato tras otro, sin ninguna separacin, en el mismo
orden que lo habamos definido para Registro. No es necesario utilizar separaciones ya
que el programa sabe que longitud tiene cada dato y el orden de colocacin. Lo sabe
236
Estudiante///////////Lus
Surez
Bernaldo//////////Ediciones
donde se ha sustituido el carcter nulo por una barra ( / ) con el fin de hacerlo visible en el
texto. Si se molesta en contar los caracteres que tiene el registro observar que son 88,
que es la suma de 30 + 30 + 15 + 6 + 4 + 3 que son los caracteres asignados a cada uno
de las partes que forman el registro (Ttulo, Autor, etc.) Para hablar con propiedad, a esas
partes que componen el registro lea vamos a llamar CAMPOS. Un Registro est formado
por varios Campos, y cada Campo contiene una informacin.
Imagnese que introducimos otro libro. El primer campo de ese nuevo registro se colocar
en el fichero inmediatamente despus del ltimo campo existente, sin ningn tipo de
separacin. No hace falta esa separacin, pues VB conoce donde finaliza un registro y
comienza otro, ya que la longitud total del registro se le ha introducido en la instruccin
para abrir el fichero, que repetimos aqu por comodidad :
Open Nombrefichero For Random As # Numerocanal Len = LongitudRegistro
(Si se omite el dato LongitudRegistro VB colocar la longitud por defecto, 128 caracteres)
LongitudRegistro deber ser igual o mayor que la suma de caracteres de cada uno de los
campos declarados en la instruccin Type, que tambin reproducimos :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edicin As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Deber ser igual o mayor, o estrictamente igual ? La respuesta es igual o mayor. Pero si
declaramos en la instruccin Open que el registro es mayor que la suma de los caracteres
de todos los campos que lo componen, estaremos perdiendo espacio de disco duro, tanto
como la diferencia entre lo declarado en la instruccin Open menos la suma de los
caracteres de cada uno de los campos. Y esa cifra, multiplicada por el nmero de registros
existentes. Por lo tanto debe declararse en la instruccin Open exactamente la suma de los
caracteres de todos los campos. En el ejemplo anterior era bastante fcil, ya que todos los
campos eran del tipo String (cadena de caracteres) y cada carcter ocupa un byte. La cosa
se complica si uno o varios de los campos son de tipo numrico, porque nos obligar a
recordar cuantos bytes ocupa un integer, un Long, etc. Si hubisemos declarado en la
instruccin Type Precio as Long, Existencias as Integer deberamos tener en cuenta que un
Long (nmero entero entre -2.147.483.648 y 2.147.483.647, inclusive) ocupa 4 bytes y un
237
integer
(nmero entero entre -32.768 y 32.767) ocupa 2 bytes. Se reproduce a
continuacin la longitud en Bytes de cada uno de los tipos de datos. No se moleste en
aprendrsela de memoria, pues en la Ayuda de Visual Basic puede encontrarla como
Resumen de tipos de datos. Pero fjese en algo tan curioso como que un dato tipo
Boolean que solamente puede tomar 2 valores (S / No) ocupa 2 bytes frente a un dato
tipo Byte, que puede tomar 256 valores y ocupa solamente un Byte.
Tipo de Dato
Byte
Boolean
Integer
Long(entero largo)
Single(coma flotante Simple precisin)
Double(coma flotante Doble Precisin)
Currency
Date
Object
String (longitud variable)
String (longitud fija)
Variant (con nmeros)
Variant (con caracteres)
Ocupa
1 byte
2 bytes
2 bytes
4 bytes
4 bytes
8 bytes
8 bytes
8 bytes
4 bytes
10 bytes + longitud de cadena
longitud declarada de la cadena
16 bytes
22 bytes + longitud de cadena
Ya le estoy viendo tomando buena nota de cuanto ocupa cada variable. Y echando nmeros
para saber la longitud exacta de la variable y no perder ningn byte del disco duro
desaprovechndolo sin informacin. No habr algo que nos lo facilite ? S, lgicamente.
La instruccin LEN
LEN nos da la longitud de un texto (Var=Len (Hola que tal), o de una variable
Var=Len(Variable)
Podemos usarla para conocer la longitud total de la variable MiVariable
LongitudRegistro = Len (MiVariable)
Pero si quiere reducir mas la cosa, abra el fichero de esta forma :
Open Nombrefichero For Random As # Numerocanal Len = Len (MiVariable)
Ni que decir tiene que si se abre ese fichero en varias partes del programa con distintas
instrucciones Open el valor de LongitudRegistro debe ser igual en todas ellas.
La declaracin del registro mediante la instruccin Type debe hacerse en la seccin de
declaraciones de un Mdulo. Esta instruccin Type en realidad lo que est haciendo es
definir un nuevo tipo de variable, (una variable definida por el usuario) que servir de
muestra para que en otra parte del programa le digamos, mediante una instruccin Dim,
que tal variable es del tipo definido anteriormente mediante la instruccin Type. Por lo
tanto, debemos declarar una variable en la parte que corresponda del programa,
dependiendo del mbito que se le quiera dar a esa variable, diciendo que ser del tipo de
la declarada mediante la instruccin Type.
Usando la declaracin de Registro del ejemplo anterior, vamos a retomar el ejemplo de la
biblioteca. Declararemos (posiblemente en la seccin de declaraciones del formulario) una
variable que llamaremos p.e. REGLIBROS de la siguiente forma :
Dim REGLIBROS as Registro
238
A partir de este momento, el programa sabe que REGLIBROS es una variable que tiene 6
campos (Titulo, Autor, Editorial, Edicin, Precio y Existencias) y que cada campo tiene los
caracteres especificados en la instruccin Type.
Ahora nos cabe una pregunta Cuantos registros tiene un fichero Random? La respuesta es
sencilla. Basta conocer la longitud del fichero mediante la instruccin LOF si el fichero ya
est abierto, o con la instruccin FILELEN si no lo est, y dividir el dato obtenido con
cualquiera de las dos instrucciones anteriores por el valor LongitudRegistro.
Escribir datos en un fichero Random. Instruccin Put
Una vez abierto el fichero Random podemos leer y escribir datos en l. Para escribir datos
utilizaremos la instruccin Put. La sintaxis de Put es la siguiente:
Put # Numerocanal , NumeroRegistro, Variable
Puede omitirse NumeroRegistro. En este caso, el nmero de registro que se escribir ser
el siguiente al ltimo registro escrito.
NumeroRegistro es el nmero del registro que queremos escribir, y Variable es el
contenido de ese registro. Siguiendo con nuestro ejemplo de biblioteca, Variable tiene en
este caso el nombre REGLIBROS, que no es un String ni un Integer, sino una variable
definida por el usuario ya que la declaramos con Dim REGLIBROS as Registro. Por lo
tanto, la variable REGLIBROS contendr los mismos campos que habamos declarado para
Registro en la instruccin Type. Recuerde :
Type Registro
Titulo As String * 30
Autor As String * 30
Editorial As String * 15
Edicin As String * 6
Precio As String * 4
Existencias As String * 3
End Type
Luego REGLIBROS tendr 6 campos (Titulo, Autor, Editorial, Edicin, Precio y Existencias),
cada uno de una longitud determinada, la definida en la instruccin Type.
Antes de introducir REGLIBROS en el fichero habr que decir que valor tiene. Pero cada
campo que lo compone tendr un valor. Podramos hacer una aplicacin en la que, a
travs de varios TextBox, le introdujsemos los valores de los campos, y el nmero de
registro en el cual queremos escribir. El nombre de cada uno de los TextBox para cada uno
de los datos es el siguiente :
Campo Ttulo :
TBTITULO
TBEDITORIAL
Campo Edicin :TBEDICION
TBEXISTENCIAS
Campo Autor :
Campo
Precio :
TBAUTOR
TBPRECIO
Campo Editorial :
Campo
Existencias :
La aplicacin deber introducir en cada campo el valor (string) existente en cada uno de
esos TextBox. El valor de la variable REGLIBROS lo compondremos de la siguiente forma :
REGLIBROS.Titulo = TBTITULO.Text
REGLIBROS.Autor = TBAUTOR.Text
239
REGLIBROS.Editorial = TBEDITORIAL.Text
REGLIBROS.Edicion = TBEDICION.Text
REGLIBROS.Precio = TBPRECIO.Text
REGLIBROS.Existencias = TBEXISTENCIAS.Text
(Si se hubiese omitido alguna de estas igualdades, el campo correspondiente contendra el
valor nulo)
De esta forma, REGLIBROS ya tiene un valor que se puede escribir en el fichero mediante
la instruccin Put.
240
Observe que ya se le han introducido otros controles (TextBox para introducir el nombre
del fichero, otro para el nmero de registro, botones para leer, escribir, abrir el fichero
(EXAMINAR), un par de botones para subir o bajar el nmero de registro y un botn para
salir de la aplicacin. El TextBox para introducir el nombre del fichero se llama
TBNOMBREFICHERO y en el que debemos introducir el nmero de registro a leer o escribir
TBLEERESCR.
El Botn EXAMINAR cierra cualquier fichero que pudiese estar abierto, abre el fichero
indicado en TBNOMBREFICHERO, calcula el nmero de registros y escribe este nmero en
el Label con nombre LNUMFICH. El cdigo de su procedimiento Click es el siguiente :
Private Sub BEXAMINAR_Click()
Close
Cierra cualquier fichero abierto
Open TBNOMBREFICHERO For Random As #1 Len = 88 Abre el fichero deseado
LONGITUDFICH = LOF(1)
Obtiene su longitud
NUMREGS = LONGITUDFICH / 88
Calcula el N. de registros
LNUMFICH.Caption = NUMREGS
Pone ese N. en el Label
End Sub
Veamos como se escribe un registro. Analicemos el cdigo del procedimiento click del
botn ESCRIBIR
Private Sub BESCRIBIR_Click()
REGISTROLIBRO.Titulo = TBTITULO.Text
REGISTROLIBRO.Autor = TBAUTOR.Text
REGISTROLIBRO.Editorial = TBEDITORIAL.Text
REGISTROLIBRO.Edicin = TBEDICION.Text
REGISTROLIBRO.Precio = TBPRECIO.Text
REGISTROLIBRO.Existencias = TBEXISTENCIAS.Text
Put #1, Val(TBLEERESCR), REGISTROLIBRO
End Sub
Se escribe el registro
241
Para leer los datos de un fichero Random utilizaremos la instruccin Get. Su sintaxis es la
siguiente :
Get # Numerocanal , NumeroRegistro, Variable
Puede omitirse NumeroRegistro. En este caso, el nmero de registro que se leer ser el
siguiente al ltimo registro ledo.
La Instruccin Get leer un registro completo. Ese registro contendr varios campos, y
seguramente nos interesar conocer el valor de cada campo dentro de ese registro.
Variable es una variable que contendr todos los campos. En nuestra aplicacin de
biblioteca, Variable tiene por nombre REGISTROLIBRO (El mismo que tena para la
instruccin Put de escribir. Es pura comodidad del programador. Puede tener cualquier otro
nombre)
Para obtener el contenido de cada campo, realizaremos un proceso similar al empleado
para la escritura, pero al revs. En nuestra aplicacin, pretendemos poner el contenido de
cada campo en los mismos TextBox que se utilizaron para escribirlos. Veamos el contenido
del procedimiento click del botn LEER
Private Sub BLEER_Click()
Get #1, Val(TBLEERESCR), REGISTROLIBRO
Lee el registro completo
TBTITULO.Text = REGISTROLIBRO.Titulo
Obtiene el valor del campo Titulo
TBAUTOR.Text = REGISTROLIBRO.Autor
Autor, Editorial, Edicin, Precio
TBEDITORIAL.Text = REGISTROLIBRO.Editorial y Existencias y los pone en los
TBEDICION.Text = REGISTROLIBRO.Edicin
TextBox correspondientes a cada
TBPRECIO.Text = REGISTROLIBRO.Precio
dato
TBEXISTENCIAS.Text = REGISTROLIBRO.Existencias
End Sub
Funciones e instrucciones aplicables a los ficheros Random.
Funciones Seek y Loc.
En los ficheros Random tienen especial importancia las funciones Seek y Loc.
Mediante la Funcin Loc podemos conocer la el ltimo registro manipulado, bien por
lectura, escritura. Si abrimos el fichero y no se ha hecho ninguna lectura o escritura de
registros, el nmero devuelto por la funcin Loc es 0.
La sintaxis de la funcin Loc es :
Variable = Loc (Numerocanal)
Variable tomar un valor igual al nmero del registro escrito o ledo por ltima vez.
Mediante la Funcin Seek podemos conocer el prximo registro que ser manipulado en
una operacin de lectura o escritura. Si abrimos el fichero y no se ha hecho an ninguna
operacin de lectura o escritura, Seek devuelve el valor 1.
Seek puede ser una funcin (lee un Dato) o una instruccin (fuerza un
dato) ! ! !
Instruccin Seek
La instruccin Seek establece el prximo registro a leer o escribir en un fichero Random.
Sintaxis
Seek (Numerocanal), posicin
posicin es el nmero de registro que se va a leer o escribir en la siguiente operacin. No
acepta el 0 como nmero de registro, el mas bajo debe ser el 1. Si se intenta forzar a la
posicin 0 dar un error.
Funciones de los ficheros Random:
EOF
Devuelve un valor que indica si se ha llegado al final de un archivo.
Sintaxis
EOF(Numerocanal)
En archivos Random, EOF devuelve False hasta que se haya ejecutado una instruccin Get
y no haya podido leer el registro completo, en cuyo caso devolver True.
La funcin EOF no suele emplearse en ficheros Random, ya que en estos nos movemos a
base de registros, y es muy fcil controlar cuantos registros existen en el fichero y en que
registro nos encontramos o nos vamos a mover, mediante las funciones LOF, LOC y SEEK
LOF
( Lenght Of File )
Devuelve la longitud de un fichero .
Sintaxis
Variable = LOF(Numerocanal)
243
FICHEROS BINARIOS
Un fichero binario es una sucesin de bytes, uno tras otro, que puede almacenar cualquier
tipo de informacin. Cuando se explicaban los ficheros secuenciales, decamos que eran
los mas adecuados para introducir informacin de un texto, con los Random podamos
realizar una base de datos de forma sencilla, a base de controlar los registros y sus
campos. Con un fichero binario podemos almacenar cualquier informacin. (texto y
cualquier tipo de datos) .
Para abrir un fichero secuencial se abre utilizando la instruccin :
Open Nombrefichero For Binary As # Numerocanal
Como siempre en VB, Numerocanal puede ser un nmero comprendido entre 1 y 255, que
define ea fichero. No pueden existir al mismo tiempo 2 ficheros abiertos con el mismo
Numero de canal.
Nombrefichero es el nombre completo del fichero, con su Path.
Una vez abierto un fichero se binario, podemos leer o escribir datos en l.
Para escribir uno o varios caracteres en un fichero binario, usaremos la instruccin Put.
Put # Numerocanal, Posicin, Variable
Donde Posicin es el Byte donde comenzar la escritura, y Variable es el nombre de la
variable que contiene el dato a escribir. Este dato puede ser un byte o varios bytes.
Para escribir varios bytes podemos hacerlo de dos formas :
- Si se puede conocer de antemano el nmero de bytes a escribir, puede declararse
Variable como un string de ese nmero de caracteres mediante la instruccin Dim, por
ejemplo :
Dim Variable As String * numero de bytes
y en este caso siempre escribir el nmero de bytes declarado. Cuidado ! Si los datos a
introducir sobrepasan el nmero de bytes declarados para Variable, los datos sobrantes no
se escribirn en el fichero. Si los datos a escribir en el fichero fuesen menos que los
declarados para Variable, la diferencia se rellenar con el byte nulo ( 0 ).
- Si no se conoce de antemano el nmero de bytes a escribir, podemos declarar la variable
sin especificar el nmero de bytes que tiene, y de esta forma se escribirn todos los bytes
que componen la variable :
Dim Variable As String
Pero en este caso debemos volver a decir Cuidado !, si no conocemos el nmero de
bytes que vamos a escribir, puede que machaquemos parte de la informacin que ya
tenemos en el fichero, pues la instruccin Put va a colocar los bytes que componen
Variable en la posicin especificada por Posicin y siguientes, hasta que quepa toda la
cadena de bytes que le queremos introducir. Si la posicin en la que introducimos esos
bytes es una posicin intermedia, y no controlamos bien el nmero de bytes a introducir y
las informaciones que ya existen en el fichero en las posiciones colindantes con las que
vamos a introducir los datos, es muy probable que perdamos esa informacin al introducir
la nueva.
244
245
Seek (1), 48
Variable = Input (35, #1)
Variable contendr ahora los 35 bytes deseados.
Al igual que se hizo para los ficheros secuenciales y Random, vamos a ver con un ejemplo
prctico como se manejan los ficheros binarios.
El formulario del ejemplo tiene esta forma :
Con el botn ABRIR se abre el fichero deseado. Si no existe en el disco, lo crea, ya que la
instruccin
Open Nombrefichero For Binary As # Numerocanal
intenta abrir un fichero existente llamado Nombrefichero, y si este no existe, lo crea. Si
existe el fichero, presenta todo su contenido en el TextBox inferior, para poder tener una
referencia de que lugar ocupan los distintos caracteres (un fichero binario puede guardar
cualquier byte, por lo que si abre un fichero generado con cualquier programa puede ser
que muchos de los bytes no contengan informacin de un carcter, por lo que le
recomendamos haga esta prctica con un fichero creado por la misma prctica)
El botn CERRAR cierra el fichero. SALIR sale de la aplicacin. El TextBox superior
(variable) sirve para introducir la variable a escribir en el fichero, o para presentar la
variable leda en caso de lectura . El TextBox posicin sirve para indicar la posicin del
primer byte. Posicin por defecto presenta la posicin que se extrae mediante la funcin
Seek cada vez que se hace una lectura o escritura en el fichero. Longitud de la variable
permite introducir esa longitud, para leer mediante la instruccin Input.
El botn ESCRIBIR escribe el dato Variable en el fichero, LEER (GET) lee un nico byte, y
LEER (INPUT) lee una cadena de caracteres, de longitud la especificada en el TextBox
Longitud de la variable.
Se enumera a continuacin el cdigo de cada uno, dejando para las explicaciones del
profesor en clase, o el estudio del alumno, la interpretacin de cada una de susu partes.
FORMULARIO.
DECLARACIONES
246
Option Explicit
Dim LONGVAR As Integer
Dim COMIENZA As Long
Dim TESTO As String
Dim pospordef As Long
BOTON ABRIR
Private Sub BABRIR_Click()
CD1.ShowOpen
CD1 es un CommonDialog para buscar el fichero
Open CD1.filename For Binary As #1
Abre el fichero indicado en CD1
TESTO = Input(LOF(1), #1) Lee de un golpe el fichero y lo mete en la variable TESTO
TBFICHERO.Text = TESTO Presenta el fichero en el TextBox TBFICHERO
End Sub
BOTON CERRAR
Private Sub BCERRAR_Click()
Close
End Sub
BOTON ESCRIBIR
Private Sub BESCRIBIR_Click()
TBVAR2.BackColor = RGB(255, 0, 0)
Pone el TB long. De la variable en rojo
Dim escribe As String
Declara la variable escribe como string, sin
limitacin
escribe = TBVAR1.Text
Pasa el contenido de TBVAR a la variable
escribe
Put #1, Val(TBVAR3), escribe
Instruccin Put. Val(TBVAR3) es la posicin del
1er byte
pospordef = Seek(1)
Analiza donde qued el puntero del fichero
Lvar5 = Str(pospordef)
y pone este valor en la etiqueta Lvar5
End Sub
BOTON LEER (GET)
Private Sub BLEER_Click()
TBVAR2.BackColor = RGB(255, 0,
variable)
TBVAR2.Text = "1"
If Seek(1) >= LOF(1) Then
Seek #1, 1
End If
Dim TEXTO As String * 1
If TBVAR3.Text <> "" Then
COMIENZA = Val(TBVAR3.Text)
TBVAR3
ElseIf Lvar5.Caption <> "" Then
COMIENZA = Val(Lvar5.Caption)
Else
COMIENZA = Seek(1)
End If
Get #1, COMIENZA, TEXTO
TBVAR1.Text = TEXTO
pospordef = Seek(1)
Lvar5 = Str(pospordef)
End Sub
0)
BOTON SALIR
Private Sub BSALIR_Click()
End
End Sub
Sale de la aplicacin.
Dir[(nombreruta[, atributos])]
nombreruta
Valor
Descripcin
vbNormal
vbHidden
vbSystem
vbVolume
vbDirectory
0
2
4
8
16
Normal.
Oculto.
Sistema
Etiqueta de volumen; si se especifica se ignoran todos los atributos
Directorio o carpeta.
En Microsoft Windows, Dir permite el empleo de los caracteres comodn '*' (mltiples
caracteres) y '?' (un solo carcter) para especificar varios archivos.
La primera vez que se llama a la funcin Dir se debe especificar el nombreruta, de lo
contrario se produce un error. Si adems se especifican atributos de archivo, se debe
248
incluir el nombreruta.
Dir devuelve el primer nombre de archivo que coincide con el nombreruta. Para obtener
ms nombres de archivo que coincidan con el nombreruta, se debe volver a llamar a Dir
sin argumentos.
Cuando no hay ms nombres de archivo coincidentes, Dir devuelve una cadena de
caracteres de longitud cero. Cuando se devuelve una cadena de longitud cero, en las
siguientes llamadas se debe especificar nombreruta o se producir un error. Se puede
cambiar el nombreruta sin haber obtenido todos los nombres de archivo que coinciden con
el nombreruta actual. Sin embargo, no se puede llamar a la funcin Dir.
FILECOPY
Copia un archivo.
Sintaxis
Variable = FileDateTime(nombreRuta)
Variable = GetAttr(nombreRuta)
Constante
Descripcin
0
1
2
4
16
32
vbNormal
vbReadOnly
vbHidden
vbSystem
vbDirectory
vbArchive
Normal.
Slo lectura.
Oculto.
Archivo de sistema.
Directorio o carpeta.
El archivo ha sido modificado despus de efectuar la ltima copia de
seguridad.
SETATTR
Establece los atributos de un archivo.
Sintaxis
nombreRuta
el
atributos
SetAttr nombreRuta;atributos
Las constantes y valores de atributos son los mismos que para la instruccin GetAttr
Si se trata de establecer los atributos de un archivo abierto, se producir un error en
tiempo de
ejecucin.
FREEFILE
Devuelve el siguiente nmero de archivo disponible para ser usado con la instruccin
Open.
Sintaxis
FreeFile[(nmerodeintervalo)]
250
el
Sintaxis 2
(Con esta sintaxis trazar una lnea desde las coordenadas absolutas x1,y1
hasta las coordenadas relativas a (x1,y1), x2,y2. Es decir, al poner la
palabra
Step (paso) antes de las coordenadas finales, le estamos indicando que las
coordenadas que siguen a Step son relativas. Relativas respecto a quien?.
Relativas a las coordenadas de comienzo de la lnea. Esta ltima expresin
hara lo mismo que la siguiente expresin :
objeto.Line (x1,y1) - (x1+x2, y1+y2), color, BF
Podemos darnos cuenta por la descripcin anterior que la palabra Step (palabra reservada
de Visual Basic) indica que las coordenadas que le siguen son relativas a algo. Veamos la
tercera forma de colocar una lnea :
Sintaxis 3
y1),
(x2,y2)
251
Color es el nmero de color, que se puede poner en cualquiera de las posibles formas que
permite VB. Si no se especifica color, pondr el color por defecto, que es el valor de la
propiedad ForeColor del objeto.
BF es un parmetro opcional. En realidad este parmetro sirve para que en vez de hacer
una lnea haga un rectngulo. La expresin :
Form1.Line (x1,y1) - (x2,y2) , RGB(255,0,0), B
dibuja un rectngulo entre los puntos (x1,y1) y (x2,y2).
La expresin :
Picture1.Line (x1,y1) - (x2,y2), RGB (0,255,0), BF
dibuja un rectngulo relleno del mismo color de la lnea (en este caso verde) con esquinas
en las coordenadas (x1,y1) y (x2,y2)
De lo explicado se deduce que si el parmetro opcional BF es solamente B dibuja un
cuadrado con esquinas en las coordenadas indicadas (pueden ser absolutas o relativas), y
si es BF pinta ese rectngulo y adems lo rellena con el mismo color elegido en el
parmetro color. No puede usarse solamente la F pues no tiene sentido rellenar de color
una figura abierta.
Para dibujar lneas unidas, comience la lnea siguiente en el punto final de la lnea anterior.
La anchura de la lnea dibujadas depende de la configuracin de la propiedad DrawWidth.
Cuando se ejecuta Line, las propiedades CurrentX y CurrentY toman el valor del punto final
de la lnea.
METODO Circle
Dibuja una circunferencia, crculo, elipse o arco sobre un objeto.
Sintaxis
En la expresin anterior, objeto es el objeto donde se dibujar el circulo. Puede ser, como
en el caso de la lnea, un Formulario, un PictureBox o el objeto Printer. Si se omite, se
asume que se refiere al Formulario que tenga el enfoque en ese momento.
(x, y) son las coordenadas del punto central del crculo, elipse o arco. Las unidades de
medida vendrn determinadas por las propiedades ScaleMode o ScaleWidth / ScaleHeight
del objeto.
Radio Este parmetro es requerido. Indica el radio del crculo, elipse o arco, en el mismo
sistema de unidades de medida.
Color Este parmetro es opcional. Es el nmero del color, expresado en cualquiera de las
formas aceptadas por Visual Basic. Si se omite, se utiliza el valor de la propiedad
ForeColor.
Inicio,
inicio y
es de final es
Final
Valor opcional. Cuando se dibuja un arco o parte de un crculo o elipse,
fin especifican (en radianes) la posicin inicial y final del arco. El rango de ambas
2 pi radianes a 2 pi radianes. El valor predeterminado de inicio es 0 radianes; el de
de 2 pi radianes.
252
objeto.Cls
254
anchura2 Opcional. Indica la anchura de la imagen origen. Este parmetro se usa para
establecer la relacin entre la anchura de la imagen final y la anchura de la imagen origen.
Si al realizar la copia de la imagen a Objeto, esta nos sale muy grande, podemos, bien
rebajar el parmetro anchura1 o aumentar anchura2, puesto que la medida real del
ancho de la imagen final estar en relacin directa con el cociente anchura1/anchura2
altura2
caso.
Opecod Opcional. Valor Long o cdigo que se usa slo con mapas de bits. Define una
operacin bit a bit (por ejemplo, operador Not o Xor) que se realiza sobre imagen al
dibujarla sobre objeto. Para obtener la lista completa de los operadores bit a bit, busque el
tema BitBlt en el archivo de Ayuda de Windows SDK (WIN31WH.HLP).
NOTA Como caso prctico, el autor de este texto suele guardar la imagen en una variable
tipo Picture. Se desconoce el ancho de esa imagen, que vendr dado por la anchura real
del Bitmap. Puede conocerse la anchura y altura de la imagen consultando la anchura y
altura de la variable :
AnchodelaImagen = VariableImagen.Width
AlturadelaImagen = VariableImagen.Height
Muchas veces, la imagen que se introduce en la variable tipo Picture es distinta en una
ocasin u otras, por lo que desconocemos a priori que dato debemos poner a anchura1 y
a anchura2. Todo tiene solucin. Con el cdigo siguiente el ancho y alto de la imagen se
mantendr constante independientemente de la anchura y altura que tenga el Bitmap
original.
objeto.PaintPicture Imagen, x1, y1, anchura1, altura1, , , VariableImagen.Width, _
VariableImagen.Height
donde hemos omitido x2, y2 de forma intencionada, pero observe que hemos seguido
respetando su sitio con las comas como separadores. El ltimo parmetro, Opecod se ha
omitido, pero como es el ltimo, no hace falta dejarle las comas.
Pueden omitirse tantos argumentos finales como se desee. Si se omite uno o varios
argumentos finales, no se usan comas a partir del ltimo argumento especificado. Si se
quiere especificar un argumento opcional, se deben especificar todos los argumentos
opcionales que aparecen antes en la sintaxis.
METODO
Point
Devuelve, como entero Long, el color rojo - verde - azul (RGB) del punto especificado de
un objeto Form o control PictureBox.
Sintaxis
objeto.Point(x, y)
donde
objeto Opcional. Nombre del Formulario o PictureBox donde se va a analizar el color. Si
objeto se omite se asume que el objeto es el formulario que tenga el enfoque.
x, y Parmetro requerido. Valores Single que indican las coordenadas horizontal (eje x) y
vertical (eje y) del punto segn la propiedad ScaleMode del objeto Form o control
PictureBox. Deben colocarse entre parntesis.
255
Estas coordenadas se refieren a las coordenadas del objeto que contiene el grfico, con
origen (0,0) en la esquina superior izquierda del mismo.
Si el punto definido por las coordenadas x e y est fuera de objeto, el mtodo Point
devuelve el valor -1.
METODO
Pset
256
Objeto.Print Expresin
Donde
Objeto es el nombre del Formulario, PictureBox o el Printer, donde se desea escribir
Expresin
Es una cadena de caracteres o variable que contiene el texto a escribir
El tamao, tipo, color y otras propiedades de la letra sern las que tenga el objeto sobre el
que se va a escribir en ese momento. El lugar donde se inicia la escritura ser el de la
propiedad CurrentX y CurrentY actuales.
Veamos un ejemplo para excribir sobre un formulario. El Formulario, desde el cdigo que
est dentro de el se le nombra con Me.
Me.FontName = "Arial"
Me.FontSize = 12
Me.FontBold = True
Me.Print "Hola Mundo"
SavePicture (Instruccin)
Guarda un grfico de un objeto Form, de un control PictureBox o de un control Image en
un archivo.
Sintaxis
Objeto.LoadPicture ([expcadena])
257
Usando LoadPicture sin argumento se borran los grficos de los formularios y los controles
PictureBox e imagen.
Los formatos grficos reconocidos por Visual Basic incluyen archivos de mapas de bits
(.BMP), archivos de icono (.ICO), archivos de longitud codificada (.RLE) y Metarchivo
(.WMF).
Para cargar grficos para presentarlos en un control PictureBox, Image o como fondo de un
formulario, el valor devuelto por LoadPicture debe ser asignado a la propiedad Picture del
objeto en el se quiere presentar la imagen. Por ejemplo:
Form1.Picture = LoadPicture ("FIESTA.BMP")
Imagen1.Picture = LoadPicture ("FIESTA.BMP")
Picture1.Picture = LoadPicture (FIESTA.BMP")
Para asignar un icono a un formulario, se asigna el valor devuelto por la funcin
LoadPicture a la propiedad Icon del objeto Form:
Form1.Icon = LoadPicture ("UNICONO.ICO")
Los iconos tambin pueden ser asignados a las propiedades DragIcon de todos los
controles
excepto los controles Timer y Men. Por ejemplo:
Comando1.DragIcon = LoadPicture ("UNICONO.ICO")
Para cargar grficos en el Portapapeles del sistema se usa LoadPicture de la forma
siguiente:
Clipboard.SetData LoadPicture ("FIESTA.BMP")
Puede tambin meter una imagen en una variable, y luego poner en uno de los controles
citados anteriormente la imagen guardada en la variable. Este mtodo le permite presentar
una imagen muy rpidamente, ya que no necesita acceder al disco para buscar una
imagen, pero emplea mucha memoria RAM, ya que la variable (o variables) conteniendo
la(s) imgenes estn en la RAM.
Para ello hay que declarar las variables como Picture
Option Explicit
Dim MiVariable1 As Picture, MiVariable2 As Picture
Private Sub Form_Load()
Set MiVariable1 = LoadPicture("c:\pruebavb\ athena.bmp
Set MiVariable2 = LoadPicture("c:\list_tel\rr1.bmp")
End Sub
Private Sub Command1_Click()
Picture1.Picture = MiVariable1
End Sub
Private Sub Command2_Click()
Picture1.Picture = MiVariable2
End Sub
258
")
Mediante este programa lo que hemos hecho fue guardar dos imgenes en sendas
variables, en el momento de cargar el formulario, imgenes que se pasan posteriormente
al control Picture1 con los botones de comando Command1 y Command2
Propiedades de varios controles aplicables a los mtodos grficos
DrawMode
(Propiedad)
objeto.DrawMode = nmero
Donde objeto es el nombre del Formulario, PictureBox, objeto Print, o los controles Shape
o Line, y nmero es un entero que especifica el aspecto, segn la siguiente lista:
1
2
3
del
4
5
6
7
8
9
10
11
12
13
14
15
16
Blackness.
Not Merge PenInverso del valor 15 (Merge Pen).
Mask Not PenCombinacin de los colores comunes del color de fondo y el inverso
Pen.
Not Copy PenInverso del valor 13 (Copy Pen).
Mask Pen NotCombinacin de los colores comunes al Pen y al inverso de la muestra.
InvertInverso del color de muestra.
Xor PenCombinacin de los colores en el Pen y en el color de la muestra, pero no de
ambos.
Not Mask PenInverso del valor 9 (Mask Pen).
Mask PenCombinacin de los colores comunes al Pen y a la presentacin.
Not Xor PenInverso del valor 7 (Xor Pen).
NopNadano hay cambios. De hecho, este valor desactiva el dibujado.
Merge Not PenCombinacin del color de muestra y el inverso del color del Pen.
Copy Pen (Predeterminado)Color especificado por la propiedad ForeColor.
Merge Pen NotCombinacin del color del Pen y el inverso del color de muestra.
Merge PenCombinacin del color del Pen y el color de muestra.
Whiteness.
Use esta propiedad para producir efectos visuales con controles Shape o Line o al dibujar
con mtodos grficos. Visual Basic compara cada pxel de la plantilla de dibujo con el pxel
correspondiente del fondo existente y despus aplica operaciones a nivel de bit. Por
ejemplo, el valor 7 (Xor Pen) usa el operador Xor para combinar un pxel del dibujo con un
pxel del fondo.
El efecto exacto de un valor DrawMode depende del modo en el que el color de una lnea
dibujada en tiempo de ejecucin se combina con los colores de la pantalla. Los valores 1,
6, 7, 11, 13 y 16 producen los mejores resultados.
DrawStyle
(Propiedad)
objeto.DrawStyle = nmero
Donde objeto es el nombre del Formulario, PictureBox, objeto Print sobre el que se va a
dibujar, y nmero es un entero que especifica el estilo de lnea, tal como se describe a
continuacin:
259
0
1
2
3
4
5
6
(Predeterminado) Continuo.
Rayas.
Puntos.
Raya - punto.
Raya - punto - punto.
Transparente.
Continuo interior.
Si DrawWidth se define con un valor mayor que 1, los valores de DrawStyle entre 1 y 4
producen una lnea continua (el valor de la propiedad DrawStyle no cambia). Si DrawWidth
se define como 1, DrawStyle produce el efecto para cada valor descrito en la tabla
anterior.
DrawWidth
(Propiedad)
objeto.DrawWidth = tamao
Donde objeto es el nombre del Formulario, PictureBox, objeto Printer sobre el que se va a
dibujar, y tamao es una expresin numrica comprendida entre 1 y 32.767 que
representa la anchura de la lnea en pixeles. El valor predeterminado es 1, es decir, un
pxel de ancho.
Puede incrementar el valor de esta propiedad para aumentar la anchura de la lnea. Si el
valor de la propiedad DrawWidth es mayor que 1, los valores de 1 a 4 en la propiedad
DrawStyle producirn una lnea continua (el valor de DrawStyle no se modifica). Si se
establece 1 en DrawWidth, DrawStyle producir los resultados mostrados en la tabla de
esta propiedad.
FillColor
(Propiedad)
Devuelve o establece el color usado para rellenar formas. FillColor tambin se usa para
rellenar crculos y cuadros creados con los mtodos grficos Circle y Line.
Sintaxis
objeto.FillColor = valor
Donde objeto es el nombre del Formulario, PictureBox, objeto Printer sobre el que se va a
dibujar, y valor es un valor o constante que determina el color de relleno, con cualquiera
de los criterios de VB para definir el color.
De forma predeterminada, FillColor est definido como 0 (Negro).
Excepto en el objeto Form, cuando la propiedad FillStyle se define con su valor
predeterminado, 1 (Transparente), el valor de FillColor se ignora.
FillStyle
(Propiedad)
Devuelve o establece el modelo usado para rellenar controles Shape as como los crculos y
los cuadros creados con los mtodos grficos Circle y Line.
Sintaxis
objeto.FillStyle = nmero
Donde objeto es el nombre del Formulario, PictureBox, objeto Printer sobre el que se va a
dibujar, y nmero es un entero que especifica el estilo de relleno, tal como se describe a
260
continuacin:
0
1
2
3
4
5
6
7
Continuo.
(Predeterminado) Transparente.
Lnea horizontal.
Lnea vertical.
Diagonal hacia arriba.
Diagonal hacia abajo.
Cruzado.
Diagonal Cruzada.
objeto.AutoRedraw = booleano
XX YY ZZ
262
Donde ZZ es un nmero Hexadecimal que representa la cantidad del color rojo. El mnimo
estara en 0 (H00) y el mximo en 255 (HFF)
YY representara la cantidad de color verde y XX la de color azul, ambos con los mismos
lmites explicados para el rojo.
Por ejemplo: el rojo puro sera:
Hex(0000FF) = 255
el verde puro sera: Hex(00FF00) = 652280
el azul puro sera:
Hex(FF0000) = 16711680
Una mezcla de un poco de rojo (HB1), otro poco de verde (H56) y otro poco de azul (H1F)
dara el siguiente nmero:
Hex(1F56B1) = 2053809
Por la sentencia RGB
Se puede expresar el color, poniendo simplemente RGB (rojo, verde, azul), donde rojo es
un nmero entre 0 y 255 que indica la cantidad de color rojo que se aporta al color, verde
un nmero comprendido entre 0 y 255 indicando la cantidad de verde, y lo mismo para
azul.
Esta es la forma ms sencilla de poner la propiedad color, y con la que mejor
controlaremos el mismo.
Mediante la Funcin QBColor
Devuelve o establece el cdigo de color RGB correspondiente a un nmero de color.
Sintaxis
Objeto.QBColor(color)
Color
Negro
Azul
Verde
Aguamarina
Rojo
Fucsia
Amarillo
Blanco
Nmero
8
9
10
11
12
13
14
15
Color
Gris
Azul claro
Verde claro
Aguamarina claro
Rojo claro
Fucsia claro
Amarillo claro
Blanco brillante
263
264
Printer.ScaleHeight = 2970
le estamos diciendo a nuestro programa que el papel mide 2100 unidades de ancho y 2970
unidades de alto. (Estamos suponiendo que el papel est colocado en posicin vertical). Si
tiene 2100 unidades de ancho, y el ancho real del papel es de 210 mm, nuestra unidad de
medida ser de 0,1 mm. Es decir, le decimos a nuestro programa que el papel tiene 2100
dcimas de milmetro de ancho, y 2970 dcimas de milmetro de alto. La precisin con la
que podemos colocar un punto sobre el papel ser por tanto 0,1 mm. Podramos hacerla
mayor (0,01 mm.) si pusisemos Printer.ScaleWidth = 21000 y Printer.ScaleHeight =
29700.
265
Para el trabajo ordinario de imprimir listados o dibujar grficos tipo barras, es mas que
suficiente una precisin de 0,1 mm. Si lo que queremos es un dibujo mas exacto (Dibujar
fotolitos de circuitos impresos, p.e. ) esta precisin de 0,1 mm. no nos bastara, debiendo
llegar a una precisin del orden de 0,01 mm. Pero todo ello est condicionado por el
nmero de p.p.i.
(puntos por pulgada) que nuestra impresora es capaz de dar.
Nota.- Una impresora tiene unos mrgenes sobre los que no puede escribir. Por lo tanto,
cuando decamos que el papel tiene 210 mm. de ancho, en realidad ya estamos
cometiendo un pequeo error, ya que la impresora no puede escribir en todo el ancho,
pues los 2 - 3 mm de cada lado no lo imprime. Deberemos entonces poner las propiedades
ScaleWidth y ScaleHeight del Printer de acuerdo con la superficie real de escritura de
nuestra impresora. Le adelanto que no le va a ser fcil enterarse de qu mrgenes deja sin
imprimir. Le recomiendo que imprima una lnea desde Printer.CurrentX=0 a
Printer.CurrentX= (un nmero superior a Printer.Scalewidth). Mida con un escalmetro el
ancho real de la impresin.
El objeto Printer almacenar toda la informacin sin pasarla a la impresora hasta que se
le enve la instruccin Printer.EndDoc o se le enve un salto de pgina mediante la
instruccin Printer.NewPage.
El objeto Printer, al igual que otros objetos de Visual Basic tiene sus propiedades y
mtodos.
Las principales propiedades del objeto Printer son :
Nota
El efecto de las propiedades del objeto Printer depende del controlador
suministrado por el fabricante de la impresora. Algunos valores de la propiedad pueden no
tener efecto, o varios valores distintos de la propiedad pueden tener todos el mismo
efecto. Los valores fuera del rango aceptado pueden producir error. Para obtener ms
informacin, vea la documentacin del fabricante del controlador concreto.
ColorMode
Devuelve o establece un valor que determina si una impresora de color imprime en color o
en blanco y negro. No disponible en tiempo de diseo.
Sintaxis
Printer.ColorMode [= valor]
Printer.Copies = nmero
Donde nmero debe ser una expresin numrica que especifique el nmero de copias que
266
se van a imprimir. Este valor debe ser un entero. El valor por defecto es 1.
CurrentX
CurrentY
Printer.CurrentY =y
Para conocer las coordenadas del cursor de escritura del objeto Printer
Posx = Printer.CurrentX
Posy = Printer.CurrentY
Comentarios
Las coordenadas se miden a partir de la esquina superior izquierda del objeto. El valor de
la propiedad CurrentX es 0 en el borde izquierdo de un objeto, y el valor de la propiedad
CurrentY es 0 en el borde superior. Las coordenadas se expresan en las unidades de
medida definidas por las propiedades ScaleHeight y ScaleWidth. Si se han introducido
estas propiedades (como recomendbamos mas atrs), la propiedad ScaleMode se pone
automticamente a User. Si no se establecen, ScaleMode puede estar en Twips, Point,
Pixeles, caracteres, .... unidades que supongo le sern mucho mas difcil de controlar que
si Vd. dice desde el principio que el papel de su impresora tiene unas medidas de 2100 por
2970 (Printer.ScaleWidth = 2100, Printer.ScaleHeight = 2970) Hacindolo de esta ltima
forma, cuando queramos dibujar una lnea entre dos puntos de nuestro papel DIN A4
bastar con medir las coordenadas de inicio y final de lnea, eso s, usando como unidad de
medida la dcima de milmetro. Por ejemplo, una lnea a 5 mm del borde superior, que
comience a 20 mm. Del borde izquierdo y termine a 10 mm del borde derecho, se dibujara
con la siguiente instruccin :
Printer.Line (200,50) - (2870,50)
Si queremos escribir datos en una columna, que est a 30 mm. de la parte izquierda de la
hoja, comenzaremos a escribir cada fila de esa columna con un CurrentX de 300. Para ello
primero fijaremos el punto de inicio mediante CurrentX y a continuacin usaremos el
mtodo Print :
Printer.CurrentX = 300 : Printer.CurrentY = (lo que corresponda a esa fila)
Printer.Print MiVariable
donde MiVariable contiene el dato a escribir
CurrentX y CurrentY se quedan con los valores establecidos por el ltimo mtodo grfico
o mtodo Print usado.
Cuando se est dibujando sobre el objeto Printer, los mtodos grficos Circle y Line
establecen los siguientes valores para CurrentX y CurrentY :
Circle El centro del objeto.
Line El punto final de una lnea.
El mtodo Print establece como CurrentX la coordenada correspondiente a la parte
derecha de la ltima letra impresa. Como CurrentY depende de si ha terminado la
sentencia Printer.Print MiVariable con punto y coma ( ;) o sin el. En el primer caso,
CurrentY es el mismo que tena antes de realizar ese mtodo. En el segundo caso, avanza
automticamente una lnea.
267
DeviceName
Devuelve el nombre del dispositivo permitido por un controlador. Esta propiedad es solo de
lectura
Sintaxis
Printer.DeviceName
Cada controlador de impresora acepta uno o ms dispositivos por ejemplo, HP LaserJet III
es un nombre de dispositivo.
DrawMode
Devuelve o establece un valor que determina el aspecto de la salida de un mtodo grfico.
Vea la Ayuda de VB para mayor detalle.
DrawStile
Devuelve o establece un valor que determina el estilo de lnea de la salida de mtodos
grficos.
Sintaxis
Printer.DrawStyle [= nmero]
(Predeterminado) Continuo.
Rayas.
Puntos.
Raya - punto.
Raya - punto - punto.
Transparente.
Continuo interior.
Observaciones
Si DrawWidth se define con un valor mayor que 1, los valores de DrawStyle entre 1 y 4
producen una lnea continua (el valor de la propiedad DrawStyle no cambia). Si
DrawWidth se define como 1, DrawStyle produce el efecto para cada valor descrito en la
tabla anterior.
DrawWidth
Devuelve o establece la anchura de lnea de lo dibujado con los mtodos grficos.
Sintaxis
Printer.DrawWidth [= tamao]
Comentarios
Puede incrementar el valor de esta propiedad para aumentar la anchura de la lnea. Si el
valor de la propiedad DrawWidth es mayor que 1, los valores de 1 a 4 en la propiedad
DrawStyle producirn una lnea continua (el valor de DrawStyle no se modifica). Si se
establece 1 en DrawWidth, DrawStyle producir los resultados mostrados en la tabla de
esta propiedad.
DriverName
Devuelve el nombre del controlador de un objeto Printer. Esta propiedad es solo de lectura
Sintaxis
Printer.DriverName
Printer.Duplex [= valor]
Donde valor es un valor o constante que especifica el tipo de impresin, tal como se
describe a continuacin
Constante
actual.
Valor
bPRDPSimplex
Descripcin
1
vbPRDPHorizontal
vbPRDPVertical
Con impresin a doble cara horizontal, la parte superior de ambas caras de la hoja estn
en el mismo borde de la hoja. Con impresin a doble cara vertical, la parte inferior de una
pgina est en el mismo borde de la hoja que la parte superior de la pgina siguiente.
Vase el grfico existente en la ayuda de VB para la propiedad Duplex
FillColor
Devuelve o establece el color usado para rellenar formas; FillColor tambin se usa para
rellenar crculos y cuadros creados con los mtodos grficos Circle y Line.
Sintaxis
Printer.FillColor [ = valor]
Donde valor es un valor o constante que determina el color de relleno. El valor puede
introducirse como RGB o con las constantes QB color
269
ejemplos
FillColor = QBColor(8)
FillColor = RGB (255,0,0)
El color predeterminado es el 0 (Negro).
FillStyle
Devuelve o establece el modelo usado para rellenar dibujos (crculos y los cuadros creados
con los mtodos grficos Circle y Line.
Sintaxis
printer.FillStyle [= nmero]
Donde nmero Un entero que especifica el estilo de relleno, tal como se describe a
continuacin
Valor
Descripcin
0
1
2
3
4
5
6
7
Continuo.
(Predeterminado) Transparente.
Lnea horizontal.
Lnea vertical.
Diagonal hacia arriba.
Diagonal hacia abajo.
Cruzado.
Diagonal Cruzada.
numerodefuentes = Printer.FontCount
FontName
Devuelve el nombre de la fuente que est usando el objeto Printer
270
Sintaxis
nombredelafuente = Printer.Fontname
(El Objeto Printer admite esta propiedad como Font.Name o FontName indistintamente)
Fonts
Devuelve todos los nombres de fuente disponibles para el dispositivo de presentacin
actual o la impresora activa.
Sintaxis
Printer.Fonts(ndice)
La propiedad Fonts funciona de forma conjunta con la propiedad FontCount, que devuelve
el nmero de nombres de fuente disponibles para el objeto. Las fuentes disponibles en
Visual Basic varan de acuerdo con la configuracin del sistema, y los dispositivos de
presentacin y de impresin. Use las propiedades Fonts y FontCount para obtener
informacin sobre las fuentes disponibles para pantalla o impresora.
Por ejemplo, si queremos ver en Label1 todas las fuentes disponibles para el objeto
Printer, estableceremos el siguiente cdigo :
For i = 1 To Printer.FontCount
Label1.Caption = Label1.Caption + " " + Printer.Fonts(i)
Next i
FontSize
Devuelve o establece el tamao de la fuente a utilizar para el texto mostrado en un control
o en una operacin de dibujo o impresin en tiempo de ejecucin.
Sintaxis
Printer.FontSize = puntos
Donde puntos es una expresin numrica que especifica el tamao de fuente a utilizar, en
puntos.
Puede utilizar esta propiedad para dar al texto el tamao que desee. El valor
predeterminado lo determina el sistema. Para cambiar este valor, especifique el nuevo
tamao de la fuente en puntos.
El valor mximo de FontSize es 2160 puntos.
Nota Las fuentes disponibles en Visual Basic varan dependiendo de la configuracin del
sistema y de los dispositivos de presentacin e impresin. En las propiedades relacionadas
con las fuentes slo pueden establecerse valores para los que exista una fuente.
(El objeto Printer acepta tanto Font.Size como FontSize)
FontBold, FontItalic, FontStrikethru y FontUnderline
Devuelve o establece los estilos de fuente en los siguientes formatos: Negrita, Cursiva,
Tachada y Subrayada.
con
Printer.FontBold [= lgico]
Printer.FontItalic [= lgico]
Printer.FontStrikethru [= lgico]
Printer.FontUnderline [= lgico]
letra negrita
271
FontTransparent
Devuelve o establece un valor Booleano que determina si el texto y los grficos de fondo
de un objeto Printer, se muestran en el espacio situado entre los caracteres.
Sintaxis
Printer.hDC
Width
Devuelven o establecen las dimensiones del objeto Printer. No estn disponibles en tiempo
de diseo.
272
Sintaxis
Printer.Height = nmero
Printer.Width = nmero
Donde nmero indica las dimensiones del papel configurado para el dispositivo de
impresin. No disponibles en tiempo de diseo. Si se establecen en tiempo de ejecucin,
los valores de estas propiedades se utilizarn en lugar del de la propiedad PaperSize.
Para el objeto Printer, estas propiedades se miden siempre en twips. Si establece las
propiedades Height y Width para un controlador de impresora que no admite su uso, no
se producir ningn error, y el tamao del papel continuar siendo el mismo.
Printer.Orientation = valor
Valor
Descripcin
vbPRORPortrait
vbPRORLandscape
Page
Devuelve el nmero de pgina actual.
Sintaxis
actual
Variable = Printer.Page
Printer.PaperBin = valor
Constante
Valor
Descripcin
vbPRBNUpper
vbPRBNLower
vbPRBNMiddle
vbPRBNManual
vbPRBNEnvelope
vbPRBNEnvManual
1
2
3
4
5
6
vbPRBNAuto
vbPRBNTractor
vbPRBNSmallFmt
9
vbPRBNLargeFmt
10
vbPRBNLargeCapacity
capacidad.
vbPRBNCassette
14
PaperSize
Devuelve o establece un valor que indica el tamao de papel para la impresora actual. No
disponible en tiempo de diseo. El valor predeterminado es el establecido en la
configuracin de la impresora en Windows.
Con esta propiedad no se debe jugar
alegremente. El valor que se le d a esta propiedad ser el tamao de ese papel ficticio
que comentbamos mas atrs.
Sintaxis
Printer.PaperSize = valor
valor es un valor o constante que especifica el tamao del papel, segn se describe a
continuacin
Constante
Valor Descripcin
vbPRPSLetter
vbPRPSLetterSmall
vbPRPSTabloid
vbPRPSLedger
vbPRPSLegal
vbPRPSStatement
vbPRPSExecutive
vbPRPSA3
vbPRPSA4
vbPRPSA4Small
vbPRPSA5
vbPRPSB4
bPRPSB5
vbPRPSFolio
vbPRPSQuarto
vbPRPS10x14
vbPRPS11x17
vbPRPSNote
1
2
5
6
7
8
9
10
11
12
13
14
16
17
18
Carta, 8 x 11 .
Carta pequea, 8 x 11 .
3
Tabloide, 11 x 17 .
4
Libro, 17 x 11 .
Legal, 8 x 14 .
Declaracin, 5 x 8 .
Ejecutivo, 7 x 10 .
A3, 297 x 420 mm
A4, 210 x 297 mm
A4 pequeo, 210 x 297 mm
A5, 148 x 210 mm
B4, 250 x 354 mm
B5, 182 x 257 mm
Folio, 8 x 13 .
15
Cuarto, 215 x 275 mm
10 x 14 .
11 x 17 .
Nota, 8 x 11 .
274
vbPRPSEnv9
vbPRPSEnv10
vbPRPSEnv11
vbPRPSEnv12
vbPRPSEnv14
vbPRPSCSheet
vbPRPSDSheet
vbPRPSESheet
vbPRPSEnvDL
vbPRPSEnvC3
vbPRPSEnvC4
vbPRPSEnvC5
vbPRPSEnvC6
vbPRPSEnvC65
vbPRPSEnvB4
vbPRPSEnvB5
vbPRPSEnvB6
vbPRPSEnvItaly
vbPRPSEnvMonarch
vbPRPSEnvPersonal
vbPRPSFanfoldUS
vbPRPSFanfoldStdGerman
vbPRPSFanfoldLglGerman
vbPRPSUser
19
20
21
22
23
24
25
27
29
30
28
31
32
33
34
35
36
37
38
39
40
41
256
puertousado = Printer.Port
El sistema operativo determina el nombre del puerto, como por ejemplo LPT1: o LPT2:.
PrintQuality
Devuelve o establece un valor que indica la resolucin de la impresora. No disponible en
tiempo de diseo.
Sintaxis
Printer.PrintQuality = valor
Valor
Descripcin
vbPRPQDraft
vbPRPQLow
vbPRPQMedium
vbPRPQHigh
-1
-2
-3
-4
Resolucin
Resolucin
Resolucin
Resolucin
borrador
baja
media
alta
275
Printer.ScaleHeight = valor
Printer.ScaleWidth = valor
Donde valor es una expresin numrica que especifica la medida horizontal o vertical. Este
valor va a determinar el nmero de unidades de medida que tiene el papel, NO su medida.
Es decir, podemos decir, mediante estas propiedades, que el papel tiene 2100 unidades de
ancho y 2970 unidades de alto. Si el papel es un DIN A4 (Medidas 210 x 297 mm) esa
unidad de medida sera precisamente una dcima de milmetro. Podramos haber elegido
otros valores, con lo que esa unidad de medida ya no seran dcimas de mm. Sera una
unidad de medida cualquiera, pero el papel seguira siendo DIN A4 y seguira teniendo las
mismas medidas reales.
ScaleLeft, ScaleTop
Devuelven o establecen las coordenadas horizontal (ScaleLeft) y vertical (ScaleTop) de
los
bordes izquierdo y superior de un objeto al utilizar mtodos grficos o al situar controles.
Sintaxis
Printer.ScaleLeft = valor
Printer.ScaleTop = valor
donde valor es una expresin numrica que especifica la coordenada horizontal o vertical.
El valor predeterminado es 0.
Con estas propiedades y las relacionadas ScaleHeight y ScaleWidth, puede configurar un
sistema de coordenadas completo, con coordenadas positivas y negativas. Estas cuatro
propiedades de escala se relacionan con la propiedad ScaleMode de la siguiente forma:
Al establecer un valor en cualquier otra propiedad de escala, en ScaleMode
automticamente 0.
Al establecer en ScaleMode un nmero mayor que 0, ScaleHeight y
cambian a la nueva unidad de medida, y en ScaleLeft y ScaleTop se
Adems, los valores de CurrentX y CurrentY cambian para reflejar
coordenadas del punto actual.
se establece
ScaleWidth
establece 0.
las nuevas
Resumindolo en palabras mas sencillas. Si, con las medidas de los ejemplos anteriores
(ScaleWidth = 2100, ScaleHeight = 2970) ponemos Printer.ScaleLeft = - 1050 estamos
diciendo que la coordenada horizontal absoluta en la parte izquierda de la hoja es de
-1050. Si el ancho del papel es de 2100, la coordenada X absoluta del eje central del papel
ser entonces 0. Y la coordenada X de la parte derecha del papel ser + 1050. Por lo
tanto, si ejecutamos el mtodo grfico :
Printer.Circle (0,1000), 300
276
dibujar un circulo de radio 300, con el centro en el eje vertical de la hoja (Coordenada
X=0) a una altura de 1000 (Coordenada Y=1000) de la parte superior del papel.
Si hubisemos puesto Printer.ScaleTop = - 1500 estaramos diciendo que la coordenada Y
absoluta de la parte superior del papel es - 1500. En ese caso, el crculo anterior se
colocara a una distancia de 2500 (2500 = 1000 + 1500) del borde superior del papel.
ScaleMode
Devuelve o establece un valor que indica la unidad de medida de las coordenadas de un
objeto al utilizar mtodos grficos, o al situar controles.
Sintaxis
Printer.ScaleMode = valor
donde valor es un nmero entero que especifica la unidad de medida, segn se describe a
continuacin
0
1
2
3
4
5
6
7
Recomendacin del autor de esta Gua del Estudiante. Una vez mas recomiendo que
controle la posicin de los mtodos grficos y mtodo Print fijando las unidades de medida
mediante ScaleHeight, ScaleWidth, (Si le es prctico, emplee ScaleLeft y ScaleTop para que
le coincida el punto central del papel con las coordenadas 0,0 y as usara coordenadas
positivas y negativas) y cada vez que escriba o dibuje, coloque el cursor de escritura
mediante las propiedades CurrentX y CurrentY
TrackDefault
Devuelve o establece un valor booleano que determina si el objeto Printer apunta siempre
a la misma impresora, o si la impresora a la que apunta cambia cuando se modifica la
impresora predeterminada en el Panel de control del sistema operativo. No disponible en
tiempo de diseo.
Sintaxis
Printer.TrackDefault = lgico
Donde lgico es una expresin booleana que determina la impresora a la que apunta el
objeto Printer, segn se describe a continuacin.
True (Predeterminado) El objeto Printer cambia la impresora a la que apunta al modificar
la impresora predeterminada en el Panel de control del sistema operativo.
False El objeto Printer contina apuntando a la misma impresora cuando se modifica la
impresora predeterminada en el Panel de control del sistema operativo.
277
Printer.TwipsPerPixelX
Printer.TwipsPerPixelY
En general, las rutinas del API de Windows requieren las medidas en pxels. Puede utilizar
estas propiedades para convertir rpidamente las dimensiones sin cambiar el valor de la
propiedad ScaleMode de los objetos.
Zoom
Devuelve o establece el porcentaje en que se ampla o reduce el resultado impreso. No
est disponible en tiempo de diseo.
Sintaxis
Printer.Zoom = numero
Nota
Si la coleccin Printers se usa para especificar una impresora concreta, como
Printers(3), slo se puede tener acceso a sus propiedades de modo lectura. Para leer y
escribir las propiedades de una impresora concreta, primero se tiene que definir como
impresora predeterminada de la aplicacin.
METODOS DEL OBJETO PRINTER
Circle
Dibuja un crculo, elipse o arco sobre un objeto. No acepta argumentos con nombre.
Sintaxis
Printer.EndDoc
Printer.KillDoc
279
Sintaxis
Printer.NewPage
Printer.Print lista_salida
Hola
Qu tal ?
Si pusisemos
Printer.Print Hola ;
Printer.Print Qu tal ?
Hola Qu tal ?
Nota Debido a que el mtodo Print imprime normalmente con caracteres de espaciado
proporcional, es importante recordar que no hay relacin entre el nmero de caracteres
impresos y el nmero de columnas de anchura fija que tales caracteres ocupan. Por
ejemplo, una letra ancha, como W, ocupa ms de una columna de anchura fija, mientras
que una letra estrecha, como I, ocupa menos. Para tener en cuenta los casos en el que se
utilizan caracteres con una anchura mayor que la media, deber asegurarse de que las
columnas de las tablas se encuentren lo bastante lejos unas de otras. Como alternativa,
puede utilizar en la impresin una fuente de anchura fija (como Courier) para hacer que
cada carcter utilice slo una columna.
Para controlar perfectamente el punto donde se escribir el siguiente carcter, utilice las
propiedades CurrentX y CurrentY. Es mucho mas prctico que usar, por ejemplo, el
Tabulador Tab(n)
Si usa Tab(n) con una determinada impresora, puede verse con la desagradable sorpresa
que en otra impresora no funciona de la misma forma. Como al desarrollar una aplicacin
nunca sabe sobre que impresora va a imprimir, es mejor que no utilice Tab(n),
sustituyndolo por CurrentX.
Mtodo TextWidth
Puede conocer la anchura que va a ocupar un texto en la impresora. (o en un Formulario,
en un Picture) usando el Mtodo TextWidth
AnchodelTexto = Printer.TextWidth (Textoaescribir)
Donde AnchodelTexto es una variable tipo Long que indicar el ancho (en las unidades
de medida definidas para el objeto Printer - Twips, Pixels, mm, o como siempre
recomendar, las establecidas mediante ScaleWidth y ScaleHeight) y Textoaescribir es una
variable tipo String que contiene el texto a escribir.
Si la cadena de texto cuya longitud de impresin queremos analizar contiene retornos de
carro, TextWidth devuelve la anchura de la lnea ms larga.
Mediante este mtodo puede escribir columnas de datos, mucho mejor que usando el
Tab(n).
Suponga que quiere escribir en una columna, los datos Dato(1), Dato(2), ....Dato(N) que
son nmeros. Quiere escribirlos de tal forma que la parte derecha del nmero quede
alineada, como hacemos casi siempre para poder sumarlos con facilidad. Supongamos que
hemos establecido las Propiedades Printer.ScaleWidth = 21000 y Printer.ScaleHeight =
29700. Damos por hecho que el papel es un DIN A-4 (210 x 297 mm) por lo que estamos
usando, como unidad de medida en ambas coordenadas la centsima de mm.
Si queremos que las cifras queden alineadas en una columna cuya parte final sea 5000 (la
parte final de esa columna quedar a 50 mm. del margen izquierdo del papel), deberemos
calcular la longitud de cada cifra, y poner, como inicio de escritura de esa cifra 5000 ancho :
281
Observe que el ancho de una determinada cadena de caracteres no tiene porqu ser la
misma para un Formulario que para el Printer. Depender del tipo de fuente y del tamao
de esa fuente que usemos en cada caso. Por eso, debe poner siempre Printer.TextWidth,
Form1.TextWidth, etc.
Mtodo TextHeight
Este mtodo es idntico al anterior, pero relativo a la altura. No vamos a alargar la
explicacin dada la similitud con el anterior. Este mtodo nos permite separar
adecuadamente las lneas de un escrito. Es muy til sobre todo cuando utilizamos distintos
tipos de letra dentro del mismo escrito.
Mtodo PSet
Asigna a un punto de un objeto Printer un color especificado. No acepta argumentos con
nombre.
Sintaxis
Step
Opcional. Palabra reservada que especifica que las coordenadas son relativas
a la posicin grfica actual proporcionada por las propiedades CurrentX y CurrentY.
(x, y)
Requeridos. Valores de simple precisin que indican las coordenadas
horizontales (eje x) y verticales (eje y) del punto a establecer.
color Opcional. Valor entero largo que indica el color RGB especificado para el punto. Si
se omite, se utiliza el valor de la propiedad ForeColor. Puede utilizar la funcin RGB o la
funcin QBColor para especificar el color.
El tamao del punto dibujado depende del valor de la propiedad DrawWidth. Cuando
DrawWidth es 1, PSet establece un pxel al color especificado. Cuando DrawWidth es
mayor que 1, se centra el punto en las coordenadas especificadas.
La forma en que se dibuja el punto depende de los valores de las propiedades DrawMode
y DrawStyle.
Cuando se ejecuta PSet, las propiedades CurrentX y CurrentY toman el valor del punto
especificado en los argumentos.
Vace un pxel con el mtodo PSet especificando las coordenadas del pxel y utilizando el
valor de la propiedad BackColor como argumento color.
Visual Basic - Gua del Estudiante Cap. 8
282
LA FUNCION SHELL
LA FUNCION COMMAND PARA PASAR PARAMETROS
LA FUNCION DoEvents
Cajas de mensaje (Mensaje Box)
Cajas de entrada de datos (Input Box)
El Objeto APP (La Aplicacin)
LA FUNCION SHELL
La funcin Shell se utiliza para ejecutar un programa ajeno a la aplicacin que se est
ejecutando. Imaginemos que tenemos una aplicacin Visual Basic que necesita, por
ejemplo, establecer una comunicacin telefnica, y que esa comunicacin telefnica nos la
realiza un programa desarrollado en C++ , llamado MARCADOR.EXE que funciona
perfectamente y no queremos desaprovechar. Imaginemos que ese programa tiene la
posibilidad de introducirle el nmero telefnico que debe marcar como un parmetro. Este
parmetro se le introduce, supongamos, aadiendo el nmero al nombre del programa
ejecutable. Por ejemplo:
MARCADOR.EXE 1234567
En nuestra aplicacin Visual Basic introduciremos una lnea invocando la funcin Shell
seguida del nombre (y Path) del ejecutable y del parmetro que le vamos a introducir al
ejecutable:
Shell "C:\VB\MARCADOR.EXE 080"
Mediante esta lnea, lo que hacemos es ejecutar el programa MARCADOR.EXE e introducirle
como parmetro el nmero a marcar. Resultado: el programa MARCADOR.EXE llama al
nmero 080 (Bomberos), y una vez establecida la llamada podemos pasarle a ese
Organismo datos o lo que nuestra aplicacin haga.
Veamos que dice la Ayuda de VB respecto a la Funcin Shell:
Ejecuta un programa ejecutable.
Sintaxis
donde:
Variable es identificador de la tarea (ID)
rutaDeAcceso es el nombre del programa por Ejecutar (con su Path) y cualquier
argumentos o conmutadores (switches) de lnea de comando requeridos; puede incluir
directorio o carpeta y unidad de disco. Tambin puede ser el nombre de un documento que
se ha asociado con un programa ejecutable.
estiloDeVentana es el nmero correspondiente al estilo de la ventana en la cual se va a
ejecutar el programa. En Microsoft Windows, si se omite estiloDeVentana, el programa se
inicia minimizado con enfoque.
El argumento con nombre estiloDeVentana tiene estos valores:
Constante
Valor
Descripcin
vbHide
283
vbNormalFocus
tamao
vbMinimizedFocus
vbMaximizedFocus
vbNormalNoFocus
1
2
3
4
vbMinimizedNoFocus 6
Comentarios
original.
La ventana se muestra como un icono con foco.
La ventana se maximiza con foco.
La ventana vuelve al tamao y posicin ms recientes. La
ventana activa actual permanece activa.
La ventana se muestra como un icono. La ventana activa
actual permanece activa.
284
285
La ventana DOS del ARJ tiene el Caption Finalizado - ARJ cuando ya ha terminado el
proceso. En el procedimiento ExecCmdNoFocus se analiza si esa ventana est presente
(prueba de que ARJ ya ha terminado, pues antes de terminar tiene otro Caption).
Para llamar a ese procedimiento hay que citarle por su nombre (ExecCmdNoFocus) que
como lo hemos declarado Public en un Mdulo, podemos llamarle desde cualquier parte de
la aplicacin. Debemos pasarle el parmetro CmdLine, que ser el programa que vamos a
ejecutar con Shell y los parmetros adicionales que este programa necesite (En este caso,
el programa es ARJ.EXE y a continuacin debe indicrsele el nombre del archivo ya
comprimido, a continuacin
a para que aada mas ficheros a ese archivo, y a
continuacin el nombre de ese fichero o ficheros a aadir :
El parmetro CmdLine del procedimiento es todo lo que va entre parntesis.
ExecCmdNoFocus ("C:\DirA\ARJ.EXE a C:\DirB\Fichero1.Ext")
NO se preocupe si no lo entiende ahora. Es difcil.
286
LA FUNCION COMMAND
En el ejemplo anterior usbamos un ejecutable realizado en C++ para marcar un nmero
telefnico que le introducamos como parmetro. Podemos hacer eso en una aplicacin
VB? La respuesta debe ser SI. Usaremos para ello la funcin Command. Esta funcin nos
devuelve el parmetro introducido tras el nombre del ejecutable realizado en VB, cuando
iniciamos la aplicacin VB mediante la lnea de comandos de Windows (lnea Archivo |
Ejecutar del Men de Windows 3.xx o lnea Ejecutar de W95), o desde otra aplicacin
utilizando la funcin Shell.
Veamos tambin en este caso lo que dice la Ayuda de VB:
Command (Funcin)
Devuelve parte del argumento de la lnea de comandos utilizada para lanzar Microsoft
Visual Basic o un programa ejecutable desarrollado con Visual Basic.
Cuando se inicia Visual Basic desde la lnea de comandos, la parte de la lnea de comandos
que sigue a /CMD se pasa al programa como un argumento de la lnea de comandos. En el
siguiente ejemplo, cmdlineargs representa la informacin de argumento devuelta por la
funcin Command.
VB /CMD cmdlineargs
En las aplicaciones desarrolladas con Visual Basic y compiladas en un archivo .EXE,
Command devuelve los argumentos que aparezcan en la lnea de comandos tras el nombre
de la aplicacin. Por ejemplo:
MyApp cmdlineargs
En la ventana Cdigo, puede usted cambiar el texto devuelto por Command eligiendo
Opciones del proyecto en el men Herramientas.
Veamos con un par de ejemplos como se pueden usar estas dos funciones:
Marcador Telefnico
Esta aplicacin debe marcar un nmero telefnico. El nmero a marcar se le pasar como
parmetro tras el nombre de la aplicacin. La aplicacin ya compilada se llamar
MARCADOR.EXE. Para marcar un nmero debemos poner, en la lnea de Comando de
Windows:
Marcador.exe 1234567
o como ya sabemos, introducirle el parmetro mediante una llamada con la funcin Shell
desde otra aplicacin:
Shell Marcador.exe 1234567
Como no vamos a realizar llamada alguna, sino comprobar que esto puede funcionar,
nuestra pequea aplicacin tendr solamente un Label llamado FRMARCADORL1 donde
presentaremos el nmero a marcar. Todo el cdigo necesario se lo metemos en el
procedimiento Activate del formulario:
Private Sub Form_Activate()
FRMARCADORL1.Caption = Command
287
End Sub
Tambin podemos pasar parmetros a un ejecutable, mediante el Drag & Drop de
Windows.
Hemos visto mas atrs como podemos hacer Drag & Drop en una aplicacin VB. Pero como
comentbamos, el D&D no es una funcin de VB, sino de Windows. Y Windows lo utiliza en
su Explorador de Windows para pasar como parmetro a una aplicacin el nombre del
fichero que arrastremos hacia el icono que representa a esa aplicacin. Como estoy
seguro que se ha liado, vamos con un ejemplo.
Si Vd. hace un editor de textos (Editor.EXE) que soporta un formato determinado (por
ejemplo el RichTextFormat RTF), para ejecutar su programa y meterle como parmetro el
nombre del fichero Carta.RTF de forma que al arrancar lea directamente el fichero
Carta.RTF, basta con ir al Explorador de Windows, abrir la carpeta que contenga Carta.RTF,
arrastrar el nombre de ese fichero y llevarlo al icono que representa a Editor.EXE, que
imaginemos que le ha preparado un acceso directo. Suelte el botn del ratn y su editor se
ejecutar, y adems, le meter como parmetro el nombre del fichero Carta.RTF (con su
Path correspondiente) Si Ud. haba previsto la captura del Command tal como se explic
mas atrs, y ha preparado su aplicacin para que tome el contenido de Command y
entienda que tiene que abrir y cargar ese fichero, su aplicacin Editor.EXE cargar
automticamente ese fichero.
Observe que esta es la forma de trabajar de los
procesadores de texto usados normalmente (Word, WordPerfect, Write, etc.)
288
La Funcin DoEvents
Cede el control de la ejecucin al sistema operativo, para que ste pueda procesar otros
eventos. Tambin nos permite conocer el nmero de formularios abiertos en una
aplicacin.
Sintaxis
DoEvents
Cede el control al sistema operativo
Sintaxis
variable=DoEvents
variable contendr un nmero indicando el nmero de formularios abiertos
en
este momento.
La funcin DoEvents es una instruccin obligada en todos los bucles por condicin para
evitar que, en caso de meterse en un bucle infinito, podamos salir de el aunque sea
teniendo que pulsar las teclas Ctrl-Alt-Sup. Si no lleva esa lnea DoEvents, es posible que
tenga que resetaear el ordenador.
EJEMPLO
289
290
291
292
Habr observado en la expresin anterior que se ha utilizado vbCrLf (Visual Basic Carriage
Return Line Feed, VB retorno de carro y avance de lnea) Vea mas adelante la aclaracin
de esta expresin. Con ella logramos introducir un salto de lnea.
Supongo que se habr percatado de que entre el mensaje y el ttulo de la ventana, hemos
escrito dos comas, esto es porque entre las comas, debe ir un nmero que representar el
icono a mostrar. Existen cuatro iconos diferentes adems de la posibilidad de no mostrar
ninguno. Los iconos son:
VbCritical
VbQuestion
VbExcalamqtion
294
16
32
48
Mensaje de informacin.
VbInformation
64
Ahora bien, es posible que queramos mostrar algn otro botn que o bien no sea el de
Aceptar o que adems del botn de Aceptar haya ms botones. Para este propsito,
tenemos los siguientes parmetros:
Aceptar
Aceptar y Cancelar
Anular, Reintentar, Ignorar
S, No y Cancelar
S y No
Reintentar y Cancelar
Aplicacin modal
vbOKOnly
vbOKCancel
vbAbortRetryIgnore
vbYesNoCancel
vbYesNo
vbRetryCancel
vbApplicationModal
1
2
3
5
0 (Es la caja de mensaje sin
icono)
La forma de hacer esto es sumar al parmetro del icono que queremos mostrar el valor de
los botones que deseamos que aparezcan.
As por ejemplo:
MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo , "Ejemplo"
El resultado es:
An as, es posible que deseemos que el Focus lo adquiera otro un botn determinado. Por
ejemplo, en este caso el Focus lo tiene el botn S, pero es posible que deseemos que lo
tenga el botn No por ejemplo. Esto se consigue con los siguientes parmetros:
Primer botn predeterminado
vbDefaultButton1
0
Segundo botn predeterminado
vbDefaultButton2
256
Tercer botn predeterminado
vbDefaultButton3
512
Por ejemplo: MsgBox "Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo +
vbDefaultButton2, "Ejemplo"
295
El resultado es:
1
Cancelar
vbCancel
2
Anular
vbAbort
3
Reintentar
vbRetry
4
Ignorar
vbIgnore
5
S
vbYes
6
No
vbNo
7
As por ejemplo, el siguiente cdigo:
Dim Resp As Integer
Resp = MsgBox("Hola" & vbCrLf & "Esto es un ejemplo.", VbQuestion + vbYesNo +
vbDefaultButton2, "Ejemplo")
If Resp = 6 Then
MsgBox "Ha pulsado SI"
Else
MsgBox "Ha pulsado NO"
End If
Tiene el resultado siguiente:
296
Si pulsamos el botn S obtendremos una accin, y si pulsamos el otro botn otra accin.
Ahora bien, para elegir o seleccionar un evento o accin, el usuario debe saber combinar
los cdigos, sabiendo que un MsgBox posee la siguiente sintaxis principal:
MsgBox Mensaje, Botones, Ttulo de la ventana
InputBox
El InputBox o caja de entrada es otra de las partes ms utilizadas para la interaccin del
usuario con la aplicacin. Es importante que el usuario interacte con la aplicacin para ser
el protagonista de esta.
El InputBox nos permite sacar una caja donde el usuario pasar un parmetro, valor o dato
para que el programa lo trate y lo ejecute.
El mensaje que quiere que aparezca se realiza de forma casi idntica al MessageBox.
Puede escribirse varias lneas de texto seguidas por la constante de Visual Basic vbCrLf o
salto de lnea o prrafo.
La sentencia es:
Val almacenar el texto escrito por el usuario, que puede ser una cantidad, cadena string,
etc.
Por ejemplo:
Dim Val As String
Val = InputBox("Deme su nombre", "Ejemplo")
MsgBox "Su nombre es: " & Val
Tiene como resultado:
(El usuario teclea el nombre - Mundo Visual - y hace click en Aceptar. A continuacin se
muestra el MsgBox - 2 lnea del cdigo anterior )
297
Ahora bien, podemos determinar un texto predeterminado a la caja de entrada, como por
ejemplo:
Dim Val As String
Val = InputBox("Deme su nombre", "Ejemplo", "Mundo Visual")
MsgBox "Su nombre es: " & Val
Obtendremos como resultado:
298
El Objeto App
El objeto App representa a la aplicacin. Es el objeto Visual Basic que contiene diversas
informaciones acerca de la Aplicacin.
Alguna de estas informaciones se le pueden introducir al proyecto en tiempo de diseo, en
el cuadro de Opciones. Para ello basta con ir, en la Barra de Men de Visual Basic a
Herramientas | Proyecto | Opciones y hacer click en Proyecto. Otra parte donde se
introducen es en el cuadro de dilogo Opciones de EXE. Para ver este cuadro proceda de la
misma forma que si fuese a crear un archivo .EXE de la Aplicacin, Haga click en Archivo
| Crear Archivo EXE de la Barra de Men, y una vez que le aparezca el cuadro de dilogo
para introducir el nombre, haga click en OPCIONES.
Estas informaciones son las Propiedades del objeto App. Este objeto no tiene Mtodos ni
Eventos.
Comments (Propiedad)
Devuelve o establece una cadena que contiene comentarios sobre la aplicacin en
ejecucin. Es de slo lectura en tiempo de ejecucin.
Sintaxis
MiVariable = App.Comments
(Propiedad)
Devuelve o establece un valor de tipo String que contiene el nombre de la empresa o del
creador de la aplicacin en ejecucin. Es de slo lectura en tiempo de ejecucin.
Sintaxis
Mivariable = App.CompanyName
(Propiedad)
Devuelve el nombre raz (sin la extensin) del archivo ejecutable que se est ejecutando
actualmente. Si se utiliza en el entorno de desarrollo, devuelve el nombre del proyecto.
Sintaxis
MiVariable = App.EXEName
Esta propiedad se establece bien en el cuadro de Opciones, bien al guardar el archivo .EXE
FileDescription
(Propiedad)
Devuelve o establece un valor de tipo String que contiene informacin de los archivo de la
aplicacin en ejecucin. Es de slo lectura en tiempo de ejecucin.
Sintaxis
Mivariable = App.FileDescription
299
HelpFile (Propiedad)
Ya comentada mas atrs. Especifica el nombre (con su Path) del fichero de ayuda. Se
introduce en tiempo de diseo en el cuadro de Opciones. Puede cambiarse en tiempo de
ejecucin.
hInstance
(Propiedad)
VariableLong = App.hInstance
(Propiedad)
Mivariable = App.LegalCopyright
(Propiedad)
Devuelve o establece un valor de tipo String que contiene informacin de marca registrada
sobre la aplicacin en ejecucin. Es de slo lectura en tiempo de ejecucin.
Sintaxis
MiVariable = App.LegalTrademarks
MiVariable = App.Major
MiVariable = App.Minor
MiVariable = App.Revision
300
Mediante las propiedades Major, Minor y Revision obtenemos la versin del programa. Es
muy util conocer la version del programa para saber si lo hay que actualizar. Por ejemplo,
la instruccin:
MiVariable = App.Major & . & App.Minor & . & App.Revision
Puede devolver un dato parecido a este:
MiVariable = 2.1.4
As conocemos que la versin del programa es la 2.1.4. Estos datos de Major, Minor y
Versin hay que introducirlos en el programa durante el tiempo de diseo. Se usa para ello
la caja de Propiedades del Proyecto
Path (Propiedad)
Especifica la ruta de acceso del archivo .VBP de proyecto cuando se ejecuta la aplicacin
desde el entorno de desarrollo o la ruta de acceso del archivo .EXE cuando se ejecuta la
aplicacin como un archivo ejecutable.
Esta propiedad es sumamente til. Cuando se realiza una aplicacin, no es prudente
obligar al usuario a meterla dentro de un determinado directorio impuesto por el
programador. Si no es as, no sabremos en qu directorio est el ejecutable, y es muy
conveniente saberlo, sobre todo cuando se utilizan ficheros auxiliares de inicializacin, que
deberan estar en el mismo directorio de la aplicacin. Si queremos abrir el fichero
MiAplicacion.Cfg que estar obligatoriamente en el mismo directorio de la aplicacin
(aunque no conocemos su nombre), solamente tenemos que poner la lnea de cdigo :
Open App.Path & \MiAplicacion.ICfg For Input as # 1, sin importarnos cual es el nombre
real de ese directorio.
PrevInstance (Propiedad)
Devuelve un valor booleano que indica si hay ya en ejecucin una instancia anterior de una
aplicacin. Es muy utilo saber que hay una instancia del programa en ejecucin para
impedir que se vuelva a abrir otra.
Sintaxis
VariableBooleana = App.PrevInstance
MiVariable = App.ProductName
StartMode (Propiedad)
Devuelve o establece un valor que determina si una aplicacin se inicia como proyecto
independiente o como servidor de automatizacin OLE. De slo lectura en tiempo de
ejecucin.
Sintaxis
VariableLong =App.StartMode
Valor
vbSModeStandalone 0
vbSModeAutomation 1
Descripcin
(Predeterminado) La aplicacin se inicia como proyecto
independiente.
La aplicacin se inicia como servidor de automatizacin OLE.
TaskVisible (Propiedad)
Devuelve o establece un valor que determina si la aplicacin aparece en la lista de tareas
de Windows.
Sintaxis
VariableBooleana = App.TaskVisible
Valor ser una expresin de cadena que especifica el ttulo de la aplicacin. La longitud
mxima de valor es 40 caracteres.
Esta propiedad est disponible en tiempo de diseo en el cuadro de dilogo del comando
Crear EXE del men Archivo.
Todos estos datos figuran en el archivo de proyecto (.VBP). Puede verse editndolo con el
Block de Notas de Windows, e incluso pueden modificarse estas propiedades directamente
sobre ese archivo.
Visual Basic - Gua del Estudiante Cap. 9
INTERFACE DE DOCUMENTOS MULTIPLES. (Multiple Document Interface MDI )
EL CONTROL RICH TEXT BOX
302
303
304
En realidad una Clase es la definicin de un objeto Visual Basic. Un objeto Visual Basic
puede ser un Formulario, un control, un objeto de acceso a datos.
La Instancia es la rplica de una clase. Puede ser la rplica de un Formulario, de un
control o de otro objeto. La Instancia lleva las mismas Propiedades que la clase. Se dice
que hereda las propiedades. (Excepto la propiedad Visible, que siempre, por defecto,
aparece a False). Cuando se vara una propiedad de una Instancia, no se altera el valor de
esa propiedad en la Clase ni en ninguna de las restantes Instancias.
Despus de toda esta teora, podemos saber como se crea una Clase de un formulario ? O
dicho de manera mas coloquial, Cmo se crea un Formulario para poder hacer varias
fotocopias de l ?
La respuesta es obligatoriamente mas sencilla que la teora. Con el formulario vaco que
tengamos en el proyecto (Insertemos un Formulario si fuese necesario) pongmosle todos
los controles que deseemos. Le podemos poner un Men y cambiar a nuestro antojo todas
sus propiedades. Entre ellas, la propiedad MDIChild. Si vamos a introducir las Instancias
de ese Formulario en un Formulario MDI esa propiedad debe estar a True, y por lo tanto
sus Instancias saldrn igualmente con esa propiedad a True. Pongmosle un nombre y ya
est creada la clase. Supongamos que ese nombre es FormularioHijo
Para crear ahora Instancias de ese Formulario podemos hacerlo de dos formas :
Declarar una variable tipo Objeto. No se asuste. Para declarar que una variable es un
Formulario basta con declararla de la siguiente forma :
Dim MiVentana As Form
Esta variable debe declararla en sitio adecuado para su aplicacin, y el mbito de esa
variable objeto ser el mismo que para cualquier tipo de variable. (Vea Ambito de las
Variables) La sentencia a utilizar para la declaracin ser Dim, Private, Public o Global
tal como se explic para las variables.
Una vez declarada como variable puede hacerla igual a un objeto existente que servir de
modelo (Una Clase) que estar definida por un nombre: (P.e. FormularioHijo)
Set MiVentana = New FormularioHjo
Podemos hacer las dos operaciones a un tiempo : declarar y crear la copia :
Dim MiVentana As New FormularioHijo
Una vez creado la instancia del formulario debemos cargarlo en el Formulario Padre. Para
cargarlo debemos emplear la sentencia Load MiVentana, con lo que quedar cargado en
la memoria, pero, dependiendo de como est la propiedad AutoShowChildren del
Formulario Padre se mostrar o no se mostrar. Para que se muestre, independientemente
de como est esa propiedad, basta con ejecutar MiVentana.Show. En realidad mediante
el mtodo Show un formulario no solamente se muestra, sino que tambin se carga en la
memoria si no estuviese previamente cargado. Por lo tanto podamos habernos ahorrado la
instruccin anterior para cargarlo Load MiVentana
Es muy prctico poner un Caption distinto a cada formulario que se introduzca, caso de
introducirse varios formularios hijo iguales. El Caption es una propiedad y por lo tanto
todas las instancias heredan el Caption de la Clase. Sera prudente distinguir un formulario
de otro mediante su Caption, es decir mediante su barra de ttulo.
305
Para ello podemos crear un contador en el mismo procedimiento en el que creamos una
nueva instancia, y poner el Caption de cada nuevo Formulario siguiendo un orden numeral.
Documento 1, Documento 2, Documento 3, etc.
Ese procedimiento quedar de la siguiente forma :
Static contador As Integer
Dim MiVentana As New FormularioHijo
MiVentana.Caption = Documento & Str (contador)
MiVentana.Show
Referencias a los Formularios. ActiveForm y Me
Si queremos nombrar un Formulario Hijo dentro de una aplicacin MDI el primer problema
con el que nos encontramos es que todos los formularios hijo (Instancias de la misma
Clase) tienen el mismo nombre. Por lo tanto no podemos nombrarlas con ese nombre, ya
que la aplicacin no sabra a cual de ellas nos referimos.
Si el cdigo donde vamos a nombrar ese formulario est fuera de l (P.e. en el Formulario
Padre) deberemos referirnos al formulario hijo mediante ActiveForm. ActiveForm nos
va a indicar cual es el formulario que est actualmente activo. Un formulario est activo
cuando estamos trabajando sobre l. En ese momento tiene el foco. Permanece activo
desde que hacemos click con el ratn sobre cualquiera de sus partes, hasta que activamos
otro formulario. Es sencillo reconocer cual es el formulario activo pues tiene su barra de
ttulo con el color vivo.
Cada vez que hacemos una operacin sobre una parte de un formulario ste se pondr
activo. Por ejemplo, si el formulario es un documento de texto, y contiene el texto en un
RichTextBox de nombre RTB1, si queremos hacer una operacin con el texto desde un
botn colocado en el formulario padre (poner en negrita el texto seleccionado), haramos lo
siguiente :
ActiveForm.RTB1.SelBold = True
ya que siempre estaremos seguro de que el Formulario Activo es aquel en el que acabamos
de seleccionar el texto.
Si el botn donde hemos puesto el botn no es el formulario padre, sino el hijo, tenemos
un problema similar. Su nombre ser (con los ejemplos anteriores) MiVentana, y pueden
existir varios formularios con ese nombre, tantos como documentos hayamos introducido.
No podemos por tanto nombrarlo con su nombre, pues hay (o puede haber) varios.
Tampoco lo podemos nombrar con ActiveForm, ya que esta propiedad corresponde al
Formulario Padre. La solucin es nombrarle mediante Me. Me siempre se refiere al
formulario que contiene al procedimiento donde est esa palabra. Por lo tanto, si tenemos
un botn en el formulario hijo con la instruccin :
Me.RTB1.SelBold = True
Me se refiere concretamente a ese formulario.
Colocacin de los Formularios Hijo
Mtodo ARRANGE
Mediante el mtodo Arrange podemos distribuir los formularios hijo dentro del formulario
padre. Pueden colocarse en cascada, mosaico horizontal, mosaico vertical o como iconos.
306
Sintaxis
NFMDI.Arrange distribucin
donde
NFMDI = Nombre del Formulario MDI
distribucin puede tomar los siguientes valores o constantes :
Constante
Valor
Descripcin
vbCascade
minimizados
Dispone
todos
los
formularios
MDI
secundarios
no
vbTileHorizontal
minimizados
en cascada.
Dispone todos
los
formularios
MDI
secundarios
no
en mosaico horizontal.
2
Dispone todos los formularios MDI secundarios no
vbTileVertical
minimizados
VbArrangeIcons
en mosaico vertical.
Dispone los iconos de los formularios MDI minimizados.
Las ventanas o los iconos se pueden distribuir incluso si el objeto MDIForm est
minimizado. Los resultados son visibles cuando el objeto MDIForm se maximiza.
Posicin de los Formularios en el Eje Z
Mtodo ZOrder
Cuando tenemos varios formularios hijo, unos ocultan a los otros. Mucho mas si los
formularios estn maximizados. Podemos colocar un formulario hijo en la parte frontal del
montn de formularios (para que se vea completamente) o llevarle a la posicin mas atrs
mediante el Mtodo ZOrder.
Sintaxis
NFH.ZOrder posicin
307
308
Frente a la rigidez del TextBox, este control nos permite escribir un texto utilizando
distintos tipos de fuentes en el mismo texto, e introducir mas de 65.536 caracteres, lmite
mximo del TextBox. Aparte de estas, tiene otras caractersticas respecto a la forma de
guardar y leer el texto en un fichero, que le convierten en una herramienta muy til para el
diseo de aplicaciones en las que haya que introducir documentos de texto.
El RichTextBox puede utilizar indistintamente formato de texto Ascii (que le llamaremos
Texto Plano) o formato RTF (RichTextFormat, que llamaremos Texto enriquecido) El
formato de Texto enriquecido es un formato de intercambio entre procesadores de texto.
Vea al final del captulo una explicacin ms detallada de este formato de texto. De
momento basta con decir que permite poner tipos distintos de letras, de tamaos, de
colores, introducir grficos, y toda una serie de ventajas que le van a permitir realizar
procesadores de texto casi tan perfectos como los editores comerciales mas conocidos.
Esto nos permite por ejemplo, guardar estrictamente las letras que componen el texto
(Propiedad Text de RichTextBox) o guardar el texto, con sus letras y todos los adornos que
queramos ponerles (Tipos distintos de fuente, negrita, cursiva, ). Esto lo logramos con la
propiedad TextRTF del RichTextBox. Cuando hablamos de guardar, nos estamos refiriendo
lgicamente a guardarlo en un fichero en el disco, y tambin a guardarlo en el
portapapeles. Si tenemos un RichTextBox de nombre RTB (as le llamaremos en todos los
ejemplos) con un texto tal como
Te creas muy listo Flanahan, pero tus vacas no pasarn por mis tierras
La propiedad Text contendr los siguiente
RTB.Text = Te creas muy listo Flanahan, pero tus vacas no pasarn por mis tierras
La propiedad TextRTF contiene toda la informacin, pero eso s, en formato RTF
RTB.TextRTF={\rtf1\ansi\deff0\deftab720{\fonttbl{\f0\fswissMS
Sans
Serif;}
{\f1\froman\fcharset2
Symbol;}{\f2\fswiss\fprq2Arial;}}
{\colortbl\red0\green0\blue0;}\deflang1034\pard\li708\plain\f2\fs20 Te cre\'edas muy
listo \plain\f2\fs20\b\i Flanahan\plain\f2\fs20 , pero tus \plain\f2\fs24 vacas\plain\f2\fs20
no pasar\'e1n por \plain\f2\fs20\ul mis tierras\plain\f2\fs20
\par \pard\plain\f0\fs17
\par }
(Puede que el texto anterior tenga alguna diferencia sobre el real, debido a que hubo que
introducirle algn retorno de carro para poder presentarlo)
Veamos las propiedades de este control
309
SelStart
SelText
ningn
SelFontSize
SelColor
311
Al igual que las otras propiedades, si el texto seleccionado est al final del texto, o si el
cursor de escritura est al final del escrito, la propiedad elegida permanecer vigente para
la escritura que se realice a partir de ese punto.
Esta instruccin sustituye todo el contenido del RTB por el texto Siempre nos quedar Pars
Lectura:
MiVariable = RTB.Text
312
(Escritura)
RTB.SelRTF = MiVariable
313
314
La instruccin anterior fija como distancia mxima que puede ocupar una lnea de texto la
cantidad introducida en TBAncho. Por supuesto, expresada como siempre en las unidades
de medida del formulario. La lnea puede ser mas ancha que el ancho del RichTextBox. En
este caso la lnea no cabe en el RTB, pero puede visualizar la lnea completa usando baraas
de scroll horizontales (Vea propiedad ScrollBars ms adelante)
Sangra francesa. La sangra francesa consiste en separar la segunda lnea y siguientes
cierta medida a la derecha respecto a la primera lnea. Algo as
Esta es la primera lnea de este texto donde se explica lo que es una sangra francesa
en realidad desconozco si en Francia usan este tipo de sangra, pero a m
me gusta ms la sangra espaola, siempre que est bien fresquita.
Esto se logra mediante la propiedad SelHangingIndent y afecta nicamente al prrafo
donde se encuentra la lnea en curso.
Puede hacer lo que parece mas lgico, separar la primera lnea un poco respecto a las
dems, dando un valor negativo a la propiedad SelHangingIndent. Pero para que esto
resulte, debe poner un valor al menos igual a la propiedad SelIndent.
En el ejemplo
siguiente, hacemos una sangra solamente a la primera lnea del prrafo donde est la
lnea en curso:
RTB.SelIndent = Val(TBSangriaEsp)
RTB.SelHangingIndent = -Val(TBSangriaEsp)
(Observe el signo menos en la segunda lnea) El valor de la sangra de la primera lnea
ser el contenido en TBSangriaEsp
alinea a la izquierda
alinea a la derecha
centra el texto
315
316
La solucin est en poner la propiedad TabStop de todos los controles a False, cada vez
que el RichTextBox toma el foco. Es decir, en su procedimiento GotFocus. De esta forma,
al dar el tabulador ningn control se querr quedar con el foco, y por lo tanto el foco
seguir en el RichTextBox. En estas condiciones el resultado es que el cursor de escritura
pasar a la siguiente tabulacin.
Vamos a ver como se puede poner la propiedad TabStop a False en todos los controles del
formulario. Para ello vamos a explicar un nuevo objeto Visual Basic, el objeto Controls.
Este objeto es una coleccin, y est formada por todos los controles del formulario. Como
cualquier coleccin tendr una propiedad, la propiedad Count que toma el valor igual al
nmero de controles existentes en el formulario. Como cualquier cosa de VB formada por
varios elementos, cada uno de ellos se distingue por su ndice. Y este ndice comienza por
el 0 y termina por el n-1, siendo n = nmero de elementos de esa coleccin.
Para poner la propiedad TabStop a False en todos los controles de la coleccin Controls del
formulario, basta con poner este cdigo en el procedimiento GotFocus del RTB
Private Sub RTB_GotFocus()
Dim I As Integer
Con la siguiente lnea se evita el error producido en aquellos controles que no tienen la
propiedad TabStop
On Error Resume Next
For I = 0 To Me.Controls.Count - 1
Controls(I).TabStop = False
Next I
End Sub
Podemos hacerlo de otra forma. Declaremos una variable tipo Objeto Control
Private Sub RTB_GotFocus()
Dim Pepe As Control
On Error Resume Next
'De esta forma se evita el error producido en aquellos controles
que no tienen la propiedad TabStop
For Each Pepe In Controls
Pepe.TabStop = False
Next
End Sub
Nota. Si va a la informacin del RichTextBox podr ver un ejemplo de esto, con el
siguiente cdigo:
For Each Control In Controls
Control.TabStop = False
Next Control
Milagros del Visual Basic: As no funciona
Ya funciona perfectamente el tabulador en el RichTextBox. Pero cuando salgamos del
RichTextBox, debemos volver a poner la propiedad TabStop de todos los controles a True.
Para ello, en el procedimiento LostFocus del RTB pondremos el cdigo anterior, poniendo
True en vez de False en la propiedad TabStop.
Programar las medidas de las tabulaciones.
Propiedad SelTabCount
Establece el nmero de tabulaciones en un RTB. P.e., si queremos crear 5 tabulaciones
317
RTB.SelTabCount = 5
Propiedad SelTabs
Establece el valor numrico (separacin desde el borde izquierdo) de las tabulaciones.
Dado que pueden existir varias tabulaciones, deberemos distinguirlas entre ellas mediante
un ndice. El ndice para la primera tabulacin es el 0
RTB.SelTabs(0)
RTB.SelTabs(1)
RTB.SelTabs(2)
RTB.SelTabs(3)
tabulacin de
RTB.SelTabs(4)
=
=
=
=
1000
2000
3000
4000
= 5000
Con
estas
lneas
determinaramos
la
posicin
de
los 5 tabuladores.
Antes de darle valor a la propiedad SelTabs deberemos haber creado los tabuladores
mediante SelTabCount. Si pretende darle valor a un tabulador mayor que el nmero de
tabuladores real (por ejemplo, si pone en el caso anterior RTB.SelTabs(5) = 5000) le dar
un error.
Recuerde que los valores de los tabuladores debe darlos en las unidades de medida del
formulario.
OTRAS PROPIEDADES
Propiedad SelCharOffset
Nos permite crear subndices y superndices. La sintaxis es:
RTB.SelCharOffset = Nmero
Donde Nmero indica la separacin del superndice o subndice en Twips. Si Nmero es
positivo, obtendremos un superndice, si es negativo, un subndice.
Esta forma de escribir subndices y superndices se debe aplicar cada vez que queramos
escribir uno de ellos, e inmediatamente, poner esa propiedad a 0, ya que si no lo hacemos
as, escribira como subndice o superndice el resto del texto. P.e. para poner un
superndice:
TamIni = RTB.SelFontSize
RTB.SelFontSize = TamIni - 4
RTB.SelCharOffset = 40
RTB.SetFocus
Para restaurar los valores anteriores
RTB.SelFontSize = TamIni
RTB.SelCharOffset = 0
RTB.SetFocus
318
Propiedad SelProtected
Es una propiedad Booleana, que nos permite proteger contra cualquier cambio a una parte
del texto (o todo el texto) que contiene el RTB. Para proteger una parte del texto basta con
seleccionarla y a continuacin ejecutar la instruccin
RTB.SelProtected = True
Una vez protegida una parte del texto, esa parte no se puede variar. Puede desprotegerse,
volviendo a seleccionarla y ejecutando la instruccin:
RTB.SelProtected = False
Propiedad ScrollBars
Pone barras de desplazamiento al RichTextBox.
Esta propiedad puede establecerse a 0 (None, ninguna), a 1 (Horizontal), 2 (Vertical) o 3
(Both, ambas). Cuando las barras de desplazamiento no son necesarias, bien porque hay
pocas lneas, bien porque hay pocos caracteres por lnea, las barras de desplazamiento
estn desactivadas.
Es frecuente pensar que las barras de desplazamiento horizontal no funcionan. Y eso
ocurre porque siempre se ven desactivadas. En realidad lo que pasa es que solamente se
activan cuando la lnea de texto es mas ancha que el ancho del RichTextBox. Puede ocurrir
eso cuando la propiedad RightMargin tiene un valor superior a la anchura del control,
circunstancia que nos permite escribir salindonos del control, y es en solamente en ese
caso en el que se activa la barra de scroll horizontal.
Las barras de desplazamiento pueden desactivarse mediante la propiedad DisableNoScroll.
Propiedad DisableNoScroll
Devuelve o establece un valor que determina si estn desactivadas las barras de
desplazamiento en el control RichTextBox.
Sintaxis
Propiedad Enabled
Propiedad Booleana. Activa o desactiva el RichTextBox
FileName
Esta propiedad devuelve o establece el nombre del fichero .RTF cargado en el RichTextBox.
Si ejecutamos la lnea de cdigo :
RTB1.Filename =C :\CursoVB\Mitexto.rtf
lo que ocurrir es que nuestra aplicacin cargar el fichero C :\CursoVB\Mitexto.rtf en el
RichTextBox RTB1. Es decir, hace lo mismo que el Mtodo LoadFile (Vea mas abajo).
Slo puede especificar los nombres de archivos de texto o archivos .RTF vlidos para esta
propiedad.
Le recomendamos que para cargar un texto en un RTB use siempre el mtodo LoadFile
en vez de la propiedad Filename.
Si lo que hacemos con esta propiedad es consultar el fichero cargado en el RTB :
Variable = RTB1.Filename
obtendremos en Variable el nombre (y Path) del fichero que tenemos cargado en el RTB
HideSelection
Devuelve o establece un valor que determina si el texto seleccionado aparece resaltado
cuando el RichTextBox pierde el enfoque. Esto es justamente lo que ocurre cuando
seleccionamos un trozo de texto (Por ejemplo para pasar ese texto a negrita) y hacemos
click sobre otro control (Por ejemplo, sobre un botn de comando para cambiar a Negrita)
Si tenemos esta propiedad a False el texto seleccionado sigue seleccionado. Si est a True,
el texto se deselecciona.
NOTA Le recomiendo que cuando tenga un control para cambiar el tipo de letra, hgalo
sobre un control que no acepte el foco (Label, p.e.)
Sintaxis
propiedad
para establecer la
para leerla
Propiedad Locked
Igual que le ocurre al TextBox, si ponemos esta propiedad a True impedimos que se pueda
cambiar el texto existente en el RichTextBox mediante el teclado.
MaxLength
Esta propiedad marca el nmero mximo de caracteres que puede contener. Si se pone a 0
(Predeterminado) admite cualquier nmero de caracteres.
MousePointer
Igual que para el resto de los controles.
Multiline
Igual que para el TextBox. Si est a True (predeterminado) el RichTextBox puede contener
varias lneas. Si est a False, una solo.
OLEDragMode
320
OLEDropMode
Estas dos propiedades son similares a la DragMode de otros controles. Se vern con mas
detalle al estudiar el Drag & Drop.
METODOS DEL CONTROL RichTextBox
El control RichTextBox cuenta con unos mtodos especiales para abrir un fichero y guardar
el texto que contiene un poco especiales. Estos mtodos (SaveFile y LoadFile) se pueden
usar solamente cuando queremos guardar o leer el texto en formato .RTF. Con ellos no es
necesario abrir el fichero (con Open Nombrefichero .....) ni cerrarlo, pero siempre para
guardar o leer texto en formato RTF. Podemos leer o guardar el texto de un RichTextBox
como texto plano (Como los ficheros ASCII .TXT). Para ello debemos utilizar los mtodos
Open Nombrefichero For Input / Output vistos en el captulo de ficheros.
METODO SaveFile
Guarda el contenido de un control RichTextBox en un archivo.
Sintaxis
NombredelRTB.SaveFile(nombre_ruta, tipo_archivo)
Donde nombre_ruta (Parmetro requerido) es una expresin de cadena que define la ruta
de acceso y el nombre del archivo que va a recibir el contenido del control, y tipo_archivo
es un entero o una constante que especifica el tipo de archivo cargado, como se describe a
continuacin :
0
1
rtfRTF
rtfText
RTB1.SaveFile C :\CursoVB\mitexto.rtf, 0
Guarda el contenido del RichTextBox RTB1 en un fichero llamado mitexto.rtf que est en el
directorio CursoVB, con formato RTF
Aparte del mtodo SaveFile, puede utilizar la funcin Print de Visual Basic y las
propiedades TextRTF y SelRTF del control RichTextBox para escribir archivos .RTF. Por
ejemplo, puede guardar el contenido de un control RichTextBox en un archivo .RTF de este
modo:
Open "mitexto.rtf" For Output As 1
Print #1, RichTextBox1.TextRTF
Close #1
METODO LoadFile
Carga un archivo .RTF o un archivo de texto en un control RichTextBox.
Sintaxis
Donde nombre_ruta (Parmetro requerido) es una expresin de cadena que define la ruta
de acceso y el nombre del archivo que se va a cargar en el control, y tipo_archivo
es un
entero o una constante que especifica el tipo de archivo cargado, como se describe a
continuacin
321
0
1
rtfRTF
rtfText
Al cargar un archivo con el mtodo LoadFile, el contenido del archivo cargado reemplaza a
todo el contenido del control RichTextBox. Esto hace que cambien los valores de las
propiedades Text y rtfText.
Tambin puede usar la funcin Input de Visual Basic y las propiedades TextRTF y SelRTF
del control RichTextBox para leer archivos .RTF. Por ejemplo, puede cargar el contenido de
un archivo .RTF en el control RichTextBox de este modo:
Open "C :\CursoVB\mitexto.rtf" For Input As 1
RichTextBox1.TextRTF = Input$(LOF(1), 1)
Close #1
METODO Find
Busca una cadena especfica en el texto de un control RichTextBox.
Sintaxis
Donde :
cadena
(Necesario) Una expresin de cadena que desea buscar en el control.
inicio (Opcional)
Un ndice de caracteres de tipo Integer que determina dnde
comienza
la bsqueda. Cada carcter del control tiene un ndice entero que lo
identifica de forma nica. El primer carcter de texto del control tiene
un ndice 0.
fin
(Opcional)
Un ndice de carcter de entero que determina dnde termina la
bsqueda.
Opciones (Opcional)
Una o ms valores o constantes utilizadas para especificar
caractersticas opcionales, como se describe a continuacin.
Valor
Constante
Descripcin
Inicio
Fin
Comportamiento de bsqueda
Especificado
Especificado
Especificado
final del
Omitido
Omitido
ubicacin
Omitido
seleccionado o en
METODO GetLineFromChar
Devuelve el nmero de la lnea que contiene una posicin de carcter especificado en un
control RichTextBox.
Sintaxis
Donde pos_carcter (Requerido) es un entero largo que especifica la posicin del carcter
cuya lnea desea identificar. El ndice del primer carcter del control RichTextBox es 0.
Utilice el mtodo GetLineFromChar para averiguar qu lnea del texto de un control
RichTextBox contiene una determinada posicin de carcter. Es posible que necesite
hacerlo porque puede variar el nmero de caracteres de cada lnea, lo que hace muy difcil
averiguar qu lnea del texto contiene un determinado carcter, identificado por su posicin
en el texto.
METODO SelPrint
Enva texto con formato de un control RichTextBox a un dispositivo de impresin.
Sintaxis
NombreRTB.SelPrint(hdc)
Donde hdc es el contexto de dispositivo del dispositivo que va a utilizar para imprimir el
contenido del control.
Si hay texto seleccionado en el control RichTextBox, el mtodo SelPrint slo enviar el
texto seleccionado al dispositivo de destino. Si no hay texto seleccionado, se enviar el
contenido completo del control RichTextBox al dispositivo.
El mtodo SelPrint no imprime texto desde el control RichTextBox. En su lugar, enva una
copia del texto con formato a un dispositivo que pueda imprimirlo. Por ejemplo, puede
enviar el texto al objeto Printer utilizando cdigo como ste:
RichTextBox1.SelPrint(Printer.hDC)
Observe que la propiedad hDC del objeto Printer se utiliza para especificar el argumento de
contexto de dispositivo del mtodo SelPrint.
Nota
Si utiliza el objeto Printer como destino del texto desde el control RichTextBox,
deber inicializar en primer lugar el contexto de dispositivo del objeto Printer. Esto es
necesario, ya que Visual Basic no conoce el hDC del Printer hasta que se imprime algo. La
informacin de Microsoft recomienda imprimir una cadena de longitud cero.
323
donde :
juego_caracteres (Requerido) Una expresin de cadena que especifica el juego de
caracteres que se va a buscar al ampliar la seleccin, basndose en el valor de negado.
hacia_adelante (Opcional) Una expresin booleana que determina en qu sentido se
mueve el punto de insercin, como se describe mas adelante.
Negado (Opcional) Una expresin booleana que determina si los caracteres de
juego_caracteres definen el conjunto de caracteres de destino o se excluyen del conjunto
de caracteres de destino, como se describe mas adelante.
Los valores para hacia_adelante son:
True (Predeterminado) Selecciona texto desde el punto de insercin actual o desde el
principio de la seleccin actual hacia delante, hacia el final del texto.
False Selecciona texto desde el punto de insercin actual o el principio de la seleccin
actual hacia atrs, hacia el principio del texto.
Los valores para negado son:
True Los caracteres incluidos en la seleccin son los que no aparecen en el argumento
juego_caracteres. La seleccin se detiene en el primer carcter encontrado que aparece en
el argumento juego_caracteres.
False (Predeterminado) Los caracteres incluidos en la seleccin son los que aparecen en
el argumento juego_caracteres. La seleccin se detiene en el primer carcter encontrado
que no aparece en el argumento juego_caracteres.
El mtodo Span se utiliza principalmente para seleccionar fcilmente una palabra o una
frase en el control RichTextBox.
Si el mtodo Span no encuentra los caracteres especificados basndose en los valores de
los argumentos, el punto de insercin o la seleccin actual permanece sin cambios.
El mtodo Span no devuelve datos.
METODO Upto
Mueve el punto de insercin hasta el primer carcter (sin incluirlo) que sea miembro del
conjunto de caracteres especificado en un control RichTextBox.
Sintaxis
Donde :
324
Clipboard.SetText RTB1.SelText
Valor
Descripcin
Propiedad Appearance
rtfFlat
0
Uniforme. Pinta sin efectos visuales.
rtfThreeD
1
(Predeterminado). 3D. Pinta con efectos tridimensionales.
Mtodo Find
rtfWholeWord 2
rtfMatchCase 4
rtfNoHighlight 8
326
rtfSizeNWSE 8
rtfSizeEW
9
rtfUpArrow
10
rtfHourglass 11
rtfNoDrop
12
rtfArrowHourglass
rtfArrowQuestion
rtfSizeAll
15
rtfCustom
99
Propiedad Selalignment
rtfLeft
0
(Predeterminado) Izquierda. El prrafo se alinea a lo largo del
margen
izquierdo.
rtfRight
1
Derecha. El prrafo se alinea a lo largo del margen derecho.
rtfCenter
2
Centro. El prrafo se centra entre los mrgenes izquierdo y derecho.
Propiedad Scrollbars
rtfNone
0
(Predeterminado) Ninguna.
rtfHorizontal 1
Slo barra de desplazamiento horizontal.
rtfVertical
2
Slo barra de desplazamiento vertical.
rtfBoth
3
Barras de desplazamiento horizontal y vertical.
El FORMATO RTF
Cuando se edita un texto mediante un procesador de textos, el fichero resultante
guarda don un formato distinto para cada procesador. De esta forma, un texto editado
WP no es compatible con el P.T. AmiPro, con Word o con cualquier otro. Los fabricantes
estos procesadores de textos han tenido que incluir una herramienta capaz de convertir
formato a otro para poder alcanzar la compatibilidad entre ellos que el mercado exiga.
se
en
de
un
El Formato de Texto Enriquecido pretende ser un nexo de unin entre todos los
procesadores de texto, para poder intercambiar ficheros editados en uno u otro. De hecho,
las ltimas versiones de los mas importantes procesadores de textos incluyen la posibilidad
de guardar y buscar el texto en este formato. (WP, Word)
Este formato consiste en guardar mediante caracteres ASCII plenamente legibles tanto el
texto escrito como los tipos de letra, tamao, saltos de carro, etc. Veamos un ejemplo
comparativo del mismo texto escrito en Word, guardado en RTF y en ASCII :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva,
letra subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos
cambiar el tamao de las letras a tamao mas grande, mas pequeo, etc.
Fin Texto 1
El mismo texto en ASCII puro :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva,
letra
327
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el
tamao de las letras a tamao mas grande, mas pequeo, etc.
Fin Texto 1
Y ahora el mismo texto en formato RTF. En este formato hubo que seccionar las lneas para
poder mostrarlas en una hoja, ya que RTF utiliza lneas sin retornos de carro. Se han
seccionado las lneas terminndolas con un guin bajo y comenzando en la lnea siguiente
tambin con un guin bajo.
{\rtf1\ansi \deff5\deflang1033{\fonttbl{\f5\fswiss\fcharset0\fprq2 Arial;}}_
_{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;_
_\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\_
_green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\_
blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue_
_192;}{\stylesheet{\widctlpar
\f5\fs20\lang1034 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}_
_}{\info{\author LUIS SUAREZ BERNALDO}{\operator LUIS SUAREZ BERNALDO}_
_{\creatim\yr1997\mo3\dy9\hr11\min8}{\revtim\yr1997\mo3\dy9\hr11\min9}_
_{\version1}{\edmins1}{\nofpages1}
{\nofwords38}{\nofchars220}{\*\company }{\vern57431}}\margl1701\margr1701\_
_margt1417\margb1417 \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\formshade_
_ \fet0\sectd \linex0\headery709\footery709\colsx709\endnhere {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstar_
_t1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\_
_pnhang{\pntxta
.}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta
)}}
{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcl_
_tr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\_
_pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pn_
_start1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{_
_\pntxtb (}{\pntxta )}}\pard\plain \qj\widctlpar \f5\fs20\lang1034 Texto1
\par
\par Este texto est\'e1 escrito en Word. Observe que podemos poner letra _
_{\b negrita}, letra {\i cursiva}, letra {\ul subrayada}. Podemos cambiar_
_ el color de las letras, {\cf6 rojo}, {\cf4 verde}, {\cf2 azul}. Podemos _
_cambiar el tama\'f1o de las letras a {
\fs24 tama\'f1o mas grande}, {\fs16 mas peque\'f1o}, etc.
\par
\par
\par Fin Texto 1
\par \pard \widctlpar
\par }
Como puede observar, el RTF incluye el texto escrito casi en ASCII, pero aadiendo una
serie de datos respecto al tipo de letra, codifica los acentos, las ees, y hasta incluye,
tomndolo del ordenador, el nombre del operador que lo ha escrito. Estas informaciones
tambin se guardan cuando se archiva un texto en el formato propio del procesador de
textos, pero lo hace en binario, por lo que no lo podemos visualizar. El formato RTF, dentro
de que mete toda esa informacin adicional, lo archiva con caracteres ASCII.
MUY IMPORTANTE
328
Observe que el fichero .RTF comienza por {\rtf Cuando tenga que importar un texto hacia
un RichTextBox, puede que ese texto est en formato RTF o como Texto Plano (Fichero
ASCII puro) Para saber si el texto est en RTF analice los Cinco primeros caracteres del
texto a importar. Si son {\rtf es que est en presencia de un texto RTF.
Para saber si un fichero contiene texto enriquecido, basta con abrirlo como un fichero
secuencial, (recuerde que un fichero .RTF tiene solamente caracteres ASCII) y leer los
cinco primeros caracteres.
329
En esta ventana debe teclear el nombre que quiere dar al Procedimiento. En tipo debe
elegir la opcin Procedimiento (Veremos mas adelante la Funcin y en otro captulo las
opciones Propiedad y Evento) y en el Ambito debe elegir Public o Private dependiendo del
mbito que quiera darle :
Public. Se podr acceder a l desde cualquier Formulario o Mdulo del programa.
Dependiendo de donde se haya insertado el Procedimiento (Formulario o Mdulo), debe
citarse de la siguiente forma :
Si se ha insertado en un Mdulo, puede citarse solamente por su nombre. Puede citarse
tambin por el nombre del mdulo seguido por el nombre del procedimiento, separando
ambos por un punto. Si el procedimiento tiene por nombre NombreProcedimiento y se ha
insertado en el Mdulo1 puede citarse de las dos formas siguientes en cualquier parte del
programa:
NombreProcedimiento
Modulo1.NombreProcedimiento
Si se ha insertado en un Formulario, desde ese Formulario basta con citarle por su nombre.
Desde otro Formulario o Mdulo, hay que citarlo mediante el nombre del Formulario donde
est insertado, seguido del nombre del procedimiento, separados por un punto.
Private. Si elige este mbito, slo se podr acceder a ese Procedimiento desde el
Formulario o Mdulo donde se haya insertado.
La caja de opcin (Check) que pone Todas las variables locales como estticas nos va
a poner todas las variables declaradas dentro del procedimiento como estticas (No ponen
a cero o nulo su valor cuando salimos y volvemos a entrar en ese procedimiento). Puede
ahorrarnos un poco de cdigo.
El cdigo de los Procedimientos se guarda en el General del Formulario o Mdulo donde se
han insertado :
330
Para llamar a un procedimiento desde cualquier parte del cdigo basta con escribir en una
lnea el nombre del procedimiento.
fpublico
Muchos programadores anteponen la palabra Call
Call fpublico
No hace falta poner Call, aunque Visual Basic lo admite. Algunos programadores me dicen
que al poner Call, siempre se enteran mejor de que estn llamando a un procedimiento.
Me parece muy bien, y creo que es una buena razn. Pero no existe otra razn para ello.
Los datos que se puedan generar en un procedimiento debe extraerlos de ese
procedimiento mediante variables. Ver que con las funciones es distinto.
Cuando se llama a un procedimiento, se lleva a ese procedimiento la condicin de
tratamiento de errores que existe en el procedimiento desde el que se llam. Por ejemplo:
Private Sub Boton1_Click()
On Error GoTo RutErr
Lineas de cdigo de este procedimiento
Llamada al Procedimiento Calcula_Dietas
Calcula_Dietas
Mas lneas de cdigo de este procedimiento
RutErr:
End Sub
Si al ejecutarse el procedimiento Calcula_Dietas ocurre un error, al detectarse ese error
interceptable, el programa salta a ejecutar la lnea RutErr del procedimiento Boton1_Click.
Esto puede producirse serios problemas a la hora de depurar su programa. Para evitar que
suceda eso, y que se pare la ejecucin del programa en la lnea del procedimiento
331
Calcula_Dietas en la que se produjo el error, inicie este procedimiento con una instruccin
que anule la condicin de tratamiento de errores:
Public Sub Calcula_Dietas()
On Error Goto 0
.
Ens Sub
Funciones
Una funcin es una forma especial de realizar un procedimiento. En realidad es un
procedimiento al que le pasamos una o varios parmetros con los que realizar una
operacin (cualquier operacin, no tiene porqu ser matemtica) y obtendr un resultado
de esos parmetros. Este resultado puede leerse desde otra parte de la aplicacin en una
variable que tienen el mismo nombre que la funcin. La forma de obtener los datos de la
funcin es llamar directamente a esa funcin, como ver un poco ms adelante.
Para insertar una Funcin se procede de igual forma que para un Procedimiento, pero
marcando el botn de opcin Tipo Funcin en la caja de dilogo de la figura anterior.
El mbito de una Funcin es el mismo que el un Procedimiento. Si se declara Pblica puede
usarse en toda la aplicacin. Si se declara Privada, solamente en el Formulario o Mdulo
donde se haya insertado.
Para llamar a una Funcin son vlidos igualmente los criterios expuestos para los
Procedimientos en cuanto a la sentencia Call.
Variable2 = 14
Obtendramos como resultado la cadena
Ya se habr dado cuenta de que debemos emplear Left para obtener los caracteres
iniciales de una cadena. Nuestra funcin quedar de la forma :
Public Function MiFuncion(ByVal Variable1 as String, ByVal Variable2 as Integer) As String
MiFuncion =Left (Variable1, Variable2)
End Function
(Observe que hemos aadido la expresin As String al final de la declaracin. Esto quiere
significa que le estamos diciendo a la funcin que su resultado es un String,)
Donde MiFuncion es una variable que se ve en todo el mbito de la funcin. Para llamar a
la funcin, basta con citarla por su nombre y ponerle los parmetros necesarios. Cuando
est tecleando el cdigo, Visual Basic le invitar a introducir los parmetros citndole su
nombre. (En nuestro ejemplo, ByVal Variable1 as String, ByVal Variable2 as Integer
En cualquier parte del programa podemos poner :
Label1.Caption = MiFuncion (Gua del Estudiante, 14)
y Label1 tomar como Caption la cadena Gua del Estud
Pruebe esto con una pequea aplicacin. En un formulario, ponga un TextBox (Text1)
donde va a introducir la cadena original, otro TextBox donde va a introducir el nmero de
caracteres a tomar, y un Label (Label1) donde va a ver el resultado. Ponga un Botn de
comando (Command1) donde llamar a la funcin. Inserte una funcin (MiFuncion) en ese
formulario :
Veamos esto de una forma muy sencilla : Vamos a hacer una funcin que multiplica dos
nmeros. Pero dentro de la funcin vamos a cambiar uno de esos nmeros, sumndole 2.
Una vez realizada la operacin presentamos el valor de los dos factores en dos Label a ver
si ha cambiado. Insertemos dos funciones, MultiplicaA y MultiplicaB. En MultiplicaA le
introducimos los datos Por Valor y en MultiplicaB por Referencia.
Public Function MultiplicaA(ByVal X1 As Integer, ByVal X2 As Integer) As Integer
x1 = x1 + 2
MultiplicaA = x1 * x2
End Function
Public Function MultiplicaB(ByRef X1 As Integer, ByRef X2 As Integer) As Integer
x1 = x1 + 2
MultiplicaB = x1 * x2
End Function
Las dos funciones son idnticas, excepto en la forma de pasarle los parmetros. Pongamos
un Botn de Comando para multiplicarlo con MultiplicaA y otro con MultiplicaB. Al final del
procedimiento click de cada uno de ellos presentamos las dos variables que se pasan a la
funcin en sendos Label. Cuando se usa MultiplicaA el valor de X1
(pepe en el
CommandButton) se mantiene. En MultiplicaB cambia al valor pepe+2
Private Sub Command1_Click()
Dim pepe As Integer
Dim juan As Integer
pepe = Val(Text1)
juan = Val(Text2)
Label1 = MultiplicaA(pepe, juan)
Label2 = pepe
Label3 = juan
End Sub
Tras esto, se pone en Lable2 el valor pepe
Private Sub Command2_Click()
Dim pepe As Integer
Dim juan As Integer
pepe = Val(Text1)
juan = Val(Text2)
Label1 = MultiplicaB(pepe, juan)
Label2 = pepe
Label3 = juan
End Sub
Tras esto, se pone en Label2 el valor pepe + 2 (se mantienen el cambio realizado en la
funcin MultiplicaB
x1 = x1 + 2
No queda ah la cosa. Un valor puede pasarse tambin por ParamArray. En principio
parece que esto ya es para nota. No es para tanto.
Vamos a ver que sucede cuando queremos realizar una suma. La suma de los importes de
varios productos de un ticket de compra. En principio no sabemos cuantos productos va a
comprar un cliente, por lo tanto no sabemos a priori cuantos parmetros le tenemos que
pasar. Para pode pasar un nmero indeterminado de parmetros se los pasamos como
PamArray :
334
los
End If
End Sub
Salir de una funcin
La forma natural de salir de una funcin es cuando se ejecuta todo su cdigo. Al final
siempre tiene la sentencia End Function
Se puede salir de una funcin antes de que termine. Por ejemplo, si se cumple una
determinada condicin, se puede salir de la funcin mediante la sentencia Exit Function
336
detectar. No porque no los conozca, sino porque el propio error deja sin trabajar a Visual
Basic o incluso al sistema operativo. Afortunadamente el sistema operativo est muy
protegido, pero no por ello dejan de ocurrir estos errores. Recuerda la frase El programa
xxx ha causado un error de proteccin general en el Mdulo..... Bueno, acaba de
producir un error No Interceptable.
No solamente existen estos errores, tambin hay errores no catalogados y aplicables
solamente al programador. Piense en un bucle infinito. Un bucle infinito es una secuencia
de instrucciones tal como:
Do While n < 2000
n=n+1
If n = 1000 then n = 0
Loop
Podr advertir que este bucle no se termina nunca, ya que n no podr alcanzar nunca el
valor 2000 ya que cada vez que llega a 1000 le cambiamos su valor a 0. Este tipo de error,
ms normal de lo que parece, ni lo detecta VB ni produce una cada del sistema operativo.
Sin embargo es un error, pero en este caso ser el propio programador quien se tenga que
dar cuenta de l, ya que VB no puede ayudarnos debido a que el cdigo, lnea a lnea, est
perfectamente escrito.
Vemos por tanto que VB solamente nos ayudar en los errores de sintaxis, durante el
tiempo de diseo, y los errores interceptables en tiempo de ejecucin.
Errores Interceptables.
Veamos lo que dice la ayuda de VB para este tema:
Los errores interceptables pueden producirse cuando est ejecutando una aplicacin,
tanto en el entorno de Visual Basic como en modo autnomo. Algunos de estos errores
pueden ocurrir tambin en tiempo de diseo o en durante la compilacin.
Un error interceptable es, como decamos anteriormente, un error que Visual Basic conoce.
Para conocerlos, VB dispone de un objeto que vamos a ver a continuacin. El Objeto Error
Objeto Error
Contiene informacin sobre errores en tiempo de ejecucin.
El Objeto Error tiene Propiedades y Mtodos. Las propiedades del objeto Error las establece
quien genera el error. Por ejemplo, si el error se genera durante la ejecucin, ser VB
quien genera las propiedades del objeto Error. Pero puede ser tambin el programador
quien genere el error. Lo veremos mas adelante
Al objeto Error se le designa por Err
Las propiedades del Objeto Error son:
Description, HelpContext, HelpFile, LastDLLError, Number, Source
Propiedad Description
Devuelve o establece una cadena descriptiva asociada a un error.
338
Sintaxis
Variable = Err.Description
Err.Description = Cadena descriptiva del error
Propiedad HelpContext
Devuelve o establece el identificador de contexto de un tema para un archivo de Ayuda de
Microsoft Windows.
Sintaxis
Err.HelpContext [= id_contexto]
Variable = Err.HelpContext
Err.HelpFile = C:\MiCarpeta\MiFicherodeAyuda.Hlp
Variable = Err.Number
339
Variable = Err
Source
Devuelve o establece el nombre del objeto o aplicacin que ha generado el error
originariamente.
Sintaxis
Variable = Err.Source
Err.Source = expresin_cadena
Err.Clear
Puede utilizar Clear para borrar explcitamente el objeto Err una vez que se ha tratado un
error. Visual Basic llama al mtodo Clear automticamente siempre que se ejecuta alguna
de las instrucciones siguientes:
Cualquier tipo de instruccin Resume
Exit Sub, Exit Function, Exit Property
Cualquier instruccin On Error
De aqu se desprende que un error no sale del procedimiento en el que se gener. Para
salir de un procedimiento el programa debe pasar necesariamente por una instruccin Exit
Sub. En ese momento, desaparecen todas las propiedades del Objeto Error.
Mtodo Raise
Genera un error en tiempo de ejecucin.
Sintaxis
ContextAyuda)
Err.Raise(Nmero,
Origen,
Descripcin,
ArchivoAyuda,
340
Decamos al principio del Objeto Error que sus propiedades las establece quien las gener.
Con el Mtodo Raise se genera un error. Y vea que se pueden establecer sus propiedades.
Control de los errores
Ya sabemos que herramienta usa Visual Basic para detectar errores. Vamos a ver ahora
como usarla. Pero veamos previamente lo que es en Visual Basic una Rutina. No se
extrae si alguien le llama Label o Etiqueta. En otros lenguajes se llama as, incluso en
Q-Basic, donde no existan los controles Visual Basic llamados etiquetas, se usaba esta
denominacin. En Visual Basic no podemos usarla, para no confundirla con el control.
Una Rutina es un trozo de cdigo escrito en un procedimiento, que tiene un nombre. El
nombre de la Rutina puede ser cualquiera, y debe terminar con el carcter dos puntos (:)
Por ejemplo:
RutinaErrores:
El nombre de la rutina debe ocupar l solo una lnea. Se accede directamente a la rutina
cuando citamos su nombre en el cdigo del procedimiento donde est la Rutina.
Para citarla, debemos usar ese nombre, quitando el carcter dos puntos final. Podemos
llamarla mediante la sentencia GoTo. Veamos un pequeo ejemplo. Es un botn de
comando, y un TextBox. Si el TextBox (Text1) mantiene su texto original (Text1) hacemos
que el programa pase por la rutina. Si lo hemos variado, hacemos que no pase:
Private Sub Command1_Click()
If Text1 = "Text1" Then
GoTo Rutina
Else
MsgBox "No pasa por la Rutina"
End If
Exit Sub
Rutina:
MsgBox "S pas por la Rutina"
End Sub
La rutina es en realidad un trozo de cdigo del procedimiento que se ejecutar, bien
porque hayamos dirigido all la ejecucin del programa (mediante GoTo) o bien porque el
programa pase por la rutina al ejecutarse. Observe el Exit Sub que tiene en la lnea
inmediatamente anterior a la Rutina. Si no lo ponemos, el programa pasar por la rutina
una vez ejecutada la sentencia condicional If - Else - End If, igual que si se tratase de
cualquier otra parte del programa. Para evitar que pase por ella, ponemos ese Exit Sub que
har que el programa salga del procedimiento sin llegar al final.
En el ejemplo anterior, la condicin para que pasase por la rutina era que se cumpliese una
determinada condicin en Text1. Para que pase por una rutina, al darse la condicin de que
ha ocurrido un error, usaremos la instruccin On Error GoTo
Importante. Cuidado con GoTo
Hay un dicho entre los programadores de Visual Basic. Los programadores se dividen en
tres grupos. Los que nunca usan GoTo. Los que usan GoTo sin saber usarla y los que usan
GoTo sabiendo usarla, pero dicen que de estos ltimos hay muy pocos.
341
actual.
Va a la Rutina especificada
Pasa del error y contina en la lnea
la que provoc el error
Desactiva todo el tratamiento de errores que
haya activado en el procedimiento
Si estuviese metido el disco, pero no tuviera un fichero llamado Mificher.Txt, dara este
error:
Se ha producido el Error 53 de tiempo de ejecucin. No se ha encontrado el
archivo
En realidad estos errores no son de programa, sino de una utilizacin incorrecta del
programa, ya que debera estar metido el disco, y que contuviese un fichero llamado
Mificher.Txt. Pero en programacin hay que prever estas eventualidades. Y lo lgico sera
poner un aviso dicindole al usuario que la unidad A: no est preparada (caso 1) o que el
disco no contiene el fichero buscado (caso 2)
Instruccin Resume
Hemos visto en el apartado anterior la sentencia On Error Resume Next, de la que
decamos que pasaba del error y contina en la lnea siguiente a la que provoc el error.
Es as ya que la Instruccin Resume hace desaparecer el error mediante cdigo (Pone
Err.Numbber = 0). Si le aadimos Next el programa sigue ejecutndose en la lnea
siguiente a la que gener el error.
La Instruccin Resume puede tener las siguientes sintaxis:
Sintaxis
Resume [0]
Resume Next
Resume Rutina
o simplemente
Hemos visto la forma de detectar un error y tomar las medidas oportunas para que el
programa siga funcionando. Aqu lo hemos hecho solicitndole una operacin al usuario. En
otros casos nos interesar que el programa pase del error, en otras que repita un
procedimiento... El programador deber ver en cada caso la respuesta que debe dar el
programa a un determinado error.
Un programa perfecto es aquel que contempla todas las posibilidades de error y les da
solucin a todas. Esto quiere decir, que un programa debera tener en cada procedimiento
344
una llamada a la deteccin de errores (On error GoTo ... ) y una rutina de correccin. El
trabajo es grande. La recompensa tambin.
Pero un error muy comn entre programadores es autocomprobar sus errores. Realiza un
programa y comienza a ejecutarlo intentando descubrir los errores en los que puede caer.
Le recomiendo que esa labor la realice un compaero. La persona que realiz el programa
sabe perfectamente lo que debe hacer. Y an queriendo, le cuesta mucho trabajo cometer
errores. Una persona que nunca haya trabajado con el programa, lo que le cuesta trabajo
es no cometerlos.
345
LA AYUDA DE WINDOWS
NOTA sobre las ayudas de los programas Windows
Hasta ahora era normal presentar las ayudas en el formato csico de fichero .Hlp. Sin
embargo, dado el auge que ha tomado el formato Html (sobre todo desde que Microsoft lo
incluy como una parte ms de Windows), actualmente se est usando ms el formato
.Html que el .Hlp.
mucho mas sencilla que la de un Hlp (Y si no se lo cree, lase este captulo) Pese a todo,
se sigue incluyendo este tema, ya que el formato Hlp sigue siendo actual. Eso s, este
captulo no se ha actualizado, y cuando se habla del HC.Exe deberamos estar hablando
del HelpWorkShop (HWC.Exe), un programa que funciona en Windows, y para el que es
aplicable todo lo descrito aque de los fichero .Hpj.
Toda aplicacin bien terminada debe tener una ayuda. Cualquier aplicacin realizada en
Visual Basic puede tenerla, usando para ello los recursos que brida Windows.
La presentacin de la ayuda podra hacerse mediante un formulario, donde se presentan
distintos ficheros segn las necesidades del usuario. Sin embargo esta forma de presentar
la ayuda nunca llegar a ser tan completa como la que brinda Windows, y el trabajo a
desarrollar para igualar la presentacin de Windows sera laborioso. Solucin : utilizar los
recursos de Windows.
El recurso de Windows es un programa capaz de presentar ficheros de ayuda. Estos
ficheros son un poco especiales y solamente se pueden presentar mediante ese
presentador de ficheros de ayuda. Ese es el programa WinHelp.Exe para las versiones de
16 bits y las primeras versiones de Windows 95, y el WinHlp32.Exe para Windows 98 y
Windows NT4. Como en todas las aplicaciones de Microsoft (MS) tienen compatibilidad
hacia arriba. Por lo tanto no se extrae que una ayuda que le abre perfectamente el
WinHlp32.Exe, si la pretende abrir con el WinHelp.exe (que es ms antiguo) le diga que no
se trata de un fichero de ayuda.
Windows dispone de otra utilidad, el programa HC.EXE (Help Compiler) que puede
adaptar el fichero .RTF donde escribir la ayuda, a un formato capaz de ser interpretado
por el WINHELP.EXE Lo vamos viendo todo paso a paso.
Antes de comenzar a explicar como se realiza una ayuda Windows vamos a comentar el
formato de archivos RTF. Este formato posiblemente le sea familiar debido a que el control
RichTextBox puede guardar y leer ficheros en ese formato. Las siglas RTF vienen
precisamente de Rich Text Format, en castellano, Formato de Texto Enriquecido.
Cuando se edita un texto mediante un procesador de textos, el fichero resultante
guarda don un formato distinto para cada procesador. De esta forma, un texto editado
WP no es compatible con el P.T. AmiPro, con Word o con cualquier otro. Los fabricantes
estos procesadores de textos han tenido que incluir una herramienta capaz de convertir
formato a otro para poder alcanzar la compatibilidad entre ellos que el mercado exiga.
se
en
de
un
El Formato de Texto Enriquecido pretende ser un nexo de unin entre todos los
procesadores de texto, para poder intercambiar ficheros editados en uno u otro. De hecho,
las ltimas versiones de los mas importantes procesadores de textos incluyen la posibilidad
de guardar y buscar el texto en este formato. (WP, Word)
346
Este formato consiste en guardar mediante caracteres ASCII plenamente legibles tanto el
texto escrito como los tipos de letra, tamao, saltos de carro, etc. Veamos un ejemplo
comparativo del mismo texto escrito en Word, guardado en RTF y en ASCII :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva,
letra subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos
cambiar el tamao de las letras a tamao mas grande, mas pequeo, etc.
Fin Texto 1
El mismo texto en ASCII puro :
Texto1
Este texto est escrito en Word. Observe que podemos poner letra negrita, letra cursiva,
letra
subrayada. Podemos cambiar el color de las letras, rojo, verde, azul. Podemos cambiar el
tamao de las letras a tamao mas grande, mas pequeo, etc.
Fin Texto 1
Y ahora el mismo texto en formato RTF. En este formato hubo que seccionar las lneas para
poder mostrarlas en una hoja, ya que RTF utiliza lneas sin retornos de carro. Se han
seccionado las lneas terminndolas con un guin bajo y comenzando en la lnea siguiente
tambin con un guin bajo.
{\rtf1\ansi \deff5\deflang1033{\fonttbl{\f5\fswiss\fcharset0\fprq2 Arial;}}_
_{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;_
_\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;
\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\_
_green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\_
blue0;\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue_
_192;}{\stylesheet{\widctlpar
\f5\fs20\lang1034 \snext0 Normal;}{\*\cs10 \additive Default Paragraph Font;}_
_}{\info{\author LUIS SUAREZ BERNALDO}{\operator LUIS SUAREZ BERNALDO}_
_{\creatim\yr1997\mo3\dy9\hr11\min8}{\revtim\yr1997\mo3\dy9\hr11\min9}_
_{\version1}{\edmins1}{\nofpages1}
{\nofwords38}{\nofchars220}{\*\company }{\vern57431}}\margl1701\margr1701\_
_margt1417\margb1417 \deftab708\widowctrl\ftnbj\aenddoc\hyphhotz425\formshade_
_ \fet0\sectd \linex0\headery709\footery709\colsx709\endnhere {\*\pnseclvl1
\pnucrm\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr\pnstar_
_t1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3\pndec\pnstart1\pnindent720\_
_pnhang{\pntxta
.}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang{\pntxta
)}}
{\*\pnseclvl5
\pndec\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcl_
_tr\pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl7\pnlcrm\_
_pnstart1\pnindent720\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pn_
_start1\pnindent720\pnhang
{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang{_
_\pntxtb (}{\pntxta )}}\pard\plain \qj\widctlpar \f5\fs20\lang1034 Texto1
\par
\par Este texto est\'e1 escrito en Word. Observe que podemos poner letra _
_{\b negrita}, letra {\i cursiva}, letra {\ul subrayada}. Podemos cambiar_
347
_ el color de las letras, {\cf6 rojo}, {\cf4 verde}, {\cf2 azul}. Podemos _
_cambiar el tama\'f1o de las letras a {
\fs24 tama\'f1o mas grande}, {\fs16 mas peque\'f1o}, etc.
\par
\par
\par Fin Texto 1
\par \pard \widctlpar
\par }
Como puede observar, el RTF incluye el texto escrito casi en ASCII, pero aadiendo una
serie de datos respecto al tipo de letra, codifica los acentos, las ees, y hasta incluye,
tomndolo del ordenador, el nombre del operador que lo ha escrito. Estas informaciones
tambin se guardan cuando se archiva un texto en el formato propio del procesador de
textos, pero lo hace en binario, por lo que no lo podemos visualizar. El formato RTF, dentro
de que mete toda esa informacin adicional, lo archiva con caracteres ASCII.
La utilidad que tiene Windows para presentar las ayudas utiliza precisamente este formato
RTF. Por ello, debemos disponer de un procesador de textos que pueda guardar el texto
escrito en este formato. (Word, WP5, WP6 y otros) Los ejemplos de estos apuntes se han
realizado en Word.
Antes de decidirnos a escribir el fichero de ayuda debemos pensar muy bien lo que vamos
a poner en l. Pensemos ante todo a que personas va dirigida la aplicacin, sus posibles
conocimientos de informtica y de otros temas que estarn relacionados con la aplicacin.
Es decir, planifiquemos la ayuda antes de comenzar a hacerla.
Para acceder a la ayuda, Windows ofrece la posibilidad de pulsar F1 . Nuestras aplicaciones
deben sacar la ayuda pulsando F1. Lo podrn hacer mediante otros procedimientos.
Comencemos por lo mas sencillo, una ayuda de una nica pgina.
Escriba el texto de ayuda con Word y gurdelo en formato RTF, en cualquier directorio,
pero preferentemente en uno que no se mezcle con otros ficheros para poder localizarlo
mejor. Cree si es necesario un directorio exclusivo para la ayuda. Imaginemos que lo
creamos y es el C :\DIRAYUDA, donde guardamos el fichero de ayuda con el nombre
AYUDA1.RTF
Este archivo no lo puede utilizar directamente el programa WINHELP.EXE. Hay que
compilarlo. Para ello utilizamos el compilador HC.EXE. Este compilador no es una
herramienta Windows, por lo que tendr que ir al DOS y ejecutarlo. El programa HC.EXE se
encuentra en el directorio C :\ ..... \VB\HC
Pero al compilador HC.EXE hay que suministrarle la informacin para que pueda trabajar.
Esa informacin se la damos en un fichero que le pasaremos como parmetro, que debe
tener extensin .HPJ y que meteremos en el mismo directorio donde tengamos el fichero
de ayuda AYUDA1.RTF
Este fichero estar editado en ASCII puro. Puede editarlo con el EDIT de MS-DOS o con el
Block de Notas de Windows. Imaginemos que lo vamos a llamar FICHAYUD.HPJ y como se
dijo, se meter en el mismo directorio donde est el fichero de ayuda. (C :\DIRAYUDA) El
nombre que decida para este fichero con extensin .HPJ ser el que tenga el fichero de
ayuda (Que se obtendr de la compilacin y tendr por extensin .HLP) Tendr, de
momento, dos lneas.
[FILES]
AYUDA1.RTF
Vayamos al directorio C :\ ...... \VB\HC
HC C:\DIRAYUDA\ FICHAYUD.HPJ
La compilacin no suele dar problemas sobre todo en un fichero de ayuda tan simple de
una nica pgina. Al compilar, obtenemos un fichero con el mismo nombre que el
fichero .HPJ y extensin .HLP, (FICHAYUD.HLP en nuestro caso) que lo dejar en el
directorio donde estuviera el programa HC.EXE. (Posiblemente el C :\VB\HC) Debe moverlo
a otro directorio donde no estorbe y lo podamos localizar sin problemas. Movmoslo al
C :\DIRAYUDA Vayamos a nuestra aplicacin VB y abramos el men de Herramientas |
Opciones para sacar el cuadro de Opciones. Vaya a la pestaa de Proyecto y busque el
directorio y nombre del fichero .HLP haciendo click sobre el cuadrado con tres puntos (...)
que est a la derecha del TextBox de Archivo de Ayuda. Se le abrir un CommonDialog
para buscarlo.
NOTA : Para evitar liarse con los directorios, es medida siempre prudente llevarse
el compilador de ayudas HC.EXE al directorio donde tengamos el fichero .RTF y
el .HPJ.
Haga click en Aceptar y ejecute la aplicacin. Pulse F1. SORPRESA ! Tenemos en pantalla
la ventana de ayuda de Windows con el fichero que habamos escrito. F1 ha invocado a
WINHELP.EXE y este programa present el fichero de ayuda asociado con el proyecto.
Observe que el texto se adapta a las dimensiones de la ventana. Y si supera en vertical las
dimensiones de la ventana, aparecen barras de scroll verticales. Puede de esta forma
recorrer todo el fichero de ayuda.
Sin embargo este procedimiento no sera el mas indicado para una informacin de ayuda
extensa. Deberemos poner varias pginas. Si lo hacemos as, al pulsar F1 siempre
aparecer la pgina 1. Si aparece siempre la pgina 1, pongamos en esta primera pgina
el ndice de temas, y en las pginas sucesivas cada uno de los temas. Ya veremos como
acceder a cada una de las pginas haciendo click sobre la lnea del ndice que contiene el
ttulo del tema deseado. Tal y como lo hace con cualquier aplicacin Windows.
349
Volvamos al editor Word y abramos el fichero que habamos creado de una pgina, y
adale mas pginas introduciendo avances de pgina manuales (Se introducen con
Control + Intro)
Imaginemos que tenemos esta configuracin del fichero :
INDICE
1
2
3
4
Introduccin a la aplicacin
Acceso a la Base de Datos
Introduccin de datos
Lectura de datos
-------------------
Introduccin a la Aplicacin
Esta aplicacin est realizada para . . . . . . . . . .
-------------------
Introduccin de datos
Para introducir datos . . . . . . . . . . . .
-------------------
Lectura de datos
Para leer los datos . . . . . . . . . . . . . . . .
Ya tenemos hecho un fichero de ayuda con varias pginas. No es suficiente esto, ya que
WINHELP.EXE , pulsando F1, solamente nos mostrar la pgina 1. Debemos hacer algo
para, una vez en la pgina 1, que nos estar mostrando el ndice, poder acceder a cada
una de las pginas haciendo click sobre la lnea del ndice que contiene el tema de inters.
Para ello debemos poner un identificador a cada una de las pginas. Este identificador debe
ser nico, es decir, no pueden existir dos pginas con el mismo identificador.
Para introducir un identificador en una pgina, una vez que tenga el fichero de ayuda
terminado, sitese con el cursor al comienzo del ttulo de la primera pgina (despus del
ndice), justamente al lado de Introduccin a la Aplicacin . Inserte en ese punto una
Nota al pi (Abra el Men Insertar | Nota al Pi del Word) Le aparecer esta ventana :
350
Introduzca una almohadilla (#) en el TextBox Marca personal. Haga click sobre Aceptar.
Le aparecer en la parte inferior de la pantalla un cuadro para introducir el identificador de
esa pgina. Repita el proceso para todas las pginas insertndoles una Nota al pi a cada
una. Al final obtendr este resultado :
INDICE
1 - Introduccin a la aplicacin
2 - Acceso a la Base de Datos
3 - Introduccin de datos
4 - Lectura de datos
- - - - - - - - - - - - - - - - - - - - - salto de pgina manual
----#
Introduccin a la Aplicacin
-------------------
-------------------
-------------------
------------------
Introduccin
Introduccin
Acceso
#
Meterdatos
#
Leerdatos
#
351
#
#
#
Acceso
Meterdatos
Leerdatos
(Observe que estamos simulando la ventana de Word. Donde ve - - salto de pgina manual
-entienda que estamos simulando lo que Vd. ve en la ventana real)
En la parte inferior puede ver los identificadores que se han asociado a cada pgina. Qu
podemos hacer para asociar estos identificadores a las lneas correspondientes del ndice ?
Muy sencillo, y es el siguiente paso que debe hacer :
Volvamos a la primera pgina del documento Word, donde tenemos el ndice.
INDICE
1
2
3
4
Introduccin a la aplicacin
Acceso a la Base de Datos
Introduccin de datos
Lectura de datos
Habr observado en las aplicaciones Windows que para seleccionar un tema hay que poner
el puntero del ratn sobre la lnea deseada, que est en color verde, y en ese momento el
puntero se convierte en una mano. En nuestra aplicacin ocurrir lo mismo. Seleccione
todas las lneas que quiere asociar a cada uno de los identificadores (Una a una o todas a
la vez, dependiendo de como las tenga dispuestas), y vaya al men Formato | Fuentes .
Le aparecer el cuadro de dilogo. Vaya al TextBox Subrayado de ese cuadro de dilogo y
elija Doble.
352
del editor Word. Ver tambin todos los caracteres de control del documento. Si lo prefiere,
vaya al men Herramientas | Opciones y sobre la pestaa Ver seleccione Texto oculto.
Proceda de igual forma con todas las lneas del ndice. Cuando termine, guarde el
documento en formato RTF y complelo de la forma explicada mas atrs. Posiblemente
ahora le salgan errores de compilacin, pues el compilador comprueba que todos los
identificadores se corresponden en el ndice y en las pginas. Si le falta algn pie de pgina
o un salto de carro manual le dar error. Tambin le dar un error, mejor dicho una
observacin, indicndole que hay prrafos ocultos. Es lgico, ha detectado los textos
ocultos que contiene el fichero. Ni caso. Le habr creado el archivo .HLP y le sugiero que lo
pruebe, movindolo al directorio C :\DIRAYUDA y ejecutando la aplicacin. Pulse F1 y le
saldr la pgina con el ndice y las lneas del ndice en verde. Si lo ha hecho todo
perfectamente, al seleccionar una y otra lnea le aparecer la pgina correspondiente.
Ya tenemos una ayuda de varias pginas !
Ventanas Emergentes
Es posible que dentro de la informacin presentada en cualquiera de las pginas
anteriores, exista una palabra o frase que quisiera explicar con mas detalles. Habr
observado en las ayudas de Windows que algunas frases dentro de las pginas de ayuda
estn en verde, y al acercar el puntero del ratn a ellas se convierte en una mano. Para
poder hacer lo mismo en nuestra ayuda, volvamos al documento Word.
INDICE
1 - Introduccin a la aplicacin
2 - Acceso a la Base de Datos
3 - Introduccin de datos
4 - Lectura de datos
- - - - - - - - - - - - - - - - - - - - - salto de pgina manual
----#
Introduccin a la Aplicacin
-------------------
-------------------
Introduccin
Acceso
353
-------------------
Introduccin de datos
------------------
Observe unas palabras que estn subrayadas. Imagnese que esas palabras tienen un
significado que queremos explicar con mayor detalle. Puestos en nuestro caso, queremos
explicar con mas detalle lo que es una aplicacin, una Base de Datos, introducir y leer.
Pretendemos que, al hacer click sobre una de estas palabras se abra, dentro de la ventana
de ayuda, otra ventana con la explicacin de lo que es esa palabra concreta. Por lo tanto,
debemos introducir esas informaciones a base de introducir nuevas pginas en el
documento Word donde editamos el fichero de ayuda. Adalas de la misma forma
insertndoles un pie de pgina y el identificador deseado, de la misma forma que se
explic mas atrs. Recuerde que el identificador debe ser nico.
Una vez terminado de introducir todas las nuevas pginas, vaya a las palabras o frases que
quiere explicar con el texto de esas pginas, seleccinelas y deles el atributo de
subrayado simple (Hgalo de forma similar a cuando hizo lo del subrayado doble, pero
esta vez SIMPLE) Introduzca inmediatamente despus de la palabra o frase un texto
oculto con el nombre del identificador seleccionado para la pgina deseada en esa palabra.
Guarde el documento Word y vuelva a compilar como anteriormente. Ejecute la aplicacin
y compruebe como vamos avanzando en el tema de las ayudas de Windows.
Si repasamos las propiedades de los controles, seguro que se acuerda de la propiedad
HelpContextID que tenan la mayora de los controles VB. En aquel momento decamos
que esa propiedad que establece un nmero de contexto asociado para este control. Este
nmero se aplica para determinar la ayuda interactiva asociada a este control. Ha llegado
el momento de sacarle partido a esa propiedad.
Podemos usar la tecla F1 para acceder al ndice de la ayuda de una aplicacin y movernos
a lo largo de la ayuda seleccionando una u otra informacin. A veces resulta prctico
seleccionar directamente la ayuda correspondiente a la funcin de un control. Para poder
hacer esto, asociaremos una de las pginas del documento Word anterior al nmero que
figura en la propiedad HelpContextID. Cuando ese control tenga el foco, al pulsar F1 saldr
como pgina por defecto la pgina asociada mediante la propiedad HelpContextID.
Para establecer esta relacin vayamos al fichero con extensin .HPJ que serva para
introducir los datos al Help Compiler. En nuestro caso se llamaba FICHAYUD.HPJ y tena
por el momento, solamente dos lneas.
[FILES]
AYUDA1.RTF
En estas dos lneas le introducamos el nombre del fichero de ayuda [FILE]. Aadamos
ahora en otro apartado [MAP] la relacin entre los identificadores de pgina y los nmeros
de contexto de la propiedad HelpContextID de cada uno de los controles que la tengan
#
#
Meterdatos
Leerdatos
354
activada (valor distinto a 0). Se escribir el nombre del identificador de pgina, y separado
por un espacio o un tabulador, el nmero de contexto :
[MAP]
Identificador1 1
Identificador2 2
Identificador3 3
Identificador4 4
En este caso, cuando un control que tiene en su propiedad HelpContextID el nmero 3
tiene el foco, al pulsar F1 aparecer como pgina por defecto la correspondiente a la
explicacin con identificador nombre Identificador3. Lo mismo ocurrir con el resto de los
identificadores.
Aada a su aplicacin 4 TextBox y asgneles los valores 1, 2, 3 y 4 a sus propiedades
HelpContextID. Vuelva a compilar la ayuda y ejecute la aplicacin. Vaya pasando el foco de
uno a otro TextBox y comprobndolo.
Puede que las ayudas que quiera aportar a cada uno de los controles sea muy breve, caso
por ejemplo de la que puede introducir en los TextBox para indicar al usuario lo que se va a
hacer con el dato concreto que se va a meter en ese TextBox. Y que esas ayudas breves
sean muy numerosas y tal vez cambiantes de un usuario a otro. Esto complicara su
fichero de ayuda original, al que debera introducir muchas pginas nuevas. Puede editar
estas pequeas ayudas en otro documento Word, de la misma forma que se ha descrito, y
darle un determinado nombre (AYUDA2.RTF para nuestro ejemplo) y aadirlo como otro
fichero en la lista [FILES]. Colquelo tras el fichero anterior, pues el que lleva el ndice
debe ser el primero que figure en la lista. Debe aadir la relacin entre los nombres de
identificador que haya puesto en ese nuevo fichero y los nmeros de contexto de cada
control.
El fichero FICHAYUD.HPJ queda de momento con la siguiente forma :
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1 1
Identificador2 2
Identificador3 3
Identificador4 4
Este procedimiento de acudir rpidamente a la ayuda de un determinado control puede
que no sea el ideal, ya que en una aplicacin, siempre tiene el foco algn control. Si ese
control que ahora mismo tiene el foco tiene activado el HelpContextID, y el usuario pulsa
F1, con la intencin de ir a ver cualquier cosa no relacionada con el control que tiene
actualmente el foco, se ver sorprendido con que aparece una informacin que nada tiene
que ver con la esperada (ndice). En cualquier caso, siempre podr ir al ndice haciendo
click en el botn CONTENIDO de la ventana de ayuda, pero en principio no est bien que le
aparezca en pantalla una informacin no esperada. Tiene solucin, incluya en el men
(palabra Ayuda) o en un control Image con el smbolo ? una llamada al programa
WINHELP.EXE, pasndole como parmetro el nombre del fichero de ayuda. Esto lo
podemos hacer mediante la funcin SHELL
SHELL WINHELP.EXE C:\DIRAYUDA\FICHAYUD.HLP , 1
355
(Vea funcin Shell. No se olvide del 1 final, pues si no lo pone la ayuda le saldr
minimizada. Puede poner tambin un 4)
Tambin puede utilizar para este fin el CommonDialog. Introduzca un CommonDialog en su
aplicacin y ponga en su propiedad HelpFile el nombre del fichero de ayuda. La propiedad
HelpCommand de este CommonDialog debe estar puesta a 3 para que comience
mostrando el ndice de la ayuda. En estas condiciones, en vez de acudir a la funcin Shell
para ejecutar el WINHELP.EXE,
ejecute CommonDialog.ShowHelp.
Vea con mas
detalles las propiedades del CommonDialog, pues le permite presentar otras funciones de
la ayuda de Windows (Ayuda de la Ayuda, etc.)
Titulo de la ventana de Ayuda
Habr observado que la ventana de ayuda tiene, en la barra de ttulo el siguiente texto :
Ayuda de Windows. Si deseamos personalizarlo y poner el nombre de nuestra aplicacin,
basta con aadir un par de lneas al fichero FICHAYUD.HPJ. Las correspondientes al
apartado [OPTIONS]. Este apartado debe ir en primer lugar del fichero, y puede llevar la
informacin de la barra de ttulo y el CopyRight. Estos dos parmetros se introducen de la
siguiente forma :
[OPTIONS]
TITLE= Nuestra Aplicacin VB - Fichero de Ayuda
COPYRIGHT= Nombre del Autor(a)
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1 1
Identificador2 2
Identificador3 3
Identificador4 4
El dato introducido en la lnea COPYRIGHT sale en el men de la pantalla de ayuda, en
Ayuda | Versin.
356
ayuda est habilitado. Haga click en este botn y ver que esas palabras ya figuran en la
lista.
Usar los Grficos de la Ayuda como enlaces a pginas
Lo mismo que hacamos con las palabras, bien las del ndice, a las que con un subrayado
doble les introducamos un enlace a una pgina, o con cualquier palabra o frase de una
pgina, que mediante un subrayado simple les introducamos un enlace a una ventana
emergente, lo mismo podemos hacer con la referencia a un grfico. (Vea un poco mas
arriba, las referencias a los grficos del tipo {bmc c:\dirayuda\grafico1.bmp} ) Si
seleccionamos esa referencia y le ponemos el atributo de doble subrayado, al acercar el
puntero del ratn a ese grfico (en la ayuda) nos mostrar una mano, y haciendo click
sobre el grfico sacar la pgina correspondiente. Si le ponemos el atributo de subrayado
simple, nos sacar una ventana emergente. Eso s, en cualquiera de los dos casos,
deberemos poner, a continuacin de la referencia al grfico, con texto invisible, el indicador
de pgina que especifique la pgina o ventana emergente que queremos mostrar.
Pginas en secuencia
Si tenemos una ayuda muy larga y la queremos leer toda, con lo que sabemos deberamos
ir al ndice y desde all acceder a la pgina 1, leerla, volver al ndice, acceder a la pgina 2,
leerla, volver al ndice ....
Para evitar este proceso, y acceder secuencialmente a cada una de las pginas, podemos
asignar a cada una de las pginas un cdigo de secuencia, que podr estar formado por
caracteres alfanumricos. Este cdigo de secuencia ser el que marque el orden de
aparicin de las pginas. Pero el orden de aparicin ser segn el cdigo ASCII de los
caracteres que formen ese cdigo, comenzando por la izquierda. Por lo tanto puede
ocurrirle la paradoja de que aparezca primero la pgina 100 que la 65. Es decir, si los
cdigos estn formados por nmeros aparecern primero todas las pginas que comiencen
por 1, aunque el valor numrico de una de ellas sea superior a otra que comience por 2, 3,
4, ...
Para asignar este cdigo de secuencia deberemos introducir otra nota al pi para cada
pgina, en este caso con la marca personal + (signo mas). Tambin deberemos indicarle
al WinHelp que deseamos sacar los botones (<<) y (>>) para desplazarnos por las
pginas. Esto se consigue aadiendo una nueva seccin al archivo .HPJ que se denomina
[CONFIG] y le introduciremos en esta seccin la expresin BrowseButtons()
El fichero FICHAYUD.HPJ quedar de la siguiente forma :
[OPTIONS]
TITLE= Nuestra Aplicacin VB - Fichero de Ayuda
COPYRIGHT= Nombre del Autor(a)
[FILES]
AYUDA1.RTF
AYUDA2.RTF
[MAP]
Identificador1 1
Identificador2 2
Identificador3 3
Identificador4 4
[CONFIG]
358
BrowseButtons()
Encabezado de pginas
Habr observado en la ayuda de Visual basic que una o dos lneas en la parte superior de
la ventana de ayuda se conservan all continuamente aunque nos desplacemos hacia abajo
mediante los cursores de desplazamiento. Esas lneas son el Encabezado de pgina. Para
conseguir esto en nuestra ayuda deberemos escribir las lneas que queramos que se
conserven como encabezado de pgina al principio de cada pgina, seleccionarlas con el
cursor del ratn y abrir el men Formato | Prrafo (Se supone que est utilizando el
procesador de texto Microsoft Word) donde le aparecer un cuadro de dilogo con dos
solapas, Sangra y Espacio y Presentacin. Elija Presentacin y dentro de esta
solapa, active la casilla Conservar con el Siguiente. Las lneas que hubiera seleccionado
se le conservarn como Encabezado de pgina.
VENTANAS MULTIPLES
Con frecuencia es til emplear varias ventanas para mostrar la informacin de una
aplicacin. El ejemplo que tenemos mas a mano es el de la Ayuda de Visual Basic. Cuando
tenemos seleccionada la ayuda de un control, se pueden observar al menos dos palabras
que nos llevan a una segunda ventana : Propiedades y Eventos. Cuando elegimos una de
estas informaciones aparece una segunda ventana que nos muestra la informacin pedida,
sin perder la informacin que tenemos en la primera ventana.
Esta segunda ventana se comporta de manera idntica a la primera, en cuanto a llamadas
a otras pginas o a mens emergentes.
Para poder presentar esta segunda ventana es necesario primero definirla. Para ello
volvamos a nuestro fichero .HPJ y le aadiremos un nuevo apartado : WINDOWS, donde
introduciremos el nombre de la nueva ventana, el ttulo de la misma (El ttulo que
aparecer en su parte superior), y, entre parntesis, su posicin y dimensiones.
El fichero .HPJ quedar de la siguiente forma, tras introducirle dos nuevas ventanas :
[OPTIONS]
TITLE= Nuestra Aplicacin VB - Fichero de Ayuda
359
..... \
..... \ nuevaayuda.hlp"
el fichero RTF creado por W97 es distinto del creado por W95, lo cual, aparte de dar una
idea de como se trabajan los temas de compatibilidad entre procesadores que deberan ser
compatibles, nos obliga a buscar otro compilador de ayudas.
No lo intente con el HCP.EXE. Tampoco vale. Busque por Internet un fichero llamado
HCW.EXE, compilador que tiene adems la ventaja de que trabaja en Windows. Usa el
mismo fichero .HPJ y acepta los ficheros .RTF creados con W95 y W97
El aspecto de este compilador de ayudas es el siguiente :
Aparte de este compilador, existen otros que funcionan de forma similar. No vamos a
explicar cada uno de los compiladores que podamos encontrar, que como se dijo hay
bastantes y (creo que) shareware. Lo importante es que todo lo dicho respecto a la
edicin de los ficheros :RTF y .HPJ sigue siendo vlida para estos compiladores. Existen
algunos compiladores que tambin crean el fichero .HPJ. Es comprensible no intentar
examinar uno a uno en esta Gua del Estudiante.
Visual Basic - Gua del Estudiante Cap. 11
BASES DE DATOS EN VISUAL BASIC (1)
A modo de introduccin
Todo lo visto hasta ahora en este libro es el Visual Basic elemental que debe conocer
necesariamente para realizar una aplicacin. Sin embargo hay algo que falta. El 90 % de
las aplicaciones que va a realizar van a llevar una base de datos. Es lgico. Una aplicacin
se hace normalmente para presentar datos, datos que habr que introducir y mostrar de
forma conveniente. Lo de introducir y mostrar datos son las materias que va a ver en
los captulos siguientes, pero no olvide lo de mostrarlos de forma conveniente, y es en
eso donde tendr que aplicar todo lo que lleva aprendido hasta ahora. Se observa con
mucha frecuencia que el alumno tiene una prisa desmesurada por llegar a los temas que
tratan las bases de datos, dejando un poco de lado la interface necesaria para su
introduccin y presentacin, que es lo que da ergonoma y elegancia a una aplicacin. El
conocimiento de bases de datos es necesario. Lo explicado hasta ahora, imprescindible.
361
Visual Basic nos permite trabajar directamente con distintas bases de datos (ACCESS,
dBaseIII, dBaseIV , dBase 5, Excel3, Excel4, Excel5, Excel7, FoxPro2.x, Foxpro3.0,
LotusWK1, LotusWK3, LotusWk4, Paradox3.x, Paradox4.x y Paradox5.x Esto lo logra
mediante el Motor de Bases de Datos Jet, herramienta de Microsoft para administrar los
datos en bases de datos Access. Tiene un nombre que mas parece de una materia de
ingeniera aeronutica, pero en realidad no es mas que un conjunto de programas que se
cargan en el disco duro cuando instala Access o Visual Basic. E esta forma de acceder a
las bases de datos se le llama Acceso mediante objetos DAO. Lo de DAO viene de Data
Access Objet. Y es la forma ms sencilla y rpida de acceder a una base de datos Access
instalada en el propio disco duro o en un disco de red de rea local rpida. (Lo de facilidad
de acceso a una base de datos Access viene implcito en la poltica de Microsoft de facilitar
la compatibilidad entre sus aplicaciones)
Pero esto se quedara muy corto si solamente se pudiese conectar con las bases de datos
citadas. No se puede concebir un sistema de desarrollo que no pueda acceder a bases
como Oracle, Informix, SQL Server, etc. Estas bases de datos, aparte de tener su propia
interface para acceso a datos, disponen de una forma de acceso comn a todas : ODBC
Lo de ODBC (Open Data Base Conectivity) es un mecanismo de conexin entre bases de
datos abiertas. Lo de abiertas significa que tienen esa interface de acceso comn, interface
a travs de la cual puede acceder a sus datos cualquier aplicacin. Esta interface utiliza el
lenguaje SQL, y es necesario establecer una conexin ODBC en Windows. Lo veremos mas
adelante.
Los objetos DAO pueden acceder tambin a bases de datos a travs de ODBC. Esto
podemos decirlo con la versin DAO 3.5, no podemos decir lo mismo con la 2.5,
procedimiento previsto pero que no funcionaba.
Este pobre funcionamiento de DAO con ODBC llev a Microsoft a crear otro tipo de acceso
a datos: el RDO (Remote Data Objet), y los objetos de acceso a datos RDO. Esto consiste
en objetos parecidos a los DAO, pero que en vez de atacar directamente a la base de datos
como lo hace DAO, lo hacen a travs de una conexin ODBC previamente establecida en
Windows. As por ejemplo, en un objeto DAO hablamos del nombre de la base de datos,
refirindonos
al
nombre
del
fichero
que
contiene
los
datos
(C:\Mis
Documentos\MiBase.Mdb), y en RDO nos referimos al nombre de la conexin ODBC
(Connection) refirindonos al nombre de una conexin ODBC ya establecida, que apunta a
una base de datos que es donde vamos a leer o escribir. Este mtodo tiene la gran ventaja
de que podemos establecer hoy una conexin con una base determinada, y si queremos
cambiar maana la base de datos sobre la que vamos a trabajar, basta con cambiar esa
conexin apuntando hacia otra base de datos. As no es necesario realizar ningn cambio a
nuestro cdigo
Un error bastante general con los objetos RDO es pensar (seguramente por aquello de
Remote Data Objet) que solamente pueden trabajar con una base de datos que est en
otro ordenador, al cual estaremos unidos por cualquier forma de conexin. No tiene nada
que ver. RDO significa solamente que accedemos a los datos a travs de ODBC, y podemos
hacerlo (al igual que con DAO) a una base que est en el mismo disco duro que la
aplicacin, o una que est en un servidor unido a travs de una Red de Area Local.
Pero RDO no tiene las prestaciones que tiene DAO para trabajar con bases de datos
Access. De hecho, RDO pierde grandes facilidades que aporta DAO para este tipo de bases
de datos. RDO trabaja sobre una conexin ya instalada, que apunta a una base de datos
ya creada. Con RDO no podemos crear esa base de datos. Esto es obvio, con RDO
podemos entrar en una base de datos Oracle, por ejemplo. Nadie puede pretender que
362
Visual Basic cree una base de datos de esa marca. Sin embargo, con ADO s podemos
crear una base de datos Access. Piense en la facilidad para distribuir una aplicacin que
tenga una base de datos Access cuyos campos puedan tener un tamao definido por el
propio usuario. Bastara poner una herramienta en la propia aplicacin donde el usuario
introdujese los tamaos de los campos tipo texto, para adaptar la base de datos a sus
necesidades. Esto puede hacerlo con DAO puesto que nos permite crear bases de datos
Access, pero no lo podemos hacer mediante RDO.
RDO utiliza una terminologa ligeramente distinta de DAO. Por ejemplo, sonde en DAO
ponemos OpenRecordset, en RDO debemos poner OpenResultset. Es una pena que no se
pueda trabajar con la misma terminologa y con todas las prestaciones que tiene DAO a
travs de ODBC. Esto mismo pens Microsoft, y esa fue la razn de implementar en los
objetos DAO 3.5 la conexin ODBCDirect.
ODBCDirect nos permite trabajar con los mismos objetos DAO pero a travs de una
conexin ODBC, que en este caso, funciona. Puede ser un poco ms lenta que DAO, pero
en esto hay opiniones para todos. De esta forma es posible seguir utilizando los viejos
mtodos aprendidos para DAO (Y lo que es mejor, reutilizar el cdigo ya escrito en
anteriores aplicaciones) a travs de una conexin ODBC. Lo veremos mas adelante.
Pero no debemos pensar que aqu se acaban los mtodos de acceso a datos. Existe otro
mas, muy reciente denominado ADO. ADO quiere sustituir a DAO y RDO.
En este punto pona hace dos aos que eso lo va a determinar el mercado. Hoy (Nov.2002)
se puede decir que ADO ha sustituido en todas las aplicaciones nuevas a RDO, y ha dejado
a DAO solamente el mercado de las pequeas aplicaciones domsticas. ADO es una
maravilla. Por eso, la Gua del Estudiante dedica un nuevo captulo y un amplio ejemplo a
ADO. Pero eso no implica que no haya que ir paso a paso. Y primero hay que aprender
DAO. Pero ahora todo lo que aprenda de DAO le va a servir para ADO, pues en ADO s
coincide el cdigo. Aprendamos pues DAO, y luego aplicaremos nuestros conocimientos a
ADO. La gran ventaja de ADO es que en aquellas aplicaciones que leen una base situada
en un servidor, ocupa menos la red de rea local, ya que trabaja una aplicacin Cliente
Servidor.
Adelanto de trminos. Aplicaciones Cliente servidor Piense en una base de datos
instalada en una red no muy rpida. Si creamos un acceso a datos (recordset) con DAO, el
trfico de datos por la red es muy grande, dado que puede darse el caso de tener que ver
toda la base de datos para extraer de ella solamente un dato. Una aplicacin Cliente
Servidor lo que hace es montar un programa en el servidor, al cual le pedimos desde
nuestra aplicacin el dato deseado. Ese programa posiblemente tenga que ver toda la base
de datos para encontrar el dato que nos interesa, pero lo hace localmente en el servidor,
sin verter todos los datos a la red de rea local. Una vez que lo ha encontrado, nos pasa a
travs de la red el dato solicitado, con lo que bajamos el trfico por la red de forma muy
importante. Lo veremos mas adelante pero no con una gran profundidad. Es un tema que
se sale necesariamente de este curso debido a su extensin. Existen multitud de libros que
tratan el tema.
363
No se preocupe de los que acaba de leer. Con las explicaciones anteriores parece que esto
de las bases de datos debe ser cosa de gurs informticos, vedado al resto de los
mortales. Nada mas lejos de la realidad. Y para demostrarlo, en lo que queda de captulo
vamos a trabajar con bases de datos SIN escribir una sola lnea de cdigo. No digo que
sea lo mejor, pero puede hacerse. Esto se logra mediante controles OCX creados por
Microsoft, que controlan directamente a ese conjunto de programas que habamos dado en
llamar Motor de bases de Datos Jet o a los programas similares de RDO o ADO.
Comenzaremos el estudio de bases de datos con los objetos DAO. Y para DAO el control
que organiza el trabajo al Motor Jet es el Control Data. Existen controles similares para
RDO y para ADO. Pero no corramos y centrmonos sobre DAO y nuestro motor Jet
Decamos que el control Data sirve de enlace entre la base de datos y los controles que
pueden presentar datos. Estos controles a los que nos referimos son los llamados
Controles Enlazados a Datos, y que son viejos conocidos nuestros, al menos algunos
de ellos.
Los dos ms sencillos son el control Label y el control TextBox
Un control Label puede presentar un dato. Si queremos que ese dato sea un campo de una
tabla de una base de datos, basta que enlacemos la base de datos al control data, y que
enlacemos luego el control Label con el control Data. Si hacemos lo mismo con el TextBox,
no solamente podremos presentar datos de la BD, sino que los podemos introducir, al ser
el TextBox un control bidireccional.
Veamos como se enlaza un control data a una base de datos. Se supone que el alumno
conoce la estructura de una base Access, BD con la que vamos a iniciar este estudio. De
cualquier forma, y para los que han suspendido la asignatura de base de datos Access,
citar solamente que una base de datos Access contiene dentro de un fichero (P.e.
C:\MiCarpeta\MiBase.Mdb) varias Tablas (P.e. Tabla1, Tabla2 y Tabla3) Cada tabla es en
364
Con esto ya podra trabajar, pero le faltan an ciertos detalles. Por ejemplo, el tipo de
recordset que debe crear. (Dynaset, Snapshot, Table) Esto se lo indicamos en la propiedad
RecordsetType, que por defecto le va a poner Dynaset. (Ya veremos que es cada uno de
ellos) Y ya tenemos casi todas las propiedades del control Data cubiertas. Las dems son
las tpicas de todos los controles. Casi todas las propiedades, porque hay una que se ha
introducido en la versin 6 de VB para permitir las dos formas de atacar a la base de
datos, con el motor Jet o a travs del citado ODBCDirect.. Esa propiedad es DefaultType
y nos permite elegir entre usar el motor de base de datos Jet (Poniendo a esta propiedad
el valor 2 o dbUseJet) o usar ODBCDirect (Ponindole el valor 1 dbUseODBC) El valor
por defecto es usar el motor Jet y as trabajaremos en principio.
Ya tenemos enlazado el control Data a la base de datos. Falta ahora enlazar una etiqueta y
un TextBox al control Data para tener el enlace completo. Eso es an ms sencillo. Si
desplegamos las propiedades del TextBox por ejemplo, veremos que tiene unas
propiedades que cuando lo estudiamos, las habamos pasado un poco por alto:
DataSource y DataField.
En la figura puede ver que la propiedad DataSource puede desplegarse, mostrando en este
caso el nombre del nico control Data que tenemos en el formulario: Data1 Si tuvisemos
mas controles Data, apareceran los nombres de todos ellos. Se elige uno.
365
Podemos observar que ya funciona. Si ponemos tantos TextBox como campos tiene la tabla
elegida, podemos ver todo el contenido de la Base de datos movindonos a lo largo de ella
mediante las flechas de cursor del control Data. Todo ello sin escribir una lnea de cdigo
tal y como habamos prometido.
Entremos ahora en un estudio un poco ms avanzado del control Data.
El control Data proporciona acceso a datos almacenados en bases de datos usando uno de
los tres tipos de objetos Recordset. El control Data le permite ir de registro en registro y
presentar y manipular los datos de los en controles enlazados. Sin un control Data, los
controles enlazados con datos de un formulario no pueden tener acceso
automticamente a los datos.
Los controles enlazados solamente pueden tener acceso a un control Data si este est
en el mismo Formulario.
En el tema de Bases de Datos se emplean trminos no conocidos an. Se irn viendo a lo
largo del curso, pero no queda otro remedio mas que comenzar a utilizarlos. Se irn
haciendo avances de estos trminos, que sern explicados en profundidad en su momento.
Avance de trminos.
Objeto Recordset (conjunto de registros)
Es un conjunto lgico de registros. Los tres tipos de objetos Recordset son Dynaset,
(Permite la lectura y escritura de un registro) Snapshot (Realiza una lectura instantnea
de los registros, no permitiendo modificarlos) y Table. (Representacin en el cdigo de
una tabla base que puede utilizarse para agregar, modificar o eliminar registros de una
sola tabla).
Controles enlazados
Son los controles que pueden presentar directamente datos de uno o varios campos de
una Base de Datos. Los controles DBList, DBCombo y DBGrid tienen la posibilidad de
presentar un conjunto de registros cuando se asocian con un control Data. Los controles
CheckBox, TextBox, Label, Picture, Image, ListBox y ComboBox tambin son controles
enlazados con datos y pueden asociarse a un nico campo de un Recordset administrado
por un control Data.
La mayora de las operaciones de acceso a datos se pueden realizar usando el control Data
sin escribir ningn cdigo. Los controles enlazados con un control Data presentan de forma
automtica los datos de uno o ms campos del registro actual o, en algunos casos, de un
conjunto de registros a ambos lados del registro actual. El control Data realiza todas las
operaciones sobre el registro actual.
Avance de trminos
Registro Actual. Un registro es un conjunto completo de campos. Una base puede tener
muchos registros, pero el puntero de la base de datos apunta a un nico registro en cada
momento. Ese registro al que apunta el puntero se llama registro actual.
Si el control Data recibe instrucciones de moverse a un registro diferente, todos los
controles enlazados pasan automticamente los cambios al control Data para ser
366
Data1.Recordset
El objeto Database creado por un control Data no se cierra aunque se cambie la propiedad
DatabaseName del control Data. Lo mismo ocurre con el objeto Recordset. Solamente
podemos cerrarlos utilizando el mtodo Close :
Data1.Database.Close
Data1.Recordset.Close
Esta observacin debe ser tenida muy en cuenta sobre todo cuando el control Data abre la
Base de Datos de forma exclusiva, o cuando tenemos que hacer una operacin con la Base
de Datos que exija que est cerrada. Por ejemplo, el mtodo CompactDatabase y otros
mtodos que veremos mas adelante.
Objetos para acceso a datos
Los objetos para acceso a datos Database y Recordset creados por el control Data
tienen cada uno sus propiedades y mtodos propios y se pueden escribir procedimientos
que usen estas propiedades y mtodos para manipular los datos.
Por ejemplo, el mtodo MoveNext de un objeto Recordset mueve el registro actual al
siguiente registro del Recordset. Para invocar este mtodo, se podra usar el siguiente
cdigo:
Data1.Recordset.MoveNext
El control Data puede crear cualquiera de los tres tipos de objetos Recordset (Dynaset,
Snapshot, Table) Si no se indica el tipo a crear, se crea un Recordset de tipo Dynaset.
Nota. Las constantes usadas para requerir un tipo especfico de Recordset cuando se usa
un control Data son diferentes de las constantes usadas para determinar el tipo de
Recordset creado o que se va crear usando el mtodo OpenRecordset.
Para seleccionar un tipo especfico de Recordset, establezca la propiedad RecordsetType
del control Data a:
Tipo de Recordset
Valor
Table
Dynaset
Snapshot
0
1
2
vbRSTypeTable
vbRSTypeDynaset
vbRSTypeSnapshot
Constante OpenRecordset
dbOpenTable
dbOpenDynaset
dbOpenSnapshot
En la pequea aplicacin realizada al comienzo de este tema ha visto que los controles
enlazados a datos permiten visualizar e introducir datos en la base de datos a travs del
control Data. Efectivamente, no tendra sentido poner un control data sin enlazarlo a otros
controles para que estos nos sirvan de elementos de presentacin y captura de datos.
Veremos mas adelante en este captulo los controles enlazados a datos.
Consultas almacenadas
Otra opcin importante cuando se usa el control Data es la posibilidad de presentar una
consulta realizada previamente en Access. Si se ha creado previamente una consulta, el
control Data nos mostrar esa consulta como si se tratase de una tabla ms de la base de
datos, al desplegar la lista de tablas para cubrir la propiedad RecordSource. Puede por lo
tanto presentar solamente los campos que necesite en su aplicacin, tomados de una tabla
(o de varias tablas si ha establecido las relaciones oportunas) y de esta forma su aplicacin
va a trabajar ms rpido que si tuviese que seleccionar esos campos mediante una
instruccin SQL Para presentar una consulta, establezca la propiedad RecordSource del
control Data al nombre de esa consulta (En vez de poner el nombre de una tabla, ponga el
nombre de la consulta). Esto no puede hacerse si la consulta contiene parmetros. Esto le
ocurre cuando la consulta se ha creado partiendo de los datos de otra consulta.
Es mucho ms rpida una consulta utilizando una consulta ya creada en Access que
introduciendo la consulta en SQL. La razn es muy sencilla. Al crear una consulta es Access
quien crea una especie de tabla nueva en la propia base de datos. Esta tabla nueva no
contiene datos, sino referencias a registros de una tabla. Por lo tanto, el motor de bases de
datos se limita a recorrer esa tabla nueva, tomar el nmero del registro que debe
presentar, ir a ese registro y tomar el dato que contiene. Si lo que hace es una consulta
SQL, se debe obtener la informacin registro a registro segn las condiciones establecidas
en la clusula SQL. Esta segunda opcin tarda logicamente ms. Y si est leyendo la base
de datos a travs de una red de rea local, la ocupacin de esta red es mucho menor si el
recordset se crea con la consulta de Access.
Estamos hablando de una consulta SQL establecida en el control Data.
Dnde?
Justamente en la propiedad RecordSource del control data. Hasta ahora habamos puesto
en esa propiedad el nombre de una tabla o de una consulta ya hecha en Access. Si en vez
del nombre de la tabla ponemos una consulta SQL, la cosa tambin funciona:
Con una Tabla
Data1.RecordSource = Autores
Con una consulta SQL
Data1.RecordSource = Select * From Autores Where Apellidos = Cervantes Saavedra
Esta consulta obtiene de la tabla Autores, solamente los registros en los que el campo
Apellidos sea igual a Cervantes Saavedra Funciona, pero para averiguar el nmero de
registros que tienen esos apellidos deber recorrerlos todos, comprobar si son iguales a los
expresados en la sentencia SQL y en caso afirmativo pasarlos al recordset creado. Si se
hubiera creado una consulta previamente en Access, y pusisemos el nombre de la
consulta en la propiedad RecordSource del control Data, ste ira directamente a los
registros que gozan de tan ilustres apellidos, ya que Access habra hecho una tabla con los
nmeros de los registros que cumplen esa condicin (esa tabla no contiene los datos, sino
el nmero de los registros que los contienen), el control data leera esos nmeros e ira a
los registros indicados en esos nmeros, evitando de esta forma tener que leer el
contenido del campo Apellidos del resto de los registros. De cualquier forma, si la base de
datos est en el mismo ordenador que la aplicacin, esto empieza a ser importante cuando
trate tablas con muchos registros. Si est en una red de rea local no hace falta tener
369
Administracin de BOF/EOF
Las propiedades BOFAction y EOFAction establecen el comportamiento del control Data
cuando llega al principio o final de los registros. En esos casos se produce el BOF y EOF
respectivamente.
BOF (Begin Of File). Se produce el BOF cuando el control Data se posiciona sobre el
registro inmediatamente anterior al primero (No es un juego de palabras). Este registro
ser el -1.
EOF (End Of File) Se produce la condicin EOF cuando el control Data se posiciona en el
registro inmediatamente posterior al ltimo. Este registro ser tambin el -1.
La propiedad BOFAction permite seleccionar el comportamiento del Data cuando nos
hemos pasado de registros por abajo. Tiene las opciones MoveFirst (se mueve al primer
registro) o BOF (se queda donde est)
La propiedad EOFAction
establece el comportamiento del control Data cuando se
sobrepasa el ltimo registro. Podemos indicarle que se mueva al ltimo registro
(MoveLast), que se quede donde est (EOF), o que introduzca un nuevo registro
(AddNew)
Caption
Connect Muy Importante. En esta propiedad debemos indicarle al control Data el tipo de
base de datos a la que va a conectarse. Admite todas las bases enumeradas al principio de
este captulo.
DatabaseName En esta propiedad se le indica el nombre (Con su Path) de la base de
datos a la que debe conectarse. Para facilitar la bsqueda de la base de datos, haciendo
click en esta propiedad en la caja de propiedades, podemos sacar un cuadro de dilogo
haciendo click de nuevo en los tres puntos que aparecen a la derecha de la propiedad. El
cuadro de dilogo seleccionar directamente las extensiones de los ficheros de bases de
datos acordes con el tipo de base de datos seleccionada en la propiedad Connect.
Database
(Solo en ejecucin)
Variable = nombredelcontroldata.Database
370
El objeto Database creado por el control Data se basa en las propiedades DatabaseName,
Exclusive, ReadOnly y Connect del control.
Los objetos Database tienen propiedades y mtodos que puede utilizar para administrar los
datos. Puede utilizar cualquier mtodo de un objeto Database con la propiedad Database
de un control Data, como Close y Execute. Tambin puede examinar la estructura interna
de la Database empleando su coleccin TableDefs y, a su vez, las colecciones Fields e
Indexes de objetos TableDef individuales.
NOTA. Aunque puede crear un objeto Recordset y pasarlo a la propiedad
Recordset de un control Data, no puede abrir una base de datos y pasar el objeto
Database recin creado a la propiedad Database del control Data.
DragIcon, DragMode , Enabled
DefaultType
Devuelve o establece un valor que indica el tipo del origen de datos (Motor Jet u
ODBCDirect) que se usan en el control Data.
Sintaxis
NombreDelControlData.DefaultType = 1
Puede tomar los valores 1 (Usa ODBCDirect) y 2 (Usa el Motor Jet) Pueden usarse
tambin las constantes dbUseODBC o dbUseJet respectivamente
EditMode
Solo lectura en tiempo de ejecucin. Devuelve un valor que indica el estado de
modificacin del registro actual.
Sintaxis
Variable = NombreDelControlData.EditMode
371
Options
Devuelve o establece un valor que especifica una o ms caractersticas del
objeto Recordset de la propiedad Recordset del control Data. Puede ponerse en el cuadro
de propiedades o en tiempo de ejecucin. Puede tomar los siguientes valores o nombres de
constantes (estos nombres solo si los introduce en tiempo de ejecucin)
1
dbDenyWrite
realizar
2
leer
dbDenyRead
4
8
dbReadOnly
dbAppendOnly
16
dbInconsistent
32
los
dbConsistent
64
dbSQLPassThrough
Cuando se utilizan controles Data con una instruccin
SQL en
la propiedad RecordSource, enva la instruccin SQL a una
base de datos ODBC, como SQL Server o Oracle, para su
procesamiento.
256 dbForwardOnly
El Recordset es un desplazamiento slo hacia adelante. El
nico mtodo de movimiento permitido es MoveNext. Esta
opcin no puede utilizarse en objetos Recordset manipulados
con el control Data.
512 dbSeeChanges
Genera un error interceptable si otro usuario est cambiando
datos que usted edita.
Para establecer mas de un valor de los descritos, basta con sumar sus valores. Tambin
puede establecer ms de un valor para esta propiedad, combinando opciones sumando
valores entre s. Por ejemplo, para establecer dbReadOnly y dbInconsistent puede
utilizar este cdigo:
Data1.Options = dbAppendOnly + dbInconsistent
Para determinar si la propiedad contiene un valor especfico, puede utilizar el operador
And. Por ejemplo, para averiguar si el Recordset est abierto para acceso de slo lectura,
podra usar este cdigo:
If Data1.Options And dbReadOnly Then...
Si cambia la propiedad Options en tiempo de ejecucin, deber utilizar el mtodo Refresh
para que el cambio sea efectivo.
ReadOnly Devuelve o establece un valor que determina si la Database del control est
abierta para acceso de slo lectura.
RecordsetType
Devuelve o establece un valor que indica el tipo de objeto Recordset que desea que cree el
control Data.
Los valores o nombre de la constante que puede adoptar son los siguientes:
372
0
1
2
vbRSTypeTable
Un Recordset de tipo tabla.
vbRSTypeDynaset (Predeterminado) Un Recordset de tipo hoja de respuestas
dinmica.
vbRSTypeSnapshot
Un Recordset de tipo instantnea.
existente en la
a los controles
lo establece la
devolvern sin
NombredelcontrolData.Refresh
Puede utilizar el mtodo Refresh sobre un control Data para abrir o reabrir la base de
datos (si han variado las propiedades DatabaseName, ReadOnly, Exclusive o Connect) y
volver a generar el objeto Recordset indicado por la propiedad Recordset del control.
374
Mtodo UpdateControls
Actualiza los datos presentes en los controles enlazados a datos vinculados al control Data.
Sintaxis
Nombredelcontroldata.UpdateControls
Utilice este mtodo para restablecer en los controles enlazados sus valores originales, por
ejemplo cuando un usuario modifica los datos y luego decide cancelar los cambios.
Este mtodo produce el mismo efecto que hacer actual de nuevo al registro actual, excepto
en que no se produce ningn evento ni introduce en la Base de Datos los posibles valores
que se hubiesen cambiado en los controles enlazados.
Mtodo UpdateRecord
Guarda en la base de datos los valores actuales de los controles enlazados.
Sintaxis
NombredelcontrolData.UpdateRecord
Puede utilizar este mtodo para guardar el contenido actual de los controles enlazados en
la base de datos. Los cambios introducidos en los controles enlazados a datos se pasan a
la base de datos al cambiar el registro actual, bien mediante cdigo
(Data1.Recordset.MoveNext, p.e.) o usando las flechas del control data, o cambiando el
registro actual en un DBGrid. Sin embargo hay circunstancias en las que no es apropiado
hacer esto. Mediante el mtodo UpdateRecord introducimos los cambios en la BD. Este
mtodo no desencadena el evento Validate.
En algunos casos, la actualizacin puede no tener lugar, debido a que la operacin vulnere
las restricciones de integridad referencial, o que la pgina que contiene el registro est
bloqueada, o que la base de datos u objeto Recordset no sean actualizables, o a que el
usuario no cuente con el permiso adecuado para la operacin. En cualquiera de estas
circunstancias, se producir un error interceptable.
Estos son los mtodos del Control Data. Este control tiene su Recordset, y el
Recordset del control Data tiene sus mtodos, idnticos a los de un Recordset
creado por cdigo.
EVENTOS DEL CONTROL DATA
Error
Se produce solamente como resultado de un error de acceso a datos que tiene lugar
cuando no est ejecutando cdigo Visual Basic. Lo explicamos.
El control data carga los datos durante la carga del formulario que lo contiene, abriendo la
base indicada en su propiedad DataBaseName. Imagnese que no existe esa base de datos
en el disco. En ese caso no se producir ningn interceptable ya que no se ejecuta ningn
cdigo escrito. Tampoco se ejecuta ningn cdigo escrito cuando el usuario hace click en
uno de los botones del control data.
El procedimiento Error del control Data se ejecuta cada vez que ocurre un error por una
maniobra de este tipo, y pasa el cdigo de error como parmetro. Analizando el cdigo de
error podemos escribir cdigo en este procedimiento para paliar el error. La ayuda de VB
tiene un buen ejemplo del uso de este procedimiento.
Este ejemplo presenta un cuadro de dilogo Abrir si no se ha podido encontrar la base de
datos especificada en la propiedad DataBaseName del control Data despus de haber
terminado el evento Form_Load.
375
vbDataActionCancel
9
10
11
vbDataActionBookmark
vbDataActionClose
vbDataActionUnload
El evento Validate se usa para realizar las ltimas comprobaciones sobre los registros que
se van a escribir en la base de datos.
Vea la ayuda de Visual Basic para mayor detalle de este evento.
TextBox Se utiliza para almacenar texto que el usuario puede introducir o modificar.
Puede utilizarse para proporcionar acceso de lectura / escritura a un campo de texto
especfico.
CheckBox Se utiliza para crear un cuadro que el usuario puede elegir de forma sencilla
para indicar si algo es verdadero o falso, o para mostrar varias opciones entre las que el
usuario pueda elegir ms de una. Puede utilizarse para proporcionar acceso de lectura /
escritura a un campo booleano o de bit especfico.
ComboBox Se utiliza para obtener una combinacin de un cuadro de lista y un cuadro de
texto. La lista se rellena con el mtodo AddItem. El usuario puede elegir un elemento de
la lista o introducir un valor en el cuadro de texto. Puede utilizarse para proporcionar
acceso de lectura / escritura a un campo de texto seleccionado en la lista. Consulte el
control DBCombo
ListBox Se utiliza para mostrar una lista en la cual el usuario puede elegir un elemento.
La lista se rellena con el mtodo AddItem. Puede usarse para proporcionar acceso de
lectura / escritura a un campo de texto especfico seleccionado en la lista. Consulte el
control DBList
PictureBox Se usa para mostrar una imagen grfica de un mapa de bits, un icono o un
meta-archivo en un formulario. Puede utilizarse para proporcionar acceso de lectura /
escritura a un campo de imagen o binario especfico.
Image Se utiliza para mostrar una imagen grfica de un mapa de bits, un icono o un
meta-archivo en un formulario. Las imgenes mostradas en un control Image utilizan
menos recursos que las de los controles PictureBox. Puede usarse para proporcionar
acceso de lectura / escritura a un campo de imagen o binario especfico.
MSFlexGrid Es un control enlazado a datos de reciente incorporacin. Apareci con la
versin 5 de VB y es un control parecido al DBGrid, pero con algunas ventajas y otros
inconveniente. En este caso, estando asociado a un control Data, el MSFlexGrid
solamente permite leer datos, no podemos variar el contenido de ningn registro.
Tampoco se mueve el registro actual del control Data cuando seleccionamos otra fila del
MSFlexGrid.
PROPIEDADES RELACIONADAS CON DATOS COMUNES A ESTOS CONTROLES
Los controles enlazados a datos tienen unas propiedades para el acceso a datos basadas
en el enlace con la base de datos a travs del control Data. Las propiedades comunes a
todos ellos son :
DataSource Fuente de datos. Es el nombre del control Data que lo enlaza con la B.D. Este
control Data es el que determina la Tabla donde estn los campos con los datos. Esta Tabla
se determina mediante la propiedad RecordSource del control Data.
DataField
Es el nombre del campo, dentro de la Tabla de la base de datos, que se va a
presentar en el control enlazado a datos. Esta propiedad no la tiene el DBGrid ni el
MSFlexGrid debido a que presentan todos los campos de la Tabla de la base de datos
seleccionada en el control Data.
Si se le ha forzado al control Data la propiedad Recordset, los campos que se pueden
mostrar en los controles enlazados a datos son justamente, los del ese Recordset al que se
le ha forzado.
Vamos a estudiar cada uno de los controles enlazados a datos con un poco mas de detalle.
378
Control Label
Posiblemente el control Label es el control ms sencillo para mostrar el contenido de un
campo de una base de datos. Como todos los controles enlazados a datos, el Label permite
presentar los datos e introducirlos en la base a travs del control Data. Lo que ocurre con
el Label es que su propiedad Caption no se puede introducir directamente por teclado, y
deber cambiarse por cdigo. Esto puede ser una ventaja (no hay posibilidad de
introducirlo accidentalmente) y un inconveniente, al tener que escribir cdigo para hacerlo.
El control Label, al poder ser origen (a travs del formulario que lo contiene) y destino de
un enlace DDE, esto nos puede resolver muchos problemas de introducin de distintos
datos de otras aplicaciones que no tengan acceso directo a una base de datos.
El control Label, en lo referente al enlace a datos, solamente tiene las propiedades
mencionadas de DataSource y DataField.
Control TextBox
Todo lo dicho del control Label es aplicable al TextBox,
que adems presenta la
particularidad de que en este control s se puede escribir directamente desde el teclado. De
esta forma podemos introducir datos o cambiar los existentes en la base de datos.
Control CheckBox
El control CheckBox permite presentar e introducir datos de tipo Booleano. Tiene las
propiedades DataSource y DataField en lo relativo a acceso a datos.
Controles ListBox y ComboBox
Estos controles tienen una caracterstica especial respecto a su comportamiento con el
enlace a la base de datos. La lista no se puede cargar directamente desde la base de
datos, sino a travs de un control intermedio, por ejemplo un Label, donde presentaremos
un campo de la base de datos. El texto de la propiedad Caption de este Label se introduce
en el ListBox o ComboBox mediante el mtodo AddItem. Una vez introducidos todos los
elementos de ese campo que nos interesen, cada vez que la base de datos se sita sobre
el registro correspondiente a uno de los elementos que est en el ListBox o ComboBox,
ste cambia su ListIndex para seleccionar el elemento correspondiente al registro actual
del control Data.
El ListBox puede contener elementos correspondientes a la base de datos y otros ajenos.
Puede emplearse esta caracterstica del ListBox para seleccionar un elemento entre varios
elementos tomados de la BD y otros introducidos por otro procedimiento, con la
particularidad de que el ListIndex de este ListBox ir a posicionarse sobre el elemento de la
BD correspondiente al registro actual del Control Data.
Tienen las propiedades DataSource y DataField en lo relativo a acceso a datos.
Controles DBList y DBCombo
Para agregar estos controles debe insertar el OCX Microsoft Data Bound List Controls 6.0
Estos controles tienen dos enlaces a controles data. Uno para rellenar la lista, que se lo
debemos indicar en la propiedad RowSource, acompaado del nombre del campo con el
que la va a rellenar, que introduciremos en la propiedad ListField, y otro enlace a otro
control Data, que se lo debemos indicar en la propiedad DataSource. El campo de este
segundo control Data se lo indicaremos en la propiedad DataField. El comportamiento de
estos dos controles es el siguiente: Mediante el enlace a travs de la propiedad
RowSource se rellena la lista, utilizando los datos del campo elegido en la propiedad
379
ListField. Imaginemos que la tabla a la que nos conectamos con estas propiedades es la
Tabla A. La tabla a la que enlazamos el DBList mediante la propiedad DataSource, le
llamamos Tabla B. Con este invento vamos a pasar un dato desde la tabla A a la tabla B.
El dato que vamos a pasar est en la tabla A en el campo sealado en la propiedad
BoundColumn del DBList. El registro de la tabla A de donde cogemos el dato ser el
seleccionado en el DBList. El registro de la tabla B donde vamos a meter el dato ser el
registro actual de ese control data, control actual que habremos seleccionado mediante
cualquier mtodo. El campo de esa tabla B que vamos a variar ser el campo indicado en
la propiedad DataField. (Esto se vuelve a explicar mas abajo, pero para entenderlo no
hay mas remedio que realizar una prctica)
Control PictureBox y Control Image
Pueden mostrar una imagen almacenada en una Base de Datos. Mediante el control Data,
se puede introducir la imagen presente en uno de estos controles en la Base de Datos.
El campo que contenga una imagen en una BD debe ser tipo Objeto OLE (Binario Largo
en versiones anteriores de Access), y el tipo de imgenes que se pueden introducir son los
mapas de bits (Archivos con extensin .BMP), los archivos de icono, (Extensin .ICO) y los
metaarchivos. (Metafiles, extensin .WMF)
Para introducir un grfico en una BD es mas prctico introducirlo mediante un control Data
y un control Picture o Image que creando por cdigo un Recordset. En realidad deberamos
decir que es el nico mtodo prctico de introducir / sacar imgenes de una Base de Datos
Control DBGrid
Es posiblemente el control que ms se use para presentar y modificar datos de una B.D. El
control DBGrid presenta todos los registros y todos los campos de la Base de Datos. Por
eso, necesita obligatoriamente un control Data para poder presentar datos. Otros controles
(Label, TextBox, Picture, etc.) que solamente presentan un dato (un campo de un registro)
pueden trabajar sin necesidad de un control data, creando un Recordset mediante cdigo.
(Lo veremos un poco mas adelante). Sin embargo el control DBGrid, al presentar todos los
datos de la base de datos necesita un control Data. Veamos porqu.
Cuando creamos un objeto Recordset mediante la instruccin : (se ver mas adelante)
Set Mirecordset = MiDataBase.Openrecordset (Select campo1, campo2 from Mitabla)
lo que estamos haciendo es seleccionar, de todos los campos que pueda tener la tabla
llamada Mitabla, los denominados campo1 y campo2. Cada vez que seleccionemos un
registro, es ese registro solamente el que se mantiene en la memoria del ordenador, (el
registro actual) y de ese registro, solamente metemos los datos del campo1 y campo2.
Cuando creamos un Recordset mediante un control Data, se meten en la memoria TODOS
los registros de la tabla especificada en el control data. Por lo tanto, al permanecer todos
los registros de esa tabla en memoria, podremos presentar sus valores en el control
DBGrid. No lo podremos hacer con un Recordset creado mediante cdigo, que solamente
mantiene un registro en memoria.
Deberemos explicar qu ocurre cuando se crea un Recordset mediante cdigo, y
posteriormente se fuerza a que el Recordset del control data sea igual a ese Recordset
creado.
Con el Recordset creado con la instruccin anterior, podemos forzar a un control Data que
su Recordset sea igual al ya creado mediante la instruccin :
380
doble cabeza (Size N S) cuando se sita sobre el divisor de filas entre selectores de
registro, y el usuario puede modificar el tamao de las filas mediante arrastre. Cualquier
cambio de tamao de columna provoca un evento RowResize.
AllowUpdate
Devuelve o establece un valor que indica si un usuario puede modificar datos del control
DBGrid.
Sintaxis
DefColWidth
Devuelve o establece un valor que indica el ancho de columna predeterminado para todas
las columnas del control DBGrid.
Sintaxis
objeto.DefColWidth [= valor]
382
383
BoundText
Devuelve o establece el valor de la propiedad BoundColumn de un control DBCombo o
384
DBList pasado desde o hacia la propiedad DataField despus de realizar una seleccin. Es
decir, es el contenido del campo especificado en la propiedad BoundColumn comentada
anteriormente.
Esta propiedad est disponible solamente en tiempo de ejecucin.
Esta propiedad es de lectura y escritura. Es sencilla de usar para conocer el contenido del
campo especificado en BoundColumn. (lectura del valor)
Cuando la queramos utilizar para forzar el valor de esta propiedad a un valor determinado,
debemos utilizar la siguiente sintaxis :
objeto.BoundText [= valor]
En este caso, el DBList o DBCombo intenta buscar un elemento coincidente en el campo
especificado en la propiedad BoundColumn de todos los registros de la BD asociada. Si
encuentra uno igual , se establece el valor de la propiedad BoundText basndose en el
campo especificado por la propiedad BoundColumn. Si no se encuentra dicha
coincidencia, la propiedad BoundText se establece en el valor Null.
Es decir, si hay coincidencia con algn valor de ese campo, BoundText seguir con el valor
especificado. Si no la hay, BoundText se pone a Nulo.
MatchWithList
Propiedad solo de lectura. Devuelve True si el contenido actual de la propiedad BoundText
coincide con uno de los registros de la parte de lista del control.
Sintaxis
Variable = objeto.MatchWithList
Si Variable = True el contenido de la propiedad BoundText coincide con uno de los registros
de la lista. Si es False, el contenido de la propiedad BoundText no coincide con ninguno de
los registros de la lista.
Cuando introduce un valor en la parte de texto del control DBCombo, la propiedad
MatchWithList se establece como True si el valor introducido es uno de los elementos que
aparecen en la lista. Usando esta propiedad, el cdigo puede interceptar entradas que no
estn la lista, o proporcionar cdigo para agregar la nueva entrada a la tabla de origen.
DataChanged
Devuelve o establece un valor que indica que han cambiado los datos del control enlazado
por algn proceso distinto de la recuperacin de datos del registro actual. No est
disponible en tiempo de diseo.
Sintaxis
de
esta
propiedad
Variable puede ser True, indicando que los datos que hay actualmente en el control no son
iguales que los del registro actual, y False (Predeterminado) que indica que los datos que
hay actualmente en el control (si los hay) son iguales que los del registro actual.
Comentarios
Cuando un control Data se mueve de un registro a otro, pasa datos desde los campos del
385
objeto.MatchEntry = valor
(Solo DBCombo)
DBCombo1.SelectedItem
objeto.VisibleCount
386
objeto.VisibleItems
Estos marcadores pueden emplearse para obtener registros individuales del conjunto de
registros empleado para rellenar la lista.
Y aqu se terminan las propiedades de DBList y DBCombo. La lata que dan y lo poco que
se usan!
Controles Picture e Image para acceso a datos a travs del control Data.
Merece la pena hablar del almacenamiento de imgenes en una base de datos. Es posible
introducir imgenes en una base de datos Access. El campo debe ser del tipo Objeto OLE
y puede manejarse de dos formas, una de forma sencilla, mediante un control Data, y otra
de forma un poco complicada, mediante los mtodos AppendChunk y GetChunk. Estos
dos mtodos los veremos un prximo captulo. Pero adelanto que es complicado usarlos.
Es muy sencillo sin embargo introducir y presentar imgenes residentes en una base de
datos mediante los controles Picture e Image. Estos controles son enlazados a datos y
pueden guardar una imagen o presentarla. Basta para ello poner los valores adecuados en
las propiedades DataSource y DataField para elegir un campo tipo Objeto OLE de la base
de datos y est el problema resuelto. Sobre todo para presentar la imagen, que lo hace
automticamente. No es lo mismo para introducir los datos, pero tambin es muy sencillo.
Basta para ello disponer de un CommonDialog, por ejemplo, para buscar una imagen
dentro del disco. El fichero puede ser un BMP, JPG o WMF. Abrimos el CommonDialog (CD1)
y buscamos la imagen deseada. A continuacin la cargamos en el Control Picture o Image
que est enlazado a datos mediante el mtodo LoadPicture. Para introducir la imagen en
la base de datos basta con cambiar de registro, o utilizar el mtodo UpdateRecord del
control Data.
Para presentar una imagen es preferible usar el control Image con la propiedad Stretch =
False a usar el control Picture. Con el Image y esa propiedad puesta a False, siempre
veremos la imagen con el tamao diseado en el formulario. Hacerlo con el control Picture
se puede, pero es algo mas complicado.
Pese a que, como se ha visto, se pueden meter imgenes en la base de datos Access, no
es aconsejable hacerlo debido al volumen tan grande de datos que genera. Es preferible
guardar la imagen en el fichero con la imagen, y meter en la base de datos la direccin
completa del fichero. Para abrirlo no hay mas que leer la direccin del fichero, y
presentarlo en el Picture o Image mediante el mtodo LoadPicture.
Control MSFlexGrid
El control MSFlexGrid es un control similar al DBGrid, pero pensado fundamentalmente
para enlazarlo a datos a travs del control Adodc1 (El control similar al Data en ADO). Sin
embargo tambin funciona con el control Data, aunque con prestaciones reducidas.
Estando enlazado al control Data, muestra los datos solo para lectura. Tampoco permite
cambiar el registro actual del control Data haciendo click sobre una de las lneas del
387
MSFlexGrid. Estas dos condiciones le hacen el control ideal para presentar todos los datos
del control Data para aquellos casos en los que no se permite cambiarlos al usuario.
Microsoft!
Objetos DAO de acceso a datos
Son muchos y tienen estructura jerrquica. Es importante resaltar lo de su estructura
jerrquica, ya que como ver, un objeto DAO crea los objetos DAO inmediatamente
inferiores en jerarqua.
Hay que sealar que las colecciones de estos objetos DAO son a su vez objetos de acceso
a datos. Esto hay que explicarlo un poco mejor. Por ejemplo, un objeto Database es un
objeto DAO que representa una base de datos abierta. Al objeto que agrupa a todas las
bases de datos abiertas en ese momento le llamamos Objeto Databases. Si tenemos dos
bases de datos abiertas en un determinado momento, el objeto Databases contendr dos
389
elementos.
Todos los objetos DAO excepto el dbEngine tienen colecciones. Es lgico. El dbEngine,
como ver mas adelante, es precisamente el Motor de Bases de Datos Jet y solamente
existe uno. Comenzaremos precisamente por l la explicacin de los objetos DAO.
El dbEngine es el motor Jet. Y como vimos en el captulo anterior, la versin 3.5 puede
trabajar directamente sobre el fichero de la base de datos o a travs de una conexin
ODBC. En el primer caso decimos que est trabajando en el espacio de trabajo
Microsoft Jet Si le hacemos trabajar a travs de ODBC decimos que estamos trabajando
en el espacio de trabajo ODBCDirect
Los objetos que emplea en cada uno de los espacios de trabajo pueden verse en las figuras
20.1 y 20.2. Puede observarse que tiene muchos mas objetos en el espacio de trabajo
Microsoft Jet que en el de ODBCDirect. Es lgico. Con el primero nos permite CREAR
bases de datos, y por lo tanto necesita tener objetos tales como el Tabledef, Index o
Relation. Lo ver un poco mas adelante.
El objeto dbEngine tiene los siguientes mtodos, propiedades y colecciones
Mtodos
CreateWorkspace,
CompactDatabase,
RepairDatabase,
RegisterDatabase
Propiedades DefaultPassword, DefaultUser, IniPath, LoginTimeout, Version
Colecciones Errors, Properties, Workspaces
Veremos estos mtodos y propiedades segn vayamos avanzando en el captulo
390
Idle,
En esta figura pueden verse los objetos y sus colecciones. Las colecciones llevan el nombre
en plural. Parece un poco complicado, y posiblemente lo ser. Lo cierto es que para el
trabajo que se hace normalmente con bases de datos este diagrama queda bastante
reducido. No se extrae tampoco de ver que objetos como el Fields y el Field existen en
varios niveles. Lo ver mucho mejor mas adelante.
391
Este modelo parece un poco mas asequible. La razn es que no hace todo lo que hace el
espacio de trabajo Microsoft Jet.
Objeto Workspace
Un objeto Workspace define una sesin de trabajo para un usuario especfico. Una sesin
de trabajo es precisamente eso, una sesin de trabajo en el ms puro estilo informtico.
Pueden existir varias sesiones de trabajo, pero en la mayora de los casos eso no es lo
normal. Ser necesario crear varias sesiones cuando necesitemos imponer restricciones de
acceso a una base de datos, cuando tengamos que usar Transacciones (*) en un sistema
multiusuario, y en algn caso ms. Las sesiones de trabajo tienen dueo (Usuario) y una
palabra clave para acceder a ellas.
Pero lo normal es tener solamente una sesin abierta. Y visual Basic nos facilita este caso
abriendo una sesin de trabajo automticamente. Cuando se inicia Visual Basic, se crea un
Workspace con palabra clave
y nombre de usuario Admin. Este Workspace es
precisamente el que ocupa el nmero cero de la coleccin de Workspaces. Es decir, es el
Workspaces(0).
No se preocupe de que ahora mismo no lo entienda. Ya lo entender. Pero hay que
exponerlo ahora. El objeto Workspace contiene:
Para el espacio de trabajo Microsoft Jet:
Grupos de trabajo, que es un grupo de usuarios de un entorno multiusuario que
comparten datos y el mismo sistema de base de datos.
Grupos de usuarios, que es una coleccin de cuentas de usuario. Estos objetos,
que no son objetos de acceso a datos, sino de explotacin de los recursos del
sistema, estn enfocados a la seguridad respecto al acceso a las bases de datos que
se trabajan conjuntamente. No tendra sentido hablar aqu de ellos si no fuese
porque encontrar referencias a estos objetos continuamente en la ayuda de Visual
Basic.
392
Bases de Datos (Databases). Este el objeto que ahora nos interesa del objeto
Workspace. Un objeto Database es una base de datos abierta.
Para el espacio de trabajo ODBCDirect:
Conexin, que representa una conexin con una base de datos a travs de ODBC
Bases de Datos (Databases).
Ya podemos comenzar a comprender una diferencia entre ambos espacios de trabajo. En el
Microsoft Jet tenemos Usuarios y Grupos de Usuarios. En el espacio ODBCDirect no los
tenemos, ya que el permiso o denegacin de acceso de uno u otro usuario a una base de
datos se establece cuando se crea (en Windows) la conexin ODBC. En el espacio
ODBCDirect tenemos un objeto llamado Connection, objeto que no tenemos en el
Microsoft Jet ya que con este sistema accedemos directamente al fichero de la base de
datos. No necesitamos ninguna conexin establecida previamente.
Al objeto Workspace se le puede dar un nombre definido por el usuario. Ese nombre habr
que declararlo como nombre de una variable objeto Workspace :
Dim Misesion as Workspace
La declaracin de la variable Objeto tiene las mismas caractersticas que cualquier variable
en cuanto al mbito en el que se puede usar. Para que pueda usarse en toda la aplicacin
deberemos declararla en un Mdulo con la sentencia Public
Public Misesion as Workspace
Esta advertencia es vlida para la declaracin de todos los objetos DAO.
Una vez declarado el nombre del objeto Workspace, hay que crearlo. En realidad, y tal
como citbamos mas atrs, cada vez que se inicia una sesin de Visual Basic, se crea
automticamente un Workspace. El nmero 0
A este Workspace no podemos ponerle
ningn tipo de palabra de acceso, ya que se la ha puesto VB : Admin. Utilicemos este
Workspace, el nmero 0 de la coleccin Workspaces, para comenzar a trabajar. Tiempo
tendremos mas adelante de ver como se crea un Workspace. Para hacer que Misesion sea
ese Workspace que crea automticamente VB basta con ejecutar la siguiente lnea de
cdigo
Set Misesion = Workspaces(0)
Pero si no queremos aprovechar este Workspace creado automticamente por Visual Basic,
y queremos usar otro, usemos el mtodo CreateWorkspace. Se ver al final del captulo.
Creacin de Objetos DAO
Para crear un objeto DAO (Cualquiera que sea) debemos usar una forma que se va a
repetir a lo largo de toda su vida profesional, mientras trabaje con Visual Basic y Bases de
Datos:
Set ObjetoDAOInferior = ObjetoDAOSuperior.Mtodo ( Aqu .... alguna cosa
)
Logicamente el trmino Aqu .... alguna cosa va a depender de cada mtodo y de lo que
Vd. quiera hacer, pero la estructura Set DAOInferior = DAOSuperior.Mtodo ( - - - - - - - - - ) se mantendr en todas las operaciones de creacin y manipulacin de objetos
DAO. Esta sintaxis es tan simple que un profesor de Visual Basic deca que es como un
juego de nios No lo olvide y se le quitar el miedo al manejo de bases de datos
393
mediante cdigo. Posiblemente hasta ahora le haya parecido muy difcil y haya optado por
usar el control Data para todas sus aplicaciones. Si recuerda este Juego de nios ver
que es ms sencillo crear objetos DAO que poner un control Data en un formulario.
Comenzaremos a explicar la operacin de bases de datos mediante DAO explicando como
se crean bases de datos Access mediante Visual Basic. Para que se van a crear bases de
datos mediante un programa si puedo hacerlo directamente con Access? . Esta pregunta
me la han hecho los alumnos durante todos mis aos de docencia. La nica respuesta para
ello es que deseo que Vd. sea programador, no usuario de ofimtica.
Objeto Database
Un objeto Database representa una base de datos abierta. Una coleccin Databases
contiene todos los objetos Database abiertos en un objeto Workspace del motor de bases
de datos Microsoft Jet.
Un objeto Database puede crearse, bien porque hemos creado una base de datos
el procedimiento CreateDataBase, o porque hemos abierto una base de datos
mediante el procedimiento OpenDatabase. En cualquiera de los dos casos,
Database existe hasta que lo cerremos (mediante el mtodo Close) o hasta que
la aplicacin.
mediante
existente
el objeto
cerremos
Al objeto Database se le debe dar un nombre definido por el usuario. Eso s, hay que
declararlo como una variable objeto Database
Dim MiDataBase As Database
El nombre que le demos al objeto DataBase no tiene nada que ver con el nombre del
fichero que alberga esa base de datos. El objeto DataBase es la base de datos que
creamos en la memoria RAM del ordenador.
Coleccin Databases Es el conjunto de Objetos Database existentes. La coleccin
Databases pertenece al Workspace.
394
Database. El nombre del objeto Database tampoco tiene porque coincidir con el nombre
del fichero que se va a crear. En el ejemplo que veremos mas adelante, el nombre del
objeto Database es MiBaseDatos y el nombre del fichero es MiBase.Mdb.
La sintaxis del mtodo CreateDataBase es el juego de nios citado antes:
Set ObjetoDAOInferior = ObjetoDAOSuperior.Mtodo ( Parmetros )
En nuestro caso el Objeto DAO superior es el Workspace Misesion, y los parmetros que
hay que pasar en este caso son:
Misesion.CreateDatabase
(C:\MiCarpeta\MiBase.MDB,
inf_local y el Password o palabra clave que quiere usar para restringir su uso. Este
Password es opcional. Debe especificar el argumento inf_local o se producir un error.
Consulte la tabla de constantes para inf_local incluida ms adelante en este tema.
En el argumento Opciones puede combinar varias opciones, segn se especifica a mas
adelante. Puede combinar varias opciones sumando las constantes correspondientes.
Descripcin
de datos codificada.
de datos que utiliza la versin 1.0 del motor de base de datos
de datos que utiliza la versin 1.1 del motor de base de datos
de datos que utiliza la versin 2.5 del motor de base de datos
de datos que utiliza la versin 3.0 del motor de base de datos
Esta Versin es compatible con la 3.5
396
Micampo11
Micampo12
Micampo13
Micampo14
Micampo15
MiTabla2.Fields.Append Micampo21
398
Ya tenemos campos formando parte de la coleccin Fields de las tablas. Ahora debemos
aadir las tablas a la coleccin de tablas de la base de datos. Esa coleccin de tablas es el
objeto Tabledefs de la base de datos, es decir, del objeto DataBase. Lo haremos tambin
mediante el mtodo Append
MiBaseDatos.TableDefs.Append Mitabla1
MiBaseDatos.Tabledefs.Append Mitabla2
Si ahora cerramos la base de datos mediante el mtodo Close:
MiBaseDatos.Close
Ya tenemos la base de datos creada en el disco de la misma forma que lo hubiera hecho
Access. Pero puede que le falte algo respecto a una base creada directamente con Access:
los Indices y las Relaciones.
Un ndice es una marca que le podemos poner a cada uno de los registros en un campo.
Esa marca puede servir por ejemplo, para ordenar los registros de la BD por ese campo.
Puede servir tambin para evitar que dos registros tengan el mismo valor para un
determinado campo. En el ejemplo que estamos preparando, el Campo11 (ID_Alumno)
queremos que sea un ndice, y adems que no se pueda repetir el mismo valor para dos
registros distintos, de forma que no puedan existir dos registros con el mismo valor en ese
campo.
Una Relacin es una correspondencia entre un campo de una tabla y otro campo de
caractersticas similares en otra tabla. Esto nos lleva al concepto de Base de Datos
Relacional que seguramente ya sabe de que se trata. En Access se puede establecer una
relacin de una forma muy sencilla. En Visual Basic tambin. Pero antes de seguir
reflexionemos y recordemos lo que hemos hecho hasta ahora.
Observe que, cada vez que creamos un objetos (DataBase, Tabledef, Field) usamos el
mencionado juego de nios. El mtodo correspondiente para crear un objeto DAO
pertenece al objeto DAO inmediatamente superior en jerarqua, es decir, CreateDatabase
es un mtodo del objeto Workspace, CreateTableDef es un mtodo del objeto Database,
CreateField es un mtodo del objetos TableDef.
Las colecciones pertenecen tambin al objeto inmediatamente superior en jerarqua al tipo
de objetos que forman la coleccin. La coleccin Fields (Objeto Fields) pertenece a un
objeto TableDef,
la coleccin TableDefs (objeto TableDefs) pertenece a un objeto
Database, y la coleccin Databases (Objeto Databases) pertenece a un objeto Workspace.
La coleccin Workspaces pertenece al DBEngine, y el DBEngine ya no podemos asignarlo a
ningn objeto DAO. Tendremos que decir que pertenece al sistema.
Recordemos ese juego de nios :
Set DAOInferior = DAOSuperior.Mtodo ( - - - - - -)
Hemos visto que despus de crear un objeto, debemos aadirlo a la coleccin a la que
debe pertenecer con el mtodo Append. El procedimiento es siempre el mismo :
Objeto superior.Coleccin.Append Objeto a aadir
Sigamos ahora perfeccionando la base de datos. Vamos a ver como se crea un Indice.
399
Mtodo CreateIndex
Para crear un ndice debe estar creado el campo al que se le va a aplicar el ndice. Puede
que le parezca un poco extrao alguno de los mtodos que vamos a usar para crear un
ndice, como por ejemplo volver a usar el procedimiento CreateField para crear un campo
que ya existe. Son las incongruencias que tiene a veces Visual Basic. Le recomiendo que si
no se acuerda bien de cmo se hace, recurra a la ayuda de VB, que en este caso es exacta
y concisa. O si lo prefiere, al ejemplo que ilustra esta Gua del Estudiante como colofn a
este captulo.
Primer debemos crear el Objeto Index. Se hace mediante el mtodo del objeto Tabledef,
CreateIndex. El ndice debe crearlo el Tabledef al que pertenece el campo que queremos
que sea ndice. La sintaxis de CreateIndex es:
Set NombreIndice = NombreTabledef.CreateIndex([Nombre])
Donde NombreIndice es el nombre de una variable declarada como tipo de dato objeto
Index.
NombreTabledef es el nombre de variable del objeto TableDef que se desea usar para crear
el nuevo objeto Index.
Nombre es una variable de tipo String que da un nombre nico al nuevo objeto Index. Este
nombre lo puede ver si abre la base de datos con Access y en la vista de Diseo de la
tabla, abre la funcin Ver | Indices de la barra de men.
En nuestro ejemplo:
Declaramos el objeto Index
Dim MiIndice as Index
Creamos el ndice
Set MiIndice = MiTabla1.CreateIndex (Indice1)
Ya tenemos creado el Objeto Index. Ahora, (y aqu empieza la incongruencia citada) este
objeto Index debe crear el campo que queremos que sea ndice. Pero ese campo ya debe
existir en el objeto Tabledef con el que hemos creado el ndice (en este caso, en MiTabla1)
Set MiCampo11 = MiIndice.CreateField (ID_Alumno, dbText, 8)
El nombre del campo, tipo y tamao deben coincidir con los datos que sirvieron para crear
el campo en el objeto Tabledef.
Pero un ndice puede tener varios campos. Por ejemplo, piense en el cdigo de un objeto
en un inventario. El cdigo es el nmero que identifica de forma unvoca a un objeto. Un
objeto inventariable (por ejemplo una mesa) tiene un cdigo de grupo (por ejemplo, el
123) Hay muchas mesas dentro de un inventario, pero todas ellas tienen un nmero
distinto (una tiene el 001, otra el 002, etc) La combinacin de cdigo de grupo ms el
nmero del objeto dentro de ese grupo queremos que sea un ndice. Ese ndice estar
formado entonces por dos campos. En este caso deberemos crear los dos campos:
Set MiCampo11 = MiIndice.CreateField (C_Grupo, dbText, 3)
Set MiCampo12 = MiIndice.CreateField (Numero, dbText, 3)
Ya tenemos el campo o los campos creados por el ndice. Ahora debemos aadirlo (o
aadirlos) a la coleccin Fields del objeto Index recin creado. Lo hacemos mediante el
mtodo Append
400
MiIndice.Fields.Append MiCampo11
Si fuesen dos los campos
MiIndice.Fields.Append MiCampo11
MiIndice.Fields.Append MiCampo12
No crea que ya hemos terminado. Un objeto Index tiene propiedades. Una de ellas ya la
hemos visto sin querer, la propiedad Name (nombre del ndice, en nuestro ejemplo,
Indice1). Otras propiedades son:
Primary - El objeto Index representa la clave primaria de la tabla.
Unique - No permite repeticin de valores en ese campo
Required - Indica que todos los campos del objeto Index deben rellenarse.
IgnoreNulls - Indica si permite valores Nulos en los campos del ndice.
(Existen adems las propiedades Clustered, Foreign, DistinctCount que no se explican
para no complicar mas el tema. Cuando los necesite no tendr inconveniente en
estudiarlos partiendo de la ayuda de VB)
Para introducir el valor de una de estas propiedades se procede con la siguiente sintaxis:
MiIndice.Uniuqe = True
MiIndice.Primary = True
Ya est creado el ndice y tiene ya metido uno o mas campos y todas sus propiedades.
Ahora debemos aadir ese ndice a la coleccin Indexes del Objeto Tabledef.
MiTabla1.Indexes.Append MiIndice
Lo confieso. Cada vez que hago esto en la vida real tengo que volver a leer este
procedimiento en la Gua del Estudiante. Es complicado, pero alguna vez se terminar
aprendiendo.
Ya tenemos la base de datos completamente creada. Sin embargo alguien dir que le falta
algo: Relacionar dos tablas
Relaciones entre tablas Mtodo CreateRelation
Una Relacin es una asociacin establecida entre dos campos del mismo tipo ubicados en
dos tablas distintas. Se pueden establecer relaciones uno a uno uno a varios. Para
relacionar un campo con otros, ese campo debe ser clave primaria. A la tabla que contiene
a este campo se le llama Tabla Principal. A la tabla que contiene el campo (o los campos)
relacionados se le llama Tabla Relacionada.
Para crear una relacin, usaremos un nuevo objeto DAO : El objeto Relation. Este objeto
forma parte de una coleccin, que es a su ves otro objeto DAO : el objeto Relations.
Para crear una relacin usaremos el Mtodo CreateRelation, que es un mtodo del objeto
Database. (Lgico, una relacin se establece entre dos tablas. Por lo tanto, la relacin debe
pertenecer al objeto DAO superior jerrquicamente a las tablas: el Objeto Database. Como
para cualquier otro objeto DAO, es necesario declararlo :
401
402
MiCampo.ForeignName = "Campo21"
Aadimos el campo creado a la coleccin Fields del objeto Relation
MiRelacin.Fields.Append MiCampo
Y ahora aadimos el objeto Relation recin creado a la coleccin Relations del objeto
Database
MiBaseDatos.Relations.Append MiRelacin
Solamente nos falta ver que valores puede tener la propiedad Attributes del objeto
Relation
dbRelationUnique
dbRelationDontEnforce
referencial).
dbRelationInherited
dbRelationUpdateCascade
dbRelationDeleteCascade
impuesta
(no
hay
integridad
Ahora ya casi podemos decir que tenemos la base de datos creada. Puede que sea as o
que le falte alguna cosa. Puede faltarle una o varias consultas. Las consultas tambin se
pueden crear mediante objetos DAO. Precisamente con un objeto QueryDef
Consultas. El Objeto QueryDef
Pero habr observado que una base de datos ACCESS puede contener, adems de tablas,
CONSULTAS. Las consultas no contienen datos. Contienen una referencia a los registros
de las tablas que los contienen. Una consulta podramos decir que son conjuntos de
registros tomados de una o varias tablas (en este ltimo caso, esas tablas deben estar
relacionadas) que cumplen unas determinadas condiciones. Pero aunque podemos ver esos
registros como tales, con sus datos exactamente igual que si se tratase de los registros de
una tabla, las consultas no contienen el dato, sino el nmero del registro dentro de la tabla
que lo contiene. A la hora de presentar los datos de una consulta, lo que estamos
presentando son los datos almacenados en la tabla o las tablas que componen esa
consulta.
Crear una consulta. Mtodo CreateQueryDef
Un objeto QueryDef representa una consulta de la base de datos. El objeto QueryDefs es
la coleccin de objetos QueryDef. La diferencia entre una consulta (Un QueryDef) y una
tabla (Un TableDef) es que la Tabla tiene dentro de s los datos. La consulta tiene dentro
una referencia al lugar de las tablas donde se encuentran los datos.
Antes de utilizar el mtodo CreateQueryDef debe declarar el nombre de los objetos a
crear, declarndolos como Variables Objeto tipo QueryDef . El mbito es igual que para
cualquier variable:
Public MiConsulta1 as QueryDef
Public MiConsulta2 as QueryDef
Ahora podemos utilizar el mtodo CreateQueryDef para crear el nuevo objeto QueryDef
en la base de datos.
403
Sintaxis
definirla por el conjunto formado por su ID_Pelicula y por su Idioma. El conjunto de esos
dos campos ser la clave primaria. (Si cree que hay campos que no tienen sentido en esta
tabla (Idioma), piense que esto es un ejemplo para poder explicar de la forma ms
didctica todas las posibles variaciones de una instruccin)
Existe otra tabla denominada Cintas, donde figurarn todas las cintas existentes en el
videoclub. Para poder relacionarla con la tabla Peliculas, le ponemos un campo llamado
ID_Pelicula que en esta tabla no ser clave primaria. Tambin le pondremos el campo
Idioma, sobre el que no haremos ningn tipo de relacin. Tendr un campo ID_Cinta que
ser la combinacin de varios datos, uno que nos indique la pelcula que tiene grabada esa
cinta (Ser la combinacin de los campos ID_Pelicula e Idioma) y de un nmero
secuencial que indicar el nmero de la copia. Si le pone imaginacin y este conjunto de
datos puede meterse en un cdigo de barras, le facilitar la operacin de alquiler y
devolucin. En este ejercicio haremos que sea as, dndole a este campo un tamao de 13
dgitos para poder meterlo en un cdigo EAN-13. Podemos aadirle mas campos a nivel
administrativo, como fecha de alta, fecha de baja, precio de esta copia, etc.
Existir una tercera tabla, Alquileres, que relacionar al cliente con la cinta que ha
alquilado. Tendr un campo llamado ID_Cliente y otro ID_Cinta. Aparte tendr otros dos
campos, fecha de alquiler y fecha de devolucin.
La base de datos deber tener dos relaciones, una, entre el campo ID_Cliente de la tabla
Clientes y el campo ID_Clientes de la tabla alquileres (Ser uno a infinito) y otra relacin,
entre el campo ID_Cinta de la tabla Cintas y el campo ID_Cinta de la tabla Alquileres
(Relacin 1 a 1 ya que solamente existe una cinta con esa ID_Cinta). Para darle ms
alegra al ejercicio le pondremos una relacin entre los campos ID_Pelicula e Idioma de las
tablas Peliculas y Cintas.
(Se ha puesto el nombre de Pelicula al campo relacionado con ID_Pelicula para que se vea
que dos campos relacionados no tienen porqu tener el mismo nombre. Eso s, deben
tener las mismas caractersticas)
Como colofn a todo esto, crearemos una consulta en la que utilizaremos todas las
relaciones.
Para llevar a cabo este ejercicio se ha partido de una interface grfica en la que pueden
verse tres botones (Borrar la base de datos, crearla y salir) y un TextBox donde se ha
puesto el nombre del fichero de la base de datos en su propiedad Text. Veamos el cdigo
de cada uno de los botones (por orden inverso de complejidad del cdigo)
Fig. 20.3 Interface grfica de la parte de crear bases de datos para la aplicacin del
Videoclub
CODIGO
Private Sub BSalir_Click()
Unload Me
End Sub
Private Sub BBorrar_Click()
On Error GoTo RutErr
405
Se crea el Objeto DataBase (Se toma el nombre del fichero del TextBox TBNombreBase
Set MiBaseDatos = Workspaces(0).CreateDatabase(TBNombreBase, dbLangGeneral)
Se
Set
Set
Set
Set
MiCampo21
MiCampo22
MiCampo23
MiCampo24
MiCampo25
=
=
=
=
=
MiTabla2.CreateField("ID_Pelicula", dbText, 8)
MiTabla2.CreateField("Titulo", dbText, 20)
MiTabla2.CreateField("Idioma", dbText, 1)
MiTabla2.CreateField("Director", dbText, 25)
MiTabla2.CreateField("Resumen", dbText, 255)
406
Set
Set
Set
Set
Set
Set
MiCampo31
MiCampo32
MiCampo33
MiCampo34
MiCampo35
MiCampo36
=
=
=
=
=
=
Set
Set
Set
Set
MiCampo41
MiCampo42
MiCampo43
MiCampo44
=
=
=
=
MiTabla4.CreateField("ID_Cliente", dbText, 8)
MiTabla4.CreateField("ID_Cinta", dbText, 13)
MiTabla4.CreateField("Fecha_Alq", dbDate)
MiTabla4.CreateField("Fecha_Dev", dbDate)
Una vez creados los campos se les ponen las peopiedades que se estime oportuno
En este caso, se ha puesto la propiedad AllowZeroLength (Permitir valores nulos en ese
campo) a lo que interesa en cada uno de los campos. Nota Tenga presente que por
defecto le va a dejar el campo que NO permite valores nulos, circunstancia que le va a
crear problemas.
MiCampo12.AllowZeroLength
MiCampo13.AllowZeroLength
MiCampo14.AllowZeroLength
MiCampo15.AllowZeroLength
=
=
=
=
True
False
True
True
MiCampo21
MiCampo22
MiCampo23
MiCampo24
MiCampo25
MiTabla3.Fields.Append
MiTabla3.Fields.Append
MiTabla3.Fields.Append
MiTabla3.Fields.Append
MiTabla3.Fields.Append
MiTabla3.Fields.Append
MiCampo31
MiCampo32
MiCampo33
MiCampo34
MiCampo35
MiCampo36
MiTabla4.Fields.Append
MiTabla4.Fields.Append
MiTabla4.Fields.Append
MiTabla4.Fields.Append
MiCampo41
MiCampo42
MiCampo43
MiCampo44
Se declaran los objetos Relation y un par de objetos Field para crear las
relaciones. Por
claridad se han declarado objetos Field distintos para la creacin de los ndices y
de las relaciones, pero podran haber sido los mismos
Dim MiRelacion1 As Relation, MiRelacion2 As Relation, MiRelacion3 As Relation
Dim CampoRelacionA As Field
Dim CampoRelacionB As Field
Se crea la primera relacin entre el campo ID_Clientes de la tabla Clientes (Tabla
primaria) y el campo ID_Cliente de la tabla Alquileres (Tabla relacionada)
Set MiRelacion1 = MiBaseDatos.CreateRelation("RelClientes", "Clientes", "Alquileres")
Set CampoRelacionA = MiRelacion1.CreateField("ID_Cliente", dbText, 8)
CampoRelacionA.ForeignName = "ID_Cliente"
MiRelacion1.Fields.Append CampoRelacionA
MiBaseDatos.Relations.Append MiRelacion1
Se crea la segunda relacin
Set MiRelacion2 = MiBaseDatos.CreateRelation("RelCintas", "Cintas", "Alquileres")
MiRelacion2.Attributes = dbRelationUnique
Set CampoRelacionA = MiRelacion1.CreateField("ID_Cinta", dbText, 13)
CampoRelacionA.ForeignName = "ID_Cinta"
MiRelacion2.Fields.Append CampoRelacionA
MiBaseDatos.Relations.Append MiRelacion2
408
El resultado de todo esto podemos verlo si abrimos la base de datos con Access
409
Fig. 20.6 Clave Primaria formada con los dos campos de la tabla Pelculas
410
que ha protegido su base. No es una proteccin total, pero s suficiente para que un
usuario normal no se la pueda abrir.
Crear bases de datos encriptada
Puede encriptar el fichero de su base de datos. Solamente le ser til para que no puedan
ver el contenido del fichero .MDB, ya que si se abre con Access, le presentar los datos de
forma correcta. Para encriptar una base de datos basta con aadir la palabra dbEncrypt
en la instruccin donde ha creado la BD
Set MiBaseDatos = Workspaces(0).CreateDatabase(TBNombreBase,dbLangGeneral &
";pwd=LSB", dbEncrypt)
Ha merecido la pena el trabajo. Hemos creado la base de datos haciendo click en un botn
de la aplicacin. No ha sido necesario venderle al cliente Access, ni enviar una base de
datos vaca con los discos de distribucin. Adems hemos controlado todos los parmetros
de los campos de nuestra BD. Merece la pena crearse las bases de datos por programa.
Anexo1
Propiedades de los campos
Ha visto mas atrs que puede ser necesario cambiar las propiedades de los campos una
vez creados (Por ejemplo, MiCampo13.AllowZeroLength = False) Alargaramos demasiado
este ya largo captulo si se explican todos los las propiedades que puede tener un campo.
Aada un poco de esfuerzo a su estudio y vea las propiedades de los objetos Field en la
ayuda. Le reseo aqu las que he considerado mas importantes
AllowZeroLength Si/NO Si es Si permite que ese campo tenga valores nulos
DataUpdatable Si/No Si es Si permite modificar el dato de ese campo. No tiene
aplicacin a la hora de crear un campo. S puede cambiar el valor de esta propiedad por
ejemplo, cuando crea un recordset.
DefaultValue Es el valor que le pone a ese campo si no introduce ninguno. Puede indicar
un valor a la hora de crear el campo:
Campo14.DefaultValue = Madrid
Required Si/No
412
Propiedad Type
Constante
Descripcin
Constante
Descripcin
dbBoolean
dbCurrency
dbDouble
dbLong
dbLongBinary
dbSingle
Campo SI/NO
dbByte
Campo tipo Byte
Tipo moneda
dbDate
Tipo Date/Time
Numrico Doble
dbInteger
Numrico Integer
Entero Long
dbMemo
Campo Memo
Binario largo (Objeto OLE)
Numrico Single
dbText
CampoTexto
Propiedad Attributes
Constante
Descripcin
dbFixedField
dbVariableField
dbAutoIncrField
dbUpdatableField
dbDescending
la
Propiedad Size
Devuelve o establece un valor que indica el tamao mximo, en bytes, de un objeto Field
que contiene texto o el tamao fijo de un objeto Field que contiene texto o valores
numricos
Esta propiedad se le debe suministrar en la sintaxis de CreateField solamente cuando
creamos un campo tipo texto - CreateField("ID_Cinta", dbText, 13). El tamao de un
campo texto puede ser desde 1 a 255 caracteres. Para el resto de los tipos de datos, el
tamao va implcito en el tipo de dato. Puede consultar el tamao ocupado por cualquier
campo, leyendo la propiedad Size de un campo:
Variable = Micampo11.Size
413
Set MiBaseDatos
origen]]])
Misesion.OpenDatabase(nombre_bd[,
exclusivo[,
slo-lectura[,
especificar
nombre_bd
hay
que
tener
en
cuenta
algunas
Si se refiere a una base de datos ya abierta por otro usuario con acceso
exclusivo, se producir un error.
Si no se refiere a una base de datos existente o a un origen de datos ODBC
vlido, se producir un error.
414
p.e.
415
EL OBJETO RECORDSET
(O la mitad de lo que Vd. necesita saber de Bases de Datos)
Un objeto Recordset contiene los registros de una tabla o de una consulta. Puede ser que
no los contenga todos, si al crear ese recordset le hemos impuesto que los registros
cumplan una determinada condicin. En resumen, un recordset es un objeto de acceso a
datos que contiene una coleccin de registros tomados, bien de una tabla, bien de un
conjunto de tablas (a travs de una consulta)
Tambin hay una coleccin Recordsets. La coleccin Recordsets contiene todos los objetos
Recordset abiertos de un objeto Database.
Al utilizar objetos de acceso a datos, casi toda la interaccin con los datos se produce a
travs de objetos Recordset. Todos los objetos Recordset estn formados por registros
(filas) y campos (columnas). Existen tres tipos de objetos Recordset:
Recordset de tipo tabla: Representacin en cdigo de una tabla base de datos que
puede utilizarse para agregar, modificar o eliminar registros de una sola tabla de base de
datos. Un Recordset tipo Tabla contiene todos los campos de una tabla y no puede
contener campos que no pertenezcan a esa tabla.
Recordset de tipo hoja de respuestas dinmica: Resultado de una consulta que puede
tener registros actualizables. Un Recordset de tipo hoja de respuestas dinmica es un
conjunto dinmico de registros que puede utilizarse para agregar, modificar o eliminar
registros de una o ms tablas de una base de datos subyacente. Este tipo de objeto
Recordset puede contener campos de una o ms tablas de una base de datos.
Recordset de tipo instantnea: Copia esttica de un conjunto de registros que puede
utilizarse para buscar datos o generar informes. Los objetos Recordset de tipo instantnea
pueden contener campos de una o ms tablas de una base de datos, pero no pueden
actualizarse. Un recordset de tipo instantnea (Snapshot) es una fotografa que se hace a
la tabla o tablas que lo componen. Los datos que tiene el recordset son los que existan
cuando se realiz la fotografa. Cualquier actualizacin posterior no se puede ver.
Resumiendo, un Recordset es un conjunto de registros. Recuerde cuando explicbamos en
control Data se deca que este control creaba un Recordset a partir de sus propiedades
DatabaseName y RecordSource. De esta forma, el conjunto de registros que tiene ese
control Data es la totalidad de los registros de la tabla (o consulta) que ponamos en la
propiedad RecordSource. Pero siempre podemos asignar a la propiedad Recordset de ese
control Data un Recordset ya creado mediante cdigo. Y en ese caso, solamente contendr
los campos que a nosotros nos interese, incluso campos de distintas tablas, cosa que viene
muy bien algunas veces.
Un Recordset lo crearemos con el mtodo OpenRecordset que estamos estudiando. El
objeto Recordset se abre desde un objeto DataBase (que es lo normal). Pero si acude a la
informacin de VB ver que tambin se puede abrir desde un TableDef, un QueryDef y
desde otro Recordset. No se complique la vida. Abra directamente los Recordsets desde la
base de datos. A lo mejor, tenemos oportunidad de ver que tambin se puede abrir desde
otro recordset, pero que en este caso solamente podemos abrirlo para cambiar alguna de
sus propiedades.
Como cualquier objeto DAO, debemos declararlo como variable tipo objeto.
Public Mirecordset As Recordset
Una vez declarado, para abrirlo basta con ejecutar la sentencia :
416
(SELECT
FROM
MiTabla,
Veamos lo que decamos antes. Crear un Recordset desde otro recordset. Se puede usar
solamente para variar sus propiedades. Si desde el Recordset anterior, queremos crear un
nuevo Recordset denominado MiRecordset1, que tenga la condicin de que sea solo
lectura, usaremos la sentencia :
Set Mirecordset1 = Mirecordset.OpenRecordset (dbReadOnly)
Este nuevo Recordset contendr los mismos campos que el Recordset origen, pero no
podremos cambiar datos en l.
Pueden crearse tantos Recordsets como se necesiten. Estos Recordsets pueden tener
campos comunes. Es ms, podramos crear dos Recordsets exactamente iguales.
Pero en la mayora de los casos, necesitaremos crear un Recordset donde se elijan varios
campos de una o varias tablas, seleccionando de esos campos unos determinados valores.
Por ejemplo, en una base con las direcciones de los clientes, a lo mejor queremos
seleccionar todas aquellas direcciones en las cuales el cdigo postal sea el 28700 (San
Sebastin de los Reyes). Imaginemos que hemos abierto la base de datos con el nombre
CLIENTES (Recuerde que este es el nombre del objeto DAO usado para abrir la B.D., no el
nombre que pueda tener esa B.D. en el disco), y esta base de datos tiene una tabla
llamada DIRECCIONES (Este s es el nombre real de la tabla dentro de la B.D.) Vamos a
abrir un Recordset con todos los clientes de San Sebastin de los Reyes :
Set Mirecordset2 = CLIENTES.OpenRecordset (SELECT * FROM DIRECCIONES WHERE
COD_POSTAL = 28700, dbOpenDynaset)
El Recordset Mirecordset2 contiene todos los campos de todos los registros de la tabla
DIRECCIONES que cumplan la condicin de que el cdigo postal (campo COD_POSTAL en
el ejemplo) sea igual a 28700.
Observe en esta y anteriores expresiones, que la sentencia SQL est entre doble comilla.
Podemos introducir cualquier sentencia SQL para determinar qu registros introducimos en
el Recordset. Por ejemplo, si queremos seleccionar todos los clientes de Madrid (su cdigo
postal comenzar necesariamente por 28 y le seguirn tres cifras) :
Set Mirecordset2 = CLIENTES.OpenRecordset (SELECT * FROM DIRECCIONES WHERE
COD_POSTAL LIKE 28???, dbOpenDynaset)
Tipo de recordset ms prctico Dynaset, Table?
A la hora de crear un recordset podemos pensar que tipo es el ms adecuado. Todo
depender de lo que necesitemos de nuestro recordset y de cmo nos queramos mover
por l. Cuando decimos movernos por l queremos decir cambiar de un registro a otro,
buscar registros, etc.
Vamos a prescindir del recordset tipo Snapshot si lo que queremos es leer y escribir datos.
Un recordset Snapshot solamente sirve para realizar informes (leer) de los datos en un
instante determinado. Veamos la eleccin entre Dynaset y Table
Si queremos seleccionar parte de los registros de una tabla, o ver registros de varias tablas
al mismo tiempo (lo que podemos ver en Access en una consulta), debemos elegir
directamente el tipo Dynaset, ya que el tipo Table debe contener TODOS los registros de
una UNICA TABLA.
Si estamos en ese caso es el nico en el que tendremos dudas respecto al tipo elegido.
418
Si creamos un recordset tipo Table se nos puede complicar un poco el cdigo a la hora de
movernos a lo largo del recordset, ya que no podemos usar ciertos mtodos como los Find
(FindFirst, FindLast, etc.) debiendo utilizar para realizar la misma funcin los mtodos
Move (MoveFirst, MoveLast, MovePrevious, MoveNext), o el mtodo Seek, un poco ms
complicado y que exige un ndice. (Lo que ganamos con la complicacin del Seek es
velocidad). Los desplazamientos a lo largo de un recordset tipo tabla son mucho ms
rpidos que sobre un recordset tipo Dynaset. Esa rapidez se nota fundamentalmente
cuando va a manejar miles de registros, en cuyo caso es indispensable usar recordsets tipo
tabla y moverse sobre un ndice. Si no va a manejar miles de registros, no apreciar
mucha diferencia entre uno y otro. Y si usa Dynaset dispone de ms recursos, sobre todo
de bsqueda. Veremos casos de uno y otro tipo.
Mtodos y Propiedades del recordset que va a necesitar inmediatamente
Propiedad RecordCount
Devuelve el nmero de registros accedidos en un objeto Recordset. El valor de esta
propiedad es de slo lectura
Sintaxis
NombredeMiRecordset.RecordCount
MiRecordset.AddNew
El mtodo AddNew crea un nuevo registro donde puede introducir nuevos datos, y
posteriormente agregarlo al conjunto de registros del objeto Recordset. Este mtodo
establece en los campos el valor Null (predeterminado para los objetos Recordset de tipo
tabla) o los valores predeterminados, si existen. El registro creado queda en la memoria, y
ah se puede modificar simplemente asignando a cada campo el valor deseado. Para
asignar un valor a un campo simplemente tenemos que poner la expresin :
MiRecordset ! MiCampo1 = Dato tipo string
MiRecordset ! MiCampo2 = Dato tipo numrico
419
Una vez que se hayan introducido los datos en el nuevo registro, debe utilizar el mtodo
Update para guardar los cambios y agregarlo al conjunto de registros. No se modificar la
base de datos hasta que se utilice el mtodo Update.
La posicin del nuevo registro depende del tipo de objeto Recordset:
En un objeto Recordset de tipo hoja de respuestas dinmica, (Dynaset) los registros se
insertan al final del conjunto, independientemente de las reglas de ordenacin que pueda
haber en vigor al abrir el conjunto de registros. En un objeto Recordset de tipo tabla cuya
propiedad Index est definida, los registros se agregan en el lugar correspondiente al
orden. Si no se ha establecido la propiedad Index, los nuevos registros se agregan al final
del conjunto.
El registro que era actual antes de utilizar el mtodo AddNew contina sindolo despus.
Esto puede comprobarlo asignando a un Label el contenido de un campo, aadir un
registro con un valor para ese campo distinto al que est presente en el Label y comprobar
que el contenido del Label no se ve afectado por haber introducido un registro nuevo. Si
desea hacer que el nuevo registro sea el actual, puede establecer en la propiedad
Bookmark el marcador identificado por el valor de la propiedad LastModified. En la
prctica anterior observar tras este proceso que se cambia el contenido del Label al nuevo
valor.
Vea la propiedad LastModified un poco mas adelante.
Mtodo Edit
Copia el registro actual de un objeto Recordset de tipo hoja de respuestas dinmica o tabla
en el bfer de copia para su edicin.
Sintaxis
MiRecordset.Edit
420
Mtodo Update
Guarda el contenido del bfer de copia en un objeto Recordset de tipo hoja de respuestas
dinmica o tabla especificado.
Es decir, mete en la Base de Datos el contenido del registro que estaba en la memoria,
bien por haber utilizado el mtodo Update, bien por haber utilizado el mtodo Edit.
Sintaxis
MiRecordset.Update
recordset.CancelUpdateTipo
421
422
NombreRecordset.LastModified
El valor devuelto por esta propiedad es un tipo de datos Variant o String. (Similar al
devuelto por Bookmark) LastModified se puede usar para colocarse en el registro ms
recientemente agregado o actualizado.
Esta propiedad puede usarse para volver al ltimo registro que ha sido modificado. Basta
para ello igualar la propiedad Bookmark a la propiedad LastModified :
NombreRecordset.Bookmark = NombreRecordset.LastModified
Mtodos MoveFirst, MoveLast, MoveNext, MovePrevious
Estos mtodos son aplicables a todos los tipos de recordset.
Se sitan en el primer, el ltimo, el siguiente o el anterior registro del objeto Recordset
especificado y lo convierten en el registro actual.
Sintaxis
Puede utilizar los mtodos Move para desplazarse de un registro a otro sin aplicar una
condicin.
Al abrir el conjunto de registros indicado en Recordset, el primer registro pasa a ser el
registro actual y en la propiedad BOF se establece False. Si el conjunto no contiene ningn
registro, se establecer en BOF el valor True y no habr registro actual.
Si el primer o el ltimo registro ya es el actual al utilizar MoveFirst o MoveLast, el
registro actual no vara.
Si utiliza MovePrevious cuando el registro actual sea el primero, en la propiedad BOF se
establecer True y no habr registro actual. Si utiliza de nuevo MovePrevious, se producir
un error y BOF continuar con el valor True.
Si utiliza MoveNext cuando el registro actual sea el ltimo, en la propiedad EOF se
establecer True y no habr registro actual. Si utiliza de nuevo MoveNext, se producir un
error y EOF continuar con el valor True.
Si Recordset hace referencia a un objeto Recordset de tipo tabla o a un objeto Table, el
movimiento se har segn el ndice actual de la tabla. Para establecer el ndice actual
423
puede usar la propiedad Index. Si no establece un ndice actual, el orden de los registros
devueltos no estar definido.
Si utiliza MoveLast en un objeto Recordset basado en una consulta SQL o QueryDef, se
forzar la terminacin de la consulta, poblando completamente el objeto Recordset.
No es posible utilizar los mtodos MoveFirst ni MovePrevious en los Recordset tipo
snapshot de desplazamiento hacia delante.
Para desplazar la posicin del registro actual en un objeto Recordset un nmero de
registros determinado hacia adelante o hacia atrs, utilice el mtodo Move.
Mtodo Move
Desplaza la posicin del registro actual en un objeto Recordset.
Sintaxis
Donde :
filas es un valor de tipo Long con signo que especifica el nmero de filas (de registros)
que se desplaza la posicin. Si filas es mayor que 0, la posicin se desplaza hacia adelante
(hacia el final del archivo). Si es menor que 0, la posicin se desplaza hacia atrs (hacia el
principio del archivo).
Inicio (opcional) es un valor de tipo String que identifica un marcador. Si se especifica
inicio, el desplazamiento ser relativo al marcador indicado. Si se omite, Move comenzar
por el registro actual. El marcador que debe utilizarse para definir el registro Inicio debe
ser un Bookmark o similar (LastModified, por ejemplo)
Si se especifica una posicin anterior al primer registro, la posicin del registro actual se
situar al principio del archivo (BOF). Si se especifica una posicin posterior al ltimo
registro, la posicin del registro actual se situar al final del archivo (EOF).
Si el objeto Recordset no contiene registros y el valor de su propiedad BOF es True, el uso
de este mtodo para desplazarse hacia atrs producir un error interceptable en tiempo de
ejecucin. Lo mismo ocurrir si el valor de la propiedad EOF es True y pretende
desplazarse hacia adelante. Si las propiedades BOF o EOF tienen el valor True y se intenta
usar el mtodo Move sin un marcador vlido, se generar un error interceptable.
Si el objeto Recordset est basado en una consulta, la operacin forzar la ejecucin de la
consulta en el nmero de filas especificado..
Mtodos FindFirst, FindLast, FindNext, FindPrevious
Estos mtodos no se pueden aplicar a un recordset tipo Tabla
Buscan el primer, el ltimo, el siguiente o el anterior registro de un objeto Recordset de
tipo instantnea u hoja de respuestas dinmica, que satisfaga el criterio especificado y lo
convierte en el registro actual.
424
Sintaxis
criterio
' S se ha encontrado.
425
Si no podemos usar los mtodos Find en un recordset tipo Tabla, Qu podemos hacer para
buscar un dato en un recordset de este tipo? Usar el mtodo Seek
El mtodo Seek busca el primer registro de un objeto Recordset indexado de tipo Table que
cumple el criterio especificado para el ndice activo y lo convierte en el registro activo. Slo
funciona en espacios de trabajo Microsoft Jet.
Sintaxis
Donde MiRecordset es un recordset de tipo Table que tiene definido un ndice en el campo
por el que se va a realizar la bsqueda. Como podemos tener varios ndices en una tabla,
deberemos indicarle cual es el ndice de bsqueda. Una vez que se lo indiquemos, ese
ndice ser el Indice activo.
comparacinEs una de esta expresiones de cadena: <, <=, =, >=, >.
clave1, clave2...clave13 Son uno o ms valores que corresponden a los campos en el
ndice activo del objeto Recordset. Puede utilizar un argumento de hasta 13 claves.
Antes de usar Seek se debe establecer el ndice activo. Todo ndice tiene un nombre.
Habamos visto cuando crebamos un ndice que deba tener un nombre. Recuerde el
ejemplo:
Set MiIndice2 = MiTabla2.CreateIndex("IndicePeliculas")
Puede ver el nombre de ese ndice en la Fig. 20.7 En este caso habamos creado el ndice
mediante cdigo y hemos podido controlar su nombre. Si lo hubisemos creado
directamente en Access, el nombre que le pone por defecto es el mismo que el nombre del
campo.
Ese nombre del ndice es el que debemos usar para crear el ndice activo. Por ejemplo, si
quisiramos que el ndice activo fuese el IndicePeliculas lo haramos ndice activo
mediante la siguiente instruccin:
MiRecordset.Index = "IndicePelculas"
A partir de ahora, el campo (o campos) de ese ndice ser sobre el que realizaremos la
bsqueda mediante Seek. Para encontrar el registro que tenga por valor 00000012
usaremos la expresin
MiRecordset.Seek "=", "00000012"
Ese registro ser ahora el registro actual. Si hubiese mas de un registro con ese valor, el
registro actual ser el primero que cumpla esa condicin
En el ejemplo hemos utilizado el comparador = para buscar un registro cuyo valor en el
campo indicado por el ndice activo sea igual al indicado en el siguiente parmetro
(00000012). Si quisisemos encontrar un registro cuyo valor sea superior a 00000012
usaramos la expresin
MiRecordset.Seek ">", "00000012"
Pero observe ahora que el 0000012 no es un nmero, es una cadena de caracteres. No se
preocupe. Seek puede comparar el contenido de un campo numrico, de un campo texto,
de un campo Fecha/Hora, etc. Eso s, debe compararlo con un valor del mismo tipo, es
decir, si el contenido del campo es numrico, en el parmetro Clave1 deberemos pasarle
un campo numrico, si el campo es texto, deberemos pasarle un dato tipo texto, etc.
426
El mtodo Seek busca en los campos clave especificados y localiza el primer registro que
cumpla el criterio especificado por comparacin y clave1. Cuando lo encuentra, convierte
ese registro en activo y la propiedad NoMatch se establece en False. Si el mtodo Seek no
consigue localizar ninguna coincidencia, la propiedad NoMatch se establece en True y el
registro activo es indefinido.
Si comparacin es igual (=),mayor o igual (>=) o mayor que (>), Seek empezar al
principio del ndice y buscar hacia adelante.
Si comparacin es menor que (<) o mayor o igual que (<=), Seek empezar al final del
ndice y buscar hacia atrs, a menos que haya entradas de ndice duplicadas al final. En
tal caso, Seek empezar en una entrada cualquiera entre las entradas duplicadas
existentes al final del ndice.
Debe especificar valores para todos los campos definidos en el ndice. Si utiliza Seek con
un ndice de mltiples columnas y no especifica un valor de comparacin para cada campo
del ndice, no podr usar el operador de igual (=) en la comparacin. Esto se debe a que
algunos de los campos de criterio(clave2, clave3, etc) estarn predeterminados en Null, lo
que posiblemente no concordar. Por tanto, el operador de igual slo funcionar
correctamente si tiene un registro que sea Null en su totalidad, excepto la clave que est
buscando. Es aconsejable usar el operador mayor que o igual en su lugar.
En el ejemplo siguiente
llamada Calles_Nombre,
nombre que el campo
BBuscaCalle_Click busca
el TextBox TBBuscaCalle
Con el mtodo Clone puede crear mltiples Recordsets. Cada uno de ellos puede tener su
propio registro actual. El uso de Clone no modifica los datos de los registros. Puede
modificar un registro desde cualquier Recordset, bien desde el que sirvi de original, bien
desde cualquiera de sus copias, pero debe hacerlo invocando los mtodos Edit - Update.
Puede compartir marcadores entre dos o ms Recordsets creados de esta forma.
Puede utilizar el mtodo Clone cuando desee realizar en un conjunto de registros una
operacin que requiera varios registros actuales. Este mtodo es ms rpido y eficiente
que crear un nuevo Recordset.
Inicialmente, un Recordset creado con Clone carece de registro actual. Para hacer que un
registro sea el actual antes de utilizar el Recordset copia, puede utilizar cualquiera de los
mtodos Move, Find o Seek (solo para Recordsets tipo Tabla), o establecer su propiedad
Bookmark
El hecho de cerrar el Recordset original no afecta al duplicado y viceversa.
Nota No es posible utilizar este mtodo con snapshots de desplazamiento hacia
delante (objetos Recordset de tipo instantnea con la opcin dbForwardOnly
activada).
Mtodo Requery
El mtodo Requery actualiza los datos de un objeto Recordset, volviendo a ejecutar la
consulta con la que se ha creado ese Recordset. Este mtodo debe usarse cada vez que se
sospeche que los datos de la Base de datos han cambiado, y se quieran presentar los datos
actualizados. Es un mtodo tpico de una BD que se est usando desde varios puestos a
travs de una Red de Area Local.
Sintaxis
NombreRecordset.Requery [NuevoQueryDef]
IMPORTE apunta el valor del dinero a transferir, y en el campo SALDO pone la diferencia
entre lo que haba en ese campo en la ltima operacin, menos el importe del dinero
transferido.
A continuacin hace un proceso similar con la cuenta destino, pero en este caso,
sumndole el importe de la transferencia. No hay problemas. Pero que pasa si, una vez
sacado el dinero de la cuenta origen, no se puede ingresar en la cuenta destino, por la
razn que sea (cuenta bloqueada, no existe esa cuenta, fallo de la red de rea local)
Obviamente la operacin no se ha completado, y hay que devolver el dinero a la cuenta
origen. Podra hacerse un apunte, metiendo la misma cantidad de dinero que se ha
extrado anteriormente, y su saldo no se ver afectado. Pero no s lo que pensara el
cliente cuando vea un estadillo de su cuenta, en la que le han sacado una cantidad de
dinero, aunque en el siguiente apunte se lo hayan vuelto a introducir.
Para evitar estas situaciones usamos lo que se denomina una Transaccin, que es una
combinacin de estos tres mtodos. Con el mtodo BeginTrans iniciamos la Transaccin.
Con CommitTrans terminamos la transaccin y se guardan los cambios realizados (En
ambas cuentas a la vez, en el caso del ejemplo). Con Rollback se termina la transaccin
sin llegar a guardar los cambios, quedando el Objeto Workspace afectado por las
operaciones internas a esa transaccin tal y como estaba antes de comenzar dicha
operacin.
Dado que una transaccin pertenece a un Workspace, deberemos aplicar estos mtodos
al Workspace que ese usuario tenga abierto. Es decir, en un sistema con varios usuarios
que estn trabajando simultneamente sobre una Base de Datos, un determinado usuario
deber entrar con un Workspace propio (una sesin de trabajo solo para l). En estas
condiciones podemos crear una transaccin. Y aqu comenzamos a ver la necesidad de
crear Workspaces distintos para distintos usuarios. Veremos un poco ms adelante como
se crean los Workspaces.
Sintaxis
MiSesin.BeginTrans
MiSesin.CommitTrans
MiSesin.Rollback
429
Si cierra un objeto Workspace sin guardar o deshacer las transacciones pendientes, stas
se desharn automticamente.
Algunas bases de datos pueden no admitir las transacciones. En este caso la propiedad
Transactions del objeto Database o Recordset tendr el valor False. Lea detenidamente la
Ayuda de estos mtodos antes de trabajar con ellos.
El hecho de usar transacciones, aparte de lo que significa para asegurar la integridad de
los datos, ahorra accesos al disco (Importantsimo en algunas redes LAN y WAN), ya que
los cambios a introducir se van almacenando en un bfer en la memoria, y se vuelcan al
disco solamente en el momento de terminar la transaccin de modo afirmativo con
CommitTrans.
430
431
432
Podemos saber cuantos usuarios tiene el Workspaces(0) y su nombre. Con las siguientes
instrucciones vamos a introducir los nombres de los usuarios en la lista ListUsers
ListUsers.Clear
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
Creacin de nuevos Workspaces. Mtodo CreateWorkspace
Podemos crear cuantos Workspaces necesitemos. Recuerde que un Workspace es una
sesin de trabajo. Y una sesin de trabajo se abre para que trabaje un usuario. Por eso, a
la hora de crear un Workspace debemos indicarle para que usuario, y la contrasea de ese
usuario. Como el objeto Workspace pertenece al dbEngine, es este objeto el que debe
crearlo.
La sintaxis es la siguiente:
Set NuevoWorkSpace = DBEngine.CreateWorkspace (Nombre, Usuario, Contrasea, Tipo)
NuevoWorkSpace es el Workspace que queremos crear, que habremos declarado como
variable tipo objeto Workspace.
Nombre es el nombre del Workspace (P.e., MiSesion)
Usuario Nombre de un usuario registrado en la base de datos del sistema (Que lo
habremos creado con CreateUser) que ser el propietario del nuevo objeto Workspace.
Contrasea La contrasea del Usuario propietario del Workspace.
Tipo (Opcional). Indica el tipo de espacio de trabajo. Puede tomar los valores dbUseJet
para crear un espacio de trabajo Microsoft Jet, o dbUseODBC para crear un espacio de
trabajo ODBCDirect. Si omite tipo, la propiedad DefaultType del objeto DBEngine
determinar a qu tipo de origen de datos est conectado el Workspace
No es necesario aadir el nuevo Workspace a la coleccin Workspaces
Veamos un ejemplo de cmo crear un Workspace para el usuario Luis creado
anteriormente:
Dim NewWS as Workspace
Set NewWS = DBEngine.CreateWorkspace("SesiondeLuis", "Luis", "MiContrasea")
DBEngine.Workspaces.Append NewWS
Podemos ver todos los Workspaces existentes. En las siguientes instrucciones podemos ver
el cdigo para listarlos en ListWS
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
Debe tenerse en cuenta que el objeto Workspace es un objeto que solamente existe
mientras est ejecutndose la aplicacin. Cuando salimos de la aplicacin, ese Workspace
desaparece. No ocurre lo mismo con el Usuario, que queda en la base de datos del
sistema, es decir, es un objeto persistente.
Las partes de cdigo expuestas se han sacado de un ejemplo creado para ver el nmero y
nombre de los usuarios existentes, Workspaces y DataBases. Es un ejemplo para explicar
estos conceptos. No tiene otra finalidad.
433
Fig. 20.9 Aspecto de la interface grfica del ejercicio para crear Users y Workspaces
Cdigo de este ejercicio
General/Declaraciones
Option Explicit
Dim VarDrag As String
Dim NuevoWS() As Workspace
Private Sub BAnadirUser_Click()
On Error GoTo RutErr
Dim NomUsuario As String, I As Integer
If BAnadirUser.Caption = "Aadir" Then
TBNuevoUserName.Visible = True
TBNuvoUsePID.Visible = True
TBNuevoUserPw.Visible = True
LNUserName.Visible = True
LNuevoUserPID.Visible = True
LNuevoUserPw.Visible = True
BAnularUser.Left = 3480
BAnularUser.Visible = True
BBorrarUser.Visible = False
BAnadirUser.Caption = "O.K."
Exit Sub
End If
If BAnadirUser.Caption = "O.K." Then
Dim NuevoUser As User
Set
NuevoUser
=
Workspaces(0).CreateUser(TBNuevoUserName,
TBNuevoUserPw)
Workspaces(0).Users.Append NuevoUser
TBNuevoUserName.Visible = False
TBNuvoUsePID.Visible = False
TBNuevoUserPw.Visible = False
LNUserName.Visible = False
LNuevoUserPID.Visible = False
LNuevoUserPw.Visible = False
BAnularUser.Visible = False
BBorrarUser.Visible = True
BAnadirUser.Caption = "Aadir"
434
TBNuvoUsePID,
ListUsers.Clear
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
BAnularUser.Visible = False
BAnadirUser.Visible = True
End If
RutErr:
If Err = 3304 Then
MsgBox "Debe introducir el PID (Mnimo 5 caracteres, mximo 20 caracteres)"
Exit Sub
Else
If Err > 0 Then MsgBox "Ha ocurrido el error " & Err & "."
End If
End Sub
Private Sub BAnadirWs_Click()
On Error GoTo RutErr
If BAnadirWs.Caption = "Aadir" Then
TBNuevoWorkspace.Visible = True
TBNombreUser.Visible = True
TBNuevoWSPw.Visible = True
LNWSName.Visible = True
LNombreUsuario.Visible = True
LUserPw.Visible = True
BAnularWS.Left = 5520
BAnularWS.Visible = True
BEliminarWs.Visible = False
BAnadirWs.Caption = "O.K."
Exit Sub
End If
If BAnadirWs.Caption = "O.K." Then
Dim NumWS As Integer
NumWS = Workspaces.Count
ReDim Preserve NuevoWS(NumWS)
Dim I As Integer, NomWS As String
Set NuevoWS(NumWS) = DBEngine.CreateWorkspace(TBNuevoWorkspace, TBNombreUser,
TBNuevoWSPw)
DBEngine.Workspaces.Append NuevoWS(NumWS)
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
BAnadirWs.Caption = "Aadir"
TBNuevoWorkspace = ""
TBNombreUser = ""
TBNuevoWSPw = ""
TBNuevoWorkspace.Visible = False
TBNombreUser.Visible = False
TBNuevoWSPw.Visible = False
LNWSName.Visible = False
LNombreUsuario.Visible = False
LUserPw.Visible = False
BAnularWS.Visible = False
435
BEliminarWs.Visible = True
End If
RutErr:
If Err = 3029 Then
MsgBox "El Password usado no coincide con el de ese Usuario (User)"
Exit Sub
End If
End Sub
Private Sub BAnularUser_Click()
If BAnadirUser.Caption = "O.K." Then
TBNuevoUserName.Visible = False
TBNuvoUsePID.Visible = False
TBNuevoUserPw.Visible = False
LNUserName.Visible = False
LNuevoUserPID.Visible = False
LNuevoUserPw.Visible = False
BAnularUser.Visible = False
BBorrarUser.Visible = True
BAnadirUser.Caption = "Aadir"
End If
If BBorrarUser.Enabled = True Then
BBorrarUser.Enabled = False
BAnadirUser.Visible = True
BAnularUser.Visible = False
ListUsers.ListIndex = -1
End If
End Sub
Private Sub BAnularWS_Click()
If BAnadirWs.Caption = "O.K." Then
BAnadirWs.Caption = "Aadir"
TBNuevoWorkspace = ""
TBNombreUser = ""
TBNuevoWSPw = ""
TBNuevoWorkspace.Visible = False
TBNombreUser.Visible = False
TBNuevoWSPw.Visible = False
LNWSName.Visible = False
LNombreUsuario.Visible = False
LUserPw.Visible = False
BAnularWS.Visible = False
BEliminarWs.Visible = True
End If
If BEliminarWs.Enabled = True Then
BEliminarWs.Enabled = False
BAnadirWs.Visible = True
BAnularWS.Visible = False
End If
End Sub
Private Sub BBorrarUser_Click()
Dim NomUsuario As String, I As Integer
Workspaces(0).Users.Delete ListUsers.Text
ListUsers.Clear
For I = 0 To Workspaces(0).Users.Count - 1
436
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
BAnularUser.Visible = False
BAnadirUser.Visible = True
End Sub
Private Sub BEliminarWs_Click()
Dim I As Integer, NomWS As String, NumWS As Integer
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
If NomWS = ListWS.Text Then NumWS = I
Next I
Workspaces(NumWS).Close
ListWS.Clear
For I = 0 To DBEngine.Workspaces.Count - 1
NomWS = DBEngine.Workspaces(I).Name
ListWS.AddItem NomWS
Next I
BEliminarWs.Enabled = False
BAnularWS.Visible = False
BAnadirWs.Visible = True
End Sub
Private Sub BSalir_Click()
End
End Sub
Private Sub BVerIni_Click()
Shell "Notepad.exe " & App.Path & "\Cap20Usr.INI", vbNormalFocus
End Sub
Private Sub Form_Activate()
On Error GoTo RutErr
Dim LineaEntr As String
Dim LineaEntr8 As String
Dim I As Integer, NomUsuario As String
Dim PathFichero As String
Open App.Path & "\Cap20Usr.INI" For Input As #1
Do Until EOF(1)
Line Input #1, LineaEntr
LineaEntr8 = ""
LineaEntr8 = Left(LineaEntr, 8)
If UCase(LineaEntr8) = "PROYCAPT" Then Me.Caption = Right(LineaEntr, Len(LineaEntr) 9)
If UCase(LineaEntr8) = "DBENGINI" Then PathFichero = Trim(Right(LineaEntr,
Len(LineaEntr) - 9))
Loop
Close #1
LBDSys = PathFichero
TBTextINI = PathFichero
DBEngine.SystemDB = PathFichero
For I = 0 To Workspaces(0).Users.Count - 1
NomUsuario = Workspaces(0).Users(I).Name
ListUsers.AddItem NomUsuario
Next I
437
For I = 0 To DBEngine.Workspaces.Count - 1
NomUsuario = Workspaces(I).Name
ListWS.AddItem NomUsuario
Next I
RutErr:
If Err = 3028 Then
MsgBox "No se puede abrir la base de datos del sistema. Compruebe que su Path y nombre
son correctos. Vealo en Ver Ini"
End If
End Sub
Private Sub ListUsers_Click()
BAnadirUser.Visible = False
BBorrarUser.Enabled = True
BAnularUser.Left = 4560
BAnularUser.Visible = True
End Sub
Private Sub ListWS_Click()
BEliminarWs.Enabled = True
BAnadirWs.Visible = False
BAnularWS.Left = 6600
BAnularWS.Visible = True
End Sub
Private Sub Text1_MouseDown(Button As Integer, Shift As Integer, X As Single,
Y As Single)
If Shift = 1 And Button = 1 Then
VarDrag = Text1.Text
Text1.Drag
End If
End Sub
El fichero Cap20Usr.INI que debe estar necesariamente en la misma carpeta que el
programa, en el caso del PC del autor tiene esta forma
REM Visual Basic - Gua del Estudiante. Cap. 20. Creacin de Usuarios y WorkSpaces
DBEngINI=C:\WinNT\System32\System.mdw
(Deber cambiar el Path del fichero System.Mdw de acuerdo a como lo tenga en su
ordenador.)
Mantenimiento y Copia de Bases de Datos.
Vamos a ver dos mtodos del Objeto DBEngine para el mantenimiento y copia de Bases
de Datos ACCESS.
En una Base de Datos ACCESS, cuando borramos un dato en realidad no lo estamos
borrando, sino marcndolo como borrado. (No intente recuperar un dato marcado y no
borrado porque no se puede.) Por lo tanto, ver que tras sucesivas operaciones de
escritura / borrado en una BD, esta va aumentando su tamao. Se necesita un mtodo que
limpie todos los datos inservibles de la BD para disminuir su tamao. Este mtodo tambin
deber reorganizar los ndices y marcadores internos a esa BD. El objeto DAO que debe
hacer estas cosas es el Motor de Bases de Datos. Es decir, el Objeto DBEngine. Los
mtodos son CompactDatabase, que hace una copia de la base de datos (no borra la BD
438
original) sin copiar los datos intiles, y RepairDatabase, que intenta (no siempre lo
consigue) reparar los datos internos de una BD que presente datos corruptos (Se generan
con bastante facilidad cuando apagamos el ordenador con la base abierta)
Mtodo CompactDatabase
Copia, compacta y da la opcin de modificar la versin, el orden de intercalado y la
codificacin de una base de datos cerrada.
Sintaxis
DBEngine.CompactDatabase BaseDatosAnt, BaseDatosNva [, inf_local [, opciones]]
BaseDatosAnt es el nombre del fichero de la base de datos a compactar. Debe expresar
el Path completo y el nombre del fichero (C :\MiCarpeta\MiBase.MDB) Si el nombre de
archivo tiene extensin, deber especificarla. Si la red lo admite, tambin puede especificar
una ruta de red, como por ejemplo "\\MISERVID\MIDIR\MiBase.MDB".
BaseDatosNva es el nombre del fichero (con su Path completo) de la base de datos
nueva, creada al copiar la BaseDatosAnt, ya compactada. No es posible especificar en el
argumento BaseDatosNva el mismo archivo de base de datos que en BaseDatosAnt.
inf_local es una expresin de cadena utilizada para especificar el alfabeto usado a la hora
de ordenar datos de esa Base de Datos. El parmetro a introducir es el mismo que para el
argumento similar usado en la creacin de la Base de Datos (dbLangGeneral para el caso
de Espaa). Este argumento es opcional. Si se omite, la informacin local de
BaseDatosNva ser la misma que la de BaseDatosAnt.
Opciones nos permite cambiar alguna caracterstica de la Base de Datos. Puede elegirse
entre cifrarla o no cifrarla y cambiar la versin del motor de bases de datos que va a usar
la nueva Base de Datos.
dbEncrypt
dbDecrypt
dbVersion10
dbVersion11
dbVersion25
dbVersion30
Jet
Jet
Jet
Jet
DBEngine.RepairDatabase NombreBase
Donde NombreBase es el nombre (Y path) del fichero que contiene la Base de Datos a
reparar. Puede especificar una ruta de red. P.e. : "\\MISERVID\ MIDIR\NombreBase.MDB".
439
Para poder reparar la base debe estar Cerrada. Recuerde, si est en un entorno
multiusuario, que los dems usuarios tampoco pueden tenerla abierta mientras la repara.
El mtodo RepairDatabase tambin intenta validar todas las tablas del sistema y todos los
ndices. Los datos que no puedan repararse se pierden. Si la base de datos no puede
repararse, se producir un error interceptable.
Sugerencia Despus de reparar una base de datos, es aconsejable compactarla con el
mtodo CompactDatabase para desfragmentar el archivo y recuperar espacio en disco.
METODOS DEL OBJETO DataBase
Mtodo Execute
Este Mtodo es para el Objeto DataBase y para el Objeto QueryDef.
Ejecuta una consulta de acciones o una instruccin SQL en el objeto Database especificado.
Sintaxis
NombreQuerydef.Execute [opciones]
Donde NombreQuerydef es el nombre del objeto QueryDef cuya propiedad SQL especifica
la
instruccin SQL a ejecutar.
Opciones igual que para el Objeto Database.
En opciones puede utilizar las siguientes constantes:
dbDenyWrite
dbInconsistent
dbConsistent
dbSQLPassThrough
dbFailOnError
dbSeeChanges
modifica los
El mtodo Execute slo es vlido para las consultas de acciones. Si utiliza Execute con otro
tipo de consultas, se producir un error. Debido a que las consultas de acciones no
devuelven registros, Execute no devuelve un conjunto de registros.
Ejemplo. En el siguiente ejemplo, usamos EXECUTE para cambiar el campo Nombre en
una tabla llamada CLIENTES de una Base de Datos abierta, cuyo Objeto DataBase se llama
BaseDatos. Para poder jugar con el nombre a cambiar y el nombre cambiado, se
introduce el nombre que queremos cambiar en TBNombre2 y el nuevo nombre en
TBNombre1
440
441
La asociacin de la Base de datos al Control Data puede hacerse, bien mediante sus
propiedades DatabaseName y RecordSource, bien creando un Recordset con cdigo e
igualando la propiedad Recordset del Control Data a ese Recordset.
Es posible que se pueda introducir y presentar un bit-map en un control Picture o Image de
otra forma, sin usar el control Data. Eso s, complicando el cdigo. No merece la pena
liarse con esto. Lo mismo que decamos que necesitamos un Control Data cuando vamos a
usar un DBGrid, debemos usar un Control Data cuando vayamos a presentar una imagen.
442
Vaya a Inicio | Configuracin | Panel de Control | ODBC de 32 Bits. Haga doble click
y le aparecer un cuadro como el de la figura 13-1. En este cuadro figuran todos los
enlaces que estn establecidos. Estos enlaces puede establecerlos para un usuario (DSN de
usuario), de sistema o de archivo. La eleccin de uno u otro depender de los permisos de
acceso que quiera establecer (y eso es, de momento, para nota). En cualquier caso, todas
los enlaces ODBC que establezca funcionarn del mismo modo, exceptuando que puede
otorgar unas prerrogativas distintas de uso, dependiendo de como lo haya abierto.
Observe uno que figura en la lista: Luki. En esa lnea figura otro dato: Microsoft Access
Driver.(*.mdb) Esto significa que el enlace de nombre Luki est usando el driver ODBC
de Access. Y significa tambin que si queremos llamar a esa conexin deberemos llamarla
por su nombre : Luki
Fig. 13-1 Creacin de un enlace ODBC. Muestra las conexiones existentes (una vez creada
la conexin Luki)
Sigamos con la creacin del enlace ODBC. Para crear uno nuevo, haga click en el botn
Agregar de la figura 13-1. Le aparecer un cuadro donde le pide el driver que quiere
utilizar.
443
Fig. 13-3 Introduccin del nombre del enlace, comentario (descripcin) y base de datos
asociada al enlace ODBC
Veamos los datos que hemos introducido en nuestra conexin Luki
Nombre del Origen de datos. Luki
Descripcin (Opcional) Conexin ODBC Cap. 21
444
Haciendo click en Base de Datos | Seleccionar nos muestra un cuadro de dilogo donde
`podemos buscar la base de datos. Se elige la base de datos deseada. Hacemos click en
ACEPTAR y ya est creada la nueva conexin.
La base de datos del sistema deber elegirla para poder introducir usuarios con distintas
atribuciones de acceso a la base de datos. Si no introduce esta base de datos de sistema,
deber trabajar sin restriccin de acceso.
Una vez creada la conexin podemos utilizarla para conectar nuestra aplicacin con la base
de datos. El proceso para ello consiste en algo parecido a lo que hacamos trabajando con
el motor Jet en el espacio de trabajo Microsoft Jet, pero de distinta forma. En ese entorno
se manejaba la base de datos creando un objeto Database, que manipulaba el fichero de
la base de datos directamente. En este caso, la base de datos se maneja mediante un
objeto Connection.
El trabajar sobre una conexin nos aporta mayor versatilidad a las aplicaciones. Piense por
ejemplo un caso en el que se emplea una base de datos Access. Si quisisemos ampliar las
prestaciones de la base de datos de esa aplicacin posiblemente pensaramos en migrar la
BD a Oracle o SQLServer. Si atacamos a la base de datos a travs de ODBC solamente
deberamos cambiar la conexin, tal como vimos ms atrs. Nuestro programa seguira
llamando a la misma conexin ODBC, pero esta conexin, ahora, abrira una base Oracle o
SQLServer en vez de la Access que abra originalmente. No necesitaramos realizar
ninguna modificacin en nuestro programa.
Este razonamiento es vlido para cualquier sistema de acceso a bases de datos a travs de
ODBC. (RDO ADO) Sin embargo el ODBCDirect tiene una ventaja `para los que
trabajamos normalmente con DAO: usa los mismos nombres para casi todos los mtodos y
funciones, por lo que el cambio de cdigo es mnimo. El cambio se limita prcticamente a
crear el objeto Connection en vez del objeto Database. Comencemos a ver esto con u
ejemplo. Es un ejemplo uy simple, en el que abrimos una base de datos Access llamada
Alumnos.Mdb que tiene una tabla llamada Personas. Creamos la conexin Luki tal
como se describi mas atrs. La tabla personas tiene solamente tres campos: ID_Alumno,
Nombre y Apellidos. Creamos una interface grfica sencilla
445
Mediante esta sencilla aplicacin queremos visualizar los datos existentes, aadir nuevos
registros y borrar el registro actual. Veamos el cdigo con los comentarios oportunos.
General/Declaraciones
Option Explicit
Dim MiSesion As Workspace
Dim MiConexion As Connection
Dim RsODBC As Recordset
ODBCDirect. Si no le disemos ningn valor a esa propiedad, tomara el otro valor posible
(dbUseJet) que es su valor por defecto. Por eso, cuando utilizbamos los mtodos
CreateDataBase u OpenDatabase no necesitbamos darle ningn valor a esa propiedad.
Set MiConexion =
"ODBC;DSN=Luki")
MiSesion.OpenConnection("Conexion1",
dbDriverNoPrompt,
False,
Vea mas abajo la informacin de OpenConnection para ver los parmetros que hay que
pasarle a este mtodo.
Set RsODBC = MiConexion.OpenRecordset("Personal", dbOpenDynamic, dbRunAsync,
dbPessimistic)
Vea mas abajo una ampliacin del mtodo OpenRecordset
Mtodo OpenConnection
Es un mtodo del Workspace que solamente es aplicable cuando el DBEngine est
trabajando en el espacio de trabajo ODBCDirect. Abre un objeto Connection usando un
origen de datos ODBC ya creado.
El objeto Connection sera el equivalente en DAO al objeto Database. Debemos declararlo
antes de usarlo
Dim MiConexion as Connection
Si MiSesion es el Workspace que queremos usar, la sintaxis de OpenConnection es la
siguiente:
Set MiConexion = MiSesion.OpenConnection (Nombre, Opciones, Slolectura y Conectar)
En el ejemplo:
Set MiConexion =
"ODBC;DSN=Luki")
MiSesion.OpenConnection("Conexion1",
dbDriverNoPrompt,
False,
Se
comporta
449
Si omite los parmetros UID y/o el PWD, estos datos se obtendrn de las propiedades
UserName y Password del objeto Workspace.
Mtodo OpenRecordset
Este mtodo ya se estudi en el captulo anterior, pero se van a ver ciertas peculiaridades
que tiene cuando se abre un recordset en el espacio de trabajo ODBCDirect
En este caso es el objeto Connection quien abre el recordset.:
Set MiRecordset =
= MiConexion.OpenRecordset (Origen, Tipo, Opciones, Bloquearmodificaciones)
Origen Puede ser un nombre de tabla, de una consulta o una instruccin SQL que
devuelva registros.
Tipo Indica el tipo de recordset que queremos crear. El espacio de trabajo ODBCDirect no
permite recordsets tipo Tabla. Los tipos que se pueden elegir son:
DbOpenDynamic Abre un objeto Recordset de tipo Dynamic, que es parecido a un
cursor dinmico ODBC
DbOpenDynaset Abre un objeto Recordset de tipo Dynaset, similar al estudiado en
el captulo 20 para el espacio de trabajo Microsoft Jet
DbOpenSnapshot Abre un objeto Recordset de tipo Snapshot,
dbOpenForwardOnly Abre un objeto Recordset de tipo Forward-only, que tiene la
particularidad de que no permite movernos en el recordset de adelante hacia atrs.
Este es el tipo que crear por defecto si no se especifica nada en el parmetro Tipo.
Opciones Debe indicar uno de estos dos valores (si no pone alguno de ellos da error):
DbRunAsync Ejecuta una consulta asncrona, que es la forma normal de trabajar
del ODBC. Esto permite a su aplicacin seguir procesando otras instrucciones
mientras se ejecuta la consulta en segundo plano (Vea mas adelante la propiedad
StillExecuting
dbExecDirect
Ejecuta una consulta saltando el mtodo SQLPrepare y
llamando directamente al mtodo SQLExecDirect. Utilice esta opcin slo cuando
no se abra un objeto Recordset basndose en una consulta de parmetros. Para
obtener ms informacin, consulte la "Referencia del programador de Microsoft
ODBC 3.0."
Bloquearmodificaciones Este parmetro es fundamental si quiere escribir en la base de
datos, pues si lo omite le pone por defecto que la base es de solo lectura. Mediante este
parmetro va a determinar el tipo de bloqueo de la base de datos para entornos de trabajo
multiusuario. Puede poner uno de estos valores:
DbReadOnly (Predeterminado) No permite que los usuarios hagan cambios en los
registros del Recordset
DbPessimistic Permite cambiar datos y aadir registros en el recordset, utilizando
el criterio de bloqueo pesimista. Esto significa que bloquea la pgina donde se
encuentra el registros desde que se ejecuta el mtodo Edit hasta que se ejecuta el
Update. Es el criterio mas seguro de bloqueo de datos, pero debe tener en cuenta
que tiene la base bloqueada desde el Edit hasta el Update. Si hace bloqueo
pesimista, procure que las instrucciones entre uno y otro no tengan ningn tiempo
de espera, por ejemplo a que el usuario introduzca un dato. (El tamao de una
pgina depende de la base de datos que est usando. En Access es de 2048 Bytes.
Esto significa que solamente tendr bloqueada una parte relativamente pequea de
450
la base de datos, pudiendo modificar otros registros que estn fuera de ese
segmento de 2 Kbytes. Lgicamente este bloqueo solamente tendr efecto cuando
est trabajando en un entorno multiusuario.
DbOptimistic Permite cambiar datos y aadir registros en el recordset, utilizando
el criterio de bloqueo optimista. El bloqueo optimista significa que solamente estar
bloqueada la pgina que contiene el registro mientras se ejecuta el mtodo Update.
Esto puede ocasionarle que, si estn dos usuario trabajando sobre el mismo
registro, se introduzca un dato errneo. Parece as en principio que no se debe usar,
pero todo va a depender de la aplicacin, de sus datos, y de la probabilidad de que
ocurra esa colisin. La ventaja que tiene es que tiene menos tiempo bloqueada la
pgina de la base de datos.
dbOptimisticValue Utiliza la concurrencia optimista basndose en valores de fila.
Funciona de forma similar al dbOptimistic.
dbOptimisticBatch Activa la actualizacin optimista por lotes.
Actualizacin por lotes. Modelo de cursor para clientes que trabajan con cursores, pero
no mantienen bloqueos en el servidor o ejecutan actualizaciones por fila. En su lugar, el
cliente actualiza muchas filas que estn almacenadas en el bfer local y despus ejecuta
una actualizacin por lotes. Este modelo de cursor tambin permite al cliente cancelar la
conexin con el servidor y volverla a establecerla con el mismo servidor o con otro
diferente.
Para utilizar la actualizacin por lotes en DAO 3.5, debe utilizar un espacio de trabajo de
ODBCDirect,
la
propiedad
DefaultCursorDriver
se
debe
establecer
a
dbUseClientBatchCursor en el momento de abrir la conexin y se debe abrir el Recordset
con el argumento de tipo de bloqueo del mtodo OpenRecordset establecido a
dbOptimisticBatch.
Propiedad StillExecuting
Cuando abrimos una conexin mediante OpenConnection, un QueryDef o creamos un
recordset y le ponemos en Opciones DbRunAsync, la operacin se realiza de forma
asncrona, por lo tanto no sabemos cuando tendremos disponible el objeto a crear o los
datos de la consulta. Para poder controlar si la operacin se est realizando todava
leeremos la propiedad StillExecuting, que devolver True si todava se est ejecutando, y
False si ha terminado. Basta con hacer un bucle del tipo
Do While MiConexion.StillExecuting = True
DoEvents
Loop
Mientras la propiedad StillExecuting sea True, no se puede tener acceso a ningn objeto
devuelto. Por ejemplo, no pretenda crear un recordset con MiConexion Mientras que
StillExecuting sea True, pues MiConexin no existe an.
Esta propiedad puede ser muy til cuando tiene consultas encadenadas y necesita esperar
a que termine una para comenzar con la siguiente.
StillExecuting se utiliza con los objetos y para las operaciones siguientes:
Objeto Connection, para controlar que an se est ejecutando uno de los mtodos
Execute u OpenConnection
451
objeto.Cancel
452
Fig. 13-6 Estructura jerrquica de los objetos de acceso a datos en el espacio ODBCDirect
Objetos QueryDef en el espacio de trabajo ODBCDirect
Habamos visto en el captulo 20 que un QueryDef era una consulta cuando todava no
estaba guardada en el disco. Es decir, un QueryDef es una consulta en memoria RAM. Ese
QueryDef se transforma en una consulta de la base de datos una vez que se cierra el
objeto Database.
En el espacio de trabajo ODBCDirect no se pueden crear bases de datos. Se pueden crear
objetos QueryDef, que en este caso sern objetos efmeros, que solamente existirn en la
memoria RAM, desapareciendo en el momento que cerremos ese QueryDef o cerremos la
aplicacin.
Puede crear un QueryDef para crear posteriormente a partir de l un Recordset con el que
puede presentar o escribir el contenido de los registros. En el siguiente ejemplo hemos
abierto la conexin, y como paso previo a la creacin del recordset hemos creado un
QueryDef con todos aquellos registros cuyo campo Apellidos sea igual a Alvarez Prez.
Una vez creado ese QueryDef, hemos creado un recordset a partir de l. No tiene mucho
sentido hacer esto ya que podramos crear directamente el recordset imponiendo esa
condicin en el campo Apellidos. Se expone aqu con fines didcticos, no prcticos.
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
Set MiConexion = MiSesion.OpenConnection("Conexion1", dbDriverNoPrompt, False,
"ODBC;DSN=Luki")
Set MiConsulta = MiConexion.CreateQueryDef ("Pepito", "Select * From Personal Where
Apellidos = "Alvarez Prez")
Set RsODBC = MiConsulta.OpenRecordset(dbOpenDynaset, dbRunAsync, dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "El recordset no tienen ningn registro"
453
End If
Puede apreciar en la fig. 13-6 otro objeto que est jerrquicamente debajo del QueryDef.
El Objeto Parameter. Este objeto sirve para cambiar los parmetros que se le pasan al
QueryDef para crearlo. Le remito a la ayuda de VB para mayor explicacin de este objeto.
El objeto Database en el espacio de trabajo ODBCDirect
En el espacio ODBCDirect puede tambin abrir un objeto Database en vez de un objeto
Connection. La diferencia a la hora de crear un objeto Database (abrir una base d e datos)
entre el espacio de trabajo Microsoft Jet y ODBCDirect es que en el primero abrimos
directamente el fichero de la base de datos, y en el segundo, abrimos el fichero que
indique el enlace ODBC. Deberemos suministrarle informacin del enlace ODBC que debe
usar. La sintaxis sigue siendo igual que en el espacio de trabajo Microsoft Jet:
Set MiBaseDatos = MiSesion.OpenDatabase (Nombre, Opciones, Slolectura, Conexin)
Para indicarle el enlace ODBC que debe usar puede hacerlo de las dos formas que venimos
viendo para los parmetros Nombre y Conexin. Si indica el nombre del enlace en el
parmetro Nombre lo aceptar y ser necesario poner el parmetro Conexin. Si `pone
un nombre cualquiera en el parmetro Nombre deber indicar el nombre del enlace en el
parmetro Conexin.
Esta posibilidad de crear un objeto Database nos aproxima an ms al cdigo empleado en
el espacio de trabajo Microsoft Jet. Por lo tanto puede ser muy til usar este objeto en
aquellos casos en los que ya se haba escrito el cdigo, y pasamos posteriormente a usar
ODBC.
DBEngine.DefaultType = dbUseODBC
Set MiSesion = Workspaces(0)
'En la siguiente lnea le pasamos el nombre del enlace ODBC en el parmetro Nombre
Set MiBaseDatos = MiSesion.OpenDatabase("Luki", dbDriverNoPrompt)
'Pero podramos haberselo pasado en el parmetro Conexin y ponerle como parmetro
'nombre cualquier cadena de caracteres
Set MiBaseDatos =
MiSesion.OpenDatabase("BaseDatos1", dbDriverNoPrompt, False, "ODBC;DSN=Luki")
'Ahora creamos el recordset, como en los otros casos
Set RsODBC = MiBaseDatos.OpenRecordset("Personal", dbOpenDynaset, dbRunAsync,
dbOptimistic)
If RsODBC.AbsolutePosition <> -1 Then
RsODBC.MoveLast
RsODBC.MoveFirst
LNumRegs = RsODBC.RecordCount
LNumReg = RsODBC.AbsolutePosition + 1
PresentaDatos
Else
MsgBox "La base de datos no tiene ningn registro"
End If
Mediante los ejemplos expuestos en este captulo espero que el alumno comprenda como
trabaja DAO a travs de ODBC, mediante el ODBCDirect.
No olvide que sigue tratndose de DAO, y que por lo tanto deber poner la misma
referencia (En Proyecto | referencia) que en el caso del DAO trabajando en el espacio de
trabajo Microsoft Jet. En la siguiente parte de este captulo se estudiarn los objetos RDO,
objetos que trabajan exclusivamente a travs de ODBC. Con las ideas captadas hasta aqu
ver que es sencillo abordar estos nuevos objetos.
454
(*) En RDO, los usuarios y grupos de usuarios son precisamente los que lleve implcitos la
conexin ODBC.
(**) Al no trabajar directamente sobre la base de datos, no se pueden crear relaciones en
ella.
El control RemoteData
Este control nos permite crear una aplicacin de acceso a datos completa sin utilizar
cdigo. Eso s, ser necesario tener una conexin ODBC hecha, ya que el control
RemoteData no abre un fichero de BD sino una conexin ya establecida.
No est normalmente en la caja de herramientas, por lo que habr que aadirlo en
Proyecto | Componentes introduciendo el Microsoft Remote Data Control 6.0 El
456
control Remote Data tiene un aspecto similar al control Data, tanto en la caja de
herramientas como en el formulario:
El control RemoteData toma por defecto el nombre MSRDCx.
Algunas Propiedades del Control RemoteData
DatasourceName
Devuelve o establece el nombre del origen de datos (DSN). El DSN No es ms que el
nombre de la conexin ODBC.
Esta propiedad se puede dejar en blanco si la propiedad Connect del control identifica un
nombre de origen de datos (DSN) registrado en el Registro de Windows.
Sintaxis
NombredelControlRDO.DatasourceName = MiConexin
usar, el nombre de la base de datos, el servidor donde se ubica esta base de datos,
nombre de la estacin de trabajo desde la que vamos a trabajar e incluso el nombre de la
aplicacin en la que vamos a usar los datos de esa base. Esta propiedad es mucho ms
completa que la anterior, pero un poco ms complicada de usar.
457
Para introducir los datos de la propiedad Connect deber usar una palabra para definir el
dato, seguido del signo = y del dato a introducir. Como final del dato debe introducir
necesariamente el signo punto y coma ;
DSN Origen de datos ODBC registrado.
UID
Nombre de un usuario reconocido
PWD Contrasea asociada al usuario
DRIVER
Descripcin del controlador
DATABASE
Base de datos predeterminada
para usarla una vez conectado
SERVER
Nombre del servidor donde se
aloja la base de datos
WSID
Nombre de la estacin de trabajo
(Nombre del PC que se va a
comunicar con el servidor
APP
Nombre de la Aplicacin que va a
Usar la Base de Datos
DSN=MiConexinODBC;
UID=Luis;
PWD=MiContrasea;
DRIVER=SQL Server;
DATABASE=MiBase;
SERVER=MiServidor;
WSID=NombredemiPC;
APP=MiAplicacin
normal que tenga solamente el nombre, y que no apunte a ninguna base de datos
concreta). Puede incluso utilizar ambas propiedades. Es muy tpico por ejemplo, que la
conexin apunte a una determinada base de datos, (el nombre de la conexin se lo
pasamos en la propiedad DatasourceName) y que en la propiedad Connect le pasamos el
nombre del usuario y la contrasea.
Puede utilizar el control, RemoteData incluso sin tener una conexin preestablecida. Pero
deber establecer mediante el programa, utilizando los mtodos OpenConnection o
EstablishConnection. Se sale del contenido deseado para este curso comentar estos
mtodos, pero el alumno aventajado puede intentar obtener informacin en la escasa
bibliografa existente. No le recomiendo que se complique la vida rizando el rizo, pudiendo
establecer previamente la conexin ODBC.
Propiedad SQL
Mediante las dos propiedades estudiadas, DatasourceName y Connect hacemos que el
control RemoteData sepa la conexin sobre la que va a trabajar - y por lo tanto la base de
datos que utilizar. Ahora nos falta indicarle los datos que deseamos leer o escribir. Nos
falta lo que sera en DAO, darle los datos para crear el Recordset (Por ejemplo el nombre
de una tabla o una sentencia SQL, tal como hacamos en la propiedad RecordSource del
control Data). Para el control RemoteData esta informacin se le introduce en la propiedad
SQL
La propiedad SQL establece o devuelve una instruccin SQL vlida para crear un conjunto
de registros a partir del origen de datos establecido en las propiedades DatasourceName
o Connect. Esta instruccin SQL debe comenzar necesariamente por SELECT, En tiempo
de ejecucin, podemos asignar a esta propiedad el nombre de una Consulta ya almacenada
en la BD, pero en este caso, debemos anteponer la palabra EXECUTE. Tambin podemos
introducir en esta propiedad un rdoQuery, un rdoResultset o un rdoTable. Eso lo
veremos ms adelante.
Para establecer esta propiedad en tiempo de diseo, basta con escribir la instruccin SQL
en la ventana de propiedades. Una instruccin tpica sera
SELECT * From Alumnos
SELECT * From Alumnos Where Apellido1= 'Surez'
En tiempo de ejecucin podemos introducir una de estas instrucciones en la propiedad SQL
MSRDC1.SQL = "SELECT * From Alumnos Where Apellido1= 'Surez'"
Si la BD tiene una consulta (la tpica consulta de Access) llamada C_Suarez, donde hemos
seleccionado todos los registros cuyo campo Apellido1 sea Surez, podemos poner:
MSRDC1.SQL = EXECUTE C_Suarez
(No intente hacer esto mismo con el nombre de una tabla. Solamente sirve para consultas)
Con los registros seleccionados por la propiedad SQL, formamos lo que en DAO era un
recordset, pero en este caso adopta otro nombre: rdoResultset. En RDO se ha buscado
otra terminologa, posiblemente para diferenciarlo claramente de DAO. Por ejemplo, en vez
de registros es habitual hablar de Filas, y en vez de campos, hablamos de Columnas.
Si pudisemos crear un rdoResultset mediante algn procedimiento, (y seguro que
podremos hacerlo), podemos introducir directamente ese rdoResultset como
rdoResultset del control RemoteData, al igual que lo hacamos con el Recordset del
Control Data en DAO:
459
Constante
Efecto
0
1
Constante
Efecto
rdMoveLast Se mueve a la ltima fila
rdEOF
Se queda en la fila posterior a la ltima. Se genera el evento Validate
y a continuacin el evento Reposition. Se desactiva el botn de
desplazar hacia arriba.
rdAddNew Crea una nueva fila.
La propiedad EOFAction slo tiene efecto cuando se manipula el cambio de filas mediante
el ratn, sobre los botones del control RemoteData. No tiene efecto si se llega a la fila
posterior a la ltima mediante cdigo. (Por ejemplo, mediante la instruccin
MSRDC1.resultset.MoveNext)
460
Valor
rdUseIfNeeded
rdUseOdbc
rdUseServer
rdUseClientBatch
1
2
3
Descripcin
El controlador ODBC elegir el tipo de cursores adecuado.
Se usarn cursores del servidor si hay alguno disponible.
RemoteData usar la biblioteca de cursores de ODBC .
Se usarn cursores del lado del servidor.
RDO usar la biblioteca de cursores por lotes de tipo
461
optimista.
Le recomiendo que repase el tema de cursores de la base de datos concreta que est
usando, y espero que la bibliografa que le brinda el fabricante sea suficiente. No suelen
ser muy explcitos con los manuales aportados, o al menos tienen la habilidad de explicarlo
de una forma tan sutil que es a veces inescrutable. Casi siempre esas dudas se resuelven
en el curso que cada marca tienen para su base de datos, que es estrictamente de pago.
Mtodos del control RemoteData
Mtodo UpdateRow
Es equivalente al mtodo UpdateRecord del Control Data. Guarda los valores actuales de
los controles enlazados en la base de datos. El mtodo UpdateRow tiene el mismo efecto
que ejecutar el mtodo Edit, modificar una columna y despus ejecutar el mtodo
Update, excepto que no ocurre ningn evento.
Nota Cuando usa una biblioteca de cursores ClientBatch, todas las actualizaciones a las
tablas base se retrasan hasta que use el mtodo BatchUpdate. En este caso, el mtodo
UpdateRow actualiza el rdoResultset local, pero no actualiza las tablas base. Estos
cambios pueden perderse si la aplicacin termina antes de que se haya completado el
mtodo BatchUpdate.
Mtodo BatchUpdate (Mtodo del rdoResultset)
Este mtodo no es del control RemoteData, sino de su rdoResultset asociado.
De igual forma que un control data tena asociado un recordset, un RemoteData tiene
asociado un Resultset. El Resultset es el objeto rdoResultset del control RemoteData
(Coleccin de registros, o si lo prefiere, de filas ya que estamos en RDO), y que como
cualquier objeto de acceso a datos, tiene sus mtodos, y este es uno.
Realiza una actualizacin optimista por lotes.
Sintaxis
462
463
rdoEngine.rdoDefaultCursorDriver = valor
464
Nombre es la propiedad Name del nuevo objeto rdoEnvironment. (En el cdigo, para
nombrar a este rdoEnvironment debemos hacerlo con MiSesion). Debe suministrar un
nombre, ya que si no lo hace, este rdoEnvironment creado no se suma a la coleccin
rdoEnvironments.
Usuario es el nombre del usuario.
Contrasea es la contrasea usada en esa sesin. Puede tener hasta 14 caracteres.
Cuando se inicializa el rdoEngine se crea automticamente una sesin de trabajo
predeterminada, el rdoEnvironments(0), con el nombre de usuario que tenga el
rdoEngine en su propiedad rdoDefaultUser y con contrasea igual a la propiedad
rdoDefaultPassword. En una aplicacin multiusuario es necesario crear un
rdoEnvironment para cada uno de ellos, siempre que empleemos transacciones. En este
mtodo es necesario suministrar todos los parmetros (Nombre, Usuario y Contrasea)
rdoRegisterDataSource Introduce la informacin de conexin en el Registro de Windows
para un origen de datos ODBC (Crea una conexin ODBC igual que lo haramos en
Windows)
Sintaxis
rdoEngine.rdoRegisterDataSource DSN, controlador, silencio,
atributos
DSN es el nombre que queremos dar a la conexin ODBC
Controlador es el nombre del controlador ODBC. Debe ser uno de los instalados y hay que
poner el nombre exacto por el que se le conoce en Windows, NO el nombre de la DLL. Por
ejemplo, debe poner Microsoft Access Driver y no odbcjt32.dll
Silencio es un valor True / False y se refiere a si queremos que presente el cuadro de
creacin de un enlace ODBC (El mismo que aparece en Windows) Si ponemos False en esta
propiedad, le introducimos los datos de la conexin a travs de ese cuadro. Si le ponemos
True, no mostrar el cuadro, y por lo tanto deberemos pasarle todos los parmetros
correctamente. Si la informacin suministrada no es completa, mostrar el cuadro citado.
Atributos. Una expresin de cadena que es una lista de palabras clave que se van a
agregar al archivo ODBC.INI. Las palabras claves estn en una cadena delimitadas por
retornos de carro. No es trivial esta cadena de caracteres y es propia de cada controlador.
Por lo tanto, le recomiendo que si no conoce muy bien la cadena a introducir, ponga el
parmetro Silencio a False y se olvide de este parmetro de atributos. Eso s, deber ser el
usuario quien introduzca los datos a travs del cuadro de creacin del enlace ODBC.
Hasta aqu las propiedades y mtodos del rdoEngine. Vamos a bajar un nivel jerrquico y
ver el siguiente objeto RDO
El Objeto rdoEnvironment
Un objeto rdoEnvironment es una sesin de trabajo en RDO. Equivale al Workspace de
DAO.
En un rdoEnvironment podemos tener varios objetos Connection (varias
conexiones) de la misma forma que en un Workspace podamos tener varias objetos
Database.
La coleccin de todos los objetos rdoEnvironment es el objeto rdoEnvironments. Visual
Basic crea automticamente un rdoEnvironment, de la misma forma que creaba un
Workspace. El objeto rdoEnvironment creado es el rdoEnvironments(0) y el nombre de
usuario ser el que tenga el rdoEngine en su propiedad rdoDefaultUser y la contrasea
igual a la propiedad rdoDefaultPassword
NOTA. Visual Basic crea automticamente un Workspace o un rdoEnvironment si el
proyecto contiene la referencia al motor de bases de datos correspondiente. Visual Basic
no crear ninguno de ellos si no tiene la referencia a ningn motor de bases de datos.
465
Los
objetos
rdoEnvironment
se
anexan
automticamente
a
la
coleccin
rdoEnvironments a menos que no proporcione un nombre para el nuevo objeto cuando
utilice el mtodo rdoCreateEnvironment.
El
ODBC elegir
el tipo
de
cursores
Propiedad hEnv
Esta propiedad es el Handle de la conexin ODBC. Es similar a la propiedad hDC (para
controles) o hWnd (para formularios) que ya hemos visto en captulos anteriores. Esta
propiedad es slo de lectura y devuelve un Long. Este valor lo usan las APIs de Windows
para trabajar. Alguna instruccin nos pedir el hEnv como parmetro.
Propiedad LoginTimeout
Devuelve o establece el nmero de segundos que el Administrador de controladores ODBC
espera antes de que se produzca un error de espera al abrir una conexin.
Sintaxis
NombreDelObjetordoEnvironment.LoginTimeout = NumeroDeSegundos
466
DSN=MiConexinODBC;
UID=Luis;
PWD=MiContrasea;
DRIVER=SQL Server;
DATABASE=MiBase;
SERVER=MiServidor;
WSID=NombredemiPC;
APP=MiAplicacin
467
Hay algunas bases de datos que no aceptan transacciones. Puede comprobarlo analizando
la propiedad Transactions del objeto Connection.
Mtodo Close
Cierra un el rdoEnvironment y todas las conexiones que tena abiertas. Las modificaciones
pendientes de los objetos RDO inferiores que estuviesen abiertos se deshacen.
Sintaxis
MiSesion.Close
El objeto rdoConnection
Un objeto rdoConnection representa una conexin abierta con un origen de datos a
travs de ODBC. Es el equivalente al Objeto DataBase de DAO
Un objeto rdoConnection (es decir, una conexin a una base de datos a trvs de ODBC)
se crea o con un control RemoteData o mediante el mtodo OpenConnection del objeto
rdoEnvironment.
Puede tambin crear un nuevo objeto rdoConnection que no est vinculado de forma
inmediata con una conexin fsica especfica a un origen de datos. Por ejemplo, el siguiente
cdigo crea un objeto rdoConnection independiente:
Dim OtraConexion as New rdoConnection.
Posteriormente puede introducir las caractersticas que desee y establecer la conexin real
con la base de datos. No es normal hacer esto, por lo que le remito en caso necesario, a la
ayuda de VB de este objeto.
Propiedades del Objeto rdoConnection
Un objeto rdoConnection tiene Propiedades. Muchas de ellas ya se han visto, bien al
estudiar el control RemoteData o los objetos RDO ya estudiados. Las propiedades que se
han visto se describirn slo de forma somera.
Propiedad Connect Devuelve o establece un valor que proporciona informacin sobre el
origen de un objeto rdoConnection abierto. La propiedad Connect contiene la cadena de
conexin ODBC. Esta propiedad puede leerse siempre, pero no puede modificarse una vez
establecida la conexin.
Sintaxis
objeto.Connect = CadenaDeConexin
468
WSIS
APP
MiConexion.hDbc
La propiedad hDbc devuelve un valor de tipo Long. Este valor lo utilizan las APIs de
Windows. Y es similar a hDc o hWnd
Propiedad LastQueryResults
Devuelve un objeto rdoResultset, precisamente el que se ha generado la ltima consulta,
si la ha habido. Esta propiedad podemos utilizarla para crear un nuevo Resultset, clnico
del ultimo que se ha generado.
Sintaxis
Dim MiRs as rdoResultset
Set MiRs = MiConexion.LastQueryResults
Si no se haba creado todava ningn Resultset, devuelve Nothing.
Propiedad QueryTimeout
Devuelve o establece un valor que especifica el nmero de segundos que espera el
Administrador de controladores ODBC antes de que se produzca un error de tiempo de
espera al ejecutarse una consulta. El valor predeterminado es de 30 segundos.
Propiedad StillConnecting
Devuelve un valor que indica si la conexin se est estableciendo todava.
Sintaxis
MiConexion.StillConnecting
Esta propiedad devuelve True si la conexin no ha terminado de establecerse, y False si ya
est establecida. Es fundamental saber que la conexin ya est establecida antes de
realizar ninguna operacin con ella, por ejemplo, crear un Resultset
Propiedad StillExecuting
Devuelve un valor que indica si una consulta est an ejecutndose. Esta propiedad se usa
cuando creamos un rdoResultset o un rdoQuery, para conocer si ya se ha finalizado el
proceso de seleccin de filas que esa operacin implica. Esta propiedad puede aplicarse al
rdoConnection, rdoQuery y rdoResultset.
Devuelve True cuando la consulta est
ejecutndose todava, False si ya se ha finalizado.
Sintaxis
objeto.StillExecuting
Propiedad Transactions
Devuelve un valor que indica si se pueden realizar transacciones con un objeto
rdoConnection rdoResultset. Esta propiedad le permite asegurarse de esta circunstancia
antes de ejecutar la instruccin BeginTrans.
469
MiConexion.AsyncCheckInterval = valor
optimista
por
lotes.
Si
esta
propiedad
se
le
pone
el
valor
objeto.UpdateOperation [= valor]
El Objeto rdoResultset
El Objeto rdoResultset es el conjunto de filas que devuelve la ejecucin de una consulta.
Es el equivalente al Recordset de DAO
El Objeto rdoResultset se crea mediante el mtodo OpenResultset del rdoConnection.
Ejemplo:
Creamos el objeto rdoEnvironment utilizando el objeto creado automticamente por VB
Set GepaWs = rdoEnvironments(0)
El objeto rdoEnvironment crea el objeto rdoConnection
Set GepaConex = GepaWs.OpenConnection(Gepa, rdDriverNoPrompt, False)
(Gepa es el nombre de la conexin ODBC creada en el ordenador)
El objeto rdoConnection crea el objeto rdoResultset
Set GepaRs = GepaConex.OpenResultset("Select Ex_expedite, Ex_numproye, " & _
"Ex_presenta, Ex_plan, Ex_tipoexpe, Ex_tipoprop, Ex_tipotram, Ex_redaproy, Ex_situxpe,
"&_
"Ex_Numero_Ini, Ex_subsiste " & _
"From Expedientes Order By Ex_Numero_Ini", rdOpenDynamic, rdConcurRowVer)
Puede ver que el proceso de creacin de un rdoResultset en RDO no difiere demasiado de
la creacin de un recordset en DAO.
470
Descripcin
0
(Predeterminado) Abre un rdoResultset tipo forward1
Abre un rdoResultset tipo Keyset
Abre un rdoResultset tipo Dinamico
3
Abre un rdoResultset tipo esttico
Valor Descripcin
1
(Predeterminado) Slo lectura.
2
Concurrencia pesimista.
3
Concurrencia optimista basada en el Id. de fila.
4
Concurrencia optimista basada en valores de filas.
5
Concurrencia optimista usando actualizaciones de modo por
lotes. Valores Status devueltos por cada fila
xito.
Valor Descripcin
471
rdAsyncEnable
rdExecDirect
32
El objeto rdoResultset tiene algunas particularidades que no tienen los recordsets de DAO,
por ejemplo, poder obtener resultados mltiples, es decir, se pueden introducir varias
sentencias SELECT y cada una de ellas crea un conjunto de registros. Esto no significa que
haya mas de un rdoResultset, sino que existe un nico rdoResultset con resultados
mltiples. Se puede ir accediendo a cada uno de los conjuntos de registros mediante el
mtodo MoreResults.
Propiedades del Objeto rdoResultset
El rdoResultset no tiene exactamente las mismas propiedades que el Recordset. Y adems
no siempre funcionan tal como lo hacan en el recordset. En RDO van a depender del tipo
de cursor y del tipo de bloqueo. Veamos las propiedades del rdoResultset
AbsolutePosition. Igual que en RDO, pero no siempre funciona, ya que depende del tipo
de cursor.
ActiveConnection
rdoResultset
Bookmark Funciona igual que en el Recordset de DAO. Pero en RDO es posible que esa
propiedad no se pueda usar. Depende del tipo de cursor. Para asegurarse de que el objeto
rdoResultset admite marcadores, examine el valor de su propiedad Bookmarkable antes
de usar su propiedad Bookmark. Si Bookmarkable es False, el objeto rdoResultset no
admite marcadores y el uso de Bookmark producir un error
La propiedad Bookmark no se aplica a los objetos rdoResultset de tipo forward-only.
472
Valor Descripcin
RdEditNone
0
RdEditInProgress 1
RdEditInProgress 2
en la B. D.
LastModifiedDevuelve un marcador que indica la ltima fila modificada o agregada ms
recientemente. Este marcador es el Bookmark de esa fila. Devuelve un Variant.
LockEdits Devuelve un valor de tipo Booleano que indica el tipo de bloqueo en vigor. Si
devuelve True utiliza bloqueo pesimista. Si devuelve False utiliza bloqueo optimista.
Si LockEdits es True y otro usuario ya tiene la pgina bloqueada, se producir un
error al intentar usar el mtodo OpenResultset. En general, los dems usuarios
pueden leer datos de las pginas bloqueadas.
Si LockEdits es False (valor predeterminado) y utiliza despus Update mientras la
pgina est bloqueada por otro usuario, se producir un error.
El bloqueo se realiza sobre una pgina de datos. La pgina suele se de 2 K (Ese es el
tamao que utiliza Microsoft SQL Server)
LockType Devuelve o establece un valor entero de tipo Long que indica el tipo de
tratamiento de concurrencia. Los valores admitidos son:
Valo
Constante
Descripcin
r
(Predeterminado) El cursor es de slo lectura. No se admiten
rdConcurReadOnly 1
actualizaciones.
rdConcurLock
2
Concurrencia pesimista.
rdConcurRowVer
3
Concurrencia optimista basada en el identificador de fila.
rdConcurValues
4
Concurrencia optimista basada en los valores de las filas.
Concurrencia optimista con actualizaciones por lotes. Se
rdConcurBatch
5
obtienen valores de estado para cada fila actualizada
correctamente.
Lea la ayuda de VB para obtener mayor informacin de cada uno de los tipos.
Restartable Devuelve un valor que indica si un objeto rdoResultset admite el mtodo
Requery, que vuelve a ejecutar la consulta en la que est basado el objeto rdoResultset.
Debe usarse antes de utilizar el mtodo Requery para evitar que se produzca un error.
PercentPosition
Devuelve o establece un valor que indica o modifica la ubicacin aproximada de la fila
actual en el objeto rdoResultset, basndose en el porcentaje con respecto al total de filas
de dicho objeto. El valor devuelto es un Single entre 0,0 y 100,0
Puede usar la propiedad PercentPosition con una barra de desplazamiento de un control
Form o TextBox para indicar la ubicacin de la fila actual en un objeto rdoResultset.
Esta propiedad solamente se aplica a los rdoResultset tipo Keyset y Dynamic.
473
Constante
Valor
rdRowUnmodified
rdRowModified
rdRowNew
rdRowDeleted
rdRowDBDeleted
StillExecuting Devuelve un valor de tipo Booleano que indica si una consulta est an
ejecutndose.
Esta propiedad es muy til (muy necesaria) para saber si la consulta ya est disponible,
antes de presentar los datos de esa consulta. La propiedad debe ser False para poder
presentarlos. Es tpico crear un bucle parecido a este:
Do While GepaRs.StillExecuting = True
DoEvents
Loop
Transactions
transacciones.
474
abra la base de datos, y una base muy concreta, Access, dBase, etc., bases que controla
directamente Visual Basic a travs de la dll correspondiente a la versin de la BD que
vamos a abrir. Esto no es exactamente igual en RDO. Aqu quien abre el fichero que
contienen la base de datos no es Visual Basic, sino el driver de ODBC. Y no solamente eso,
dependiendo de la base de datos, unas permiten hacer unas operaciones y otras no. Lo
mismo podemos decir del tipo de rdoResultset, del cursor y de si es lado cliente o lado
servidor. Por lo tanto no se asuste si pretende ejecutar un mtodo y no funciona.
Probablemente es que Visual Basic ha puesto por defecto unas caractersticas a los objetos
que no son las adecuadas. Y si no fuese posible, en ltima instancia nos queda realizar
directamente la operacin que pretendamos realizar con el mtodo, es decir, mediante las
operaciones que nos permite el propio driver de ODBC. Eso s, en este caso estamos en sus
manos. Lo veremos ms adelante.
Mtodo AddNew
Crea una nueva fila para un objeto rdoResultset actualizable.
Sintaxis
MirdoResultset..AddNew
475
meten en la base de datos. Cuando se ejecuta este mtodo, se envan a la base de datos
todos los cambios pendientes.
Sintaxis
MirdoResultset.Close
Mtodo Delete
Elimina la fila actual de un objeto rdoResultset actualizable.
Sintaxis
MirdoResultset.Delete
MirdoResultset.Edit
Si cambia la fila actual antes de ejecutar el mtodo Update, se perdern los cambios. Si
desea anular el cambio que est realizando, basta con ejecutar el mtodo CancelUpdate.
Cuando la propiedad LockEdits del objeto rdoResultset es True (bloqueo pesimista),
todas las filas del conjunto de filas del objeto rdoResultset se bloquean en cuanto se
ejecuta Edit, y se mantienen bloqueadas hasta que se ejecuta Update.
Mtodo GetRows
Recupera mltiples filas de un rdoResultset y las introduce en una matriz.
Sintaxis
matriz es un Variant
El primer subndice de la matriz identificar la columna y el segundo identifica el nmero
de fila, de esta forma:
matriz(intColumn)(intRow)
Mtodo MoreResults
Este mtodo se utiliza cuando se ha creado un rdoResultset de resultados mltiples, es
decir, se han empleado varias sentencias SELECT para crearlo. Cada sentencia formar
dentro del rdoResultset un juego de filas. Cuando se utiliza el mtodo MoreResults se
borran las filas del conjunto de resultados actual y se colocan en su lugar las filas
correspondientes al siguiente.
MirdoResultset.Requery [opciones]
El valor admitidi para Opciones es rdAsyncEnable (32) que ejecuta la operacin de forma
asncrona
Mtodo Update
Termina una operacin de modificacin de datos o de aadir una nueva fila. Ya se ha
comentado su funcionamiento con los mtodos AddNew y Update.
477
DAO en su versin de ODBCDirect. Tendr cdigo compatible con DAO, y ms rapidez que
con RDO. Adems RDO es una tecnologa considerada obsoleta por Microsoft, con lo que
ello conlleva.
Microsoft dice, y este autor recomienda:
PROYECTOS
Pero si usa Access con la base de datos instalada en el mismo ordenador que el programa,
use directamente DAO. Si usa Access olvdese de nuevas tecnologas. Con Access DAO
significa: Rapidez, sencillez, eficacia, control sobre el programa, independencia de drivers.
O
L
E
D
B
A
D
O
Texto
O
D
B
C
R
D
O
D
A
O
478
Modelo DAO/RDO
Bases de datos
relacionales
O
D
B
C
479
Errors
Command*
Parameter*
Parameters
Recordset
*
Field*
Fields
* Todos los objetos marcados con un asterisco contienen la coleccin Properties con un
subconjunto de objetos Property.
Properties
Property
Como puede verse en la figura, existen tres objetos principales dentro de ADO: El objeto
Connection, el objeto Command y el objeto recordset. Luego veremos algunas de las
caractersticas principales de cada uno de estos objetos.
Antes de proseguir con estos objetos vamos a explicar donde y porqu se deben utilizar
objetos ADO en vez de objetos DAO u objetos RDO
Hasta ahora habamos utilizado bases de datos Access, y tambin otras bases de datos
sencillas como dBase. Acceder a Access es extremadamente fcil. Y ello es debido a que
480
Access es una base de datos sin grandes aspiraciones en cuanto a seguridad. Es una gran
base de datos, y tiene sus dispositivos de seguridad en cuanto a permisos de acceso (Vea
El dbEngine. Visin desde DAO y la propiedad SystemDB en el Captulo 12) sin embargo
estas posibilidades se usan en muy pocas ocasiones, y estos mecanismos de seguridad de
Access tampoco son una maravilla. Por lo tanto Access se ha quedado como una gran base
de datos para aplicaciones que no pasen de algunos centenares de miles de registros y con
pocos puestos de operacin. En esta base de datos, el mtodo ideal de acceso es DAO,
bien directamente o a travs de ODBC Direct. Cuando se accede directamente, la BD se
suele buscar bien mapeando el disco del servidor como una unidad ms del puesto cliente,
o bien accediendo a travs de la direccin IP del servidor.
Cuando queremos empezar a tener una seguridad en los accesos, disponer de privilegios
distintos para cada usuario, trabajar en una red de rea local con muchos usuarios, hay
que recurrir a bases de datos tipo Oracle o SQLServer. Ya empezamos a tener problemas:
Visual Basic no puede acceder directamente a abrir estas bases de datos. Podemos acceder
a travs de ODBC, pero como ya se dijo en el, captulo correspondiente, ODBC se ha
quedado obsoleto. Y Microsoft ha sacado para ello ADO. Y ADO permite abrir la base de
datos usando para ello un dispositivo intermedio que es el proveedor OLE DB. Este no es
ms que una DLL. Mejor dicho, un juego de DLLs que puede ver en la carpeta:
C:\Archivos de Programa\Archivos Comunes\System\Ado
Estas DLLs permiten conectar con las bases de datos ms conocidas (Oracle, SQLServer,
Access y las dems BD controladas por el motor Jet). ADO funciona de forma diferente a
ODBC. Con ODBC se preparan conexiones permanentes en el ordenador, y cualquier
programa puede acceder a la BD a travs de esas conexiones. Con ADO no hay que
preparar previamente ninguna conexin. Es el propio programa el que llama al proveedor
de datos OLE DB y le pasa como parmetros los datos necesarios para que este realice la
conexin y abra la BD. Si hubiese dos programas ejecutndose simultneamente y
accediendo a la misma base de datos a travs de ADO, cada programa prepara una
conexin a esa BD. En ODBC podramos ver las conexiones existentes en el PC a travs
del Panel de Control | Fuentes de Datos ODBC. En ADO no existe esa posibilidad ya
que, como se ha dicho, es el propio programa quien crea esa conexin al ajecutarse.
Para que VB pueda acceder a ADO es necesario introducir en el programa la referencia a
Microsoft ActiveX Data Objets 2.1 Library (Proyecto|Referencias)
Una particularidad de ADO frente a lo ya visto con DAO o RDO es que ADO se salta la
jerarqua a la hora de crear nuevos objetos. En DAO, el objeto DAO superior creaba al
objeto DAO inferior (Recuerde aquello del juego de nios). En ADO podemos crear cada
objeto sin que exista el objeto inmediatamente superior. Por ejemplo podemos crear un
recordset sin que exista el objeto Connection. Claro que en este caso, a la hora de crear el
objeto recordset deberemos indicarle, mediante los parmetros que debemos aportar en la
sintaxis de creacin del recordset, todos aquellos datos que le aportaramos a la creacin
del objeto Connection. Como ve no tiene ventajas. Solamente que nos desentendemos un
poco de abrir y cerrar el objeto Connection.
Veamos como se crea la conexin: Mediante el Objeto Connection
EL OBJETO CONNECTION
El objeto Connection representa una sesin con el origen de los datos. Dependiendo de la
funcionalidad del proveedor de los datos podremos utilizar determinadas propiedades,
mtodos y colecciones de este objeto. La funcin de este objeto es recoger toda la
informacin del proveedor de los datos que se va a utilizar para crear un objeto recordset.
481
Para crear un objeto Connection, previamente debemos declararlo como variable objeto
Connection:
Dim MiConexion as ADODB.Connection
El sitio donde se debe declarar depende como siempre, del mbito que deseamos que
tenga ese objeto.
Para crear el objeto Connection deberemos utilizar la siguiente sintaxis:
Set MiConexion = New ADODB.Connection
Nota: En el caso de que ejecutemos la aplicacin y nos salga un error diciendo que el tipo
no est definido por el usuario, es que no hemos aadido la referencia de Microsoft
Actives Data Objects Library x.x
La conexin est creada?. S, pero de momento es completamente intil ya que no sabe
ni siquiera que base de datos debe abrir, ni con que usuario, ni las condiciones en las que
debe abrir esa base (Solo lectura, etc.) Esta informacin se la pasamos mediante la
propiedad ConnectionString (Cadena de conexin)
La propiedad ConnectionString
Es la propiedad ms importante del objeto Connection. Se basa en encadenar una serie de
argumentos en una cadena de caracteres. Los diferentes argumentos son (dependiendo del
proveedor OLE DB y de la configuracin de la red, se necesitarn todos o parte de ellos)
Provider
482
483
484
3
una
una
5) Al pulsar el botn generar, nos aparece otra ventana en la que tenemos cuatro
pestaas aunque nicamente necesitaremos dos de ellas para crear una cadena de
conexin correcta y probada. El resto de las pestaas forman parte de otro captulo
exclusivo del control data de ADO, aunque le invito a que curiosee por ellas.
Seleccionaremos el proveedor de datos que queramos utilizar y pulsaremos el botn
siguiente para pasar a la siguiente pestaa.
485
486
Para seguir un poco el ejemplo que acompaa a este captulo, vamos a ver el cdigo
utilizado para crear la conexin. En el ejemplo usamos una base de datos Access (No es la
mejor para demostrar como funciona ADO, pero es la que los alumnos van a tener con
mayor facilidad. Una base Oracle o SQL no se instala fcilmente en un ordenador personal)
Set MiConexion = New ADODB.Connection
'MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"
'MiConexion.Open
Ahora nuestro programa ya est en contacto con la base de datos. Lo que falta ya lo puede
suponer: crear un recordset.
Aqu vamos a ver la primera diferencia con DAO. El recordset no lo crea el objeto
Connection. Se crea l a s mismo. Para que pueda existir un objeto Recordset primero
hay que declararlo:
Dim MiRecordset As ADODB.Recordset
MiConexion.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False"
Abrir el objeto Connection
MiConexion.Open
Crear el objeto recordset
Set MiRecordset = New ADODB.Recordset
Abrir el objeto Recordset
MiRecordset.Open "Alumnos", MiConexion, adOpenDynamic, adLockOptimistic
Con ADO (Sin crear el objeto Connection)
Declarar MiRecordset
Dim MiRecordset As ADODB.Recordset
Crear el Recordset
Set MiRecordset = New ADODB.Recordset
Abrir el Recordset
MiRecordset.Open "Alumnos", "Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=C:\GuiaDelEstudiante\ADO\PruebaADO.mdb;Persist Security Info=False",
adOpenDynamic, adLockOptimistic
Observe siempre que tanto en las declaraciones del objeto Connection y del objeto
Recordset, como en su creacin, debemos anteponer siempre la palabra ADODB
Tanto el objeto Recordset como el objeto Connection se debern cerrar cuando ya no se
utilicen, o al menos, al cerrar la aplicacin. Esto es tanto ms necesario cuanto mayor sea
la seguridad de la base de datos que vamos a utilizar. En algunas bases de datos, dejar
una sesin abierta significa dejar una aplicacin zombie ejecutndose en el servidor, que
habr que cerrar desde su propio sistema operativo. Este problema no le va a ocurrir
utilizando Access, pero como ya se dijo al principio, Access no es el mejor ejemplo de
utilizacin de ADO. Para cerrar una sesin y un recordset utilizaremos el mtodo Close
MiRecordset.Close
MiSesion.Close
ADO
Recordset
DataBase
WorkSpace
Recordset
Connection
A este respecto, hay que citar la propiedad CursorLocation que veremos ms adelante. Si
creamos un cursor lado cliente, seguramente nos permitir utilizar ms opciones (entre
ellas AddNew) que si lo establecemos de lado servidor. Tenga en cuenta que si usa un
cursor lado cliente, el recordset no se actualiza cuando otro usuario realiza modificaciones
en la base.
Modificar datos mediante EDIT
En ADO no hace falta usar Edit para modificar los datos del registro actual. Edit no existe
en ADO. Para modificar un dato basta con poner el mismo cdigo que utilizbamos en
DAO, pero sin comenzar por la lnea Mirecordset.Edit. Colocndonos en el registro a
modificar pondremos:
MiRecordset!Alumno_Nombre = Pedro
MiRecordset!Alumno_Ape1 = Perez
MiRecordset.Update
De cualquier forma, esto tampoco tiene porque funcionar en todas las bases de datos. En
ese caso tendremos que recurrir, al igual que para un registro nuevo, a las instrucciones
SQL, que en este caso ser Update. Pero ya lo veremos ms adelante. Hasta ahora
solamente he querido usar el cdigo ms simple para que pueda empezar con ADO, y
sobre todo, para que vea que esta es una tcnica completamente accesible, aunque, dadas
las grandes prestaciones que tiene, un poco ms adelante se va a complicar algo.
Ya ha visto que podemos trabajar perfectamente con recordsets, tal como lo hemos hecho
con el DAO de toda la vida. Pero ya lo comentbamos al principio, parece que hay que
adornar lo obvio para que no lo parezca tanto. Y ah viene el Objeto Command, que como
habr podido ver en la figura de la Jerarqua de los objetos ADO, es un objeto que an no
sabemos lo que hace.
El objeto Command lo que va a hacer es crear un recordset. O tambin, meter a capn
un nuevo registro, o borrarlo, utilizando directamente instrucciones SQL. Hay que darse
cuenta que ADO trabaja con una gran diversidad de bases de datos, y no todas trabajan
igual. Por eso, muchas veces fallan operaciones tan sencilla como aadir un nuevo registro
con el mtodo AddNew del recordset
MiRecordset.AddNew
Y hay que emplear una instruccin SQL: INSERT
En estos casos, en ADO utilizamos el mtodo EXECUTE sobre el objeto Connection.
Creamos una variable, StrIntroducir, con el contenido de la instruccin SQL y ejecutbamos
esa instruccin mediante Execute
StrIntroducir = "Insert Into INT_DOCUMENTOS " _
& "(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC, _
& L_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC,VISIBLE_DOC)"_ &
"Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & "','" & TbTitulo.Tag _
& "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date & "',0,1)"
ConexBDPrensa.Execute StrIntroducir
Esta lnea (StrIntroducir) es el contenido de la propiedad CommandText de un objeto
Command de ADO. Ni ms ni menos que una instruccin que queremos realizar sobre la
BD. Un objeto Command tiene pocas cosas ms. Como objeto ADO que es tiene sus
propiedades y mtodos. Pero en esencia es lo que acaba de ver con la instruccin EXECUTE
491
del objeto Connection. Lo que pasa, que ADO lo han hecho muy organizado, y por eso
tiene la categora de Objeto. Es hacer lo mismo, utilizando las mismas expresiones, pero
dndole ms cuerpo.
Con la instruccin anterior, lo que hacamos era aadir un registro. Si lo que queremos
hacer es crear un recordset, la instruccin SQL comenzara por Select * From . Y el
mtodo EXECUTE devolvera un Recordset
StrIntroducir = Select * From Alumnos Where Apellido1 = Suarez
Podemos crear un recordset (MiRecordset, previamente declarado como tal) con esta
instruccin
MiRecordset = ConexBDPrensa.Execute StrIntroducir
O con estas otras
Set MiComando as New ADODB.Command
MiComando.ActiveConnection = ConexBDPrensa
MiComando.CommandText = Select * From Alumnos Where Apellido1 = Suarez
MiRecordset = MiComando.Execute
Ver el ejemplo completo al final del captulo.
Ahora, tras la explicacin informal de cmo se crea una conexin y un recordset en ADO, y
que es un Command, vamos a entrar a conocer sus propiedades y mtodos. Al final, y con
un buen ejemplo realizado de varias formas, entender perfectamente la forma de trabajar
con ADO.
492
visto como crear un objeto Connection, por lo que vamos a pasar directamente a ver sus
objetos, colecciones, propiedades y mtodos.
Como puede verse en la figura, el Objeto Connection tienen los objetos Command y
Recordset, y la coleccin Errors.
El Objeto Recordset es el recordset de toda la vida: un conjunto de registros que
contienen datos. El Objeto Recordset, aunque pertenece al objeto Connection, puede
crearse sin que exista previamente un objeto Connection. Esta es una de las propiedades
de los objetos ADO: no necesita cumplir estrictamente con la jerarqua.
El Objeto Command es una definicin de un comando especfico que se piensa ejecutar
contra un origen de datos. Los objetos Command sirven para tener almacenadas
operaciones de acceso a datos y usarlas en el momento adecuado, simplemente citndolas.
Lo que obtenemos de un objeto Command es, o un recordset (ver que no merece la pena
usar un objeto Command para crear un recordset, puesto que se pueden crear
directamente) o una operacin que afecte a los registros de la base de datos (aadir
registros, borrarlos, si es que no se deja hacer eso mediante recordsets)
La Coleccin Errors es el conjunto de errores generados por el proveedor de datos ante
el fallo de una operacin de acceso. La coleccin Errors se refiere nicamente a los errores
generados por el proveedor, no a los fallos interceptables producidos por el programa, que
deben ser tratados de la forma habitual: mediante Err
Propiedades del Objeto Connection
(Lea esto de las propiedades sin complicarse
demasiado la vida. Las realmente importantes ver que estn advertidas debidamente)
Las propiedades del objeto Connection dependen de cada proveedor. No todos se
comportan de igual forma, por lo que cada propiedad debe condicionarse a si el proveedor
es capaz de ofrecerla.
Propiedad Attributes
Es un Long. Acepta dos valores o la suma de los dos:
adXactCommitRetaining
adXactAbortRetaining
Estos atributos condicionan el modo de operacin de la conexin con los mtodos
CommitTrans y RollBackTrans.
Propiedad CommandTimeout
Indica, en segundos, el intervalo de espera para que se ejecute un comando (Objeto
Command) antes de que finalice el intento y se genere un error. Es un Long. El valor
predeterminado es 30.
Propiedad ConnectionTimeout
Indica, en segundos, el intervalo de espera para establecer una conexin antes de que
finalice el intento y se genere un error. Es un Long y el valor predeterminado es 15.
493
Propiedad ConnectionString
(IMPORTANTE)
Es una cadena de caracteres que contiene la informacin que se utiliza para establecer una
conexin a un origen de datos. (Vea la explicacin amplia ms atrs)
La cadena de conexin tiene varios argumentos, todos ellos separados por un punto y
coma (;) de la forma
argumento1 = valor; argumento2 = valor; argumento3 = valor etc.
ADO procesa solamente cuatro argumentos: Provider, File Name, Remote Provider y
Remote Server. Los dems argumentos los pasa al proveedor para que el los procese
(Usuario, Password, etc)
Si al emplear el mtodo Open se utiliza el parmetro Connection String, este parmetro
utilizado en el mtodo Open sustituir a cualquier otro existente anteriormente. Una vez
abierta la conexin, esta propiedad no se puede cambiar puesto que es solamente de
lectura.
Los argumentos File Name y Provider son excluyentes.
Propiedad CursorLocation (IMPORTANTE)
Establece o devuelve la posicin de un servicio de cursores. Es un Long, y acepta las
siguientes constantes:
AdUseNone No se usan servicios de cursor. (Esta constante es obsoleta y aparece
nicamente por compatibilidad con versiones anteriores.)
AdUseClient Usa cursores del lado del cliente.
AdUseServer
Predeterminado. Usa cursores del lado servidor.
Esta propiedad parece que no dice nada. Y es sumamente importante.
Los cursores son, por decirlo de alguna manera, los mecanismos de la base de datos donde
se crean los recordsets. Se estar dando cuenta que las bases de datos que tienen
cursores son ya bases de datos con mecanismos propios para la creacin de recordsets.
(SQL Server u Oracle, p.e.) Estas bases de datos trabajan como aplicaciones cliente
servidor. Tienen en el servidor, aparte de los datos, la mayora de sus recursos. En el
cliente tienen prcticamente los recursos de conectividad, y poco ms. Esta conectividad
permite enviar desde el cliente una peticin a la base de datos alojada en el servidor. Esa
peticin ser el resultado por ejemplo, de una sentencia SQL. Al recibirla el servidor,
gestionar la obtencin de los resultados y una vez que los haya conseguido viene su
primera duda: Dnde los almaceno? Puede almacenarlos en el servidor, y cada vez que
necesitemos
un
nuevo
registro,
por
ejemplo
al
ejecutar
la
sentencia
MiRecordset.MoveNext, el cliente se lo indica al servidor y este le enva el nuevo registro.
Tambin puede almacenar los datos obtenidos en el cliente, y de esta forma el cliente
puede moverse con entera libertad a lo largo de los registros del recordset. Puede hasta
contarlos y saber en que posicin est. La diferencia entre uno y otro sistema es que en el
primer caso el trfico por la red es mnimo (solamente se enva la informacin
estrictamente necesaria) y en el segundo caso, se enva mucha informacin de un golpe, la
correspondiente a todos los registros del recordset, independientemente de si se va a usar
en el servidor o no.
Considerando el trfico generado, parece que es mejor crear los cursores en el lado
servidor. Pero esto trae tambin sus dificultades. Nos priva de muchas propiedades del
recordset. Una propiedad muy usada, AbsolutePosition, no la tienen los cursores de lado
servidor, circunstancia que no nos debe sorprender, ya que al no estar todos los registros
en el cliente, ste, aunque disponga de todos los datos guardados en todos los campos de
un determinado registro, no puede saber que posicin ocupa ese registro dentro de la
totalidad de registros del recordset. Por lo tanto, usar cursores de lado cliente o lado
494
AdModeShareDenyNone Impide que otros abran una conexin con cualquier tipo de
permiso.
Slo puede establecer la propiedad Mode cuando el objeto Connection est cerrado.
Cuando se usa en un objeto Connection del lado del cliente, la propiedad Mode slo se
puede establecer a adModeUnknown.
495
Propiedad Provider
Es un string que indica el nombre del proveedor de un objeto Connection. Si no se
especifica ningn proveedor, la propiedad tendr el valor predeterminado MSDASQL
(Proveedor de Microsoft OLE DB para ODBC).
Propiedad State
Devuelve el estado del objeto Connection: abierto (adStateOpen = 1) o cerrado
(adStateClosed = 0).
Propiedad Version
Devuelve el nmero de versin de ADO. Es un String.
Mtodos del Objeto Connection
Mtodos BeginTrans, CommitTrans y RollbackTrans
Estos mtodos de transaccin administran el proceso de la transaccin dentro de un objeto
Connection de la forma siguiente:
BeginTrans: inicia una nueva transaccin.
NombreConection.Cancel
NombredelObjetoConnection.Close
Descripcin
Indica que el proveedor tiene que evaluar CommandText
como definicin textual de un comando, como una
instruccin SQL.
Indica que ADO tiene que generar una consulta SQL para
devolver todas las filas de la tabla mencionada en
CommandText.
Indica que el proveedor tiene que devolver todas las filas de
la tabla mencionada en CommandText.
Indica que ADO tiene que generar una consulta SQL para
devolver todas las filas de la tabla mencionada en
CommandText.
Indica que el proveedor tiene que evaluar CommandText
como procedimiento almacenado.
Indica que el tipo de comando en CommandText es
desconocido.
Indica que el comando se tiene que ejecutar de forma
asncrona.
Indica que el resto de las filas siguientes a la cantidad
inicial especificada en la propiedad CacheSize tiene que ser
recuperada de forma asncrona.
497
498
Como puede observarse, algunas de las propiedades no devuelven los valores esperados:
NativeError vale 0 cuando debera valer 1017, que es el error asociado de Oracle. An as
podemos capturar el cdigo del error desde la cadena de caracteres description. Con este
comentario se pretende sugerir que se realicen pruebas con el proveedor de datos que
vayamos a utilizar para conocer su comportamiento respecto a este objeto error y dnde
nos devuelve los cdigos.
Observese en el cdigo que la declaracin de MiError se hace con ADODB.Error
Coleccin Properties
Es el conjunto de objetos Property
Objeto Property
Un objeto Property representa una caracterstica dinmica de un objeto ADO que est
definida por el proveedor.
499
500
Los registros recuperados desde la memoria cach no reflejan los cambios concurrentes
que hagan otros usuarios en el origen de datos. Para forzar una actualizacin de todos los
datos en la memoria cach, debe usarse el mtodo Resync.
Propiedad MaxRecords
Indica el nmero mximo de registros que se devuelven a un Recordset desde una
consulta. Es un Long y el valor predeterminado es 0, que significa sin lmite (Obtienen
todos los registros). Esta propiedad es de lectura y escritura cuando el recordset est
cerrado, y solamente de lectura cuando est abierto.
Esta propiedad debe usarse solamente cuando se prev que se pueden obtener un nmero
muy grande de registros. Es prudente tomar medidas frente a aquellas operaciones en las
que el ordenador pueda meterse en un proceso excesivamente largo o que ocupe ms
recursos de los disponibles. Estas cosas son las que suelen colgar al ordenador y en las
que es muy frecuente echarle luego la culpa a Windows Si estamos frente a una base de
datos con todos los datos de los afiliados a la Seguridad Social, no es del todo prudente
crear un recordset mediante esta sentencia:
SELECT * From Afiliados Where Apellido1 = Fernandez
Incluso las hay peores:
SELECT * From Afiliados
A nadie se le ocurrira, pero puede surgir involuntariamente cuando ese acceso se realiza
desde un puesto de operacin pblico (Acceso desde Internet por ejemplo). Con la
propiedad MaxRecords puede limitar el nmero de registros obtenidos. Posiblemente no
llegue a obtener el dato deseado, y se vea en la obligacin de realizar la misma consulta
sucesivas veces hasta encontrarlo.
Propiedad CursorLocation
Establece o devuelve la posicin de un servicio de cursores. Es idntica a la propiedad del
mismo nombre vista ms atrs con todo detalle para el objeto Connection.
Propiedad CursorType
Indica el tipo de cursor que se usa en un objeto Recordset. Es de lectura y escritura si el
recordset est cerrado, y solo de lectura si est abierto. Puede tomar uno de los siguientes
valores:
AdOpenForwardOnly
Predeterminado. Idntico a un cursor esttico, excepto
slo permite desplazarse hacia delante en los registros. Esto mejora el rendimiento
en situaciones en las que slo se quiere pasar una vez por cada registro.
En muchas ocasiones es necesario moverse por el recordset hacia delante y hacia
atrs. Este tipo de cursor solamente permite moverse hacia delante. Tenga presente
que este es el tipo predeterminado.
AdOpenKeyset
Cursor de conjunto de claves. Igual que un cursor dinmico,
excepto que no se pueden ver los registros que agregan otros usuarios, aunque los
registros que otros usuarios eliminan son inaccesibles desde su conjunto de
registros. Los cambios que otros usuarios hacen en los datos permanecen visibles.
AdOpenDynamic
Cursor dinmico. Las incorporaciones, cambios y eliminaciones
que hacen otros usuarios permanecen visibles, y se admiten todo tipo de
movimientos entre registros, a excepcin de los marcadores si el proveedor no los
admite. Es el equivalente en DAO al tipo Dynaset
501
AdOpenStatic
Cursor esttico. Una copia esttica de un conjunto de registros
que se puede usar para buscar datos o generar informes. Las incorporaciones,
cambios o eliminaciones que hacen otros usuarios no son visibles. Es el equivalente
en DAO al tipo Snapshot
NOTA. Si un proveedor no admite el tipo de cursor solicitado, el proveedor puede que
devuelva otro tipo de cursor. La propiedad CursorType cambiar para coincidir con el tipo
de cursor en uso cuando el objeto Recordset se abra. Para comprobar la funcionalidad
especfica del cursor devuelto, use el mtodo Supports. Cuando cierre el Recordset, la
propiedad CursorType volver a su configuracin original.
Propiedad LockType
Indica el tipo de bloqueo que se pone en los registros durante el proceso de edicin.
Establece tambin si el recordset se actualiza registro a registro o por lotes. Este ltimo
sistema permite realizar varios cambios en el recordset y mantenerlos en la cach durante
cierto tiempo, y proceder a la actualizacin de todos los cambios pendientes en una sola
operacin. Esto es muy importante cuando se est trabajando con una base de datos
situada en un servidor con un acceso lento (conexin va Internet, por ejemplo)
Los valores de la propiedad LockType pueden ser:
AdLockReadOnly Predeterminado. Slo lecturano puede modificar los datos
AdLockPessimistic Bloqueo pesimista, registro a registro: el proveedor hace lo necesario
para asegurar la modificacin correcta de los registros, generalmente
bloqueando registros en el origen de datos durante todo el proceso de
modificacin. Este valor solamente es vlido si el cursor (Propiedad
CursorLocation) esta establecido a lado servidor.
AdLockOptimistic Bloqueo optimista, registro a registro: el proveedor usa bloqueo
optimista, bloqueando registros slo cuando llama al mtodo
Update.
AdLockBatchOptimistic Actualizaciones optimistas por lotes: requerido para el modo
de
actualizacin por lotes como contraposicin al modo de
actualizacin inmediata.
Propiedad EditMode
Indica el estado de modificacin del registro actual. Es solamente de lectura. Devuelve uno
de las siguientes constantes:
AdEditNone
AdEditInProgress
no
AdEditAdd
situado
se ha
AdEditDelete
Propiedad Filter
Esta propiedad solamente la tienen los recordset ADO. Y es que ADO presupone que est
obteniendo datos de una base de datos alojada en un servidor y que la comunicacin entre
servidor y cliente puede ser especialmente lenta. Mediante Filter puede descartar registros
que no cumplan una determinada condicin. En realidad lo que hacemos mediante Filter es
crear un nuevo Recordset a partir de otro Recordset.
502
La propiedad Filter se utiliza tambin para actuar sobre determinados registros en varios
mtodos del recordset (Resync, Save, ) pero no se va a explicar en este manual la
explicacin de la utilizacin de esta propiedad en esos mtodos, ya que el nivel del
programador que utiliza esos recursos debe ser elevado. Le reservamos por tanto la
posibilidad de conocerlo directamente desde la ayuda de Visual Basic, que en este caso es
bastante buena.
De momento lo que vamos a hacer con Filter es crear un nuevo recordset Por qu no
creamos directamente el nuevo recordset utilizando una sentencia SQL que lleve implcito
ese filtro?
Personalmente no me gusta utilizar la propiedad Filter, y prefiero crear un nuevo recordset.
Creo que solamente lo he usado para rellenar un MSHFlexGrid con parte de los datos del
recordset que uso en una parte de la aplicacin. Veamos un ejemplo:
(MiConexion es una conexin ya creada)
Dim RsInicial As ADODB.Recordset
Dim RsFiltrado As ADODB.Recordset
Set RsInicial = New ADODB.Recordset
Set RsFiltrado = New ADODB.Recordset
RsInicial.Open "Autores", MiConexion, adOpenDynamic, adLockOptimistic
Este es el recordset que uso para muchas cosas dentro de la aplicacin. Ahora quiero
presentar en un MSHFlexGrid solamente los datos de los autores de nacionalidad espaola.
Filtro el recordset anterior utilizando un criterio de igualdad de un campo: Nacionalidad
RsFiltrado = RsInicial.Filter (Nacionalidad = Espaola)
Ahora ya podemos aplicar este recordset al MSHFlexGrid:
Set MSHFlexG1.Recordset = RsFiltrado
Y cuando queremos presentar todos los autores, basta con poner la lnea:
Set MSHFlexG1.Recordset = RsInicial
Este es el nico ejemplo que puedo sacar de todas mis aplicaciones. Seguro que el alumno
va a ver ms aplicaciones de esta propiedad.
La propiedad Filter puede mostrar tambin aquellos registros que han sido manipulados
recientemente, mediante las constantes siguientes:
AdFilterNone
503
Propiedad Index
Indica el nombre del ndice que se utiliza actualmente en el Recordset. Es un String con el
nombre del ndice.
El ndice se utiliza para moverse a lo largo del recordset mediante el mtodo Move. El
ndice ya debe estar creado en la tabla de la base de datos.
Al utilizar un ndice, el orden de los registros se cambia al orden establecido en ese ndice.
Por lo tanto, los valores obtenidos anteriormente por la propiedad AbsolutePosition
cambiarn completamente.
No todos los proveedores de datos aceptan la propiedad Index. Puede comprobarlo
mediante el mtodo Supports.
Propiedad MarshalOptions
Esta propiedad se usa cuando estamos trabajando con cursores lado cliente. En este
caso, como vimos ms atrs, los registros del recordset estn en el equipo cliente. Todas
las operaciones realizadas sobre el recordset se realizan en el cliente, por lo tanto llegar
el momento en que habr que actualizar en el servidor los datos que hayamos modificado
en el recordset que est en el equipo cliente. Mediante esta propiedad podemos hacer que
se enven al servidor todos los registros (filas) o solamente los que han cambiado. Acepta
estas dos constantes:
AdMarshalAll
devuelven al
AdMarshalModifiedOnly
Esta propiedad puede mejorar el rendimiento de la aplicacin para aquellos casos en los
que se use un canal de comunicacin lento.
Propiedad PageSize
Indica cuntos registros constituyen una pgina del objeto Recordset. Es de lectura y
escritura. Devuelve un Long y su valor predeterminado es 10.
Esta propiedad permite determinar cuntos registros componen una pgina lgica de
datos. Al establecer un tamao de pgina, puede utilizar la propiedad AbsolutePage y se
mover al primer registro de una pgina especfica. Esto es til en las situaciones de
servidor Web cuando se desea permitir que el usuario pase pginas de datos y vea cierto
nmero de registros al mismo tiempo. Esta propiedad se puede establecer en cualquier
momento y su valor se utilizar para calcular la ubicacin del primer registro de una pgina
especfica.
Propiedad PageCount
Indica cuntas pginas de datos contiene el objeto Recordset. Es solamente de lectura.
Devuelve un Long. Si el objeto Recordset no admite esta propiedad, el valor ser -1 para
indicar que no se puede determinar el valor de PageCount.
Propiedad AbsolutePage
Especifica en qu pgina reside el registro actual. Es de lectura y escritura. Devuelve un
Long o una de las siguientes constantes:
AdPosUnknown
AdPosBOF
El puntero del registro actual est al comienzo del archivo (es decir, la
propiedad BOF tiene el valor True).
504
AdPosEOF
El puntero del registro actual est al final del archivo (es decir, la
propiedad EOF tiene el valor True).
Propiedad RecordCount
Indica el nmero actual de registros de un objeto Recordset. Devuelve un Long
Es posible que esta propiedad no la permita el proveedor de datos, o que no pueda llegar a
averiguarse, ya que dependiendo del tipo de cursor utilizado puede que no suministre ese
dato.
Propiedad Source
Devuelve la tabla, consulta o sentencia SQL utilizado en el mtodo Open para crear el
recordset. Es un String.
Propiedad State
Indica el estado (abierto, cerrado, proceso de ejecucin) en el que se encuentra el
recordset. Devuelve uno de los siguientes valores:
Constante
Descripcin
Valor predeterminado. Indica que el objeto
adStateClosed
est cerrado.
adStateOpen
Indica que el objeto est abierto.
Indica que el objeto Recordset se est
adStateConnecting
conectando.
Indica que el objeto Recordset est
adStateExecuting
ejecutando un comando.
Indica que se est obteniendo el conjunto
adStateFetching
de filas del objeto Recordset.
Puede tener una combinacin de valores. Por ejemplo, si se est ejecutando una
instruccin, esta propiedad tendr un valor combinado de adStateOpen y
adStateExecuting.
Propiedad Status
Esta propiedad se refiere al registro actual. Indica el estado de este registro respecto a las
operaciones de actualizacin por lotes u otras operaciones masivas. No es una propiedad
que se use todos los das. Vea la ayuda para mas detalles.
Propiedades dinmicas del objeto recordset
Las propiedades anteriores se refieren a propiedades del recordset que se refieren a unas
caractersticas propias del recordset una vez creado. Son estas:
Unique Table, Unique Schema y Unique Catalog
Unique Table especifica la tabla sobre la que se permite realizar modificaciones de datos
(Insertar o actualizar), en el caso de que el recordset se haya creado mediante una
operacin JOIN
Unique Schema indica el nombre del propietario de la tabla
Unique Catalog indica el nombre de la base de datos a la que pertenece la tabla. Estas
dos ltimas propiedades deben tener un valor para poder poner valor a la propiedad
Unique Table. Estas propiedades son tipo String
Estas propiedades dinmicas se anexan a la coleccin Properties del objeto Recordset al
asignar el valor adUseClient a la propiedad Cursor Location.
505
Mtodo Open
Es el mtodo que ABRE el recordset. Este mtodo es el que busca los registros que han de
rellenar el recordset.
Sintaxis. Esta es la sintaxis general:
MiRecordset.Open Source, ActiveConnection, CursorType, LockType, Options
Un recordset puede abrirse partiendo de una conexin ya abierta. Pero tambin puede
crearse directamente, sin abrir previamente la conexin. Al final, deber aportar todos los
datos necesarios para determinar en que base de datos se abre ese recordset. Sobre que
tabla, consulta o sentencia SQL., que tipo de cursor va a ser, etc. Lo que ocurre es que
ADO es muy flexible y nos permite hacerlo de varias formas, aunque todas ellas conducen
a lo mismo.
Source (Opcional) Es el nombre de una tabla, consulta o sentencia SQL de la cual se
obtienen los registros del Recordset.
ActiveConnection (Opcional). Es el nombre de un objeto Connection abierto o una
cadena de conexin vlida. Esta cadena es la misma que la que emplearamos para abrir el
objeto Connection.
CursorType (Opcional). Un valor que determina el tipo de cursor que el proveedor debe
usar al abrir el Recordset. Puede ser una de las siguientes constantes
AdOpenForwardOnly
(Predeterminado) Abre un cursor de tipo slo avance.
AdOpenKeyset
Abre un cursor de tipo conjunto de claves.
AdOpenDynamic
Abre un cursor de tipo dinmico. (Igual que el Dynaset de
DAO)
AdOpenStatic
LockType (Opcional). Un valor que determina el tipo de bloqueo que debe usar el
proveedor al abrir el Recordset. Con este parmetro se le indica tambin si debe hacer las
actualizaciones registro a registro o en bloque. Puede ser una de las siguientes constantes
AdLockReadOnly (Predeterminado) Slo lectura. No puede modificar los datos.
AdLockPessimistic Bloqueo pesimista, registro a registro. El proveedor hace lo
necesario para asegurar una modificacin correcta de los
registros, normalmente
bloqueando registros en el origen
de
datos inmediatamente antes de la modificacin.
AdLockOptimistic Bloqueo optimista, registro a registro. El proveedor usa
bloqueooptimista, bloqueando registros slo cuando se llama
al
mtodo Update.
AdLockBatchOptimistic Actualizaciones optimistas por lotes. Requeridas en el
modo de actualizacin por lotes en oposicin al modo
de actualizacin inmediata. (Actualizacin en bloque)
Options (Opcional). Constante que determina como va a evaluar el proveedor de datos el
argumento Source. Puede ser una de las siguientes constantes de esta lista.
AdCmdText Indica que el proveedor debe evaluar Source como una definicin
textual de un comando.
AdCmdTable Indica que ADO debe generar una consulta SQL para devolver
todaslas filas de la tabla nombrada en Source.
AdCmdTableDirect Indica que el proveedor debe devolver todas las filas de la
tabla nombrada en Source.
507
MiRecordset.Requery Opciones
Optiones Opcional. Mscara de bits que indica opciones que afectan a esta operacin. Si el
valor de este parmetro est establecido a adAsyncExecute, esta operacin se ejecutar
de forma asncrona y se emitir un evento RecordsetChangeComplete cuando concluya.
Mtodo Resync
Actualiza los datos del objeto Recordset actual. Este mtodo, a diferencia del mtodo
Requery, no vuelve a ejecutar el comando de creacin del recordset, sino que lee los
registros existentes en el recordset para actualizar su valor, pero no presenta aquellos
registros que hubieran sido creados con posterioridad a la apertura del recordset. Es ms
rpido que el mtodo Requery, y en muchos casos solamente nos interesa actualizar los
registros sobre los que estamos trabajando.
Sintaxis
Los parmetros FieldList y Values son opcionales. En caso de ponerlos, FieldList sern los
nombres de los campos a los que se les va a poner un valor, y Values son los valores de
cada uno de estos campos. El orden nombre - valor debe mantenerse estrictamente.
Siempre recomendar que, en vez de meter los datos mediante estos parmetros, se
metan posteriormente linera a lnea, tal como se hizo siempre con los recordsets
508
NombreDelRecordset!NombredelCampo = ValorDelCampo
NombreDelRecordset(NombredelCampo) = ValorDelCampo
Esta segunda forma es necesaria cuando el nombre del campo tiene espacios. Nunca es
recomendable poner espacios en los nombres de campos, pero en caso de que existan,
debe optar por utilizar la sintaxis segunda, con los parntesis y comillas dobles.
No siempre se puede utilizar el mtodo AddNew. Puede comprobar si se puede utilizar,
usando el mtodo Supports visto anteriormente.
El mtodo AddNew convierte a este registro recin creado en registro actual. Pero este
registro solamente existe en el recordset. Para introducir los datos en la base de datos, (Y
por lo tanto en el disco duro) es necesario invocar el mtodo Update una vez introducidos
todos los valores de los campos que deseamos introducir. Con algn tipo de cursor es
necesario tambin utilizar el mtodo Requery para poder acceder al registro recin
creado.
Si se invoca el mtodo AddNew mientras se est editando el registro actual, o durante
otra operacin AddNew, ADO invoca automticamente el mtodo Update para guardar
los cambios. Vea ms adelante los mtodos Update y UpdateBatch.
Mtodo Update
Guarda los cambios realizados en el registro actual de un objeto Recordset. Se utiliza tanto
para rematar una operacin de creacin de un registro iniciada con AddNew, como para
guardar los nuevos datos del registro actual (Recuerde que en ADO no existe el mtodo
Edit, tal como ocurra en DAO)
.
Sintaxis
NombreDelRecordset.Update Fields, Values
En esta sintaxis, Fields y Values son opcionales, y solamente tienen aplicacin cuando se
trata de cambiar los valores del registro actual, no de terminar una operacin de creacin
de un nuevo registro mediante AddNew.
Vuelvo a recomendar lo anterior. Para cambiar los valores de varios campos de un registro,
nos colocaremos sobre ese registro, y sin invocar ningn mtodo, ejecutaremos este
cdigo
MiRecordset!Campo1 = Valor1
MiRecordset!Campo2 = Valor2
.
MiRecordset!CampoN = ValorN
MiRecordset.Update
Pero en ADO pasa una cosa que no pasaba en DAO. Si cambiamos de registro una vez
modificado el valor de un registro, ADO invoca automticamente el mtodo Update. Por lo
tanto, el cdigo siguiente:
MiRecordset!Campo1 = Valor1
MiRecordset!Campo2 = Valor2
.
MiRecordset!CampoN = ValorN
Tendr el mismo resultado que el anterior cuando cambiemos de registro actual. Esto
puede ser bueno a malo, pero personalmente pienso que no es prctico porque implica
tener mucho ms cuidado que en DAO. Hace lo mismo que cuando tenemos unos controles
enlazados a datos mediante un control Data.
509
MiRecordset.UpdateBatch AffectRecords
valor
Mtodo Cancel
Cancela la ejecucin del mtodo Open.
Sintaxis
NombreDelRecordset.Cancel
El mtodo Cancel solamente puede usarse si el mtodo Open fue invocado con la opcin
adAsyncConnect, adAsyncExecute o adAsyncFetch.
Mtodo Delete
Elimina el registro actual o un grupo de registros. Por defecto elimina solamente el registro
actual. Vea la ayuda para ampliar los detalles respecto al parmetro opcional
AffectRecords
Sintaxis
MiRecordset.Delete AffectRecords
Mtodo CancelUpdate
Habamos visto ms atrs que el ADO no existe el mtodo Edit. Para modificar un registro
basta con poner una instruccin tal como esta:
MiRecordset!MiCampo = MiNuevoValor
Y a continuacin rematar la operacin mediante el mtodo Update
MiRecordset.Update
Si por cualquier circunstancia se ha ejecutado la primera instruccin, y luego queremos
volvernos atrs, antes de ejecutar el mtodo Update debemos deshacer el cambio con el
mtodo CancelUpdate, con lo que el registro afectado recuperar nuevamente su valor
original.
Sintaxis
MiRecordset.CancelUpdate
510
Recuerde que ADO funciona de forma distinta a DAO con estos mtodos de modificacin de
los registros. Recuerde que si est en proceso de modificacin de un registro (Ha
ejecutado la primera lnea del ejemplo anterior) y cambia de registro, por el hecho de
cambiar de registro, ADO invoca automticamente el mtodo Update.
Mtodo CancelBatch
Cancela una actualizacin por lotes pendiente. Es similar a la anterior, pero para
actualizacin por lotes.
Sintaxis
MiRecordset.CancelBatch AffectRecords
Mtodo Clone
Crea un objeto Recordset duplicado a partir de un objeto Recordset existente.
Opcionalmente, puede especificarse que el nuevo recordset sea solamente de lectura
Sintaxis
(El objeto rstDuplicate debe estar declarado previamente como objeto ADODB.Recordset)
LockType puede tomar uno de los siguientes valores:
AdLockUnspecified (Predeterminado) El recordset resultante tendr el mismo tipo de
bloqueo que el original.
AdLockReadOnly El recordset creado es solamente de lectura.
El recordset resultante del mtodo Clone, aunque igual al original en el momento de su
creacin, es completamente independiente de este a partir de ese momento, por lo que las
actualizaciones efectuadas en el original no afectan al clonado.
Mtodo Move
Mueve la posicin del registro actual de un objeto Recordset
.
Sintaxis
MiRrecordset.Move NumRecords, Start
NumRecords
Un valor Long con signo que especifica el nmero de registros que
debe moverse a partir de la posicin del registro actual o del registro especificado en el
parmetro Start, si es que se especifica.
Start Opcional. Un String o Variant cuyo resultado sea un marcador del tipo Bookmark.
Puede utilizar tambin una de las siguientes constantes:
AdBookmarkCurrent
(Predeterminado) Cuenta a partir del registro actual
AdBookmarkFirst Cuenta a partir del primer registro
AdBookmarkLast Cuenta a partir del ltimo registro
Mtodos MoveFirst, MoveLast, MoveNext y MovePrevious
Pasa al primer, ltimo, siguiente o anterior registro de un objeto Recordset especificado y
lo convierte en el registro actual. Funciona igual que en DAO
Tenga en cuenta a la hora de usar los mtodos Move que pueden existir Recordsets que no
permiten el movimiento hacia atrs.
Mtodo Find
Busca el primer registro del recordset que satisfaga los criterios especificados en el criterio
de bsqueda. Si se cumple el criterio de bsqueda, la posicin del recordset se establece
en el primer registro encontrado; si no, la posicin se establece al final del recordset.
511
Sintaxis
criterio
Es el criterio de bsqueda. Por ejemplo Pais = Espaa siendo Pais el
nombre del campo en el cual buscamos el valor Espaa
SkipRows
(Opciopnal) Es un Long, cuyo valor predeterminado es cero, que especifica
el nmero de registros a partir del registro actual donde debe empezar la bsqueda.
searchDirection (Opcional) Un valor que especifica si la bsqueda se realiza en
direccin al final del recordset (adSearchForward) o en direccin hacia el principio del
recordset (adSearchBackward). La bsqueda termina al final o al principio del recordset,
dependiendo del valor de searchDirection.
start
(Opcional) Un marcador tipo BookMark que se utiliza como posicin inicial
de la bsqueda.
El operador de comparacin de criterio puede ser ">", "<", "=", ">=" , "<=", "<>"
(distinto de) o "like" (coincidencia parcial de cadenas). El valor de comparacin puede ser
una cadena, un nmero en coma flotante o una fecha. Los valores de cadena estn
delimitados con comillas sencillas (por ejemplo, "Pais = 'Espaa'"). Los valores de fecha
estn delimitados con signos "#" y con formato mm/dd/yy (por ejemplo, "fecha_inicial >
#7/22/97#"). Si el operador de comparacin es "like", el valor de la cadena puede
contener los caracteres comodn "*" o "_". (Funcionan de forma idntica, sustituyendo a
cualquier sucesin de caracteres.) No acepta el carcter ? (Por ejemplo, "Pais like Es_" o
Pais Like Es* encuentra Espaa y Estonia)
ADO no tiene los mtodos FindFirst, FindNext, FindPrevious y FindLast. Deber emplear el
mtodo Find de forma inteligente para implementar estos otros.
Mtodo Save
Este mtodo permite guardar el contenido de un Recordset en un fichero. Puede ser muy
til cuando queremos exportar ese recordset hacia otra aplicacin.
Sintaxis
el
AAdPersistXML
Si ya existe el fichero le dar un error. Cercirese que no existe (Mediante la funcin Dir) y
brrelo antes de volver a utilizar el mtodo Save.
512
Mtodo Seek
Este mtodo busca un registro desplazndose por el recordset a lo largo de un ndice o un
conjunto de ndices. La bsqueda mediante Seek es mucho ms rpida que con Find, ya
que la realiza siguiendo el ordenamiento de los registros segn un ndice.
Para poder usar el mtodo Index es necesario que el proveedor acepte ndices en el objeto
recordset. Esto ha llevado al autor a no poder presentar ningn ejemplo de este mtodo,
ya que todas las bases de datos ensayadas no permitan ndices. Puede ver si acepta
ndices mediante el mtodo Supports:
If MiRecordset1.Supports(adIndex) = True Then
Vea la ayuda de VB para mayor informacin
Mtodo NextRecordset
Para entender este mtodo es necesario explicar previamente como se puede crear un
recordset compuesto.
Un recordset compuesto es un recordset que se crea concatenando sentencias SELECT, y
cada una de ellas crear, dentro del mismo Recordset, un recordset particular. Al crear el
recordset, el recordset particular que va a estar activo es el correspondiente a la primera
sentencia SELECT. Mediante el mtodo NextRecordset podemos ir avanzando a travs de
los siguientes recordsets particulares. El carcter de separacin entre las sentencias
SELECT es el punto y coma ( ; )
MiRecordset1.Open "Select * From Regimenes; Select * From Regimen_Seguimiento
Where Rs_Origen = 'LSB'", MiConexionADO, adOpenDynamic, adLockOptimistic
(La instruccin anterior debe leerse como una sola lnea)
MiRecordset es un recordset compuesto. Toma datos de dos tablas distintas, pero podra
haberlo hecho solamente de una tabla con una condicin distinta en la SELECT.
Cuando se ejecuta esa lnea, el recordset actual es el correspondiente a la primera
seleccin. (Select * From Regimenes). Ejecutando el mtodo NextRecordset ese recordset
primero se borra y pasa a ser recordset actual el creado con la seleccin segunda (Select *
From Regimen_Seguimiento Where Rs_Origen = 'LSB'")
Set MiRecordset1 = MiRecordset1.NextRecordset
Puede usar tambin este recordset para crear un nuevo recordset a partir del primero
Set MiRecordset2 = MiRecordset1.NextRecordset
MiRecordset2 debe estar declarado como objeto recordset, y creado con la instruccin
New:
Set MiRecordset2 = New ADOBD.Recodset
513
Un objeto Recordset tiene una coleccin Fields que contiene todos los objetos Field.
Cada objeto Field se corresponde a una columna del Recordset.
Vamos a ver aqu un truco que nos permite ADO. Podemos crear un recordset Sin
necesidad de una base de datos!
Cuando estudiamos el objeto recordset vimos que el recordset se crea con una instruccin
como esta:
Set MiRecordset1 = New ADODB.Recordset
Ahora ya podemos abrir el recordset leyendo los datos desde una base de datos.
Utilizamos para ello el mtodo Open del recordset:
MiRecordset1.Open "Select * From Regimenes", MiConexionADO, adOpenDynamic,
adLockOptimistic
Mediante el mtodo Open lo que hace el recordset es conocer su estructura (Que campos
tiene, propiedades de estos campos, etc) y el valor de cada uno de los campos de sus
registros. Qu pasara si en vez de abrir el recordset le vamos aadiendo objetos Field a
su coleccin Fields? Lo hacemos mediante el mtodo Append:
MiRecordset1.Fields.Append "MiCampo1", adBigInt
MiRecordset1.Fields.Append "MiCampo2", adChar, 25
MiRecordset1.Fields.Append "MiCampo3", adBSTR
Lo que ocurre es que el recordset ya tiene tres campos, el primero de nombre MiCampo1,
numrico Long, el segundo, un string de 25 caracteres de nombre MiCampo2, y el tercero,
de nombre MiCampo3, una cadena de caracteres de longitud indefinida, terminada en un
carcter nulo. Ya tenemos una estructura de un recordset sin necesidad de haber ledo la
base de datos. No es necesario por lo tanto que exista una tabla o consulta almacenada
con esa estructura. Ahora podemos abrir el recordset:
MiRecordset1.Open
Lo abrimos sin pasarle ningn parmetro. Ahora ya est abierto y podemos trabajar con el
como con un recordset cualquiera. Recuerde que al principio est vaco.
MiRecordset1.AddNew
MiRecordset1!MiCampo1 = 34
MiRecordset1!MiCampo2 = "Gua del Estudiante"
MiRecordset1!MiCampo3 = "Hola mi amor" & vbCrLf & "Yo soy tu lobo"
MiRecordset1.Update
Ya tenemos un registro dentro del recordset. Podemos introducirle tantos registros como
queramos, y luego movernos por el recordset mediante los mtodos Movexxxx. Ahora
podremos leer el contenido del registro actual:
Label1 = MiRecordset1!MiCampo1
Label2 = MiRecordset1!MiCampo2
Label3 = MiRecordset1!MiCampo3
El resultado del cdigo de el ejemplo se traducir en algo como esto:
514
Y ahora vienen lo mejor. Para que queremos un recordset que no tienen datos ledos
desde una base de datos? Las aplicaciones de esto solamente est limitadas por la
imaginacin. Pienso, por ejemplo, en introducir en un recordset todos los datos ledos de
un fichero de configuracin, y as tener todos esos datos disponibles durante toda la
aplicacin, en vez de en variables, como
MiRecordset!MiDato1
Es una idea, pero piense que esto no regala nada. El espacio de memoria consumido ser
similar a si usa variables. Pero posiblemente estar ms cmodo y ms inteligible su
cdigo.
Veamos los mtodos de la coleccin Fields
Mtodo Append
Agrega un campo a una coleccin Fields de un Recoprdset.
Sintaxis
Name Un String con el nombre del nuevo objeto Field, que tiene que ser nico dentro de
la coleccn Fields.
Type Tipo de datos que va a contener ese campo. Puede tomar uno de estos valores:
adArray
adBigInt
adBinary
adBoolean
adByRef
adBSTR
adChar
adCurrency
adDate
adDBDate
adDBTime
adDBTimeStamp
adDecimal
adDouble
adEmpty
adError
adGUID
adIDispatch
adInteger
adIUnknown
adLongVarBinary
adLongVarChar
adLongVarWChar
adNumeric
adSingle
adSmallInt
adTinyInt
adUnsignedBigInt
adUnsignedInt
adUnsignedSmallInt
adUnsignedTinyInt
adUserDefined
adVarBinary
adVarChar
adVariant
adVector
adVarWChar
adWChar
DefinedSize Un Long que define el tamao del campo si fuese necesario. (Por ejemplo
para un string)
Attrib
valores:
(Opcional). Especifica los atributos del campo a aadir. Puede tomar estos
adFldMayDefer
adFldUpdatable
adFldUnknownUpdatab
le
adFldFixed
adFldIsNullable
adFldMayBeNull
adFldLong
adFldRowID
adFldRowVersion
adFldCacheDeferred
nico, etc.).
Indica que el campo contiene algn tipo de marca de hora o
de fecha que se utiliza para efectuar actualizaciones.
Indica que el proveedor almacena los valores del campo en la
memoria cach y que las lecturas siguientes se efectan en
dicha memoria .
Mtodo Delete
Tericamente elimina un objeto de la coleccin Fields.
Sintaxis
Fields.Delete Field
Field
Un Variant que designa el objeto Field que se va a eliminar. Este parmetro
tiene que ser el nombre del objeto Field; no puede ser una posicin ordinal o el propio
objeto Field.
Comentarios
La llamada al mtodo Fields.Delete en un Recordset abierto provoca un error de
ejecucin.
(Como ha ocurrido en otras ocasiones, al autor le ha sido imposible ejecutar este mtodo
con los resultados esperados)
Mtodo Item
Sintaxis
MiRecordset.Fields.Item (Index)
517
518
El Objeto Command
Un objeto Command es la definicin de un comando especfico que se piensa ejecutar
contra un origen de datos. Mediante un objeto Command podemos crear un recordset,
pero recuerde que un recordset lo podemos tambin crear directamente.
Utilice un objeto Command para consultar una base de datos y obtener registros en un
objeto Recordset, para aadir o eliminar registros, ejecutar una operacin de manejo
masivo de datos o para manipular la estructura de una base de datos.
Propiedades del Objeto Command
Propiedad ActiveConnection
Indica a qu objeto Connection pertenece actualmente el objeto Command. Es un string
con el nombre de la conexin.
Propiedad CommandText
Contiene el texto del comando que se quiere emitir al proveedor. Es un string. Suele ser
una instruccin SQL, un nombre de tabla o un procedimiento almacenado, o cualquier otra
instruccin que reconozca el proveedor. El valor predeterminado es una cadena vaca.
Propiedad CommandTimeout
Especifica el intervalo de espera para que se ejecute un comando antes de que finalice el
intento y se genere un error. Es un Long que indica en segundos ese tiempo. El valor
predeterminado es 30.
Propiedad CommandType(IMPORTANTE)
Indica el tipo de un objeto Command. Esta propiedad se usa para optimizar la evaluacin
de la propiedad CommandText, ya que de esta forma el proveedor no tiene que perder
tiempo examinando si es una instruccin SQL, un procedimiento almacenado o un nombre
de tabla. Si el valor de esta propiedad es adCmdUnknown (valor predeterminado),
estamos forzando al proveedor a que realice esa investigacin lo que provocar
probablemente un descenso en su rendimiento. Si sabe qu tipo de comando est usando,
el establecimiento de la propiedad CommandType instruye a ADO a que vaya
directamente al cdigo relevante. Si la propiedad CommandType no coincide con el tipo
de comando de la propiedad CommandText, ocurre un error cuando llama al mtodo
Execute.
Valores posibles
AdCmdText
un
AdCmdTable
AdCmdFile
519
AdExecuteNoRecords
Indica que es un comando o un procedimiento almacenado
que no devuelve filas (por ejemplo, un comando que slo inserta datos). Si se recupera
alguna fila, se descarta y no se devuelve. Siempre se combina con adCmdText o
adCmdStoredProc.
Propiedad Prepared
Es un Booleano que indica si se debe guardar una versin compilada de un comando antes
de su ejecucin. Esta propiedad fuerza al proveedor a guardar una versin preparada
(compilada) de la consulta especificada en la propiedad CommandText antes de la primera
ejecucin de un objeto Command. Esto puede disminuir el rendimiento de la primera
ejecucin de un comando, pero cuando el proveedor haya compilado el comando, utilizar
la versin compilada del mismo para las ejecuciones siguientes, lo cual aumentar el
rendimiento.
Si el proveedor no admite la preparacin del comando, puede devolver un error cuando
esta propiedad se establezca a True. Si no devuelve un error, simplemente ignora la
solicitud de preparar el comando y establece la propiedad Prepared a False.
Propiedad State
Describe el estado del objeto: abierto o cerrado. Devuelve un Long o una constante:
adStateClosed o adStateOpen
Mtodos del Objeto Command
Mtodo Execute (IMPORTANTE, ms bien diramos, el objetivo del Command)
Ejecuta la consulta, la instruccin SQL o el procedimiento almacenado especificado en la
propiedad CommandText. Devuelve un recordset o modifica la base de datos.
Sintaxis
Para un Command que devuelva filas:
Set recordset = command.Execute(RecordsAffected, Parameters, Options)
Para un Command que no devuelva filas:
command.Execute RecordsAffected, Parameters, Options
command es el nombre del Objeto Command
RecordsAffected Opcional. Una variable Long en la que el proveedor devuelve el nmero
de registros afectados por la operacin.
Parameters Opcional. Una matriz Variant con los valores de los parmetros pasados con
una instruccin SQL. (Los parmetros de salida no devuelven valores correctos cuando se
pasan en este argumento).
Options Opcional. Un valor Long o una constante. Acepta estos valores
adCmdText
adCmdTable
devolver
CommandText.
adCmdTableDirect Indica que el proveedor tiene que devolver todas las filas de la tabla
mencionada en CommandText.
AdCmdStoredProc Indica que el proveedor tiene que evaluar CommandText como
procedimiento almacenado.
520
adCmdUnknown
adAsyncExecute
adAsyncFetch
especificada en la
forma asncrona.
Mtodo Cancel
Cancela la ejecucin de una llamada asncrona pendiente al mtodo Execute
Sintaxis
NombredelObjetoCommand.Cancel
Utilice el mtodo Cancel para terminar la ejecucin de una llamada asncrona a un mtodo
Execute (es decir, el mtodo fue invocado con la opcin adAsyncExecute o
adAsyncFetch).
Comandos parametrizados.
Los objetos Command pueden utilizar parmetros. De esta forma, podemos construir una
consulta utilizando la interrogacin (?) como comodn. As cada vez que ejecutemos el
comando, V.B. se encargar de sustituir el comodn por los parmetros asociados a dicho
command. Adems podemos utilizar los parmetros para recoger los valores devueltos
por un Procedimiento almacenado en la base de datos. Para entender mejor este tipo de
consultas primero veremos qu es el objeto parameter.
Ejemplo de la utilizacin de Command
Veamos un ejemplo de cmo usar el Objeto Command. Pero previamente vamos a ver un
cdigo del que hemos partido para hacer ver al alumno que ADO permite hacer las cosas
de muchas maneras. Este cdigo mete los datos de un documento en una base de datos
Oracle, leyendo previamente el nmero ms alto del documento para poner al nuevo
documento un nmero igual al ltimo + 1.:
Declaraciones
Dim ConexBDPrensa As ADODB.Connection
Dim RsBDPrensa1 As ADODB.Recordset
Dim StrIntroducir As String, NumeroDocumento as long
Rem Se abre un objeto Connection para crear sobre l el recordset
Set ConexBDPrensa = New ADODB.Connection
ConexBDPrensa.ConnectionString = "Provider=MSDAORA.1; & _
User ID=INTRANET;Password=INTRANET;Data Source=intranet; & _
Persist Security Info=False"
ConexBDPrensa.Open
Rem Se abre un recordset para leer el nmero, se lee y se vuelve a cerrar
RsBDPrensa1.Open
"Int_Documentos
Order
By
CL_DOC",
ConexBDPrensa,
adOpenDynamic, adLockOptimistic
RsBDPrensa1.MoveLast
NumeroDocumento = RsBDPrensa1!CL_DOC
NumeroDocumento = NumeroDocumento + 1
RsBDPrensa1.Close
(* Este es el punto donde cambia el cdigo que ver ms adelante)
521
Rem Se introduce en una variable tipo String una instruccin para aadir un nuevo
registro
Rem Esa instruccin se va a ejecutar desde el objeto Connection mediante su mtodo
Execute
StrIntroducir = "Insert Into INT_DOCUMENTOS " & _
"(CL_DOC,NOM_DOC,TITULO_DOC,AUTOR_DOC,CL_TEMA_DOC,CL_DPT_DOC, & _
CL_TIPO_DOC,FICH_DOC,FECHA_EMISION_DOC,ULTIMA_HORA_DOC, & _
VISIBLE_DOC) Values (" & NumeroDocumento & ",'" & TbTitulo & "','" & TbTitulo & _
"','" & TbTitulo.Tag & "',19,2,1,'" & HRefPrensa & "/" & TbNombFichTIF & "','" & Date &
"',0,1)"
Rem Observe que los valores tipo string introducidos (TbXXX) van entre comilla simple
Rem Se ejecuta esa instruccin desde el objeto Connection ConexBDPrensa
ConexBDPrensa.Execute StrIntroducir
Rem Se cierra el Objeto Connection
ConexBDPrensa.Close
Rem Aqu termina la operacin de crear un nuevo registro
MsgBox "Documento enviado"
Este es el cdigo real de una aplicacin que introduce los datos el resumen de prensa
diario en una base de datos. Se introduce un nuevo registro en la tabla
INT_DOCUMENTOS. El resumen de prensa es un fichero .Tiff de nombre TbNombFichTIF
que se mete en una carpeta del servidor mediante FTP, y para su loccalizacin y
presentacin en una pgina Web es necesario introducir su nombre y Path y otros datos en
una base de datos. Los campos que se introducen y los valores de cada uno son:
Campo
Valor
CL_DOC,
NOM_DOC
TITULO_DOC
AUTOR_DOC
CL_TEMA_DOC
CL_DPT_DOC
CL_TIPO_DOC
FICH_DOC
RsBDPrensa!ULTIMA_HORA_DOC = 0
Rematamos con el mtodo Update
RsBDPrensa.Update
Cerramos el recordset.
RsBDPrensa.Close
Cerramos la conexin
ConexBDPrensa.Close
Nota 1. Muchos programadores se rinden cuando ven que no les funciona los mtodos
AddNew / Update para introducir nuevos datos. Cierto es que cada base de datos se
comporta de forma distinta respecto a este mtodo. Pero antes de rendirse y usar el
cdigo a capn intente ver como tienen la propiedad CursorLocation, el tipo de recordset
abierto y el tipo de bloque elegido (Recuerde que por defecto es de solo lectura). Eso s,
el mtodo a capn funciona siempre (Excepto que sea solo lectura), independientemente
del bloqueo y del tipo de cursor
524
Hagamos un repaso de sus propiedades. Veremos solamente aquellas que son especficas
de ADO:
Propiedad BOFAction.
Establece la forma de proceder cuando llega a la fila anterior a la primera. Toma uno de
estos valores:
0 adDoMoveFirst
1 adDoStayBOF
Propiedad CommandType
Es idntica a la misma propiedad del objeto Command. Acepta los valores:
AdCmdText
un
AdCmdTable
Propiedad ConnectionString
Esta propiedad ya le hemos visto ms atrs. Es la cadena de conexin con la base de
datos.
Propiedad CursorLocation
Es la misma que la vista para el objeto Recordset.
Propiedad CursorType
Es la misma que para el objeto Recordset. Acepta los valores:
1 adOpenKeyset
2 - adOpenDynamic
525
3 adOpenStatic
Propiedad EOFAction
Establece la forma de proceder cuando llega a la fila EOF. Acepta los valores:
0 adDoMoveLast
1 adStayEOF
2 adDoAddNew
Propiedad LockType
Tipo de Bloque. Igual a la misma propiedad del Objeto Recordset
Propiedad MaxRecords
Es similar a la del Objeto Recordset. Establece el nmero de filas que obtiene en su
recordset asociado.
Propiedad Mode.
Igual a la misma propiedad del objeto Recordset
Propiedades Password
Establece la contrasea para crear la cadena de conexin durante la creacin del objeto
Recordset asociado. Esta contrasea es la contrasea del usuario en la base de datos.
Esta propiedad es solamente de escritura. Si se pretende leer da error.
Propiedad UserName
Establece el nombre del usuario. Debe ser uno de los usuarios registrados en la base de
datos. Esta propiedad es de lectura y escritura. El valor de la propiedad Password debe ser
el asociado a este usuario.
Propiedad RecordSource
Es una cadena de caracteres con el nombre de una tabla o una sentencia SQL que
devuelve filas.
Mtodos del control Adodc
UpdateControls
Actualiza la informacin de los controles enlazados a datos.
UpdateRecords.
No existe el mtodo
Refresh
Vuelve a construir el recordset. Es idntico al del control Data de DAO.
Vistas ya las propiedades y mtodos del control Adodc, vamos a ver un poco como
funciona y cuales son sus diferencias con el control data de DAO
Funcionamiento del Adodc
El Adodc puede enlazar una base de datos a los tpicos controles enlazados (Label,
TextBox) usando la tecnologa ADO. Los dems controles enlazados no tienen un
comportamiento igual con el Adodc, Control Data o RDODataControl. En la siguiente lista
puede ver que controles trabajan con uno u otro control Data.
526
Control
DBGrid
DataGrid
DataList
DataCombo
DBList
DBCombo
MSFlexGrid
MSHFlexGrid
NO
SI
SI
SI
SI
SI
NO
SI
ADO
RDO
DAO
Referencia
SI
NO
SI
SI
SI
SI
SI
NO
SI
NO
SI
SI
SI
SI
SI
NO
Microsoft
Microsoft
Microsoft
Microsoft
Microsoft
Microsoft
Microsoft
Microsoft
527
En la base de datos es necesario introducir los nombres de usuario que estn permitidos, y
la clave de acceso para cada usuario. Lgicamente para que un puesto pueda acceder a la
BD debe conocer su nombre de usuario y la clave de acceso. Estos datos normalmente se
introducen en el cliente en su configuracin, y no es necesario teclearlas cada vez que se
inicia una sesin.
La configuracin del sistema de la base de datos es la de cliente - servidor.
El servidor tiene un programa que es el Gestor de la Base de Datos. La base de datos
propiamente dicha estar formada por uno o ms ficheros con los datos que tienen
introducidos y la estructura de tablas, consultas e ndices que tenga. El programa gestor es
quien controla estos ficheros y puede obtener de ellos los datos en una forma adecuada.
El cliente necesita tener un programa que ser el que se comunique con el programa
gestor que est en el servidor. Este programa lo realiza el mismo fabricante de la base de
datos y se distribuye en el mismo disco que el programa servidor y el resto del sistema. A
esta parte de la aplicacin cliente servidor que se instala en cada cliente se le llama
Componentes de Conectividad. Y la misin de estos componentes de conectividad es
servir de intermediario entre el gestor de la base de datos instalado en el servidor, y el
programa que en el equipo cliente va a manejar los datos de esa base de datos. Este
programa que va a manejar los datos puede ser el Administrador Corporativo de SQL
Server, el Developper 2000 de Oracle, o una aplicacin realizada por nosotros en Visual
Basic. Pero el funcionamiento es siempre el mismo, el programa que va a manejar los
datos en el cliente conecta con el programa Componentes de Conectividad y es este
quien conecta con el Gestor de la Base de Datos para que realice la operacin que tenga
que realizar y le devuelva, si ha lugar, la informacin extrada de la base de datos. Por lo
tanto para poder trabajar desde un cliente con la base de datos, es necesario que en el
servidor est corriendo el programa gestor de la base de datos, y en el cliente, que estn
instalados los componentes de conectividad.
Los componentes de conectividad, tal como se dijo ms atrs, estn fabricados por el
mismo fabricante de la BD, pero no se extrae si encuentra algn programa fabricado por
otro fabricante. Para Oracle hay varios fabricantes que han realizado un producto de este
tipo. No es difcil, ya que al tratarse de una aplicacin cliente servidor, lo nico
importante es el protocolo de comunicacin entre el programa gestor de la BD y los
componentes de conectividad. Vea el capitulo correspondiente a aplicaciones cliente
servidor para ms detalles.
Instalacin de los componentes de conectividad para SQL Server
Para instalar los componentes de conectividad de SQL Server en un puesto cliente basta
con introducir el disco de distribucin de SQL Server y dejar que se ejecute el Autorun.
Se le indica que instale el servidor de bases de datos. Al darse cuenta que no tiene
Windows 2000, dice que no puede instalar ms que los componentes del cliente.
Deje que siga la instalacin aceptando todos los avisos que se produzcan. Llegar a esta
ventana:
528
SQL Server tiene dos discos, Standard y Profesional. El Profesional le permite hacer
instalaciones en equipos remotos, y en ese caso estara la opcin Equipo Remoto
habilitada. No es nuestro caso, ya que solamente debemos instalar en el equipo local. Siga
la instalacin en la que en sucesivas ventanas le aparecer la opcin: Crear una nueva
instancia de SQL Server o instalar herramientas de cliente. Acepte esa opcin. A
530
van
apareciendo
sucesivas ventanas en
una
le
pide
directorio
quiere
el
donde
instalar
el
programa, en otra le
pide
permiso
para
531
La parte que afecta a la aplicacin en la que me conecto con Oracle es la que comienza por
la linea:
Intranet.world =
Los datos son reales. Pero he de manifestar que no conozco Oracle tan bien como para
explicarlo, y que la instalacin la hizo personal de una distribuidora de Oracle. De cualquier
forma puede verse que est definiendo la conexin Intranet , que tienen el Host en la
direccin 10.3.22.4 y el puerto de comunicacin es el 1521, con una segunda alternativa
en el puerto 1526.
Le recomiendo que si su caso es una conexin a Oracle se informe mejor de la
configuracin de sus clientes. Es de suponer que los tcnicos de Oracle le resuelvan las
grandes dudas que le pueden surgir por las escasa explicaciones de este cursode Visual
Basic.
Visual Basic con el que se escribi estas lneas para crear una conexin ADO con esa base
de datos:
Set ConexBDPrensa = New ADODB.Connection
ConexBDPrensa.ConnectionString = "Provider=MSDAORA.1;User ID=INTRANET; & _
Password=INTRANET;Data Source=intranet;Persist Security Info=False"
ConexBDPrensa.Open
El parmetro Data Source=intranet es el que emplea la conectividad de Oracle para
buscar en el fichero TNSNAMES.ORA la direccin del Host y el puerto empleado.
Puede darse cuenta que tanto en SQL Server como en Oracle estamos empleando
conexiones ADO. Podra hacerse tambin mediante RDO, creando un enlace ODBC (Para
poder crear ese enlace ODBC tambin es necesario instalar previamente la conectividad).
Pero ODBC es una tecnologa que ya est considerada obsoleta, por lo que prescindimos de
cualquier ejemplo.
Se sale necesariamente de este curso una explicacin ms profunda de estas dos bases de
datos.
Visual Basic - Gua del Estudiante Cap. 16
CONTROLES AVANZADOS DE VISUAL BASIC
Este captulo pretende ampliar el conocimiento de ciertos controles introducidos con la
versin 6 de VB, que, aunque ya son de uso habitual en cualquier aplicacin, se salen un
poco de los conceptos estudiados en los controles de los captulos 1 y 2. Vienen
generalmente como un paquete OCX que contiene varios de ellos.
Se estudian algunos de los paquetes distribuidos por Microsoft, sean o no fabricados por
esta compaa. Sera interminable comentar los paquetes realizados por casas
especializadas, controles de gran calidad, normalmente caros y para aplicaciones
especficas dentro del mbito comercial en el que se mueve la empresa que lo realiza.
Existen tambin gran cantidad de controles realizados por particulares, con la mejor
intencin, que se pueden encontrar en Internet distribuidos de forma gratuita. Son
desaconsejables. No porque no funcionen, sino simplemente porque no ofrecen ningn tipo
de garanta, estn normalmente sin informacin de funcionamiento, y en caso de
533
problemas no se puede recurrir a nadie para resolverlos. Una aplicacin profesional nunca
deber llevar un control shareware.
Paquete MSCOMCTL.OCX
Este paquete se denomina Microsoft Windows Common Controls 6.0
siguientes controles:
TabStrip
Contiene los
Fig. 16.1
ToolBar
StatusBar
534
ImageList
TreeView
ListView
Es un control que permite presentar datos en una lista, utilizando para ello
grficos y texto, con cuatro disposiciones distintas.
ImageCombo
Es como un combo convencional, pero en este se pueden insertar
tambin grficos y hacer sangras independientes para cada elemento.
Estos cuatro ltimos controles se explican a continuacin con detalle.
Control ImageList
Es un almacn de imgenes. Se representa en la caja de herramientas
esta forma:
de
Fig. 16.6
535
truco es la nica solucin para poder poner iconos grandes o pequeos en el TreeView.
Para cambiar el tamao es necesario que el ImageList no tenga cargada an ninguna
imagen.
Fig. 16.8 Pestaa de Imgenes
En esta se pueden introducir las imgenes que vamos a utilizar en los controles que tengan
asociado este ImageList. Es importante citar la propiedad Key de cada imagen, que sirve
para elegir la imagen. Una imagen de un ImageList se puede elegir mediante su ndice (El
ndice va de 1 a n, siendo n el nmero de imgenes), pero eso puede llevarnos a error, ya
que dice muy poco el nmero de la imagen dentro del ImageList, adems de que ese
nmero puede variar si introducimos posteriormente una imagen nueva en una posicin
central. Podemos utilizar para definir la imagen el texto que introduzcamos en la propiedad
Key. Por ejemplo, en la figura anterior, la imagen que presenta una interrogacin tiene el
valor Question, valor que expresa de forma inconfundible el contenido de esa imagen, y
que es inalterable sea cual sea la posicin que ocupa esa imagen en el ImageList. De esta
forma, para poner esa imagen en el nodo nmero 1 del TreeView1 basta con poner:
TreeView1.Nodes(1).Image = "Question"
Otras propiedades y mtodos del control ImageList
536
ImageList.MaskColor = color
Donde Indice1 e Indice2 son la propiedad Index o la propiedad Key de la imagen que se va
a superponer (Indice1) y de la imagen sobre la que se va a superponer la primera
(Indice2). Control es un control capaz de contener una imagen (Picture, Image,
Formulario)
Antes de utilizar el mtodo Overlay deberemos poner un valor a la propiedad MaskColor.
(La transparencia de un color solamente va a funcionar cuando vamos a superponer dos
imgenes en formato BMP)
Control TreeView.
537
Es un control que permite presentar datos que estn estructurados de forma jerrquica.
Los datos se pueden presentar como un texto, acompaados de un icono que determina el
tipo de dato. Puede por ejemplo presentar el organigrama de una empresa, mostrando los
departamentos
que
la
componen, y dentro de
estos, las personas que
pertenecen
departamento,
cada
cada
y
para
persona,
su
domicilio,
todos
ellos,
representados
con
un
un
icono
despliegan
se
los
elementos que existen bajo ese icono. Volviendo a hacer doble clic, se ocultan. Es lo ms
parecido al funcionamiento del explorador de Windows.
Fig. 16.9 TreeView mostrando seis nodos, a la izquierda con iconos grandes y a la derecha
con iconos pequeos.
La vista de la Fig. 16.9 nos lleva a la primera idea acerca del TreeView: los Nodos.
cualquier estructura jerrquica,
En
pueden depender otros elementos. Esto nos lleva al concepto de Nodo. En el TreeView los
datos se presentan mediante nodos. El conjunto de todos los nodos es la coleccin Nodes.
Esta coleccin como cualquier coleccin en visual basic tiene sus propiedades y mtodos.
538
Para empezar, la coleccin Nodes tiene el mtodo Add. De esta forma ya podemos
introducir nodos en el TreeView. Tambin tienen los mtodo Remove, para eliminar uno de
los nodos, y Clear, para eliminar todos los nodos del TreeView.
El TreeView tiene varios estilos de presentacin. Puede presentar los datos solamente con
textos,
con texto y un icono, con un signo + para indicar que ese nodo tiene
elementos bajo l, puede tener lneas o no. El estilo de presentacin lo elegimos mediante
la propiedad Style del TreeView.
Propiedad Style.
Determina el estilo de presentacin del TreeView. Es de lectura y escritura
Sintaxis
NombredelTreeView.Style = Nmero
Nmero = NombredelTreeView.Style
(Establece el estilo)
(Devuelve el estilo)
+/-
imagen y texto
4 = Lneas y texto
(RelativoA,
Imagen2)
Donde:
539
TipodeRelacion,
Key,
Texto,
Imagen1,
nodo indicado en el parmetro RelativoA. Vea ms abajo los valores aceptados en este
parmetro.
Key es una cadena de caracteres que define a este nodo. Esta cadena de caracteres debe
ser nica, es decir, no se puede repetir en dos o ms nodos.
Valor
Descripcin
TvwFirst
TvwLast
se
agregan
secuencialmente
se
irn
situando
detrs
del
ltimo
agregado.
TvwNext
especificado en RelativoA.
TvwPrevious 3
TvwChild
nodoespecificado en RelativoA.
El Index de la coleccin Nodes comienza a numerar por el 1. Cada vez que se aade un
nodo, el Index de ese nodo ser el Index del ltimo + 1, independientemente de la
posicin que va a ocupar ese nodo dentro del TreeView. No controlamos directamente esta
propiedad. Por eso, es mucho ms prctico definir a los nodos mediante su propiedad Key.
540
Ya estamos en condiciones de rellenar un TreeView con varios nodos. El cdigo para colocar
los nodos de la figura 16.9 es: (El nombre del TreeView es TreeV1)
Dim MiNodo As Node Declaramos la variable tipo Node
TreeV1.Style = 7
Y la
541
Fig. 16.10
Propiedades de la coleccin Nodes del TreeView
Propiedad ExpandedImage
Establece la imagen del nodo cuando est expandido, es decir, cuando se ven los nodos
que dependen de l. Es la propiedad Index o Key que tiene esa imagen en el control
ImageList asociado al TreeView.
Sintaxis
NombredelTreeView.Nodes(Index).ExpandedImage = Valor
Donde Valor puede ser, o bien el Index o el Key de la imagen en el ImageList asociado al
TreeView.
Propiedad Expanded
Devuelve o establece un valor que determina si un objeto Node de un control TreeView
se encuentra expandido o contrado. Es una propiedad Booleana
Sintaxis
NombredelTreeView.Nodes(Index).Expanded = True/False
Esta propiedad puede usarse para expandir por programa un objeto Node. Si un objeto
Node no tiene nodos secundarios, el valor de esta propiedad se pasa por alto.
Propiedad Children
Devuelve el nmero de objetos Node secundarios contenidos en un objeto Node. Esta
propiedad es solamente de lectura.
Sintaxis
VariableNumerica = NombredelTreeView.Nodes(Index).Children
Propiedad FullPath
Devuelve la ruta completa de un objeto Node. El valor devuelto es una cadena de
caracteres que es el resultado de concatenar el texto de la propiedad Text del objeto
Node referenciado con los valores de las propiedades Text de todos sus predecesores. El
valor de la propiedad PathSeparator del TreeView determina el delimitador utilizado para
separar el Text de uno y otro nodo.
Sintaxis
NombredelTreeView.Nodes(Index).FullPath
Esta propiedad puede usarse en el procedimiento NodeClick del TreeView, que ya pasa
como parmetro el nodo sobre el que hemos hecho click:
Private Sub TreeV1_NodeClick(ByVal Node As MSComctlLib.Node)
VariableTipoString = Node.FullPath
End Sub
Propiedad Count
Devuelve el nmero de elementos de la coleccin Nodes
Sintaxis
VariableNumerica = NombredelTreeView.Nodes.Count
Propiedad Key
Esta propiedad establece o devuelve una cadena de caracteres que identifica unvocamente
a un nodo. Esta propiedad se le asigna normalmente durante la creacin de ese nodo
mediante el mtodo Add, pero puede cambiarse posteriormente por programa.
La propiedad Key puede usarse para nombrar al nodo, al tratarse de una cadena nica. No
puede haber dos nodos con el mismo Key. Si la cadena no es nica, se produce un error.
Sintaxis
NombredelTreeView.Nodes(Index).Key = cadena
NombredelTreeView.Nodes(Index).Image= Valor
Propiedad SelectedImage
Es lo mismo que la propiedad anterior, pero en este caso se establece la imagen que
presenta el nodo cuando est seleccionado.
Recuerde que estas propiedades son de la coleccin Nodes del TreeView. Veremos ahora
las propiedades del TreeView.
Propiedades del Control TreeView
Ya se han visto algunas ms atrs. Se comentan solamente aquellas propiedades que no
son comunes al resto de los controles.
Propiedad Checkboxes
Establece si se muestran las casillas de verificacin. (True/False)
Sintaxis
NombredelTreeView.Checkboxes = True/False
543
Y a continuacin se aaden los nodos mediante el mtodo Add. Si quiere cambiar los
iconos durante la ejecucin del programa (es muy tpico colocar en una lnea del men el
tipo de iconos a presentar) observar que al cambiar el ImageList desaparecen los iconos.
No hay otro remedio ms que volver a cargarlos, usando los mtodos de la coleccin
Nodes Clear (para vaciarla) y Add. Este es el cdigo que he usado en el ejemplo que
ilustra este captulo:
Set TreeV1.ImageList = ImageList2
TreeV1.Nodes.Clear
cmdIntroducirNodos_Click (cmdIntroducirNodos es un botn con el cdigo para aadir los
nodos)
Propiedad Indentation
Establece el ancho de la sangra de los nodos. Afecta a todos los niveles de nodos. Puede
cambiarse en tiempo de ejecucin.
Propiedad LabelEdit
Devuelve o establece un valor que determina si el usuario puede modificar la propiedad
Text de los objetos Node de un control TreeView.
544
Sintaxis
NombredelTreeView.LabelEdit = entero
Valor
0
etiqueta de
TvwManual
Descripcin
Predeterminado) Automtico. Se genera el evento
BeforeLabelEdit cuando el usuario hace clic en la
un nodo seleccionado.
Manual. El evento BeforeLabelEdit slo se genera al invocar el
mtodo StartLabelEdit.
NombredelTreeView.LineStyle = nmero
Acepta los valores 0 (tvwTreeLines) con lo que presentar solamente las lneas entre los
nodos de un mismo nivel y su nodo primario, y 1 (tvwRootLines) que presenta, adems de
las anteriores, lneas entre los nodos raiz.
Propiedad Nodes
Devuelve una referencia a la coleccin de objetos Node de un control TreeView
Parent (Propiedad)
Devuelve una referencia al formulario que contiene un control u otro objeto o coleccin.
Propiedad PathSeparator
Establece el carcter delimitador utilizado en la ruta devuelta por la propiedad FullPath. El
carcter predeterminado es "\".
Scroll (Propiedad)
Devuelve o establece un valor que especifica si se muestran barras de desplazamiento.
SelectedItem (Propiedad, controles ActiveX)
Devuelve la referencia al objeto Node seleccionado.
Propiedad SingleSel
Establece si un nodo debe expandirse cuando se selecciona. Un nodo, con otros nodos
dependiendo de l, se expande al hacer doble clic sobre l, o al hacer clic sobre el +
asociado a ese nodo. Se contrae volviendo a realizar la misma operacin. Si esta
propiedad est a True, se expande o contrae cuando se hace clic sobre l.
Propiedad Sorted
Ya explicada para la coleccin Nodes.
545
Mtodo GetVisibleCount
Devuelve el nmero de objetos Node que caben en el rea interna de un control
TreeView.
El nmero de objetos Node viene determinado por la cantidad de lneas que caben en una
ventana. El nmero total de lneas posibles lo determina el alto del control y la propiedad
Size del objeto Font. En este nmero se cuenta el elemento situado al final de la lista y
que slo es visible parcialmente.
Puede usar la propiedad GetVisibleCount para asegurarse de que es visible un nmero
mnimo de lneas que permita al usuario hacerse una idea de la jerarqua. Si no es visible
este mnimo, puede restablecer el tamao del control TreeView mediante la propiedad
Height. Si un determinado objeto Node debe ser visible, utilice el mtodo EnsureVisible
para desplazar y expandir el control TreeView.
Mtodo HitTest
Devuelve la referencia del objeto Node situado en las coordenadas x e y. Se utiliza sobre
todo en las operaciones de arrastrar y colocar para determinar si hay disponible en la
ubicacin actual un elemento de destino de colocacin. Si no hay ningn objeto en las
coordenadas especificadas, el mtodo HitTest devuelve Nothing.
El mtodo HitTest se utiliza casi siempre junto con la propiedad DropHighlight para
resaltar un objeto cuando se arrastra el mouse sobre l durante una operacin de Drag &
Drop. La propiedad DropHighlight requiere una referencia a un objeto especfico para
resaltarlo. Para determinar el objeto, se usa el mtodo HitTest junto con un evento que
devuelva las coordenadas x e y, como DragOver, con el siguiente cdigo:
Private Sub TreeV1_DragOver(Source As Control, x As Single, y As Single, State As
Integer)
Set TreeV1.DropHighlight = TreeV1.HitTest(x, y)
End Sub
Mtodo StartLabelEdit
Inicia el proceso de modificacin de la propiedad Text de un nodo, cuando la propiedad
LabelEdit est puesta a 1 (Manual).
Sintaxis
NombredelTreeView.StartLabelEdit
Para comenzar a modificar una etiqueta, el usuario debe hacer clic primero en el objeto
para seleccionarlo y hacer clic una segunda vez para iniciar la operacin. El evento
BeforeLabelEdit se produce despus del segundo clic.
Para determinar a qu objeto pertenece la etiqueta que se va a modificar, utilice la
propiedad SelectedItem. En el ejemplo siguiente se comprueba el ndice de un objeto
Node antes de permitir su edicin. Si el ndice es 1, se cancela la operacin.
Private Sub TreeView1_BeforeLabelEdit(Cancel As Integer)
If TreeView1.SelectedItem.Index = 1 Then
Cancel = True ' Se cancela la operacin
End If
End Sub
Evento AfterLabelEdit
Se produce cuando se termina de modificar la etiqueta (Propiedad Text) de un Node
Sintaxis
Private Sub NombredelTreeView_AfterLabelEdit(cancelar As Integer, nuevaCadena As
String)
Donde cancelar es un entero que, si no es 0, se cancela la operacin de edicin, y
NuevaCadena es la cadena de caracteres que el usuario ha escrito en esa etiqueta, o Null
si se ha cancelado la operacin de edicin.
El evento AfterLabelEdit se genera despus de que el usuario termina la operacin de
edicin, lo que ocurre cuando hace clic en otro objeto Node o cuando presiona la tecla
ENTRAR.
Para cancelar una operacin de edicin de etiqueta, establezca True o cualquier valor
distinto de cero en cancelar. Al cancelar la operacin, se restaurar la etiqueta existente
anteriormente.
El argumento nuevaCadena puede usarse para comprobar una condicin antes de cancelar
una operacin. Por ejemplo, el cdigo siguiente cancela la operacin si nuevaCadena es un
nmero:
Private Sub TreeView1_AfterLabelEdit(Cancel As Integer, NewString As String)
If IsNumeric(NewString) Then
MsgBox "No se permiten nmeros"
Cancel = True
End If
End Sub
Los eventos AfterLabelEdit y BeforeLabelEdit slo se generan si el valor de la propiedad
LabelEdit es 0 (Automtica) o si se invoca el mtodo StartLabelEdit.
Evento Collapse
Se genera al contraer cualquier objeto Node de un control TreeView, es decir, cuando sus
nodos secundarios se ocultan.
Sintaxis
547
Evento Expand
Se produce al expandir un objeto Node de un control TreeView, es decir, cuando sus
nodos secundarios se hacen visibles.
Sintaxis
Cuando el usuario hace clic en cualquier punto de un control TreeView, fuera de un objeto
nodo, se genera el evento Click estndar. El evento NodeClick se genera cuando el usuario
hace clic en un objeto Node determinado y devuelve una referencia al objeto Node que
puede usarse para validarlo antes de realizar alguna otra accin.
El evento NodeClick se produce antes del evento Click estndar.
Evento Validate
Ocurre cuando el foco cambia a otro control que tiene su propiedad CausesValidation
establecida a True. (Este evento es comn a todos los controles ActiveX)
Sintaxis
Boolean)
548
El control ListView
Este control es el complemento ideal para el TreeView. En el TreeView se presentaban
datos de forma jerrquica. Es el control ideal para presentar, por ejemplo, los
departamentos de una empresa u organismo.
Pero el TreeView solamente presenta un pequeo texto, acompaado generalmente de un
icono. Si seguimos hacia abajo por la estructura jerrquica del TreeView que muestra los
departamentos de un organismo, llegaremos al final a las personas. Y aqu ya ser
necesario introducir ms datos. Supongamos que estamos haciendo una lista de todas las
personas, y que la informacin de stas ser su nombre, puesto de trabajo, despacho que
ocupa, telfono, etc. El TreeView no es control aconsejado para mostrar esa cantidad de
datos. Estara muy bien poder mostrar todos los datos de esa persona en un control que
tambin permita grficos y textos, de forma que el domicilio figure al lado de un icono con
una casa, el telfono al lado de un icono con un telfono, etc. Esto lo vamos a lograr
mediante el TreeView.
El ListView puede presentar los datos de cuatro formas distintas:
- Iconos.
editarse. Al
ItemClick en el
como dato el
datos, por ejemplo)
- SmallIcons (Iconos pequeos). Igual que el anterior, pero puede presentar ms
iconos.
- Lista
Presenta la informacin en lneas, acompaada de un icono. El texto
de
cada lnea puede editarse, pero no puede cambiarse el orden de las
lneas.
- Report
(Informe) La informacin se divide en varios campos (SubItems) y se
presenta en columnas encabezadas por un texto indicativo.
549
Fig. 16.11 Las 4 formas de presentacin del ListView: Iconos grandes, pequeos, Lista y
Report
Propiedades del ListView
Propiedades Icons y SmallIcons
El ListView necesita DOS ImageList para almacenar los iconos. Uno para los iconos grandes
y otro para los iconos pequeos. Las imgenes en cada uno de ellos pueden (deben) ser
las mismas, con el mismo truco explicado para el TreeView: el de los iconos grandes con
una resolucin de 32 x 32
y el de los iconos
pequeos con una
resolucin de 16 x 16. Esta
propiedad puede
establecerse en tiempo de
diseo, mediante el cuadro
de propiedades
personalizado, o en
tiempo de ejecucin
mediante las propiedades
Icons y SmallIcons
Fig. 16.12 Pgina de
propiedades del ListView
mostrando los ImageList
ListView1.Icons = IMList1
ListView1.SmallIcons = IMList2
Las propiedades Icons y SmallIcons deben estar puestas antes de aadir elementos a la
coleccin ListItems del ListView. Si no es as, dar un error que dice que es necesario
inicializarlas.
Propiedad ListItems (Coleccin ListItems)
Esta propiedad es la equivalente a la propiedad Nodes del TreeView. Pero en este caso, un
elemento de esta coleccin no solamente contiene un dato, sino que adems puede tener
dentro de s otra coleccin de datos. Por ejemplo, pensando en una agenda, un elemento
de la coleccin puede tener como propiedad Text el alias de una persona, y como subitems
de ese elemento, el nombre y apellidos de la persona a la que se refiere el alias, su
telfono y su domicilio. Un elemento de la coleccin ListItems puede tener tantos subitems
como queramos.
Los elementos de la coleccin ListItems se aaden mediante el mtodo Add, con la
siguiente sintaxis
NombreDelListView.ListItems.Add(ndice, clave, texto, icono, iconoPequeo)
Donde
NombreDelListView es el nombre del ListView al que pertenece la coleccin ListItems
Indice es el ndice de ese elemento. Comienzan por 1. No es obligatorio poner este
parmetro,
y en ese caso, pone el nmero siguiente al mayor Index que tenga.
Clave Es una cadena de caracteres por la que se puede nombrar a ese elemento. Esta
cadena es nica para cada elemento de la coleccin. Puede contener nmeros, pero
el
primer carcter debe ser una letra
Texto Es el texto que se va a ver en el ListView, bien solo, bien acompaado de un icono
550
Icono Es una cadena de caracteres con la propiedad Key, dentro del ImageList destinado a
los iconos grandes, del icono que queremos poner en
ese elemento, cuando el
ListView est en modo de presentacin Iconos grandes. Tambin podemos poner
aqu el nmero del ndice de ese icono dentro del mismo ImageList.
IconoPequeo Idntica a la anterior, pero referida al icono mostrado cuando el ListView
est
en modo de presentacin de iconos pequeos.
Propiedades de la coleccin ListItems
La coleccin ListItems tambin tiene sus propiedades. Se enumeran a continuacin las ms
importantes.
Propiedad ListSubItems (Propiedad de la coleccin ListItems)
Una coleccin ListSubItems pertenece a cada uno de los elementos de la coleccin
ListItems. Cada ListItem puede tener varios ListSubItems, que son los elementos de
informacin relativos al ListItem del que dependen. Los ListSubItems se aaden a la
coleccin mediante el mtodo Add, con la suguiente sintaxis:
ListView1.ListItems(1).ListSubItems.Add (Index, Key, Texto, ReportIcon, TextToolTip
Donde
ListView1
ListItems(1)
Index
Key
Texto
ReportIcon
TextToolTip
Sintaxis
NombredelListView.ListItems.Remove Indice
Indice puede ser un nmero con la propiedad Index del elemento a quitar, o una cadena de
caracteres con su propiedad Key
CreateDragImage
Crea una imagen de arrastre con una versin difuminada de la imagen asociada a un
elemento de la coleccin ListImages. Normalmente, esta imagen se utiliza como DragIcon
en las operaciones de arrastrar y colocar.
Sintaxis
ListView1.DragIcon =
ListView.SelectedItem.CreateDragImage
EnsureVisible
Asegura que el objeto ListItem especificado sea visible.
Propiedades del control ListView (Continuacin)
Propiedad Arrange
Establece cmo se organizan los iconos en la vista Iconos o Iconos pequeos de un control
ListView.
Sintaxis
NombredelListView.Arrange = valor
Valor
0
LvwAutoLeft
largo
LvwAutoTop
1
2
Efecto
Ninguna. Los iconos pueden colocarse arrastrndolos con el
ratn en cualquier parte del ListView.
Izquierda. Los elementos se alinean automticamente a lo
de la parte izquierda del control.
Superior. Los elementos se alinean automticamente a lo largo
de la parte superior del control.
Propiedad Checkboxes
Establece si se muestran las casillas de verificacin.
Sintaxis
Propiedad ColumnHeaderIcons
Es similar a la propiedad Icons o SmallIcons, pero sta se refiere al ImageList que contiene
los iconos que se van a poner en las cabeceras de las columnas (cuando est en vista
Report)
Sintaxis
NombredelListView.ColumnHeaderIcons = NombredelImageList
552
El nmero de columnas del ListView debe ser igual al nmero de ListSubItems de cada
elemento ListItems. De esta forma, cada ListSubItem se presentar en una columna. Para
aadir columnas al ListView se usa el mtodo Add aplicado a la coleccin ColumnHeaders
Sintaxis
ListView1.ColumnHeaders.Add Index, Key, TextoCabecera, Ancho, Alineamiento, Icono
Index Indice de esa columna
Key
Cadena de caracteres nica que identifica esa columna
TextoCabecera
Texto que figurar en la cabecera de la columna
Ancho Ancho de la columna en unidades del Formulario que contiene al ListView
Alineamiento 0 = izquierda, 1 = Derecha, 2 = Centrado
Icono Key del icono a introducir en la cabecera de la columna
La coleccin ColumnHeaders tienen tambin sus propiedades y mtodos. Vamos a citar las
ms destacables:
Propiedades de la coleccin ColumnHeaders
Propiedad Alignment
Establece la alineacin del texto en la cabecera de un ColumnHeader. Acepta 3 valores:
0 = izquierda, 1 = Derecha, 2 = Centrado
Sintaxis
Propiedad Position
Devuelve o establece la posicin de una columna.
Sintaxis
ListView1.ColumnHeaders(Index) = entero
553
554
Estos son los controles integrados en el paquete Mscomct2.Ocx. Son cinco controles:
-
MonthView
Animation
DTPicker
UpDown
FlatScrollBar
Control MonthView
El control MonthView permite crear aplicaciones donde los usuarios pueden elegir una
fecha mediante una interfaz parecida a un calendario.
Fig. 16.14 Control MonthView
Este control permite seleccionar de una forma muy sencilla
una fecha o un intervalo de fechas. Puede tener el aspecto
mostrado en la Fig. 16.14 o mostrar varios meses a la vez.
Esto puede lograrse mediante las propiedades MonthColumns
y MonthRows. Las fechas mnimas y mximas a presentar se
pueden establecer con las propiedades MinDate y MaxDate.
Este control est enlazado a datos. De esta forma puede
presentar un dato fecha hora existente en una base de datos.
Para permitir a los usuarios del programa seleccionar un intervalo continuo de fechas,
asigne a la propiedad MultiSelect el valor True y especifique con MaxSelProperty el
nmero de das que podrn seleccionar. Las propiedades SelStart y SelEnd devuelven las
flechas del principio y el final de una seleccin.
Existen muchas formas de personalizar la apariencia de un control MonthView. Existen
varios atributos de colores, como MonthBackColor, TitleBackColor, TitleForeColor y
TrailingForeColor, que le permiten crear combinaciones de colores exclusivas para el
control.
Establezca las propiedades MonthRows y MonthColumns para mostrar ms de un mes a
la vez (hasta 12 meses) en un control MonthView. El nmero total de propiedades
MonthRows y MonthColumns debe ser inferior o igual a 12.
Es un control enlazado a datos, por lo que puede presentar o introducir una fecha de una
base de datos a travs de este control, previamente enlazado a la base de datos mediante
un control Data.
Propiedades del control MonthView
Propiedad Day
Devuelve o establece un valor numrico que especifica el nmero del da actual.
Sintaxis
NombredelMonthView.Day = nmero
Variable = NombredelMonthView.Day
Sintaxis
NombredelMonthView.DayBold(fecha) = True/False
La propiedad DayBold es una matriz que corresponde a la propiedad VisibleDays. Cada
elemento booleano indica si la fecha correspondiente debe mostrarse o no en negrita.
Son vlidas nicamente las fechas mostradas actualmente. Las fechas vlidas pueden
buscarse en la propiedad VisibleDays.
A medida que pasa de un mes a otro, no se conserva la informacin de la propiedad.
Propiedad DayOfWeek
Devuelve o establece un valor que especifica el da de la semana actual.
Sintaxis
objeto.DayOfWeek = nmero
mvwMonday
mvwTuesday
mvwWednesday
mvwThursday
mvwFriday
mvwSaturday
2
3
4
5
6
7
Descripcin
(Predeterminado)
Domingo
Lunes
Martes
Mircoles
Jueves
Viernes
Sbado
objeto.MaxSelCount = nmero
objeto.Month = nmero
Valores admitidos.
556
La propiedad Month puede tomar cualquier valor o constante de las expresadas en la tabla
siguiente:
Los valores admitidos para nmero son:
Constante
Valor
Descripcin
mvwJanuary
1
Enero
mvwFebruary
2
Febrero
mvwMarch
3
Marzo
mvwApril
4
Abril
mvwMay
5
Mayo
mvwJune
6
Junio
mvwJuly
7
Julio
mvwAugust
8
Agosto
mvwSeptember
9
Septiembre
mvwOctober
10
Octubre
mvwNovember
11
Noviembre
mvwDecember
12
Diciembre
Propiedad MonthBackColor
Devuelve o establece un valor que especifica el color de fondo mostrado para un mes.
Sintaxis
objeto.MonthBackColor = color
objeto.MonthColumns = nmero
objeto.MonthRows = nmero
objeto.MultiSelect = booleano
Propiedad Parent
Devuelve el formulario, objeto o coleccin que contiene un control u otro objeto o
coleccin.
Sintaxis
objeto.Parent
Utilice la propiedad Parent para tener acceso a las propiedades, los mtodos o los
controles del primario de un objeto. Por ejemplo:
MiBotn.Parent.MousePointer = 4
557
Propiedad ScrollRate
Devuelve o establece un valor que especifica el nmero de meses que se desplazar
cuando el usuario haga clic en uno de los botones de desplazamiento. La propiedad
ScrollRate permite al usuario realizar desplazamientos de ms de un mes cada vez.
Propiedad ShowToday
Devuelve o establece un valor Booleano que determina si se muestra la fecha actual en la
parte inferior del control.
Propiedades SelEnd, SelStart
Devuelve o establece los lmites inferior y superior del intervalo de fechas seleccionado.
Sintaxis
objeto.SelEnd = fecha
objeto.SelStart = fecha
Las propiedades SelStart y SelEnd definen el lmite inferior y superior del intervalo de
fechas seleccionado. El intervalo de fechas seleccionado puede abarcar varios meses. Es
posible incluir fechas que no estn visibles actualmente.
Para que la seleccin mltiple de fechas funcione correctamente, asigne a la propiedad
MaxSelCount un valor superior a la diferencia de los valores de las propiedades SelStart
y SelEnd.
Los valores SelStart y SelEnd slo son vlidos cuando la propiedad MultiSelect tiene el
valor True.
Propiedad ShowWeekNumbers
Devuelve o establece un valor que determina si los nmeros de semana aparecen junto a
la semana.
Sintaxis
objeto.ShowWeekNumbers = booleano
Propiedad StartOfWeek
Devuelve o establece un valor que especifica el primer da de la semana.
Sintaxis
objeto.StartOfWeek = entero
Los valores admitidos para entero son iguales que para la propiedad DayOfWeek
Propiedades TitleBackColor, TitleForeColor
Devuelven o establecen valores que especifican los colores de fondo y primer plano del
rea de ttulo del control.
Sintaxis
objeto.TitleBackColor = color
objeto.TitleForeColor = color
objeto.TrailingForeColor = color
558
Propiedad Value
Devuelve o establece la fecha que se muestra actualmente. El valor devuelto es de tipo
Date
Sintaxis
objeto.Value = fecha
VariableTipoDate = Objeto.Value
Mediante el mtodo HitTest puede obtener una fecha del control MonthView simplemente
haciendo clik encima de ella. El mtodo HitTest devuelve Null si no existe ninguna fecha
en las coordenadas especificadas.
Private Sub MonthView1_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As
Single)
Dim FechaElegida As Date
559
MonthView1.HitTest X, Y, FechaElegida
LabelFecha = FechaElegida
End Sub
Eventos del control MonthView
DateClick (Evento)
Ocurre cuando se hace clic en una fecha del control.
Private Sub objeto_DateClick([Index As Integer], DateClicked As Date)
Se utiliza este evento para determinar la fecha en la que se hizo clic.
Private Sub MonthView1_DateClick(ByVal DateClicked As Date)
LabelFecha = MonthView1.Value
End Sub
Se deja al alumno el estudio exahustivo de este control, que no se separa mucho del
MonthView visto anteriormente.
Control Animation
560
Este control nos permite introducir en nuestra aplicacin un elemento muy elegante:
visualizacin de ficheros .avi Existen en Windows muchos fichero .avi aplicados para
distintas funciones: copiar ficheros, bajar ficheros de Internet, y otros empleados como
elemento tranquilizador en procesos lentos. Veamos un par de ejemplos:
Para probar este control basta con poner un controlen el formulario, un CommonDialog
(CD1) y dos botones, uno para arrancar y otro para parar la presentacin del fichero avi.
El tamao que se le de en el formulario debe ser suficientemente grande para que quepa la
presentacin en su tamao real. No acepta zoom.
En el procedimiento click del botn de arrancar basta con poner este cdigo:
CD1.Filter = "avi (*.avi)|*.avi"
CD1.ShowOpen
With Animation1
.Open CD1.FileName
.Play
End With
Para parar la ejecucin:
Animation1.Stop
El control Animation tienen pocas propiedades distintas de los dems controles. Podemos
citar estas:
Propiedad Center
Establece si el fichero .avi se presenta en el centro del control (Center = True) o si se
presenta en las coordenadas 0,0 del mismo (Center = False)
Propiedad AutoPlay
Devuelve o establece un valor que determina si el control Animation empezar a
reproducir un archivo .avi cuando ste se cargue en el control.
Mtodos del control Animation
Play
Stop
est
Ejecuta la animacin.
Detiene la animacin. No se puede ejecutar este mtodo si la propiedad AutoPlay
a True.
Control UpDown
561
Este control sirve para introducir saltos de un paso en otros controles o en cualquier
parte del cdigo de la aplicacin.
Este control es tan sencillo que no se va a explicar. Solamente citar que sus dos
procedimientos ms importantes son el DownClick y el UpClick
Control FlatScrollBar
Es un control de scroll. Tiene como todos los controles de este tipo, una propiedad Max
para darle el valor mximo, Min para ajustar el valor mnimo, SmallChange y LargeChange
para fijar las variaciones al hacer click en la fkecha o en el cuerpo respectivamente, y unna
propiedad Value para leer el valor actual.
Solamente tienen el procedimiento Scroll que se produce al variar la posicin del cursor.
Dejamos aqu el estudio de controles avanzados. No es que no haya ms, sino que el curso
debe tener un final. Para conocer a fondo los controles lo mejor es tomar un control de la
lista que sale del men de VB Proyecto | Componentes, y ponerse con el. No voy a decir
que sea ms fcil que estudiarlos con la ayuda de la Gua del Estudiante. Eso s, le va a
resultar bastante ms divertido.
interesante para Vd. apunte todo lo que vaya aprendiendo de l. Por experiencia puedo
decirle que se olvida. Crese su propia Gua del Estudiante. A final de cuentas esta
comenz as y ya va bastante adelantada.
Visual Basic Gua del Estudiante Captulo 17
Funciones API de Windows
Las APIs de Windows son un serie de funciones que Windows tienen implementadas al
servicio del programador. Estas funciones se llaman API (Interfaz para Programacin de
Aplicaciones) y estn en las innumerables DLLs que tiene Windows. Las APIs tienen la
virtud de acceder a partes de la mquina o del sistema operativo a las que no podramos
acceder mediante Visual Basic. Las APIs pertenecen como decamos a Windows, por lo que
pueden ser usadas por programas escritos en cualquier lenguaje de programacin. Es muy
interesante utilizarlas, pues reducen el tamao del programa ejecutable frente a otras
posibilidades con controles, aparte de darle mayor rapidez de ejecucin, al tratarse de
cdigo ya compilado.
Dado que este libro tiene lgicamente un alcance limitado, y el tema de APIs es enorme,
se recomienda recurrir a un libro especfico de APIs. Este no puede ser otro que el
siguiente :
562
TITULO
API de Win32. Gua del Programador de Visual Basic
AUTOR
Daniel Appleman. Editorial InforBooks - Barcelona
ISBN
84-89700-22-2
Citaremos este libro repetidas veces a lo largo de este captulo.
Daniel Appleman es el fundador de Desaware Inc. http://www.desaware.com/ Su pgina
es visita obligada.
Nota introducida en el 2001 - Aparte de este libro, existe un recurso en Internet que
incluso le supera, y que tiene la gran ventaja de que se trata de un sistema informtico
donde puede copiar y pegar cdigo. Puede encontrarlo en
http://www.allapi.net/
Desde que lo he descubierto he dejado el Libro de Appleman un poco aparcado. Sin
embargo las explicaciones aportadas en ese libro son difcilmente sustituibles.
Para usar una funcin API lo primeros que tenemos que hacer es declararla en nuestra
aplicacin. La declaracin debe hacerse en la seccin de declaraciones de un formulario o
mdulo. Si la declaramos en un formulario, necesariamente debemos declararla como
privada.
Una declaracin sencilla podra ser la de la funcin API Sleep :
Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
Aqu se ha declarado como pblica. Es lo mismo que decir:
Public Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
En un formulario no se puede declarar como pblica. Deberemos poner
Private Declare Sub Sleep Lib "kernel32" Alias "Sleep" (ByVal dwMilliseconds As Long)
En esta declaracin lo que le estamos diciendo es que, en la librera kernel32 est escrita
una funcin llamada Sleep (Es el nombre que figura entre comillas en la declaracin) y
que le tenemos que pasar un parmetro, el tiempo que queremos que se pare la ejecucin
de la aplicacin, expresado en milisegundos. Nos dice la declaracin que el parmetro se le
pasa Por Valor (ByVal) y que ese dato debe ser un Long, es decir, si se lo pasamos como
una variable, esa variable debe ser del tipo Long. Una vez declarada esta funcin, en la
seccin de declaraciones de un mdulo o de un formulario, podremos acceder a ella en
cualquier parte de la aplicacin (las partes de la aplicacin donde se puede usar depender
del mbito de la declaracin, que es idntica que para las variables) usando una lnea de
cdigo como esta :
Sleep (500)
(en
Sleep (tiempo)
563
Aqu ya se ha complicado un poco la cosa. Pero tras un anlisis detenido veremos que esa
complicacin es slo aparente.
En primer lugar vemos que la librera donde est esta funcin es, como en la funcin
Sleep, el kernel32 . Esto quiere decir que la librera kernel32 contiene varias funciones.
Pero qu es la librera kernel32 ? Ni mas ni menos que una DLL llamada kernel32.dll
que puede encontrar en el directorio C :\WINDOWS\SYSTEM, y que es el alma de
Windows. (Kernell significa, como muy bien sabr, ncleo)
En segundo lugar, vemos que el nombre de esta funcin dentro de la DLL kernel32.dll es
GetVolumeInformationA, que es lo que figura entre comillas en la declaracin. El
nombre GetVolumeInformation que figura como nombre de la funcin, al principio de la
declaracin, es el nombre por el que nos vamos a referir a la funcin en nuestra aplicacin.
Ese nombre puede cambiarse, cambiando tambin el nombre con el que vamos a llamar a
esta funcin a lo largo de nuestra aplicacin. Esto se lo digo solamente a nivel informativo.
No
lo haga. Su aplicacin no podra ser interpretada por otra persona. No es
profesional y quien mas perder por ello es Vd. Le hago especial hincapi en esto,
porque es una forma de proteger sus programas por parte de algunos programadores.
Pero un analista experto encuentra enseguida el truco. Y algunos no perdonan. Seamos
profesionales
En tercer lugar, vemos que la declaracin de esta funcin termina con la expresin As
Long. Esto significa que esta funcin devuelve un dato, y es concretamente, un Long. Por
lo tanto, si ese dato nos sirve para algo, podemos obtenerlo. Ver que no es necesario,
pero en muchas ocasiones, ese dato nos va a indicar si la funcin se ejecut
correctamente. Concretamente, esta funcin devuelve un 0 si ha existido algn problema
para obtener el nmero del disco, o un nmero distinto de 0 si lo ha obtenido. Las dems
constantes deberemos declararlas en el procedimiento donde vamos a usar la funcin (o en
otro lugar, si as lo exige el mbito que les queramos dar, pero generalmente, en el mismo
procedimiento), e invocar la funcin pasndole los parmetros correctos.
La sintaxis de las Apis va a ser distinta si deseamos obtener el valor que devuelve o no.
Por ejemplo, para la funcin anterior podemos poner perfectamente estas dos expresiones
Dim Respuesta as Long
Respuesta
= GetVolumeInformation("C:\", volbuf, 255, serialnum, componentlength,
sysflags, _
sysname, 255)
volbuf As String
sysname As String
serialnum As Long
esta variable ser la que contenga el nmero del disco
sysflags As Long
lpFileSystemFlags
componentlength As Long
lpMaximumComponentLength
res As Long
564
volbuf = String(256, 0)
sysname = String(256, 0)
Estas variables son las que se van a pasar como parmetros a la funcin. La
correspondencia entre el nombre del parmetro y cada una de las variables es la
siguiente :
lpRootPathName
Se lo metemos directamente : C :\ - no olvidar la barra \
lpVolumeNameBuffer
volbuf Label del disco
nVolumeNameSize
Tamao del buffer anterior. Directamente 255
lpVolumeSerialNumber serialnum. Contendr el nmero del disco
lpMaximumComponentLength componentlength
lpFileSystemFlags
sysflags
lpFileSystemNameBuffer sysname
nFileSystemNameSize
Tamao buffer anterior. Directo, 255
res = GetVolumeInformation("C:\", volbuf, 255, serialnum, componentlength, sysflags, _
sysname, 255)
If res = 0 Then ' ha ocurrido un error y no puede leer el VOL
MsgBox ("Ha ocurrido un error al intentar arrancar la aplicacin.")
Else
'lo ha ledo perfectamente
VOLUM = Trim(Str(serialnum)) 'convertimos un Long en String
'si tiene menos de 12 caracteres, le aadimos los ceros necesarios por la izquierda
If Len(VOLUM) < 12 Then VOLUM = String(12 - Len(VOLUM), "0") & VOLUM
' lo presentamos en el TextBox TBVOL
TBVOL.Text = VOLUM
End If
Repasemos la declaracin y veamos que es cada una de sus partes
Funcin GetVolumeInformation
Declare Function GetVolumeInformation Lib "kernel32" Alias "GetVolumeInformationA"
(ByVal lpRootPathName As String, ByVal lpVolumeNameBuffer As String, ByVal
nVolumeNameSize As Long, lpVolumeSerialNumber As Long, lpMaximumComponentLength
As Long, lpFileSystemFlags As Long, ByVal lpFileSystemNameBuffer As String, ByVal
nFileSystemNameSize As Long) As Long
lpRootPathName
Es un string que contiene el directorio raz del disco a analizar. Si es te parmetro es Null,
se toma el directorio raz del directorio actual. Esta parmetro puede indicar el disco de un
servidor, en cuyo caso debe indicarse con dos backslash. (\\Servidor\Disco)
lpVolumeNameBuffer
Apunta a una variable que va a recibir el nombre del Label del disco. Hay que declararla
con un tamao predeterminado, siempre mayor que el que va a tener el dato
p.e.
Dim VolBuf As String * 255
nVolumeNameSize
Especifica la longitud de la variable anterior. No importa que la hayamos declarado ya con
determinado tamao. Hay que poner aqu otra vez ese tamao, que ser el mismo que
tena declarado la variable.
lpVolumeSerialNumber
Apunta a una variable tipo Long, donde se va a meter el nmero del disco.
565
lpMaximumComponentLength
Apunta a una variable Long (En realidad se mete en esta variable el resultado de la
concatenacin de dos bytes) donde se va a poner el nmero mximo de caracteres
permitido por el sistema de ficheros. Eeste nmero de caracteres corresponde con los
caracteres comprendidos entre dos backslahs. Si ese valor es 255 indica que el sistema de
ficheros soporta nombres largos. Si indica 8.3 solamente acepta nombres cortos
lpFileSystemFlags
Apunta a una variable tipo Long, (Igual que la anterior, concatenacin de dos bytes) que
especifican los Flags asociados al sistema de ficheros. Puede ser la combinacin de dos de
los
siguientes
parmetros
(Excepcin:
FS_FILE_COMPRESSION
y
FS_VOL_IS_COMPRESSED son mutuamente excluyentes).
FS_CASE_IS_PRESERVED
If this flag is set, the file system preserves the case of filenames when it places a name on
disk.
FS_CASE_SENSITIVE
El sistema de ficheros diferencia maysculas y minsculas.
FS_UNICODE_STORED_ON_DISK
FS_PERSISTENT_ACLS
FS_FILE_COMPRESSION
FS_VOL_IS_COMPRESSED
El disco especificado se trata de un disco comprimido. Por ejemplo, es un disco al que se le
ha aplicado DoubleSpace.
lpFileSystemNameBuffer
Apunta a una variable tipo string, donde se mete el sistema de ficheros soportado (FAT or
NTFS). Esta variable debe declararse con un nmero prefijado de caracteres, siempre
superior al que vaya a tener realmente (p.e. Dim SysName As String * 255)
nFileSystemNameSize
Especifica el nmero de caracteres de la variable anterior. Debe introducirse el mismo
nmero con el que se ha declarado la longitud de esa variable. (255 en el ejemplo).
Ya vamos viendo que las APIs no son tan difciles de entender. Vamos a ver otra, la
inversa de la anterior, que pone el valor al parmetro Label del disco. Observe que el resto
de los parmetros no pueden variarse ya que vienen marcados en el disco (nmero) o
implcitos en el sistema operativo.
Funcin SetVolumeLabel
Private Declare Function SetVolumeLabel Lib "kernel32" Alias "SetVolumeLabelA" (ByVal
lpRootPathName As String, ByVal lpVolumeName As String) As Long
lpRootPathName
Variable tipo string donde se introduce el directorio raz del disco al que se le va a poner o
cambiar el Label. Si este parmetro es Null, se entiende que es el raz del directorio actual.
lpVolumeName
Variable tipo string que contienen el Label a poner. Si es Null, borra el Label actual.
Vemos que no es tan complicado operar con funciones API. Para trabajar con APIs
solamente es necesario conocer la sintaxis exacta de la declaracin. Pero parece en
566
principio un poco difcil, a sabiendas de que deben existir varios cientos de APIs.
SOLUCION : Que VB nos aporte un chuleta con todas las declaraciones.
Esta chuleta no es otro que el Visor de Texto API (API Text Wiever en Ingls). Este es un
programa que se distribuye con Visual Basic y que se instala al tiempo que este, formando
parte del mismo grupo de programas. Haciendo clic en su icono aparece esta ventana :
Haciendo Click sobre la palabra Archivo de la Barra de Men, aparecen unos ficheros que
contienen las declaraciones de las funciones API :
Win32Api.txt
Winmmsys.txt
Estos dos ficheros son los que suministra Microsoft con VB6. El primero contiene las
declaraciones de las funciones API no relacionadas con el tema multimedia. El segundo
contiene las declaraciones de las API relacionadas con este tema de multimedia.
Si ha adquirido el libro de Appleman puede tener otro fichero : Api32.txt. El autor de este
libro asegura que es mucho mas completo que el fichero que entrega Microsoft. De hecho
contiene bastantes mas declaraciones.
API-Guide presenta tambin la declaracin del API para ser copiada directamente en el
portapapeles y pegada en nuestra aplicacin. ltimamente es la nica que uso, ya que al
tiempo, se obtienen una explicacin de cada uno de los parmetros.
567
Estos ficheros estn en ASCII. Puede convertirlos a una base de datos ACCESS y el acceso
ser un poco ms rpido. No olvide que tambin le ocupar un sitio respetable en el disco
duro de su ordenador.
Para obtener una o varias declaraciones, seleccione las funciones en la ventana de arriba
del visor, haga click en Agregar y esa funcin le pasar para la ventana de abajo. Una vez
que tenga en esa ventana todas las funciones que necesita, haga click en el botn Copiar y
las declaraciones completas le pasarn al portapapeles.
Una vez que ya sabemos donde se pueden copiar las declaraciones de las APIs, veamos
una que nos permitir obtener la hora desde el sistema operativo :
Declare Sub GetSystemTime Lib "kernel32" Alias "GetSystemTime" (lpSystemTime _
As SYSTEMTIME)
Ahora nos surge una duda Qu es SYSTEMTIME ? Es una variable que hay que declararla
con la instruccin Type, igual que hacamos con las variables con varios campos en los
ficheros tipo Random. Repase este captulo si no lo tiene claro.
Para poder declarar esta variable, podemos obtener su declaracin del mismo Visor de
Texto API
Para ello, en la ventana Tipo API en vez de figurar Declaraciones debe poner Tipos.
Busque esta opcin desplegando la ventana con la flecha que tiene a la derecha. Busque
ahora la variable cuya declaracin quiere conocer. Repitiendo el proceso anterior, se llevar
en el portapapeles la declaracin de la variable :
Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
Haga un pequeo ejercicio para obtener la fecha y hora usando un API :
Para ello debemos introducir un mdulo donde definiremos la variable SYSTEMTIME y
donde podemos declarar la funcin GetSystemTime :
Mdulo 1
Declaraciones
Option Explicit
Type SYSTEMTIME
wYear As Integer
wMonth As Integer
wDayOfWeek As Integer
wDay As Integer
wHour As Integer
wMinute As Integer
wSecond As Integer
wMilliseconds As Integer
End Type
568
569
APIS DE WINDOWS
Funcin Shell_NotifyIcon
Fig. 1 - Icono del programa Wsk colocado en el System Tray con su ToolTipText y
PopupMen
Este sistema permite comunicar la aplicacin con el icono creado en el System Tray.
Lgicamente, primero debe crearse el icono (Se crea normalmente en el Load del
formulario inicial de la aplicacin), y permanece ah mientras dura la ejecucin de la
aplicacin. Si se minimiza la aplicacin, no aparece su icono en la barra de tareas. Por lo
tanto se necesitar algn artilugio para poder poner otra vez la aplicacin en su estado
normal. Esto se hace mediante una comunicacin entre el icono del System Tray y la
aplicacin. Esa comunicacin es lo que llamaremos mensaje de retorno. Al recibir ese
mensaje de retorno, el formulario va a tratarlo en uno de sus procedimientos. El
procedimiento donde lo va a tratar se le especifica en la llamada a la API como se ver
mas adelante. El mensaje de retorno va a depender de lo que se haga sobre el icono del
System Tray, (Tecnologa Windows) y es en principio un poco complicado, pero ver
tambin ms adelante una breve explicacin sobre este valor devuelto. Para que el icono
no siga en el System Tray una vez hayamos salido de la aplicacin, es necesario eliminarlo
en el procedimiento Unload del formulario inicial.
El icono puede cambiarse en tiempo de ejecucin, y es una de las aplicaciones ms
vistosas de este sistema. Puede, por ejemplo, cambiar el color del icono para indicar que
se ha recibido un mensaje, que se est conectado, etc.
El API encargada de realizar esta funcin es Shell_NotifyIcon, cuya declaracin es:
Public Declare Function Shell_NotifyIcon Lib "shell32" _ Alias "Shell_NotifyIconA" _
(ByVal dwMessage As Long, pnid As NOTIFYICONDATA) As Boolean
Vemos que la declaracin incluye una variable definida por el usuario: NOTIFYCONDATA. Se
define de esta forma
Public Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
570
uId As Long
uFlags As Long
uCallBackMessage As Long
hIcon As Long
szTip As String * 64
End Type
El primer parmetro que se le pasa a la funcin (dwMessage) le va a indicar la operacin
que debe realizar, y puede tomar uno de los tres siguientes valores (Se indica tambin el
nombre de la constante que suele sustituir a esos valores):
Constante
NIM_ADD
NIM_MODIFY
NIM_DELETE
0
1
2
Valor
Operacin que realiza
Aade un icono al System Tray
Cambia el icono actual por otro
Quita el icono del System Tray
El segundo parmetro (pnid) es una variable tipo NOTIFYICONDATA tal como se defini
ms atrs. Vemos a continuacin cada componente de esta variable:
CbSize
Hwnd
UId
Es el identificador del icono del System Tray. Puede ser cualquier
nmero Long. Solamente ser necesario usar un nmero si hace falta identificar ese icono
para una operacin posterior. Si no se va hacer ninguna operacin con l, caso ms
habitual, basta con poner vbNull como valor de esta parte.
UFlags
Constante
NIF_MESSAGE1
NIF_ICON
NIF_TIP
Valor
Resultado
El identificador del mensaje de retorno ser el
especificado en uCallBackMessage
2
El icono que se pone en el System Tray es el
que se le indica en hIcon.
4
El ToolTipText del icono del System Tray ser
el especificado en szTip.
Uflags puede contener los tres valores, validando de esta forma las tres condiciones
anteriores. Es muy tipico ver que UFlags toma el valor:
.uFlags = NIF_ICON Or NIF_TIP Or NIF_MESSAGE
571
Constante
Valor
WM_MOUSEMOVE
WM_LBUTTONDOWN
WM_LBUTTONUP
WM_LBUTTONDBLCLK
WM_RBUTTONDOWN
WM_RBUTTONUP
WM_RBUTTONDBLCLK
HIcon
SzTip
&H200
&H201
&H202
&H203
&H204
&H205
&H206
572
extrado aqu lo que se refiere a la aplicacin de esta API. Puede cortarse y pegarse el
cdigo a otra aplicacin, con garanta total de funcionamiento.
EJERCICIO PRACTICO
En un mdulo del programa, en la seccin de declaraciones, debemos introducir la
definicin de la variable NOTIFYICONDATA
Public Type NOTIFYICONDATA
cbSize As Long
hwnd As Long
uId As Long
uFlags As Long
uCallBackMessage As Long
hIcon As Long
szTip As String * 64
End Type
En el mismo mdulo introducimos las constantes que va a requerir, tanto la llamada a la
funcin Shell_NotifyIcon como las que vamos a necesitar para analizar el mensaje de
retorno:
Public
Public
Public
Public
Public
Public
Const
Const
Const
Const
Const
Const
NIM_ADD = &H0
NIM_MODIFY = &H1
NIM_DELETE = &H2
NIF_MESSAGE = &H1
NIF_ICON = &H2
NIF_TIP = &H4
Public
Public
Public
Public
Public
Public
Public
Const
Const
Const
Const
Const
Const
Const
WM_MOUSEMOVE = &H200
WM_LBUTTONDOWN = &H201
WM_LBUTTONUP = &H202
WM_LBUTTONDBLCLK = &H203
WM_RBUTTONDOWN = &H204
WM_RBUTTONUP = &H205
WM_RBUTTONDBLCLK = &H206
573
Con el cdigo introducido en el Load del formulario inicial ya hemos puesto el icono en el
System Tray. Ahora ya podemos hacer clic sobre este icono (y otros eventos) para que el
icono enve al formulario el mensaje de retorno. Ese mensaje ser tratado en el
procedimiento MouseMove, puesto que as se lo hemos indicado a la funcin
Shell_NotifyIcon con
uCallBackMessage = WM_MOUSEMOVE. En este procedimiento
prevemos todos los mensajes de retorno que puede recibir.
Evento MouseMove del formulario receptor de mensajes de retorno.
Private Sub Form_MouseMove(Button As Integer, Shift As Integer, X As Single, Y As Single)
Este procedimiento espera recibir 4 parmetros, sin embargo solamente va a recibir 3. Por
lo tanto, el valor de Y ser siempre nulo a lo largo de este procedimiento.
Dim Result As Long
Dim msg As Long
'El valor recibido en la posicin X vara dependiendo del ScaleMode
Windows)
If Me.ScaleMode = vbPixels Then
msg = X
Else
msg = X / Screen.TwipsPerPixelX
End If
575
(Cosas de
(Recuerde que estos valores estn en Hexadecimal). Por ejemplo, cuando hacemos clic en
el icono con el botn derecho (R), en el instante de bajar el botn (ButtonDown) se genera
como mensaje de retorno el nmero 204 en hexadecimal. Ese valor, que no depende de la
programacin, sino que es un valor que Windows tiene prefijado, se lo asociamos a una
constante llamada WM_RBUTTONDOWN (La podramos haber llamado de otra forma, pero
Microsoft la llama as, y si todos la llamamos as existir cierta semejanza entre el cdigo
de todos los programadores). Luego, en el procedimiento MouseMove del formulario, en
vez de preguntar si el mensaje de retorno vale &H204, preguntamos si vale
WM_RBUTTONDOWN
Podemos hacer que el icono del System Tray cambie en determinadas circunstancias. Por
ejemplo, si el programa minimizado es un correo electrnico, podemos hacer que cambie
576
577
VISUAL BASIC Y LAS APIS DE WINDOS LAS APIS DEL REGISTRO DE WINDOWS
El registro de Windows es sin duda el gran tab de los programadores. Hay quien cree que
si se toca el registro, el PC nunca ms va a volver a trabajar correctamente. Y desde luego
no le falta razn a quien as opina. No le falta razn, le falta matizar: Si se toca el registro
de Windows sin saber, es muy probable que el PC no vuelva a trabajar bien.
El nico secreto que tiene el registro de Windows es NO TOCAR lo existente. Podemos
introducir cosas nuevas y borrar estas cosas nuevas. Y qudese tranquilo que Visual Basic,
solamente har lo que le digamos que haga, por lo tanto podemos estar seguros que no
tocar nada de lo que nosotros no le hayamos indicado.
El registro puede manejarse mediante dos instrucciones de VB ya explicadas en captulos
anteriores: SaveSettings y GetSettings. Y es lo que se dice en un curso bsico de VB.
Cuando termine de leer este captulo Vd. Mismo se convencer que esas instrucciones son
solamente para empezar. Un programador profesional siempre usa APIS para leer y
escribir el Registro de Windows.
Va a encontrar en este captulo una palabra muy repetida: Clave del registro. (Key) Una
clave del registro es una de las muchas informaciones que existen en el registro. Por
ejemplo:
HKEY_CURRENT_USER/Software/VB And VBA Program
Settings/AgendaTel/Colores/Fondo
Esta clave contiene el color de fondo del formulario de la aplicacin AgendaTel, y debe
contener un valor, concretamente el nmero que expresa el color de fondo citado. En el
caso del ejemplo, mi PC contena el valor 8454016, (contiene la cadena de caracteres
8454016, no el nmero 8.454.016, por eso va entre comillas). Por eso, al tratar ese dato,
debe hacerse pensando que es un string.
Dim VarColor As String
VarColor = GetSetting(AppName:="AgendaTel", Section:="Colores", Key:="Fondo")
Me.BackColor = CLng(VarColor)
Lo mismo ocurre cuando se trate de una fecha.
Las claves se expresan con una estructura similar a la de las carpetas (directorios) del
explorador de Windows. No es que sea as, ya que el registro es un fichero nico, pero su
estructura jerrquica es similar. Por eso, hablaremos de Claves y Subclaves, lo mismo que
hablamos de directorios y subdirectorios (Carpetas y Subcarpetas). Una clave tendr
subclaves si hay ms claves por debajo de su nivel jerrquico. En el ejemplo anterior, la
clave
HKEY_CURRENT_USER/Software/VB And VBA Program Settings/AgendaTel
tiene la subclave Colores y esta a su vez tiene la subclave Fondo. La clave Fondo
no tiene subclaves.
Los datos de una clave pueden ser cadenas
de caracteres o numricas.
Puede
diferenciar unas de otras mediante el icono
que aparece a su lado al editar el registro.
Una clave puede tener varios datos. Cada
dato tienen un nombre y un valor (Nombre
= fonts.fon y su valor vgafix.fon)
578
El valor de las claves numricas puede ponerse como binario puro, o como un Long (32
bits), y en este caso, con estructura Big Endian (El byte de mayor peso est en ltimo
lugar) o Little Endian. (El byte de menor peso est en ltimo lugar). En cualquier caso las
claves numricas el editor del registro las presenta en Hexadecimal. En la Fig. anterior,
Hex(00000060) = 96 en decimal. Las claves que son cadenas de caracteres las presenta
entre comillas dobles.
Se enumeran a continuacin las APIS relacionadas con el registro de 32 bits. Se incluye la
declaracin de cada una de ellas y la explicacin de cada uno de sus parmetros. Se
omiten aquellas que solamente funcionan en Windows 3.11 o que existen por
compatibilidad con Windows 3.11.
Podramos clasificarlas en dos grupos, uno la de aquellas que sirven para leer y guardar
valores, y otro, con aquellas Apis que sirven para mantenimiento del registro.
La primera operacin que debemos hacer para trabajar sobre una clave es abrirla
(Exceptuando lgicamente la operacin de crearla). Para abrir una clave se usa el API
RegOpenKeyEx. Al final, una vez realizadas todas las operaciones deseadas, hay que
cerrarla. Se cierra mediante el API RegCloseKey
Handle = Manejador en espaol, pero esta es una de estas palabras que es mejor no
traducirlas. Utilizaremos la expresin Handle durante todo este captulo.
Funcin RegOpenKeyEx
Abre la clave especificada. Es la primera operacin que hay que hacer para trabajar con
una clave. (Es similar, en ficheros, a Open NombreFichero For xxx As #n)
Declaracin:
Declare Function RegOpenKeyEx Lib "advapi32.dll" Alias "RegOpenKeyExA" (ByVal hKey As
Long, ByVal lpSubKey As String, ByVal ulOptions As Long, ByVal samDesired As Long,
phkResult As Long) As Long
HKey es el Handle de la clave de nivel superior. Hkey acepta cualquiera de los
valores predefinidos:
HKEY_CLASSES_ROOT
(= Hex 80000000)
HKEY_CURRENT_USER
(= Hex 80000001)
HKEY_LOCAL_MACHINE
(= Hex 80000002)
HKEY_USERS
(= Hex 80000003)
constante que habr que declarar. Lo que ocurre es que en Windows, esa constante
siempre tiene el mismo valor (Concretamente Hex 80000002). No declare una constante
con ese mismo nombre con un valor distinto a ese.)
LpSubKey es una variable que contiene el nombre de la subclave a abrir. Esta
variable es una cadena de caracteres, que indica la ruta total de la clave a abrir,
desde la clave expresada en el parmetro anterior. Si este parmetro es nulo o la
cadena vaca, la funcin crear un nuevo handle de la clave definida por el
parmetro Hkey . En este caso, la funcin no cierra el handle creado previamente.
579
UlOptions
Funcin RegCreateKeyEx
Crea la clave especificada. Si existe ya esa clave, la abre.
Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA" (ByVal hKey
As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal lpClass As String, ByVal
dwOptions
As
Long,
ByVal
samDesired
As
Long,
lpSecurityAttributes
580
As
581
Funcin RegDeleteKey
Borra una clave del registro de Windows. Funciona de forma distinta en W95 que
en WNT. En W95 borra esa clave y todas sus subclaves. En WNT no permite
borrar una clave que tenga subclaves.
Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal
hKey As Long, ByVal lpSubKey As String) As Long
HKey Es el Handle de una clave abierta. Puede ser tambin una de las siguientes
constantes:
HKEY_CLASSES_ROOT
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_USERS
LpSubKey Es la subclave a borrar. Esta subclave debe estar dentro de la clave
especificada en el parmetro Hkey . Este parmetro no puede ser nulo. En WNT, la
clave a borrar no puede tener subclaves.
Aplicacin prctica de lo visto hasta aqu: Crear una clave y eliminarla
Para crear una clave, primero hay que abrir todas las claves jerrquicamente superiores a
esa clave a crear. En este ejemplo vamos a crear una clave de la siguiente forma:
HKEY_CURRENT_USER/Software/GuiadelEstudiante/Colores
La clave HKEY_CURRENT_USER existe, ya que es una de las de ms alto nivel. La clave
Software tambin existe, ya que vienen predeterminada. La que posiblemente no existe es
la de GuiadelEstudiante, y tampoco la de Colores dentro de ella. Estas claves no existirn
en principio, pero una vez que las hayamos creado, ya pueden existir. Por lo tanto
deberemos comprobar si existen. Esta clave va a tener varios valores. Se refiere a los
valores del color de un programa, y tendr los colores de Fondo, Etiquetas, Letras y
Desplegables. Aunque el color se expresa con un nmero, aqu lo vamos a introducir de
momento como una cadena de caracteres.
El cdigo para crear la
clave lo introducimos en
un botn de nombre
cmdCrearClave
Private Sub cmdCrearClave_Click()
Dim LpClass As String
Dim Manejador1 As Long, Manejador2 As Long, Manejador3 As Long, Disposicion As Long
'Abre la clave HKEY_CURRENT_USER/Software y obtiene el handle (Manejador1)
RegOpenKeyEx HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, Manejador1
'Crea la clave GuiadelEstudiante como subclave de HKEY_CURRENT_USER/Software. Si ya
existe. la abre
RegCreateKeyEx Manejador1, "GuiadelEstudiante", 0, LpClass, _
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, 0, Manejador2, Disposicion
'Si ha ocurrido algn error, Manejador2 sera 0
If Manejador2 = 0 Then
MsgBox "Error durante la creacin de la clave!"
582
Exit Sub
End If
'Si no ha fallado (Manejador2 <> 0) creamos la clave Colores dentro de la clave
GuiadelEstudiante
RegCreateKeyEx Manejador2, "Colores", 0, LpClass, REG_OPTION_NON_VOLATILE,
primero
las
subclaves.
Deberemos
ir
borrando
en
orden
ascendente. Una vez borradas las claves, cerramos las claves superiores a la
borrada. En el siguiente ejemplo se borra la clave GuiadelEstudiante y su
subclave, Colores
Private Sub cmdEliminarClave_Click()
Dim Manejador1 As Long, Manejador2 As Long, Manejador3 As Long, Disposicion As
Long
'Abre la clave HKEY_CURRENT_USER/Software y obtiene el handle (Manejador1)
RegOpenKeyEx HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, Manejador1
'comprueba que la funcin se ha ejecutado correctamente. Si no es as, sale del
procedimiento
If Manejador1 = 0 Then Exit Sub
'Abre la clave GuiadelEstudiante que es subclave de la anterior
RegOpenKeyEx Manejador1, "GuiadelEstudiante", 0, KEY_ALL_ACCESS, Manejador2
If Manejador2 = 0 Then Exit Sub
'Borra ya la clave Colores
RegDeleteKey Manejador2, "Colores"
'Cerramos la clave GuiadelEstudiante. Podramos no cerrarla
RegCloseKey Manejador2
'Borramos la clave GuiadelEstudiante
RegDeleteKey Manejador1, "GuiadelEstudiante"
'Cerramos la clave HKEY_CURRENT_USER
RegCloseKey Manejador1
End Sub
Para que todas estas funciones puedan trabajar es necesario haberlas declarado
previamente. La declaracin puede hacerse, o bien en la seccin de declaraciones de un
583
KEY_READ
((STANDARD_RIGHTS_READ
Or
KEY_QUERY_VALUE
Or
Or
KEY_WRITE
((STANDARD_RIGHTS_WRITE
Or
KEY_SET_VALUE
KEY_SET_VALUE
Or
KEY_CREATE_SUB_KEY
Or
KEY_ENUMERATE_SUB_KEYS
Or
584
Private Declare Function RegOpenKey Lib "advapi32.dll" Alias "RegOpenKeyA" (ByVal hKey
_ As Long, ByVal lpSubKey As String, phkResult As Long) As Long
Private Declare Function RegEnumKeyEx Lib "advapi32.dll" Alias "RegEnumKeyExA" (ByVal
_ hKey As Long, ByVal dwIndex As Long, ByVal lpName As String, lpcbName As Long,
ByVal _ lpReserved As Long, ByVal LpClass As String, lpcbClass As Long, lpftLastWriteTime
As Any) _ As Long
Private Declare Function RegEnumValue Lib "advapi32.dll" Alias "RegEnumValueA" (ByVal _
hKey As Long, ByVal dwIndex As Long, ByVal lpValueName As String, lpcbValueName As _
Long, ByVal lpReserved As Long, lpType As Long, lpData As Any, lpcbData As Long) As
Long
Private Declare Function RegCreateKeyEx Lib "advapi32.dll" Alias "RegCreateKeyExA"
(ByVal hKey As Long, ByVal lpSubKey As String, ByVal Reserved As Long, ByVal LpClass _
As String, ByVal dwOptions As Long, ByVal samDesired As Long, lpSecurityAttributes As _
Long, phkResult As Long, lpdwDisposition As Long) As Long
Private Declare Function RegDeleteKey Lib "advapi32.dll" Alias "RegDeleteKeyA" (ByVal _
hKey As Long, ByVal lpSubKey As String) As Long
Vamos a ver ahora como se introducen los datos en las claves. Para introducir cada dato,
debemos introducir el nombre y el valor de cada uno de ellos.
Funcin RegSetValueEx
Guarda un dato en una clave previamente abierta. Con esta funcin, puede tambin
modificar el valor y el tipo de informacin que almacena ese dato.
Declaracin
Declare Function RegSetValueEx Lib "advapi32.dll" Alias "RegSetValueExA" (ByVal hKey As
Long, ByVal lpValueName As String, ByVal Reserved As Long, ByVal dwType As Long,
lpData As Any, ByVal cbData As Long) As Long
(Si declara el parmetro lpData como String, debe pasarlo por valor - By Val lpData As
String)
hKey es el Handle de la clave. Ser el valor devuelto por la funcin RegOpenKeyEx
en el parmetro phkResult.
lpValueName
Reserved
debe ponerse a 0
dwType
cbData
Funcin RegQueryValueEx
Devuelve el tipo y el valor de un dato almacenado en una clave abierta.
Declaracin
Declare Function RegQueryValueEx Lib "advapi32.dll" Alias "RegQueryValueExA" (ByVal
hKey As Long, ByVal lpValueName As String, ByVal lpReserved As Long, lpType As Long,
lpData As Any, lpcbData As Long) As Long
(Si se declara el parmetro lpData como String, debe pasarse por Valor -By Val).
hKey Es el handle de una clave abierta.
lpValueName
Sigamos con el ejemplo prctico. Vamos a introducir y leer valores en una clave.
586
Para poner el valor a un dato de una clave, esa clave debe estar abierta. Se irn abriendo
las claves de forma jerrquica hasta llegar a la clave deseada. Una vez abierta esa clave,
se utilizar la funcin RegSetValueEx. Luego se cierran todas las claves en orden inverso
a la apertura.
Private Sub cmdPonerValor_Click()
Dim Manejador1 As Long, Manejador2 As Long, Manejador3 As Long
Dim Var_lpValueName As String, Var_lpData As String, Var_cbData As Long
Var_lpValueName = TbNombreDato
TbNombreDato y TbValorClave son dos TextBox
Var_lpData = TbValorClave
donde se introducen el nombre del dato y su
Var_cbData = Len(Var_lpData)
valor respectivamente.
RegOpenKeyEx HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, Manejador1
If Manejador1 = 0 Then Exit Sub Comprueba que se ha abierto correctamente
RegOpenKeyEx Manejador1, "GuiadelEstudiante", 0, KEY_ALL_ACCESS, Manejador2
If Manejador2 = 0 Then Exit Sub
RegOpenKeyEx Manejador2, "Colores", 0, KEY_ALL_ACCESS, Manejador3
RegSetValueEx Manejador3, Var_lpValueName, 0, REG_SZ, ByVal Var_lpData, ByVal _
Var_cbData
RegCloseKey Manejador3
RegCloseKey Manejador2
RegCloseKey Manejador1
End Sub
Para leer un dato hay que proceder de forma similar, abriendo jerrquicamente las claves
hasta
llegar
la
clave
leer,
una
vez
abierta,
proceder
con
la
funcin
RegQueryValueEx. Recuerde que esta funcin hay que ejecutarla 2 veces para conseguir
el valor del dato.
RegCloseKey Manejador3
RegCloseKey Manejador2
RegCloseKey Manejador1
LValorClaveRet = Trim(Var_lpData)
LTamanoValor = Var_lpcbData
End Sub
Podemos aprovechar la primera ejecucin de la funcin para leer el dato lpcbData que nos
indica el tamao de lpData. A continuacin hacemos que la variable Var_lpData tenga ese
tamao, rellenando tantos caracteres con espacios. Es otra forma de hacer lo mismo.
Private Sub cmdLeerValor2_Click()
Dim Manejador1 As Long, Manejador2 As Long, Manejador3 As Long
Dim Var_lpValueName As String, Var_lpType As Long, Var_lpData As String, Var_lpcbData
As Long
Dim Resp As Long
Var_lpValueName = Trim(TbNombreDato)
Var_lpType = 1
RegOpenKeyEx HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, Manejador1
If Manejador1 = 0 Then Exit Sub
RegOpenKeyEx Manejador1, "GuiadelEstudiante", 0, KEY_ALL_ACCESS, Manejador2
If Manejador2 = 0 Then Exit Sub
RegOpenKeyEx Manejador2, "Colores", 0, KEY_ALL_ACCESS, Manejador3
If Manejador3 = 0 Then Exit Sub
'Leemos el valor de Var_lpcbData
RegQueryValueEx Manejador3, Var_lpValueName, 0, Var_lpType, ByVal Var_lpData,
Var_lpcbData
'Hacemos que Var_lpData tenga el tamao obtenido en Var_lpcbData
Var_lpData = String(Var_lpcbData, " ")
RegQueryValueEx Manejador3, Var_lpValueName, 0, Var_lpType, ByVal Var_lpData,
Var_lpcbData
RegCloseKey Manejador3
RegCloseKey Manejador2
RegCloseKey Manejador1
LValorClaveRet = Var_lpData
LTamanoValor = Var_lpcbData
End Sub
Vamos a ver ahora como podemos borrar un valor. Se usa para ello la funcin
RegDeleteValue
Funcin Function RegDeleteValue
Elimina un valor dentro de una clave.
Declaracin
Declare Function RegDeleteValue Lib "advapi32.dll" Alias "RegDeleteValueA" (ByVal hKey
As Long, ByVal lpValueName As String) As Long
HKey
LpValueName
588
lpType
lpData
lpcbData
589
Las variables que van a contener datos tipo string hay que
declararlas con un tamao superior al que van a tener (P.e. Var_lpValueName As String *
255) o rellenarlas previamente con un nmero de caracteres superior al tamao que van a
tener. El carcter ideal son los espacios, ya que luego se pueden eliminar con Trim [Se
realiza en las lneas Var_lpValueName = Space(255) y
variables Long que almacenan el tamao de las variables string hay que darles un valor
superior al que van a tener en la funcin (Var_lpcbValueName = 255 y Var_lpcbData =
255) Observe que se us la sintaxis de VarLong = Funcin (Parmetros) para que pueda
devolvernos el nmero 0 259, dependiendo de si hay o no hay elementos con ese ndice.
Private Sub cmdVerValores_Click()
Dim Manejador1 As Long, Manejador2 As Long, Manejador3 As Long
Dim I As Long, Var_lpValueName As String, Var_lpcbValueName As Long
Dim Var_lpType As Long, Var_lpData As String, Var_lpcbData As Long
Dim Resp As Long
RegOpenKeyEx HKEY_CURRENT_USER, "Software", 0, KEY_ALL_ACCESS, Manejador1
RegOpenKeyEx Manejador1, "GuiadelEstudiante", 0, KEY_ALL_ACCESS, Manejador2
RegOpenKeyEx Manejador2, "Colores", 0, KEY_ALL_ACCESS, Manejador3
Do While Resp = 0
Var_lpValueName = Space(255)
Var_lpData = Space(255)
Var_lpcbValueName = 255
Var_lpcbData = 255
Resp = RegEnumValue(Manejador3, I, Var_lpValueName, Var_lpcbValueName, 0,
Var_lpType, ByVal Var_lpData, Var_lpcbData)
Var_lpValueName = Left(Var_lpValueName, Var_lpcbValueName)
Var_lpData = Left(Var_lpData, Var_lpcbData)
List1.AddItem I & " - " & Trim(Var_lpValueName) & " - " & Trim(Var_lpData)
I=I+1
Loop
RegCloseKey Manejador3
RegCloseKey Manejador2
RegCloseKey Manejador1
End Sub
Funcin RegEnumKeyEx
Devuelve los nombres de las subclaves de una clave del registro previamente abierta. Esta
funcin obtiene el nombre de una nica subclave cada vez que se le llama, por lo que para
leerlos todos, es necesario recurrir a llamadas en bucle.
Declaracin
590
dwIndex
Este buffer va a
LpClas sin contar el carcter nulo de terminacin. Este parmetro debe ser
Null solamente cuando LpClass sea Null
LpftLastWriteTime
591
para poder realizar todas las funciones que una aplicacin normal pueda hacer sobre el
registro.
592
End If
End If
' Ahora mete el contenido de LongBuffer() en PrintInfo()
If NumPrinters <> 0 Then ReDim PrintInfo(0 To NumPrinters - 1) As PRINTER_INFO_1
'PrintInfo contiene a su vez 4 variables que almacenan toda la informacin de la
impresora
'Recordamos la definicin de PrintInfo
'Private Type PRINTER_INFO_1
' flags As Long
' pDescription As String
' pName As String
' pComment As String
'End Type
For C = 0 To NumPrinters - 1
'Bucle que coloca cada juego de informacin de
LongBuffer() en cada elemento de PrintInfo.Longbuffer(4 * c) = .flags, longbuffer(4 * c +
1) = .pDescription, etc.
'Para los valores tipo String, previamente se rellenan de espacios con la funcin Space y
luego les introduce el valor obtenido mediante la funcin lstrcpy.
PrintInfo(C).flags = LongBuffer(4 * C)
PrintInfo(C).pDescription = Space(lstrlen(LongBuffer(4 * C + 1)))
RetVal = lstrcpy(PrintInfo(C).pDescription, LongBuffer(4 * C + 1))
PrintInfo(C).pName = Space(lstrlen(LongBuffer(4 * C + 2)))
RetVal = lstrcpy(PrintInfo(C).pName, LongBuffer(4 * C + 2))
PrintInfo(C).pComment = Space(lstrlen(LongBuffer(4 * C + 3)))
RetVal = lstrcpy(PrintInfo(C).pComment, LongBuffer(4 * C + 3))
Next C
' Presenta el nombre de las impresoras
For C = 0 To NumPrinters - 1
LbPrinters.AddItem PrintInfo(C).pName
Next C
End Sub
El cdigo no est nada mal. Aunque lleva
comentarios con el fin de entender el
funcionamiento de esta funcin, hay que reconocer
que es largo. El resultado puede verse en la figura.
Estn todas las impresoras disponibles.
Pero vamos a ver otro cdigo que hace lo mismo sin usar Apis.
Private Sub cmdBuscarPrinters_Click()
Dim I As Integer
For I = 0 To Printers.Count - 1
LbBuscaPrinters.AddItem Printers(I).DeviceName
Next I
End Sub
El resultado es el de la figura de la izquierda. Seis
lneas frente a dos pginas. El buen programador usa la
sencillez de cdigo como su mejor arma. Y si se pueden
usar 6 lneas en vez de 30, hay que usar 6 lneas.
594
La razn de que la propiedad DeviceName del objeto Printer nos d el nombre de las
impresoras es que ese cdigo largo de la pgina anterior ya est implementado en Visual
Basic.
Solamente nos falta satisfacer la curiosidad de cmo se selecciona una impresora (botn
inferior) Con Apis? Se puede. Desea escribir otras dos pginas de cdigo, o le es
suficiente con este?
Private Sub cmdSeleccionarPrinter_Click()
If LbBuscaPrinters = "" Then
MsgBox "Debe elegir una impresora"
Exit Sub
End If
Dim sImpresora As String, pPrinter As Printer
sImpresora = LbBuscaPrinters.Text
' Buscamos la impresora selecionada en la lista entre todas las impresoras existentes
For Each pPrinter In Printers
If UCase(pPrinter.DeviceName) = UCase(sImpresora) Then
Set Printer = pPrinter
'A partir de ahora, pPrinter ser la impresora elegida a la que VB dirigir la
impresin cada vez que citemos Printer.Print.
Exit For
End If
Next
End Sub
De las APIs queda mucho por estudiar. Pero ya debe ser el alumno quien ahonde en ello
segn sus propias necesidades. Creo que con lo expuesto hay suficiente para empezar.
Visual Basic - Gua del Estudiante Cap. 18
Visual Basic e Internet
Internet es la tentacin en la que actualmente todos los estudiantes quieren caer. Y tienen
motivos para ello. Internet ofrece unas posibilidades de comunicacin como nunca las ha
habido, lo que brinda unas oportunidades inmensas al programador si analiza de forma
pausada lo que la red le puede ofrecer.
Y digo si las analiza de forma pausada porque esa tentacin en la que caen todos los
estudiantes es pretender crear un navegador similar al Internet Explorer o al Netescape,
un correo que supere al Eudora y un programa de FTP que sea capaz de bajarle la
Enciclopedia Britnica en menos de media hora. Pero hay que ponerse con los pies en la
tierra y comprender que esos programas llevan mucho trabajo de muchos programadores,
mucho tiempo de prueba y unos medios econmicos y comerciales tras ellos que hacen
que esos productos tengan que ser necesariamente mejores que lo que puede hacer un
estudiante, por mucho inters e ilusin que ponga.
Sin embargo s puede ser muy ilustrativo que en este curso nos propongamos la meta de
hacer un programa que sea al tiempo el mejor navegador, el mejor correo (por dos
procedimientos), y el mejor FTP que se pueda concebir, y encima que pueda hacer chat,
ping y Telnet. Ser el mejor, sin duda, porque ser el nico que nos permita aprender a
manejar los controles que Visual Basic nos tienen reservados para los entornos IP.
Nota para alumnos expertos. Si de verdad es Ud. un experto y se lo sabe todo sobre IP
puede saltar directamente al tema Controles de Visual Basic para las redes IP. La
595
coleccin Gua del Estudiante est escrita pensando en quien no sabe y quiere saber. Por
eso no puedo pasar pos alto conceptos de nomenclatura de redes IP que se repetirn a lo
largo del captulo, y que seguro que a ms de un alumno le aportarn nuevos
conocimientos. Si pese a ser un experto, su humildad le aconseja lerselo, ver que a lo
mejor se le aclara ms de un concepto.
Redes IP. Protocolos de comunicacin en redes IP
Una red IP es una red de comunicacin basada en la transmisin bidireccional de paquetes.
Cuando decimos esto queremos expresar que la comunicacin entre dos puntos de la red
(entre dos ordenadores conectados a la red) no es continua, sino que la informacin se
parte en origen en pequeos trozos que se envan por la red hasta el destino. Una vez all,
se vuelven a poner cada uno de los paquetes en su sitio para volver a formar el bloque de
informacin que tenamos en origen. Esta tcnica permite compartir al mismo tiempo los
recursos de la red por muchos usuarios, sin que ninguno de ellos pueda bloquear la red por
el hecho de enviar una gran cantidad de informacin. Cada usuario podr enviar el mismo
nmero de paquetes por unidad de tiempo (ms o menos) por lo tanto quien deba enviar
ms informacin tardar ms tiempo que otro que tenga menos informacin. Y todo sin
llegar a bloquear la red. Eso s, cuantos ms usuarios estn presentes en un determinado
momento, ms lenta la veremos, ya que nos corresponder menos nmero de paquetes
por unidad de tiempo.
El hecho de que la informacin original se trocee en paquetes que se envan a la red
implica poner una direccin de destino a cada uno de esos paquetes (para saber a quien
van dirigidos) y la direccin del origen, (para saber quien lo enva). De esta forma, la red
sabe a quien debe entregar el paquete y el destino sabe de quien procede. Todo esto lo
hace el protocolo IP (Internet Protocol) Esto es como si IP trabajase solamente de cartero.
Coge paquetes en un buzn y los enva a su destinatario sin importarle el contenido del
paquete. Luego veremos lo de la direccin. Lo cierto es que el paquete llega al destino.
A este nivel de comunicacin le llamaremos Nivel de Red. Si lo prefiere, tambin le
puede llamar Nivel de Enlace. Es problema de terminologa. No se complique la vida. Al
protocolo IP le podemos denominar por tanto, Protocolo de Red.
Lo que no sabe el destino es el orden en el que tiene que colocar el paquete dentro del
bloque total de informacin. Debido a que el camino seguido por los paquetes no tiene
porqu ser el mismo para todos, es posible que se reciba primero un paquete que se ha
transmitido con posterioridad. Por lo tanto ser necesario poder establecer el nmero de
orden de cada uno de los paquetes dentro del grupo total de paquetes que se han
generado para la transmisin. Tambin ser necesario en ciertos casos conocer si el
destino ha recibido correctamente el paquete. Estas cosas las hace el Protocolo de
Transporte.
El protocolo IP tiene dos protocolos de transporte: el TCP y el UDP.
El TCP establece una comunicacin en la que el origen enva un paquete y espera la
confirmacin del receptor de que lo ha recibido. Si pasa un determinado tiempo sin recibir
esa confirmacin vuelve a enviar el mismo paquete. Pudo haberse perdido el paquete que
haba enviado o tambin pudo perderse la confirmacin. En cualquier caso el origen vuelve
a enviar y el receptor puede saber perfectamente lo que ha ocurrido y colocar el paquete
en su sitio si se haba perdido inicialmente, o descartarlo si la repeticin se ha debido a que
596
se haba perdido la contestacin. Cada paquete lleva un nmero que indica el nmero de
orden de ese paquete dentro del bloque total. El protocolo TCP es muy seguro. Porque
adems de lo expuesto, tiene un procedimiento de clculo de una Checksum que permite
saber si un paquete ha llegado sin ningn tipo de error. Si detecta error en un paquete,
pide repeticin. Tambin lleva el nmero del puerto por el que debe entrar esa informacin.
Ver mas adelante lo que es un puerto. Mediante el protocolo TCP podemos transportar un
fichero enorme sin ningn tipo de error. Es el que se usa normalmente en las redes IP. Por
cierto, Sabe que significa TCP? Transmision Control Protocol , o como dira Cervantes,
Protocolo de Control de Transmisin.
El protocolo UDP (que significa User Datagram Protocol) o Protocolo de Datagramas de
Usuario es un protocolo que enva paquetes sin esperar respuesta. No le preocupa que los
paquetes se pierdan. UDP usa menos recursos y por lo tanto es ms rpido. Dependiendo
del tipo de informacin que se enve, a lo mejor resulta ms prctico enviar paquetes UDP
que paquetes TCP. Sobre todo cuando son informaciones muy cortas, que no sobrepasan la
capacidad de un paquete. Dicen que no es un sistema seguro, pero eso depender en
gran medida del programa que hagamos. Dado que no es un sistema seguro, deberemos
implementar en el programa la secuencia de envo - confirmacin de recibido que tiene el
TCP. Obviamente eso lo va a complicar un poco. Quizs por eso el protocolo usado
generalmente para transmisin de informacin es el TCP.
Le ser muy familiar el TCP/IP. Es la combinacin del protocolo TCP con IP. Y es momento
ahora de explicar con un ejemplo simulado como funciona TCP/IP. Imagnese que TCP
coge el bloque de informacin a transmitir y lo trocea en varios paquetes. A cada uno de
ellos le aade el nmero de orden que tiene ese paquete dentro del bloque total de
informacin, calcula el Checksum que le corresponde y se lo anexa. Con esos datos ya
somos capaces de volver a restituir el bloque de informacin completo. Pero hace falta
todava enviarlo al destinatario. Para ello se lo entregamos al protocolo IP, que lo mete en
un "sobre" donde le apunta la direccin y el remitente. Y lo suelta a la red. La red
solamente ve la direccin y el remitente (Por favor que nadie se lo crea a pies juntillas, no
es as exactamente, esto es solamente un ejemplo) y reencamina el paquete a travs de
los enrutadores (routers) para hacerlo llegar a su destino. El destinatario abre el sobre,
analiza el Checksum, mira el nmero de paquete que es, comprueba que no lo tiene
todava, y entonces crea un pequeo paquete en el que dice que ha recibido correctamente
el paquete con ese nmero. Lo mete en un sobre IP donde pone como direccin el
remitente del paquete recibido y como remite su propia direccin, y lo enva a la red. Ya se
encargar la red de hacerlo llegar a su destino. Al recibirlo (lo recibe el terminal que
estamos llamando origen) ve que le dan conformidad al paquete enviado, y se
despreocupa ya de ese paquete. Otro tema sera que el destino hubiera recibido el paquete
y le saliera el Checksum errneo. Le mandara un paquete al origen comunicndoselo.
Entonces el origen se lo volvera a enviar. Lo mismo ocurrira si el origen, pasado cierto
tiempo, no ha recibido confirmacin de recibo de un paquete, sea afirmativa o negativa
esta confirmacin. El origen vuelve a enviar el paquete, hasta que reciba confirmacin de
que fue bien recibido. Se da cuenta ahora de porque, de vez en cuando, parece que se
paraliza la red? El orden de envo de paquetes no tiene porqu ser estricto. No es
necesario haber recibido la conformidad del paquete anterior para enviar el siguiente.
Veamos ahora lo de la direccin. Decamos que IP pone la direccin del destinatario y del
remitente. Esas direcciones son un conjunto de cuatro nmeros del 0 al 255, separados
por un punto. Por ejemplo, podra ser 195.236.12.56 As de fras son las direcciones de
Internet. Como cada nmero puede tomar los valores del 0 al 255, la numeracin total de
Internet puede llegar a 4.228.250.625 No son mucho esos cuatro mil doscientos millones.
Piense que somos seis mil millones de personas en el mundo. Por eso ha habido que
buscar formas de aprovechar al mximo las direcciones IP. No es objeto de este curso su
597
estudio, pero digamos que se logra a base de que las redes de rea local conectadas a
Internet se conectan solamente con un nmero, e internamente tienen otro (el nmero
interno no coincide con ninguno de Internet, pero se repite en todas las redes de rea
local). Otra forma de aprovechar la numeracin es asignar nmeros dinmicamente. Eso
ocurre cuando nos conectamos a Internet desde nuestras casas. Mientras dura la conexin,
nuestro ISP (Proveedor de Servicio de Internet) nos cede un nmero IP de los que le han
asignado a l. Cuando nos desconectamos, ese nmero se lo da al siguiente que se
conecte. Por eso, en nuestras casas, cuando nos conectamos a travs de la conexin
telefnica a redes, no tendremos siempre el mismo nmero IP.
Esta Direccin IP la usa el Protocolo de Red, es decir El Internet Protocol, que como
decamos antes, era como un cartero que recoge una carta del Origen y la pone en el
Destino sin saber que es lo que contiene. Ese origen y destino son mquinas, es decir,
ordenadores que estn conectados a la red.
Nota acerca de las direcciones IP. Existe una serie de direcciones IP que no se pueden
usar en Internet debido a que estn reservadas para redes de rea local. Esto se hace as
para que nunca pueda haber error entre direcciones. Si asignamos a un equipo interior a
una red un nmero posible en Internet, un Router que est separando la red de rea local
del mundo Internet podra equivocarse y enviar hacia fuera un paquete interno a nuestra
red. Por eso se han reservado esas direcciones. Son estas
De la 10.0.0.0 a la 10.255.255.255
De la 172.16.0.0 a la 172.31.255.255
De la 192.168.0.0 a la 192.168.255.255
Tampoco se pueden usar las direcciones:
0.0.0.0 a la 0.255.255.255 Se usan para llamar al ordenador local principal
255.0.0.0 a la 255.255.255.255 Son direcciones de difusin (transmisin hacia todos
los equipos)
127.0.0.0 a la 127.255.255.255 que se usan para funciones internas a la mquina.
Tcnicamente hablando se dice que estas direcciones son para LoopBack
IP Versin 6
Como esto de Internet lo nico que puede hacer es subir, y los 4.200 millones de
direcciones se van a quedar cortas tarde o temprano, se est definiendo una nueva versin
de direcciones IP, la esperada versin 6, que consistir en direcciones de 128 bits, frente a
los 32 actuales. Si pensamos que cada bit que ampliemos doblamos la capacidad, vemos
que la cifra de direcciones posibles sobrepasa las necesidades actuales. (Por sobrepasar,
sobrepasa la capacidad de mi calculadora y el resultado es Overflow). Esta solucin de 128
bits permitir conectar cualquier ordenador de una RAL con un nmero IP verdadero, es
decir, un nmero de la red Internet. Pero eso ya lo veremos en la prxima Gua del
Estudiante.
Puertos de Comunicacin.
Vamos a ver un concepto nuevo: el Puerto de Comunicacin. Hasta ahora hemos hablado
de direcciones de mquina que son las que ve el protocolo IP. Dentro de una mquina
podemos tener varios servicios (Correo, Ftp, www, o cualquier otro programa que nosotros
hagamos) Cuando llega uno de esos paquetes que contienen informacin, la mquina
598
debe saber reconocer a que servicio est destinado. Eso lo sabe mediante el Puerto de
Comunicacin al que va dirigido el paquete.
El puerto de Comunicacin no es un puerto fsico. Volvemos a lo de siempre: es una forma
de hablar. Lo mismo que la direccin IP nos conduce a una mquina, un puerto nos lleva a
un servicio dentro de esa mquina. Cuando enviamos una carta, el cartero (Protocolo IP) la
lleva al domicilio indicado en el sobre. Imagnese que ese domicilio es en edificio de
oficinas. Debemos saber ahora el nmero de la oficina donde la debemos entregar. Pero el
trabajo del cartero ya finaliz cuando nos ha entregado la carta en portera. Para saber el
nmero de la oficina debemos abrir el sobre y ver a que oficina est dirigida. De esto se
encarga el Protocolo de Transporte (TCP o UDP) que analiza el contenido del paquete y
mira el valor de dos bytes que indican el nmero del puerto. Esos dos bytes son los que
indicaran el nmero de la oficina en ese edificio de nuestro smil postal. Pero tenga en
cuenta siempre que el puerto no indica por donde entra la informacin a la mquina (entra
por la placa de red, que tiene asociado una direccin IP) sino el servicio (un programa) al
que va destinada la informacin. Dado que el nmero del puerto se expresa con dos
bytes, los nmeros de puerto posibles son del 1 al 65536.
Los 1024 primeros puertos estn reservados para distintos servicios de comunicacin
dentro de la mquina. No los use para sus aplicaciones. Los servicios ms conocidos
utilizan los siguientes puertos:
1 - tcpmux
5 - rje
7 - echo
9 - discard 11 - systat
13 - daytime
15 - netstat 17 - qotd
18 - send/rwp19 - chargen 20 - FTP (data)
21 - FTP
(control)
22 - ssh, pcAnywhere
23 - Telnet
25 - SMTP
27 - ETRN
29 - msg-icp
31 - msg-auth
33 - dsp
37 - time
38 - RAP
39 - rlp
42 - nameserv/WINS
43 - whois, nickname
49 - TACACS/Login Host
Protocol
50 - RMCP
53 - DNS
57 - MTP
59 - NFILE
63 - whois++ 66 - sql*net
67 - bootps 68 - bootpd/dhcp
69 - Trivial File Transfer Protocol (tftp)
70 - Gopher 79 - finger
80 - www-http
88 - Kerberos, WWW
95 supdup
96 DIXIE
98 - linuxconf 101 - HOSTNAME
102 - ISO, X.400, ITOT
105 - cso
106 poppassd
109 - POP2
110 - POP3
111 - Sun RPC Portmapper 113 - identd/auth
115 - sftp
117 - uucp
119 - NNTP 120 - CFDP 123 NTP
124 - SecureID
129 - PWDGEN
133 - statsrv 135 loc-srv/epmap
137 - netbios-ns 138 - netbios-dgm (UDP)
139 - NetBIOS
143 IMAP 144 NewS
152 BFTP
153 - SGMP 161 - SNMP
175 vmnet 177 - XDMCP 178 -NextStep Window Server
179 - BGP
180 - SLmail
admin
199 - smux 210 - Z39.50 218 MPP
220 - IMAP3 259 - ESRO 264 -FW1_topo
311 Apple WebAdmin
350 - MATIP type A
351 - MATIP type B
363 - RSVP tunnel
366 - ODMR (On-Demand Mail Relay)
387 - AURP (AppleTalk Update-Based Routing Protocol) 389 - LDAP
407 - Timbuktu
434 - Mobile IP
443 ssl
444 - snpp, Simple Network Paging Protocol
445 SMB
458 - QuickTime TV/Conferencing
468 - Photuris500 - ISAKMP, pluto
512 - biff, rexec
513 who, rlogin
514 - syslog, rsh
515 lp, lpr, line printer
517 - talk
520 - RIP (Routing Information Protocol) 521 RIPng 522 - ULS
543 - KLogin, AppleShare over IP
545 QuickTime
548 AFP
554 - Real Time Streaming Protocol
555 - phAse Zero
563 NNTP over SSL
575 - VEMMI 581 Bundle Discovery Protocol
593 - MS-RPC 608 - SIFT/UFT
626 Apple ASIA
631 - IPP (Internet Printing Protocol)
635 mountd (Linux)
636 sldap 642 - EMSD 648 - RRP (NSI Registry Registrar Protocol)
599
601
El protocolo TCP/IP no se utiliza solamente en Internet. Las redes de Area Local en su gran
mayora lo utilizan. Por lo tanto lo que se va a explicar en este captulo no solamente le va
a servir para Internet. Puede hacer programas que trabajen sobre una red de rea local
que usa los mismos controles.
Forma de conectarse a Internet
Para conectarse a Internet se necesita que un suministrado de servicios de Internet (ISP)
nos conecte. Internet es una red muy grande, pero que se diferencia muy poco de una red
de rea local. Solamente en su extensin. Igual que una red de rea local tiene puntos de
conexin, Internet tambin los tiene, pero esos puntos no estn en cualquier esquina.
Estn precisamente en las dependencias de los ISP, conectados a la red a travs de lneas
de comunicacin de datos suministradas por una empresa de telecomunicaciones, que en
Espaa es casi con carcter de monopolio, Telefnica. Esos ISP que tienen la conexin real
a Internet deben suministrar una parte de esa conexin a cada usuario que se quiera
conectar. Existen varias formas de hacerlo: ADSL, Conexin telefnica a redes, conexin a
travs de una red de rea local. Veamos como se conecta de cada una de estas formas,
utilizando palabras sencillas, aunque ello vaya en detrimento de la rigurosidad tcnica.
ADSL (Asimetric Data Suscriber Line). Aprovechando una lnea telefnica existente, se
enva superpuesto al servicio telefnico unas seales de datos, que no interfieren para
nada el uso del telfono conectado a esa lnea. Esta tcnica supone una modulacin de los
datos sobre dos portadoras a varios cientos de kilociclos (la frecuencia de la portadora
depende del ancho de banda contratado) por lo que las prdidas son elevadas. Esto implica
que el mdem ADSL instalado junto al terminal telefnico deber estar muy cerca de la
central telefnica desde la que envan los datos (Creo que el mximo son unos 2
kilmetros) Por lo tanto, es difcil instalar esta opcin en abonados rurales, o en zonas
urbanas con instalacin de cables muy viejas. Pueden contratarse velocidades de 128 a
512 Kbytes en sentido Usuario -> Internet, y de 256 a 2048 en sentido Internet ->
Usuario. Esta asimetra se debe a que normalmente son mas los datos que se bajan que
los que se envan, y de esta forma se optimizan los recursos del sistema. Mediante esta
conexin, estamos conectados continuamente a Internet, y generalmente se tiene un
nmero IP real fijo, pero existen compaas que lo que estn enviando a travs de esa
conexin de alta velocidad es una toma de una red de rea local que a su vez est
conectada a Internet. El nmero IP, en el caso que le den una nmero real de Internet,
ninguna empresa le garantiza que se lo vayan a conservar para siempre. Creo que ADSL es
hoy por hoy el mejor sistema de conexin a Internet.
Conexin mediante la Conexin Telefnica a redes. Para esta forma de conexin, los
ISP disponen de varias direcciones IP. Es muy normal que cada ISP tenga uno o varios
paquetes 256 direcciones, pero eso depender del trafico real que tenga. Este ISP se va a
reservar algunas de esas direcciones para su uso particular (Una al menos para que se le
pueda llamar y comunicarse con otros servidores desde dentro de la red, otra para el
servidor de pginas Web, servidor de correo, servidor DNS si lo tiene, etc.) y el resto las
va a asignar durante el tiempo que dure la conexin a sus clientes. Esta asignacin de
direcciones se le denomina asignacin dinmica. Cuando nos conectamos a Internet a
travs de la conexin telefnica a redes tendremos una direccin. La prxima vez
tendremos otra. Por eso, en el mbito particular no podemos dar una direccin IP para
que nos llamen, ya que es variable. Deberemos pedir la conexin a nuestro ISP que nos
pedir el nombre de usuario y la contrasea. Esta operacin la realiza el acceso telefnico
a redes de Windows. Si coinciden nombre y contrasea con las que tiene el ISP en su
banco de datos, nos asigna un nmero IP de los que tenga disponible y ya estamos
conectados.
Conexin a travs de Red de Area Local. Este es el caso de conectarse mediante una
RAL o mediante la mayora de las conexiones rpidas que nos brindan las compaas de
602
603
Hemos llegado por fin al Visual Basic puro. Vamos analizar los controles que nos tiene
preparados para explotar los recursos de la red. Para cada uno de los servicios anteriores
existe un control. Podemos resumirlos en la siguiente lista:
Para
Para
Para
Para
la conexin:
http
FTP
POP3, SMTP
Comencemos por el principio. Por el control que nos permite comunicarnos con otro
ordenador mediante TCP y UDP . El Control Winsock
Control Winsock
El control WinSock permite conectarse a un equipo remoto e intercambiar datos con los
Protocolos UDP y TCP. Ambos protocolos se pueden usar para crear la comunicacin con
cualquier servicio de los expresados anteriormente. Podemos crear tambin aplicaciones
que residan en un servidor al que accedemos desde varios clientes. Estamos en ese caso
creando aplicaciones Cliente - Servidor
El control Winsock podramos decir que es el control ms elemental de los controles que VB
dedica a las redes IP, ya que lo nico que hace por s es conectarnos. No implementa
ningn servicio. Eso se lo tenderemos que hacer nosotros con nuestro programa. Hay
controles que nos dan directamente la conexin y el servicio para el que han sido
diseados (WebBrowser, Internet Transfer Control) Con este slo tenemos la conexin,
pero con muchos datos y mucho control sobre ella. Quizs por eso este es el ms bonito.
Una vez con la conexin establecida, podemos establecer un servicio utilizando cdigo puro
y duro. Tiene esa opcin o usar los controles especficos que Microsoft y otras firmas le han
preparado para que Vd. trabaje menos.
El control Winsock hay que meterlo en la caja de herramientas. (Proyecto |
Componentes) El nombre del control es Microsoft Winsock Control 6.0 Solamente se
ve en tiempo de diseo. Tiene esta forma:
MiVariable = NombredelWinSock.LocalIP
604
MiVariable = NombredelWinsock.LocalHostName
(MiVariable ser una variable tipo String)
NombredelControlWinsock.Protocol = Valor
Valor = 0
Valor = 1
El control debe estar cerrado para poder establecer esta propiedad. Si lo tiene abierto,
debe cerrarlo previamente mediante el mtodo Close.
Cuarta tarea: Establecer los datos del equipo remoto
Aqu debemos distinguir si queremos enviar informacin o si deseamos recibirla. Ya
tenemos que comenzar a pensar en un concepto que seguro que le suena: cliente y
servidor.
Cuando un equipo quiere enviar informacin debe conocer la direccin completa del equipo
al que va a llamar. La direccin completa es su direccin IP y el puerto al que va dirigida la
informacin. Si el equipo va a recibir, lo nico que debemos decirle es el puerto por el que
605
NombredelControlWinsock.RemoteHost = 217.126.179.96
NombredelControlWinsock.RemoteHost =
FTP://ftp.laguiadelestudiante.com
VariableTipoString = NombredelControlWinsock.RemoteHost
Esta propiedad puede cambiarse en tiempo de ejecucin cuantas veces sea necesario, para
encaminar los datos transmitidos a uno u otro equipo remoto.
Otro parmetro que es necesario introducir al Winsock cuando nuestra aplicacin es una
aplicacin cliente (enva informacin)
enviar informacin. El puerto destino depender del servicio que estamos implementando
en nuestra aplicacin. Este parmetro se introduce en la propiedad RemotePort.
Propiedad RemotePort
Devuelve o establece el nmero del puerto remoto con el que conectar. El valor pasado en
esta propiedad es un Long comprendido entre 1 y 65535. El numero predeterminado es el
80.
Sintaxis
NombredelControlWinsock.RemotePort = puerto
606
transmitir datos, aunque puede asignar un puerto determinado para enviarlos es mucho
mas prudente dejar al Winsock que utilice el que quiera. De esta forma se asegura que
siempre emitir a travs de un puerto libre. (Experiencia propia: Si asigna un puerto
determinado para transmitir lo mas probable que le va a pasar es que se le cuelgue el
ordenador)
NombredelWinsock.LocalPort = Nmero
Por lo tanto, para paquetes UDP no hace falta hacer nada para establecer la comunicacin
con el equipo remoto, ni para transmitir ni para recibir.
Comunicacin por TCP
Aqu s debemos establecer previamente la conexin. De hecho, se dice de TCP que es un
protocolo orientado a conexin. Veamos que hay que hacer para transmitir y recibir con
TCP
Para el equipo cliente (Transmisor)
El equipo que desea enviar datos debe solicitar la conexin. Si existe un equipo destino con
direccin IP y el puerto adecuado, este equipo le contestar. (Vea mas adelante el mtodo
Accept) Tambin puede ocurrir que el equipo destino o no existe, o reciba la solicitud de
conexin y no la acepte. Veremos ms adelante qu ocurre en el caso de que nadie atienda
la solicitud.
La solicitud de conexin se realiza mediante el mtodo Connect
Mtodo Connect
Solicita una conexin con un equipo remoto.
Sintaxis
NombredelWinsock.Listen
Un Winsock solamente puede recibir una comunicacin. Por lo tanto, solamente podr
atender a un corresponsal. Esto no es lo que se busca en la mayor parte de los casos, sino
que lo que se pretende es estar a la escucha, y atender a todas las llamadas que entren,
pudiendo atender a dos o ms comunicaciones simultneamente.
Para lograr esto lo que hacemos es tener un Winsock permanentemente a la escucha para
recibir los sucesivos intentos de conexin de los corresponsales, y una vez que se recibe
uno, se crea una instancia del winsock, y es, con esta instancia, con la que le invocamos el
mtodo Accept para aceptarla. De esta forma tendremos tantas instancias (copias) del
winsock como comunicaciones activas, ms el winsock original que es el que se queda a la
escucha de nuevos intentos de conexin. Ni que decir tiene que, una vez terminada la
conexin, debe cerrarse la instancia correspondiente a esa conexin.
La instancia debe crearse en el procedimiento ConnectionRequest del winsock original.
La forma de crear esta instancia es mediante el procedimiento Load. Para ello, el winsock
original debe tener la propiedad Index para que de esta forma sea una matriz de controles,
aunque originalmente solo exista un elemento de esa matriz, con Index = 0. Las
instancias van a tener un nombre (Propiedad Name) igual a la del original, y un ndice
(Propiedad Index) que tendremos que ponerle en el momento de crear ese nuevo winsock.
Esto implica que deberemos llevar una lista con los ndices de las instancias creadas para
no repetir ninguno. No sirve aumentar una unidad el nmero del ndice, ya que no
podemos dejar que el nmero del ndice crezca hasta el infinito.
Evento ConnectionRequest
Se produce en el equipo local cuando el equipo remoto solicita una conexin.
Slo para aplicaciones de servidor TCP. El evento se activa cuando llega una solicitud de
conexin. A partir de la activacin de este evento, las propiedades RemoteHostIP y
RemotePort almacenan la informacin acerca del cliente.
Este evento pasa como parmetro un nmero Long con el identificador de la solicitud de
conexin. Este identificador (IdSolicitud) lo genera el servidor (el equipo que recibe) y lo
necesitaremos para aceptar la conexin mediante el mtodo Accept.
NombredelcontrolWinsock_ConnectionRequest (IdSolicitud As Long)
El parmetro idSolicitud va a identificar a esa conexin hasta que se cierre. La
identificacin la hace el winsock analizando en el datagrama entrante la direccin IP del
origen, puerto origen y puerto destino, parmetros que no pueden coincidir al mismo
tiempo con los de otra comunicacin. Este mecanismo va a permitir que el mismo winsock
reciba varias comunicaciones simultneas y sepa diferenciar una de otra
Metodo Accept
Este mtodo se utiliza para aceptar una conexin entrante cuando se est tratando un
evento ConnectionRequest.. Slo se usa con el protocolo TCP.
Sintaxis
NombredelWinsock.Accept IdSolicitud
609
El mtodo Accept debe hacerse sobre una nueva instancia del control Winsock. No es
estrictamente necesario cuando se est utilizando una conexin en la que sabemos con
certeza que no vamos a recibir ms de una llamada. En el caso de que se produzca un
nuevo intento de conexin mientras atiende a una conexin aceptada, adems de no poder
atenderlo, la experiencia nos dice que se producen problemas, que terminan generalmente
haciendo que el programa no responda e incluso colgando el equipo,
Recomiendo
encarecidamente que la conexin se establezca con una nueva instancia del winsock. Dicho
en otras palabras, que el mtodo Accept se ejecute sobre una nueva instancia, aunque la
informacin de Microsoft est un poco indefinida en este aspecto.
Veamos como se crea una nueva instancia del control. Se usa el mtodo Load. Para ello,
en el Winsock que colocamos en el proyecto le ponemos, en su propiedad Index el valor 0.
Con esto le estamos indicando que es una matriz de controles, pero solamente existe uno,
cuyo ndice es el 0. Cuando utilizamos el mtodo Load lo que hacemos es aadir un
elemento ms a esa matriz de controles.
Si el control que hemos introducido en el formulario se llamaba Wsk, y le hemos puesto su
propiedad Index = 0, para aadir el segundo elemento de esa matriz, que tendr la
propiedad Index = 1, ejecutaremos la siguiente lnea de cdigo:
Load Wsk (1)
Ahora ya tenemos una matriz con dos controles. (Indices 0 y 1) Dejaremos el winsock con
ndice 0 para seguir recibiendo peticiones de comunicacin y ejecutaremos el mtodo
Accept sobre el segundo winsock (el de Index = 1)
Wsk (1).Accept IdSolicitud
A partir de este momento, todo lo que tengamos que hacer para recoger la informacin
recibida, enviar respuestas al corresponsal, cerrar la comunicacin lo haremos con la
instancia creada para esa conexin. No se nos puede olvidar cerrar el winsock una vez
terminada la conexin y descargarlo a continuacin. Para descargarlo utilizamos la
instruccin Unload
Unload Wsk(1)
El winsock original lo seguiremos dedicando a recibir nuevas solicitudes de conexin, que a
su vez crearn nuevas instancias del winsock.
En principio no hay problema para que cada nueva instancia lleve un Index incrementado
en 1 respecto a la conexin anterior. Basta con declarar una variable tipo Long para
introducir ese ndice, y previsiblemente nunca llegaremos a superar los lmites del Long.
Ahora bien, es mucho mas elegante reutilizar los nmeros de las instancias que se van
cerrando. Para esto es necesario utilizar una variable o una matriz, donde llevemos la
cuenta de las instancias todava abiertas del winsock original.
Cada una de las instrucciones anteriores se debern hacer en los eventos apropiados del
winsock. As, el crear un nuevo winsock lo haremos en el evento ConnectionRequest, y el
descargarlo lo haremos en el evento Close.
Ya tenemos la conexin establecida. Veamos ahora otras propiedades y mtodos que nos
permitirn conocer la identidad del corresponsal y lo que hay que hacer para enviar y
recibir informacin.
Una vez establecida la conexin, mediante el mtodo Connect por parte del cliente, y el
mtodo Accept por parte del servidor, ya podemos conocer la identidad del corresponsal
mediante la propiedad RemoteHostIP
610
Evento Connect
Este evento ocurre en el Winsock que ha solicitado la conexin, cuando sta se ha
completado. Ocurre por lo tanto cuando el winsock remoto invoca el mtodo Accept. Puede
usar este evento parta conformar que se ha realizado la conexin.
Propiedad RemoteHostIP
Devuelve una cadena de caracteres con la direccin IP del equipo remoto.
NOTA. Esta propiedad es distinta de la de RemoteHost vista mas atrs. La
propiedad RemoteHost es la que se debe introducir antes de realizar la conexin,
y puede ser, bien una direccin IP de cuatro nmeros, o una DNS. RemoteHostIP
devuelve el valor de la direccin IP de cuatro nmeros, una vez que ya se ha
establecido la comunicacin. Puede consultarse esta propiedad para conocer el
nmero IP real de un sitio, conociendo solamente su DNS.
En las aplicaciones de cliente, despus de establecer la conexin con el mtodo Connect,
esta propiedad contiene la cadena IP del equipo remoto.
En las aplicaciones de servidor, despus de la llegada de una solicitud de llamada (evento
ConnectionRequest), esta propiedad contiene la cadena IP del equipo remoto que inici
la conexin.
Cuando utiliza el protocolo UDP, despus de producirse el evento DataArrival, esta
propiedad contiene la direccin IP del equipo que ha enviado los datos UDP.
Propiedad State
Permite conocer el estado del winsock y de la conexin que est realizando. Es slo de
lectura y no est disponible en tiempo de diseo. Devuelve un integer
Siantaxis
Variabletipointeger = NombredelWinsock.State
Nos puede devolver uno de los siguientes valores que corresponden a las siguientes
constantes
Valor
Constante
Estado
0
sckClosed
Cerrado
1
sckOpen
Abierto
2
sckListening
Escuchando
3
sckConnectionPending
Conexin pendiente
4
sckResolvingHost
Resolviendo Host
5
sckHostResolved
Host resuelto
6
sckConnecting
Conectando
7
sckConnected
Conectado
8
sckClosing
Cerrando la conexin
9
sckError
Ha detectado un error
Propiedad SocketHandle
Esta propiedad se usa para utilizarla con las Apis de Windows. Devuelve el manipulador del
Winsock. Es de slo lectura y no est disponible en tiempo de diseo.
611
Sintaxis
VariableTipoLong = NombredelWinsock(I).SocketHandle
Donde I es el ndice del Winsock. Como se deca ms atrs, esta propiedad solamente se
emplea usando APIS
NombredelWinsock(I).SendData datos
Donde NombredelWinsock es el nombre del winsock que debe enviar los datos, I es el
ndice de ese control (en el caso de que el winsock sea una instancia de un winsock
original, como se explic ms atrs) y Datos son los datos a enviar, por ejemplo el nombre
de una variable que los contiene o la propiedad text de un textbox donde se han escrito los
datos a enviar.
Si los datos a enviar son binarios, debern enviarse como una matriz de bytes.
Cuando pasa una cadena UNICODE, se convierte a cadena ANSI antes de enviarla a la red.
Mtodo GetData
Recupera los datos existentes en el bffer de recepcin del winsock, lo almacena en una
variable y borra el contenido del bffer.
Sintaxis
Donde
parmetro, se
VbByte
Entero
vbLong
Single
vbSingle
Simple
vbDouble
Moneda
vbCurrency Fecha
vbDate
vbBoolean
Cadena
vbString
Matriz de bytes
612
vbInteger
Double
Long
vbDouble
Booleano
vbArray + vbByte
El mtodo GetData se suele usar con el evento DataArrival, que incluye el argumento
bytesTotales. Si especifica una longMx menor que el argumento bytesTotales, obtendr el
mensaje de advertencia 10040, que indica que se perdern los bytes restantes.
Evento DataArrival
Se produce cuando llegan nuevos datos. Pasa como parmetro un Long con el nmero de
bytes recibidos.
Este evento no se producir si no recupera todos los datos con una llamada GetData. Slo
se activa cuando hay datos nuevos. Utilice la propiedad BytesReceived para comprobar la
cantidad de datos disponibles en cualquier momento.
Propiedad BytesReceived
Devuelve un Long la cantidad de datos recibidos (que estn actualmente en el bffer de
recepcin). Lgicamente es slo de lectura y no est disponible en tiempo de diseo.
Sintaxis
NombredeWinsock.BytesReceived
Mtodo PeekData
Este mtodo es similar a GetData, pero no elimina los datos extrados del bffer de
recepcin. Exixte otra diferencia, PeekData solamente funciona en las conexiones TCP.
La sintaxis es similar a la de GetData.
Sintaxis
Los parmetros de este mtodo son los mismos que para GetData.
Evento SendProgress
Se produce mientras se estn enviando datos. Pasa como parmetros los bytes enviados
desde la ltima vez que se activ el evento (bytesEnv) y los bytes que esperan a ser
enviados en el bffer de transmisin (bytesRest)
(NombredelWinsock_SendProgress (bytesEnv As Long, bytesRest As Long)
Evento SendComplete
Se produce cuando termina una operacin de envo. No pasa argumentos.
NombredelWinsock_SendComplete()
Evento Error
Se produce siempre que ocurre un error en los procesos de segundo plano (por ejemplo,
un fallo al conectar o un fallo al enviar o recibir en segundo plano). Pasa como parmetros
el cdigo de error, la descripcin del error, el scode del error, el origen del error, y un
booleano para cancelar o aceptar el que presente un cuadro de dialogo con el aviso de
error. (Los parmetros de fichero de ayuda y contexto de ayuda, personalmente no los he
visto en ninguno de los ejemplos preparados.
NombredelWinsock_Error(nmero As Integer, descripcin As String, scode As Long,
origen As String, archivoAyuda as String, contextoAyuda As Long, cancelarVista As
Boolean)
613
Valor
Descripcin
SckOutOfMemory
SckInvalidPropertyValue
SckGetNotSupported
SckSetNotSupported
SckBadState
la
7
380
394
383
40006
Sin memoria
El valor de la propiedad no es vlido
No se puede leer la propiedad
La propiedad es de slo lectura.
Protocolo o estado de conexin incorrecto para
SckInvalidArg
estaba en el
SckSuccess
SckUnsupported
SckInvalidOp
SckOutOfRange
SckWrongProtocol
transaccin
SckOpCanceled
SckInvalidArgument
multidifusin,
SckWouldBlock
especificada
SckInProgress
SckAlreadyComplete
efectuando
SckNotSocket
SckMsgTooBig
y se
SckPortNotSupported
SckAddressInUse
SckAddressNotAvailable
local.
SckNetworkSubsystemFailed
SckNetworkUnreachable
momento.
SckNetReset
de
SckConnectAborted
tiempo de
SckConnectionReset
remoto.
SckNoBufferSpace
SckAlreadyConnected
requerida.
10004 Se cancel la operacin.
10014 La direccin solicitada es una direccin de
pero el indicador no est activado.
10035 El socket es no bloqueante y la operacin
se bloquear.
10036 Se est efectuando una operacin de Winsock
bloqueante.
10037 Se complet la operacin. No se estn
operaciones bloqueantes.
10038 El descriptor no es un socket.
10040 El datagrama es demasiado grande para el bfer
truncar.
10043 El puerto especificado no es compatible.
10048 Direccin en uso.
10049 La direccin no est disponible en la mquina
10050 Error en el subsistema de red.
10051 El host no puede encontrar la red en este
10052 Expir el tiempo de espera de la conexin antes
establecer SO_KEEPALIVE.
10053 La conexin se ha cancelado al sobrepasar el
espera o por otro error.
10054 La conexin se ha restablecido desde el lado
10055 No hay espacio disponible en el bfer.
10056 El socket ya est conectado.
614
SckNotConnected
SckSocketShutdown
SckTimedout
SckConnectionRefused
SckNotInitialized
SckHostNotFound
SckHostNotFoundTryAgain
SckNonRecoverableError
SckNoData
Evento Close
Se produce cuando el equipo remoto cierra la conexin. Las aplicaciones deben usar el
mtodo Close para cerrar correctamente una conexin TCP.
El Mtodo Bind
El mtodo Bind sirve para reservar un puerto local cuando estamos trabajando en una
comunicacin UDP. Esto puede ser muy til para evitar que haya otra aplicacin
escuchando en ese mismo puerto. Hay que darse cuenta que en UDP puede haber muchas
aplicaciones escuchando el mismo puerto ya que al no establecerse una comunicacin, la
informacin que llega pueden tomarla mas de una aplicacin. (Es idntico al caso en el que
una persona hable y muchas escuchan) Si reserva un determinado puerto a un Winsock, a
ese puerto no se le puede conectar otro Winsock a escuchar a partir de ese momento. Hay
que invocar el mtodo Bind antes de invocar el mtodo Listen.
Tambin puede usar el mtodo Bind en una comunicacin TCP. Se emplea cuando hay ms
de un adaptador de red en el equipo (Un equipo con dos placas de red, y cada una de ellas
con un nmero IP). Si en ese equipo hay un Winsock, Qu nmero IP tiene?.
Podra
tomar uno de los dos indistintamente. Mediante Bind podemos asignar uno de esos
nmeros IP a un Winsock.
Mtodo Bind
Especifica el puerto local y la direccin IP local a usar en las conexiones TCP.
Sintaxis
Donde:
PuertoLocal: Puerto utilizado para realizar una conexin.
IPLOcal:
Direccin IP local sobre la que se va a establecer la conexin.
615
616
parte de la comunicacin.
Fig. 2
En esta figura se pueden ver dos partes bien diferenciadas, una en azul, (Mquina Local,
Instancias activas, Textos/Ficheros recibidos) con la parte de la aplicacin correspondiente
a la recepcin, La parte roja (Equipo remoto llamado) corresponde a la parte de
transmisin.
617
618
Fig. 3
619
Fig. 4 Este es el aspecto final del la aplicacin. Vea en el disco de ejemplos el cdigo
completo.
620
NombreDelInet.AccessType = tipo
621
Propiedad Proxy
Devuelve o establece el nombre del servidor proxy utilizado para comunicar con Internet.
Esta propiedad slo se utiliza cuando el valor de AccessType es icNamedProxy (3).
Sintaxis
NombredelInet.Proxy = proxy
Donde Proxi es el nombre del servidor que se desea usar.
Puede usar un proxi distinto para acceder con protocolo Http o Ftp, y determinar porque
puerto accede a cada uno de estos servicios. El proxi suele estar programado para que en
la parte interior de la red se acceda a los servicios externos a travs de un puerto distinto
al real. Es tpico en la programacin de los proxis acceder desde la red interior al sevicio
http a travs del puerto 8080, en vez del puerto 80.
Puede hacer esto estableciendo la propiedad Proxi de la siguiente forma:
NombredelInet.Proxy = "ftp=CorpFTP:123 HTTP=CorpHTTP:131"
Esta forma de establecer la propiedad har que para ftp use el servidor Proxi CorpFTP, por
el puerto 123, y que para http use el servidor CorpHTTP por el puerto 131.
Supongamos que ya estamos conectados a Internet. Que como lo sabemos? Utilizaremos
un mtodo del Inet: OpenURL para establecer una comunicacin con un servidor http
conocido. Si se completa la conexin es que ya estamos conectados.
Mtodo OpenURL
Abre y devuelve el documento ubicado en la direccin URL especificada. El documento se
devuelve con el tipo Variant. Cuando termina la ejecucin del mtodo, las propiedades
URL (y las partes de la direccin URL como el protocolo) se actualizan para reflejar la URL
actual.
Sintaxis
Donde
Variable
url
TipoDatos
Variable tipo string donde se guardarn los datos obtenidos (Texto) o una
variable Variant donde se guardarn los datos obtenidos como matriz de
bytes
Direccin URL que se desea abrir.
Entero que especifica el tipo de datos. Acepta los valores 0 (Predeteminado)
para que obtenga los datos como cadena de caracteres, o 1, para que los
obtenga como matriz de bytes. Si la URL es una pgina Web debe poner 0
en este valor.
Descripcin
No hay estado del que informar.
El control est buscando la direccin IP del host
623
t
especificado.
icHostResolved
2
El control encontr la direccin IP del host especificado.
icConnecting
3
El control est conectando con el equipo host.
icConnected
4
El control conect correctamente con el equipo host.
icRequesting
5
El control est enviando una solicitud al equipo host.
icRequestSent
6
El control envi correctamente la solicitud.
icReceivingRespons
7
El control est recibiendo una respuesta del equipo host.
e
icResponseReceive
El control recibi correctamente una respuesta del equipo
8
d
host.
icDisconnecting
9
El control se est desconectando del equipo host.
icDisconnected
10
El control se desconect correctamente del equipo host.
icError
11
Se produjo un error en la comunicacin con el equipo host.
icResponseComplet
12
La solicitud se complet y se recibieron todos los datos.
ed
Puede analizar el estado del Inet introduciendo este cdigo en este procedimiento:
Private Sub Inet1_StateChanged(ByVal State As Integer)
Select Case State
Case 0
LState = "0 - Sin actividad"
Lstate es un Label donde presentamos el estado
de la conexin
Case 1
LState = "1 - Buscando Host"
Case 2
LState = "2 - Host encontrado"
Case 3
LState = "3 - Conectando"
Case 4
LState = "4 - Conectado"
Case 5
LState = "5 - Enviando solicitud"
Case 6
LState = "6 - Solicitud enviada"
Case 7
LState = "7 - Recibiendo respuesta del Host"
Case 8
LState = "8 - Respuesta recibida"
Case 9
LState = "9 - Desconectando"
Case 10
LState = "10 - Desconectado"
Case 11
LState = "11 - Error de conexin"
Case 12
LState = "12 - Operacin completada"
End Select
End Sub
Este procedimiento no se comporta de igual forma cuando se conecta con una pgina Http
que cuando lo hace con un servidor Ftp. Nos centraremos primero en conexiones con
servidores Http, y veremos ms adelante como se comporta con servidores Ftp.
624
Inet1.GetHeader (nombreEnc)
Donde:
Inet1
NombreEnc
Inet1.Cancel
625
Es posible que este mtodo genere un error, ya que en algunas ocasiones cierra la
conexin sin poder cancelar ya el proceso que est en curso. Tenga cuidado al usarlo.
Vamos a ver ahora el mtodo ms til de este control. Con l podemos hacer todas las
funciones de envo y recogida de ficheros.
Mtodo Execute
Ejecuta una solicitud a un servidor remoto. Slo puede enviar solicitudes vlidas para el
protocolo que est utilizando. Lgicamente este mtodo funcionar de forma distinta y
necesitar parmetros distintos dependiendo del protocolo que estemos usando. Para el
protocolo Http la sintaxis es la siguiente:
Sintaxis
Inet1
Nombre del control Inet
URL
(Opcional) Cadena que especifica la direccin URL con la que se debe
conectar el control. Si no se especifica ninguna, se usar la direccin contenida en la
propiedad URL
operacin
Opcional. Cadena que especifica el tipo de operacin que desea
ejecutar. Mas abajo encontrar una lista con las operaciones admitidas.
datos
Opcional. Cadena que especifica los datos para las operaciones (vea ms
abajo).
EncabezadosSolicitud
Opcional. Cadena que especifica los encabezados adicionales para enviarlos
al servidor remoto. El formato de los mismos es el siguiente:
nombre encabezado: valor encabezado vbCrLf
Descripcin
Recupera datos de la direccin URL especificada en la propiedad
URL.
Enva los encabezados de la solicitud.
Enva datos al servidor. Los datos estn en el argumento datos.
ste es un mtodo alternativo a GET para el que se especifican
las instrucciones adicionales en el argumento datos.
Operacin de colocacin. El nombre de la pgina que se va a
reemplazar est ubicado en el argumento datos.
Es difcil probar estos comandos. Normalmente las pginas comerciales no ofrecen los
servicios que a nosotros nos gustara probar.
626
aplicacin del comando PUT (Que no podr ensayar en su casa excepto que tenga acceso a
un servidor con Password)
Vamos a mostrarle un ejemplo del comando GET. Pero previamente tenemos que hablar de
un mtodo que antes habamos citado de pasada:
Mtodo GetChunk
Obtiene datos cuando se produce el evento StateChanged al llegar al estado de respuesta
completa (icResponseCompleted = 12) Este mtodo se invoca despus de ejecutar el
mtodo Execute como una operacin GET.
Sintaxis
(Ftp)
627
url es el nombre del servidor. Este parmetro puede darle algn problema si no conoce
exactamente el nombre del servidor, (Si lleva o no lleva el encabezado FTP:// , si es una
DNS o un nmero IP, ..) Estas direcciones son un ejemplo de ello:
FTP://ftp.microsoft.com
Ftp://10.3.22.119
Instruccin es una cadena que incluye el comando (GET, PUT, ..) y el nombre o nombres de
los archivos necesarios. Ejemplos:
Inet1.Execute
"FTP://ftp.microsoft.com",
C:\Temp\Disclaimer.txt"
Inet1.Execute "FTP://ftp.microsoft.com", "PWD"
Inet1.Execute
Ftp://10.3.22.119,
PUT
/Documentos/PrensaHoy.Tiff
"GET
Disclaimer.txt
C:\Prensa\PrensaDia.Tiff
DIR archivo1
GET archivo1
archivo2
LS archivo1
MKDIR archivo1
PUT archivo1
archivo2
PWD
QUIT
RECV archivo1
archivo2
RENAME archivo1
archivo2
RMDIR archivo1
SEND archivo1
archivo2
SIZE archivo1
Descripcin
Cambiar directorio. Cambia al directorio especificado en archivo1.
Cambiar al directorio superior. Equivale a "CD.."
Cierra la conexin FTP actual.
Elimina el archivo especificado en archivo1.
Directorio. Busca en el directorio especificado en archivo1. Se
admiten comodines, pero el host remoto determina la sintaxis. Si no
especifica archivo1, obtendr una lista completa del directorio de
trabajo actual.
Puede usar el mtodo GetChunk para obtener los datos del
directorio.
Recupera el archivo remoto especificado en archivo1 y crea el nuevo
archivo local especificado en archivo2.
Lista. Busca en el directorio especificado en archivo1. Se admiten
comodines, pero el host remoto determina la sintaxis. Puede usar el
mtodo GetChunk para obtener los datos de los archivos del
directorio.
Crear directorio. Crea el directorio especificado en archivo1. El xito
de la operacin depende de los privilegios del usuario en el host
remoto.
Copia el archivo local especificado en archivo1 en el archivo del host
remoto especificado en archivo2.
Mostrar directorio de trabajo. Devuelve el nombre del directorio
actual. Puede usar el mtodo GetChunk para obtener los datos.
Termina la sesin del usuario actual.
Recupera el archivo remoto especificado en archivo1 y crea un
nuevo archivo local especificado en archivo2. Equivale a GET.
Cambia el nombre del archivo indicado en archivo1 por el nombre
especificado en archivo2. El xito de la operacin depende de los
privilegios del usuario en el host remoto.
Eliminar directorio. Elimina el directorio remoto especificado en
archivo1. El xito de la operacin depende de los privilegios del
usuario en el host remoto.
Copia el archivo local especificado en archivo1 en el archivo del host
remoto especificado en archivo2. Equivale a PUT.
Devuelve el tamao del directorio especificado en archivo1.
628
Siguiendo con el servidor Ftp de Microsoft podemos ensayar algunos de estos comandos:
Inet1.Execute "FTP://ftp.microsoft.com", "DIR"
Nos devuelve el directorio. Como no hemos realizado ninguna operacin sobre ese
directorio, nos devolver el directorio del raz.
bussys/
deskapps/
developr/
KBHelp/
MISC/
MISC1/
peropsys/
Products/
ResKit/
Services/
Softlib/
No contiene ficheros sino ms directorios. Uno de ellos es el directorio MISC.
Podemos
ReadMe1.txt
satKB/
Store/
STORE1/
sunKB/
test/
thuKB/
TREE.COM
tueKB/
wedKB/
Para realizar este tipo de operaciones debe asegurarse que la operacin se ha terminado
antes de iniciar una nueva operacin. Esto puede verlo con el valor de State del
procedimiento StateChanged. Ha de esperar a que tenga el valor icResponseCompleted
( = 12). Es en ese momento cuando debe invocar el mtodo GetChunk para sacar los
datos del bffer. Es el mismo cdigo del Select Case que ha visto antes, que le repito aqu
por comodidad:
Case 12
LState = "12 - Operacin completada"
Dim vtData As Variant ' Variable de datos.
Dim strData As String, bDone As Boolean, F As Integer
' Obtiene el primer bloque.
vtData = Inet1.GetChunk(1024, icString)
DoEvents
Do While Not bDone
strData = strData & vtData
DoEvents
' Obtiene el bloque siguiente. Est sacando bloques de 1024 caracteres
'hasta que no queda ninguno. En ese caso, GetChunk devuelve la cadena vaca
vtData = Inet1.GetChunk(1024, icString)
If Len(vtData) = 0 Then
bDone = True
End If
Loop
TbTextoExecute.Text = strData
El texto devuelto se introduce en el TextBox
TbTextoExecute
End Select
Una vez en el directorio adecuado, podemos bajarnos un fichero mediante este cdigo:
Inet1.Execute "FTP://ftp.microsoft.com", "GET ReadMe1.txt C:\PruebaVB\Leeme1.Txt"
Al ejecutarlo dej el fichero ReadMe1.txt en la carpeta C:\PruebaVB con le nombre
Leeme1.Txt. Contena esto:
The Microsoft Knowledge Base is currently published to this server in three formats. Two of
the formats are published for legacy reasons and are now obsolete. The KB will be posted
to this server only in HTM format as of August 1, 2002.
The Microsoft Knowledge base has been posted to this server in text format since 1993.
With the growth of the world wide web and the spread of browser technology, the HTML
formats of the KB became the defining standard, and in many cases the text rendering of
the content lost important data only visible in the HTML view. We will be discontinuing text
format output to ensure our customers don't miss critical data in the articles they
download from this server. One variant of text files we have been publishing is SPV files.
SPV files group articles by the product that they apply to. An article can only belong in one
630
group, which avoids duplicates if more than one collection is downloaded. Today, many
articles apply equally to multiple products. As such, the binary or arbitrary division of
articles results in information being hidden from customers who needed it. Effective August
1, we will no longer divide articles on this server by these arbitrary groupings and the
published SPV files will be deleted.
The KB will continue to be available for download at ftp://ftp.microsoft.com/misc/kb as
HTM files.
The files which were in this location will be available until July 31, 2002 at
ftp://ftp.microsoft.com/misc1.
The zipped SPV files that were being stored here are now located at
ftp://ftp.microsoft.com/misc1 until 07/31/02 at which time these files will no longer be
available.
In summary:
The following folders and/or files at:
ftp://ftp.microsoft.com/bussys/...../kb
ftp://ftp.microsoft.com/deskapps/...../kb
ftp://ftp.microsoft.com/developr/...../kb
ftp://ftp.microsoft.com/MISC/
ftp://ftp.microsoft.com/peropsys/...../kb
are all located at:
ftp://ftp.microsoft.com/MISC1/
and only at:
ftp://ftp.microsoft.com/misc/kb
will there be HTM files after 7/31/02.
Thank you,
endspv@microsoft.com
Podra enviar un fichero para el servidor. Pero no se lo iba a aceptar. Muchos de los
comandos enumerados arriba slo pueden ejecutarse si el usuario tiene privilegios en el
host servidor. Por ejemplo, los sitios FTP anonymous no permiten enviar ficheros, ni
eliminar archivos ni directorios.
Transmisin asncrona del mtodo Execute
Al contrario que el mtodo OpenURL, el mtodo Execute produce una transmisin
asncrona de los datos. Cuando se invoca el mtodo Execute, la operacin de
transferencia se produce independientemente de otros procedimientos. Por tanto, despus
de invocar el mtodo Execute es posible ejecutar otro cdigo mientras se reciben datos en
segundo plano. Pero cuidado con esto, que no podr invocar otro mtodo que afecte a la
conexin hasta que la transferencia haya terminado o haya sido abortada, por ejemplo, por
haber ocurrido un error de transmisin.
Este es el motivo por el que tras el mtodo Execute, haya que recurrir al mtodo
GetChunk, aplicndolo cuando el parmetro State del procedimiento StateChanged haya
tomado el valor 12 (Respuesta completa). No se puede saber cuando ha terminado la
recepcin de los datos, por lo tanto es necesario disponer de un recurso que nos lo
indique.
631
632
633
Inet1.Document = cadena
hInternet (Propiedad)
Devuelve el controlador de Internet de la API de Wininet.dll subyacente. Por tanto, puede
usar este controlador en llamadas directas a la API. Esta propiedad no se utiliza cuando
efecta el acceso al control desde Visual Basic.
Sintaxis
VariableLong = Inet1.hInternet
Propiedad UserName
Devuelve o establece el nombre de usuario que se enviar con las solicitudes a los equipos
remotos. Si deja en blanco esta propiedad, el control enviar "anonymous" como nombre
de usuario al realizar solicitudes.
Sintaxis
Inet1.UserName = nombre
Propiedad Password
Devuelve o establece la contrasea que se enviar junto con la solicitud de inicio de sesin
a los equipos remotos. Si deja esta propiedad en blanco, el control enviar la contrasea
predeterminada (Direccin de Correo electrnico).
Sintaxis
Inet1.Password = cadena
Propiedad Protocol
Establece el protocolo que desea usar con el mtodo Execute.
Sintaxis
Inet1.Protocol = entero
propiedad no tiene ningn efecto hasta que se invoque el siguiente mtodo Execute u
OpenURL.
Propiedad Proxy
Vista ms atrs. Devuelve o establece el nombre del servidor proxy utilizado para
comunicar con Internet.
Propiedad RequestTimeout
Devuelve o establece la duracin, en segundos, de un intervalo de espera. Si no se
responde a una solicitud dentro del intervalo especificado y si la solicitud se efectu con el
mtodo OpenURL (solicitud sncrona), se produce un error. Si la solicitud se efectu con el
mtodo Execute, se producir el mtodo StateChanged junto con un cdigo de error. El
valor 0 de esta propiedad significa espera indefinida.
Sintaxis
Inet1.RequestTimeout = tiempoensegundos
Propiedad ResponseCode
Devuelve el cdigo de error de la conexin cuando aparece el estado icError (11) en el
evento StateChanged. Si desea obtener una descripcin del error, vea la propiedad
ResponseInfo.
Sintaxis
Inet1.ResponseCode= cdigo
Propiedad ResponseInfo
Devuelve la descripcin del ltimo error que se ha producido.
Sintaxis
Inet1.ResponseInfo
VariableBooleana = Inet1.StillExecuting
Al invocar los mtodos OpenURL y Execute, cambia el valor de esta propiedad por el que
se introduzca al ejecutar esos mtodos. La modificacin de esta propiedad no tiene ningn
efecto hasta que se llama al siguiente mtodo OpenURL o Execute.
La propiedad URL debe contener al menos un protocolo y un nombre de host remoto.
La propiedad URL puede especificar un directorio o un archivo. Por ejemplo, son vlidas las
dos direcciones URL siguientes:
Inet1.URL = HTTP://www.microsoft.com ' Con esta URL slo obtendr el directorio del
archivo
635
IcShutDown
IcIncorrectUserName
IcLoginFailure
IcInetIvalidOperation
IcOperationCancelled
IcIncorrectHandleType
IcIncorrectHandleState
IcNotProxyRequest
IcRegistryValueNotFou
nd
IcbadRegistryParamete
r
IcNoDirectAccess
IcIncorrectPassword
IcNoContext
IcNoCallback
IcRequestPending
IcIncorrectFormat
IcItemNotFound
icCannotConnect
icConnectionAborted
icConnectionReset
icForceEntry
icInvalidProxyRequest
icWouldBlock
icHandleExists
icSecCertDateInvalid
icSecCertCnInvalid
icHttpsToHttpOnRedir
icMixedSecurity
icChgPostIsNotSecure
icHttpToHttpsOnRedir
icPostIsNonSecure
icClientAuthCertNeeded
icInvalidCa
icClientAuthNotSetup
icAsyncThreadFailed
icRedirectSchemeChan
ge
35778
35779
35781
35782
35783
35784
35785
35786
Apagar
Nombre de usuario incorrecto.
Error al iniciar la sesin.
Operacin no vlida.
Operacin cancelada.
Tipo incorrecto de controlador.
Estado incorrecto del controlador.
No es un proxy.
35787
35788
35789
35780
35790
35791
35792
35793
35794
35795
35796
35797
35798
35799
35800
35802
35803
35804
35806
35807
35808
35808
35809
35810
35811
35812
35813
35814
icDialogPending
35815
icRetryDialog
35816
icHttpsHttpSubmitRedir 35818
icInsertCdrom
icFtpTransferInProgres
s
icFtpDropped
icFtpNoPassiveMode
35819
35876
35877
35878
icGopherProtocolError
icGopherNotFile
icGopherDataError
icGopherEndOfData
icGopherInvalidLocator
icGopherIncorrectLocat
orType
icGopherNotGopherPlu
s
icGopherAttributeNotFo
und
icGopherUnknownLocat
or
icHeaderNotFound
icHttpDownlevelServer
icHttpInvalidServerRes
ponse
icHttpInvalidHeader
icHttpInvalidQueryReq
uest
icHttpHeaderAlreadyExi
sts
icHttpRedirectFailed
icSecurityChannelError
icUnableToCacheFile
icHttpCookieNeedsConf
irmation
35896
35897
35898
35899
35900
35901
35902
35903
35904
35916
35917
35918
35919
35920
35921
35922
35923
35924
icHttpCookieDeclined
35928
icServerUnreachable
35930
icProxyServerUnreacha
ble
35931
icBadAutoProxyScript
35932
icUnableToDownloadSc
ript
icHttpRedirectNeedsCo
nfirmation
icSecInvalidCert
icSecCertRevoked
icFailedDueToSecurityC
heck
35927
35933
35934
35935
35936
35937
638
639
640
Constante
Descripcin
READYSTATE_UNINITIALIZED
641
1
2
3
4
READYSTATE_LOADING = 1
READYSTATE_LOADED
READYSTATE_INTERACTIVE
READYSTATE_COMPLETE
Propiedad Type
Devuelve un string con el tipo de documento que est presentando
Label1 = brwWebBrowser.Type
Propiedad Visible
Establece si el WebBrowser se ve o est oculto
Mtodos de WebBrowser
Mtodo ExecWB
Ejecuta un comando usando la interface IOLECommandTarget. La sintaxis es la
siguiente:
NombreDelWebBrowser.ExecWB nCmdID, nCmdExecOpt, [pvaIn], [pvaOut]
NCmdID
(Requerido) Es un Long o una constante que identifica el comando a
ejecutar.
NCmdExecOpt(Requerido) Es un Long o constante que indica las opciones de ese
comando.
PvaIn
(Opcional) Un Variant que se emplea para introducir argumentos al
comando.
PvaOut
(Opcional) Un Variant que se emplea para recoger los resultados
La primera cuestin que surge ahora es Dnde est la lista de los comandos que se
pueden ejecutar? Desconozco donde se puede encontrar la informacin de todos los
comandos, pero pueden verse uno a uno en el Examinador de Objetos en las clases
OLECMDID para los los identificadores de comandos, y OLECMDEXECOPT para las
opciones. Asi, si quiere imprimir el contenido del WebBrowser basta con poner la
siguiente instruccin:
brwWebBrowser.ExecWB OLECMDID_PRINT, OLECMDEXECOPT_PROMPTUSER
Esto es lo mismo que decir:
brwWebBrowser.ExecWB 6, 2
Y lo que hace es, imprimir (6) y presentar el cuadro de dilogo para seleccionar la
impresora. (2)
Esto de no conocer la lista de
comandos aunque parece dificil
(y lo es) es superable. Cuando
estamos
introduciendo
el
mtodo ExecWB aparece la
lista con todos los comandos
posibles. Y habr que echar
imaginacin y ver, dentro de la
lista presentada, el comando
que nos interesa. As sugi la
lnea siguiente para guardar la
pgina:
642
brwWebBrowser.ExecWB OLECMDID_SAVEAS,
OLECMDEXECOPT_PROMPTUSER
Puede ver la lista completa de los comandos en el Explorador de Objetos (Al que se
accede pulsando F2) y que presentamos en esta pgina como recordatorio. En la imagen
est presentando la Clase OLECMDID. Puede presentar la clase OLECMDEXECOPT haciendo
clic sobre su lnea en el cuadro de la izquierda. Dejo al alumno interesado el trabajo de
realizar una lista con todos estos comandos, sus constantes y valores.
Nota. Para que aparezca en el Explorador de Objetos la lista con todos los comandos
OLECMDID debe estar introducido el control WebBrowser en el proyecto.
Mtodo GoBack
Navega hacia atrs dentro de la lista de las pginas visitadas.
Mtodo GoForward
Navega hacia delante dentro de la lista de pginas visitadas
Mtodo GoHome
Abre la pgina especificada como pgina inicial en las opciones del Internet Explorer.
Mtodo GoSearch
Abre la pgina especificada en el Internet Explorer como pgina de bsqueda ()
Mtodo Navigate
Abre la pgina especificada.
Sintaxis
:
NombreWebBrowser.Navigate URL [Flags,] [TargetFrameName,] [PostData,] [Headers]
URL Requerido. Una cadena con la direccin del documento a mostrar. Puede ser una
URL de una pgina en la Web, direccin completa de un fichero en el disco, una direccin
IP.
Flags Opcional. Un valor o constante que determina varias cosas, segn se explica en la
lista siguiente.
Pueden sumarse dos o ms valores de estos.
Constante
Valor
Descripcin
NavOpenInNewWindow
NavNoHistory
NavNoReadFromCache
NavNoWriteToCache
2
4
8
1
Abre la pgina en una nueva ventana.
No aade la pgina a la lista del histrico de pginas.
No lee de la cah del disco para buscar la pgina.
No guarda la pgina abierta en la cach
643
Mtodo Navigate2
Extiende el mtodo Navigate para poder navegar por carpetas especiales tales como el
escritorio o Mi PC. La sintaxis es idntica a la del mtodo Navigate.
Mtodo Refresh
Vuelve a cargar el documento que est presentando.
Sintaxis
NombredelWebBrowser.Refresh
Mtodo Refresh2
Vuelve a cargar el documento que est presentando. La diferencia con el Mtodo
Refresh es que este mtodo contienen un parmetro que especifica el nivel de
actualizacin.
Sintaxis
NombredelWebBrowser.Refresh2 Nivel
Nivel puede tomar uno de los siguientes valores:
Constante
Valor Descripcin
REFRESH_NORMAL
0
Realiza un refresco simple, en el que no incluye el
envio del
header
pragma:nocache al servidor
REFRESH_IFEXPIRED
1
Realiza un refresco simple si la pgina ha caducado
REFRESH_COMPLETELY
3
Realiza un refresco completo, enviando al servidor
el header
pragma:nocache
El header "pragma:nocache" obliga al servidor a no enviar una copia que tenga en su
propia cache. De esta forma sabemos que nos va a enviar la informacin ms reciente.
Los navehadores suelen enviar este header cuando el usuario selecciona Actualizar.
Esto puede causar problemas en algunos servidores.
Mtodo Stop
Cancela cualquier navegacin pendiente y la recepcin de cualquier elemento dinmico
de la pgina, como puede ser sonidos o animaciones..
Sintaxis
NombredelWebBrowser.Stop
Eventos del control WebBrowser
Evento BeforeNavigate2
Este evento ocurre cuando el control WebBrowser cambia la navegacin a otra URL
diferente. Esto puede ocurrir porque el usuario ha hecho click en un link o por cualquier
otra razn. En este evento se tiene la oportunidad de cancelar la nueva navegacin.
Private Sub object_BeforeNavigate2(ByVal pDisp As Object, ByVal URL As
String,
ByVal Flags As Long, ByVal TargetFrameName As String, PostData As Variant,
ByVal Headers As String, Cancel As Boolean)
Para impedir la navegacin a una nueva URL basta con poner esta lnea de cdigo:
Cancel = True
DocumentComplete Event
Ocurre
cuando
el
documento
que
est
siendo
bajado
pasa
al
estado
READYSTATE_COMPLETE. Este evento tienen importancia cuando un documento tiene
frames, pues se produce cada vez que se termina de enviar el documento correspondiente
a cada una de las frames.
Evento DownloadBegin
Ocurre cuando comienza una operacin de navegacin. Este evento ocurre inmediatamente
despus del BeforeNavigate2, excepto que la navegacin haya sido cancelada en aquel. A
cada evento DownloadBeguin le tiene que suceder un DownloadComplete, por lo que
puede aprovechar ambos eventos para sealar mediante un icono que se est bajando un
nuevo documento. (El Internet Explorer lo hace mediante un globo mundial girando)
Evento DownloadComplete
Ocurre cuando la navegacin termina, se detienen voluntariamente o ha fallado.
644
Evento NavigateComplete2
Ocurre cuando el WebBrowser ha alcanzado con xito la nueva URL. A partir de este
momento es cuando comienza a bajarse el documento. Este evento es el apropiado para
poner el aviso: Sitio Web encontrado.
Evento NewWindow2
Ocurre cuando se ha creado una nueva ventana para presentar un nuevo documento.
Evento OnFullScreen
Ocurre cuando ha cambiado la propiedad FullScreen
Evnto OnVisible
Ocurre cuando cambia la propiedad Visible
ProgressChange Event
Ocurre cuando se actualiza el avance de la operacin de bajar un documento.
Private Sub object_ProgressChange(ByVal Progress As Long, ByVal ProgressMax As
Long)
Progress
Long conteniendo el nmero total de Bytes transferidos
ProgressMax Long con el nmero total de bytes a tranferir.
Este evento se puede usar para colocar un aviso tranquilizante de la evolucin de la
descarga del documento.
Visual Basic - Gua del Estudiante Cap. 19
REALIZACION DE CONTROLES OCX
A modo de comentario. Hemos llegado a un captulo que todos los alumnos desean
conocer: el captulo donde vamos a ver como se crea un control personalizado. A lo largo
de mis aos de docencia he observado que los alumnos mas aventajados tienden a realizar
aplicaciones usando controles realizados por ellos mismos, en la creencia que eso protege
sus programas frente a posibles imitaciones, ya que parece que poseen la llave que da
acceso a sus secretos. Incluso hay quien piensa que el uso de este tipo de controles da
cierto prestigio como programador. Y hay tambin empresas especializadas en software
que comparten esas mismas ideas. En el mbito empresarial hay quien realiz uno de
estos controles con fecha de caducidad, de forma que pasada una fecha, el control deja de
funcionar y con l la aplicacin. Buena forma de asegurarse el contrato de mantenimiento,
ya que el control haba que reemplazarlo antes de llegar a esa fecha, pero una hermosa
forma a la vez de perder al cliente y la credibilidad como empresario y como
programador. Es una cuestin de criterios personales o comerciales, pero la creacin de
controles personalizados es una prctica que solamente debe llevarse a cabo cuando es
estrictamente necesario por no existir ningn recurso en VB que realice lo deseado. Y es
decisin muy prudente no aceptar ninguna aplicacin que llevando un control
personalizado, no se entregue con la aplicacin, toda la informacin relativa al mismo,
incluyendo su cdigo fuente.
Para crear un control, lo primero que hay que hacer es pensar, con papel y lpiz, las
funciones que debe realizar ese control, as como sus propiedades y mtodos. Hay que
pensar durante este proceso, si el control se va a encapsular dentro de
un OCX solo o con otros controles, ya que un mismo OCX puede contener
ms de un control. Una vez realizado este estudio previo, se procede a
abrir un nuevo proyecto, eligiendo en este caso la creacin de un Control
ActiveX, sobre el icono mostrado en la figura. Aparecer algo distinto a lo
que nos encontramos cuando creamos un proyecto EXE Standard.
Lo primero que observamos es que no aparece un formulario, sino algo, que si bien se le
parece, sabemos que no lo es. Esa especie de formulario es el objeto UserControl.
El UserControl es el objeto base del control que estamos creando. Un control ActiveX se
compone siempre de un UserControl y sobre l podremos colocar otros controles. A los
controles que colocamos sobre el UserControl se les denomina Controles Constituyentes.
645
controles. Pero tenga cuidado cuando meta controles dentro del mismo paquete. Piense
que cada control va a ocupar cierto sitio. Suponga que hace un OCX con 9 controles.
Ocupar ms espacio en disco que si hubiese metido 1. Cuando meta en un proyecto uno
solo de estos controles, deber meter en el proyecto la totalidad del espacio que ocupaban
los 9 controles. El caso del control de Microsoft citado tienen su razn de ser. El OCX
contiene 9 controles, que se pueden usar todos dentro del mismo proyecto (Barra de
herramientas, barra de estado, TreeView, ListView, Barra de Progreso, Slider, TabStrip,
Image Combo e ImageList)
Registrar un control. El registro de un control es una operacin que Windows debe hacer
para meter los datos de ese control (nombre y ubicacin dentro del disco) dentro del
registro de Windows. Esto le facilita la bsqueda del fichero.
Lo normal es colocar los controles OCX dentro de la carpeta C:\Windows\System. Puede
ponerlo en cualquier otra carpeta, pero esa es la usual. Eso s, una vez puesto en la
carpeta deseada y registrado no lo puede mover, ya que Windows no lo encontrara.
Hay un mtodo muy sencillo para registrar un control cuando tiene el Visual Basic instalado
en su PC. Guarde el fichero OCX en C:\Windows\System. Vaya a Proyecto | Componentes y
le aparecer el cuadro para elegir un nuevo control. No aparecer ese nuevo OCX dentro
de la lista de este cuadro, ya que todava no est registrado.
646
en
un
formulario.
Haciendo
clic
en
Herramientas
Agregar
Procedimiento. Nos aparece un cuadro donde debemos elegir Propiedad Recuerde que
el elemento del men de VB Agregar Procedimiento solamente est activado cuando est
abierta una ventana de cdigo. La ventana de cdigo abierta debe ser del proyecto del
control ActiveX (Del UserControl o de cualquiera de los controles constituyentes)
Se le
pone el nombre que desea que tenga la propiedad. Por ejemplo, si queremos que esa
propiedad sea el color de fondo del nuevo control, pondremos ColorDeFondo (Porque
habramos de poner Backcolor si el control se ha desarrollado en Espaa?)
648
649
Como puede verse, el procedimiento Property Let necesita un valor, vNewValue que ha
declarado como Variant. A ese el procedimiento para poner el valor a la propiedad necesita
que le pasemos el valor de esa propiedad. Lo que no puede saber, es el tipo de dato que
debe usar para ColorDeFondo. Por eso pone As Variant y de esta forma podemos meter
cualquier valor. Sin embargo, sabemos desde el Captulo 1 que las variables declaradas
como Variant ocupan mucho espacio en memoria, y debemos optimizar el programa
ajustando las variables. Como sabemos que el color es un nmero Long, podemos sustituir
el tipo Variant por un tipo Long:
Public Property Let ColorDeFondo(ByVal vNewValue As Long)
Public Property Get ColorDeFondo() As Long
Observe que lo hemos cambiado en los dos procedimientos. Si no se cambia en ambos
dar error.
Tambin podemos cambiar el nombre de la variable interna del procedimiento (vNewValue)
y poner algo que resulte ms comprensible:
Public Property Let ColorDeFondo(ByVal NuevoColor As Long)
En el caso del color tambin puede poner otro tipo de variable: OLE_COLOR, que es lo que
hace VB con el asistente.
Veamos ahora el cdigo a introducir en ese Procedimiento Property
Como lo que queremos hacer con la propiedad ColorDeFondo es poner de un determinado
color el fondo del control, y el fondo del control es precisamente el UserControl, bastar
con poner que la propiedad BackColor del UserControl es precisamente el nuevo control a
poner. Observe que en el UserControl la propiedad se sigue llamando Backcolor.
Public Property Let ColorDeFondo(ByVal NuevoColor As Long)
UserControl.BackColor = NuevoColor
End Property
Es muy til, no necesario, comunicar al control que ha cambiado una de sus propiedades.
Esto sirve para que pueda guardar el nuevo valor en su pgina de propiedades. Ya lo
veremos. Para comunicarle que ha cambiado una propiedad se le aade una lnea al cdigo
anterior
Public Property Let ColorDeFondo(ByVal NuevoColor As Long)
UserControl.BackColor = NuevoColor
PropertyChanged "ColorDeFondo"
End Property
Ya veremos lo que ocurre con PropertyChanged
Este procedimiento es el que se ejecuta cuando ponemos un valor al color de fondo del
nuevo control cuando ponemos, por ejemplo
TBPV1.ColorDeFondo = 255 (TBPV1 es el nombre del control en el formulario de prueba)
Vamos a ver el cdigo del procedimiento que se ejecuta cuando queremos saber el valor
que tienen esa propiedad.
Public Property Get ColorDeFondo() As Long
ColorDeFondo = UserControl.BackColor
650
End Property
Observe que el valor devuelto es el nmero de color de la propiedad BackColor del
UserControl.
651
Vamos a ver con ms detalle los procedimientos Property Let y Property Get
Instruccin Property Let
Declara el nombre, los argumentos, y el cdigo que forman el cuerpo de un procedimiento
Property Let, y asigna un valor a una propiedad.
Sintaxis
[Public Private Friend Static] Property Let NombreDelProcedimiento (argumentos)
instrucciones
Exit Property
instrucciones
End Property
El mbito del procedimiento queda determinado por la primera expresin:
Public: El procedimiento Property es accesible desde cualquier parte del proyecto
Private:
Es accesible solamente para los procedimientos del mismo mdulo
Friend (Solo para Clases)El procedimiento no es visible por el controlador de una instancia
Static Los valores de las variables locales declaradas en el procedimiento mantienen su
valor entre distintas llamadas.
NombreDelProcedimiento es el nombre por el que se va a llamar y es precisamente el
nombre de la propiedad que va a controlar. Aunque en VB no pueden existir dos
procedimientos con el mismo nombre, en este caso s, y el nombre del procedimiento
Property Let puede ser igual (de hecho siempre es igual) a otro procedimiento Property
Get
Argumentos Argumentos que deben pasarse al llamar a ese procedimiento. El tipo de
datos de cada argumento ser el mismo que en el procedimiento Property Get
Instrucciones Es el cdigo que hay que escribir en el procedimiento para que realice lo que
desea el programador. Estas instrucciones pueden generar una condicin en la que se debe
abandonar el procedimiento. En ese caso, puede salirse del procedimiento con Exit Prperty
Los argumentos pueden pasarse:
Por Valor (ByVal) El valor de la variable fuera del procedimiento mantienen el valor,
aunque ese valor cambie dentro del procedimiento.
Por Referencia (ByRef) El valor de la variable fuera del procedimiento cambia si suse
modifica en el procedimiento.
Opcional (Optional)
El parmetro es opcional. Si un parmetro es opcional, todos
los que vengan detrs tambin deben serlo, y hay que indicarlo as con la expresin
Optional para cada uno de ellos. El parmetro que da valor a la propiedad no puede ser
opcional.
Array de parmetros (ParamArray) Indica que es una matriz de parmetros.
No se puede llamar a un procedimiento Property Let dentro de otro procedimiento
Property, Sub o Function.
Property Get (Instruccin)
Declara el nombre, los argumentos y el cdigo que componen el cuerpo de un
procedimiento Property, y obtiene el valor de una propiedad.
652
Sintaxis
[Public | Private | Friend] [Static] Property Get NombreDelProcedimiento
(argumentos) As tipo
instrucciones
nombreDelProcedimiento = expresin
Exit Property
instrucciones
nombreDelProcedimiento = expresin
End Property
El mbito y la forma de pasar los parmetros son idnticas a las de Property Let
Comenzando el ejercicio prctico
En el ejercicio que ilustra este captulo vamos a hacer un control para una caja registradora
(No olviden que es un ejemplo) Ese control va a recibir el cdigo de barras de un producto
(se podr teclear directamente o leerlo mediante un escner) y analizar el nmero de
control para comprobar que es correcto. El control se encargar de buscar en una base de
datos la descripcin del producto, el precio y las unidades de oferta. Para ciertos productos
aplicar un incremento de precio en horas nocturnas y para otros un descuento en horas
de maana. Por lo tanto, debe tomar la hora del sistema y fijar el Incremento / Descuento
en razn de la hora. La interfaz grfica pensada es la siguiente:
653
Se introducen estas propiedades tal como se explic ms atrs. En la Fig 19.7 puede verse
el cuadro de propiedades del control, con todas estas propiedades ya metidas. Ese cuadro,
como sabemos, aparece pulsando F4 estando seleccionado el control.
sobre un formulario de prueba que aun no sabemos como ponerlo, pero se explicar en
breve. Este cuadro es el tpico de todos los controles, pero estamos acostumbrados a que,
haciendo clic con el botn derecho del ratn, aparezca un cuadro de dilogo donde
podemos introducir las propiedades. Y eso, no
sabemos todava como hacerlo.
Eso se hace mediante una pgina de propiedades.
Reconozco que es complicado, y pese a mi
costumbre de no usar asistentes para ahorrar
trabajo, en este caso no me queda ms remedio
que recurrir a ellos.
Vayamos al UserControl y seleccionndolo,
pulsamos F4 para sacar sus propiedades.
Vayamos a su propiedad PropertyPages (recuerde
que estamos en las propiedades del UserControl)
Sitese en esa propiedad y haga clic sobre el
botn que aparece a la derecha. Le aparecer un
cuadro como el de la Fig. 19.8. En ese cuadro se
nos pide que sealemos las pginas que deseamos
que tenga el cuadro de propiedades. En el caso del
ejemplo se han seleccionado una pgina de
propiedades vaca (PaginaPropiedades1, se le ha
cambiado el nombre que apareca por defecto), la
pgina donde se elige la fuente (StandardFont) y
la pgina donde se elige el color (StandarColor) Al
pulsar Aceptar la propiedad PropertyPages del
serControl tiene 3 Pages
Vayamos ahora al men de Visual Basic, en
Proyecto,
elegimos
Agregar
Pgina
de
654
655
656
657
Propiedad ContainerHWnd
Devuelve el controlador de la ventana (hWnd) del contenedor de un UserControl. Se usa
para programar con APIS.
Propiedad DataMembers
Devuelve una referencia a la coleccin DataMembers.
Un proveedor de datos puede proporcionar mltiples conjuntos de datos a los que un
receptor puede enlazar. Cada conjunto de datos se llama "miembro de datos" y est
identificado mediante una cadena nica.
La coleccin DataMembers contiene los nombres de todos los miembros de datos
disponibles para el receptor de datos.
Propiedad EditAtDesignTime
Establece si un control puede activarse en el tiempo de diseo del programador. Si es True
el control puede activarse en tiempo de diseo y se comportar como lo hara en tiempo
de ejecucin.
EventsFrozen (Propiedad)
Devuelve un valor que indica si el contenedor est pasando por alto los eventos
desencadenados por el control. La propiedad EventsFrozen no est disponible en tiempo
de diseo del control y es de slo lectura en tiempo de ejecucin.
Cuando la propiedad EventsFrozen es True, el contenedor pasa por alto todos los
eventos desencadenados por el control. Si el control necesita producir un evento que no se
puede perder, tiene que dejarlo en la cola hasta que EventsFrozen sea False.
Extender (Propiedad)
Devuelve, para este control, el objeto Extender que almacena las propiedades del control
mantenidas por el contenedor. La propiedad Extender no est disponible en tiempo de
diseo del control y es de slo lectura en tiempo de ejecucin.
Propiedad MaskColor
Devuelve o establece el color que determina la regin transparente del mapa de bits
asignado a la propiedad MaskPicture de un objeto UserControl cuya propiedad
BackStyle est establecida a 0 (Transparente).
Sintaxis
MiUserControl.MaskColor = color
MiUserControl.MaskPicture = imagen
Importante Esta caracterstica slo es soportada con mapas de bits de tipo imagen, como
GIF, JPEG y DIB. No es soportada con iconos, cursores o metaarchivos de Windows.
658
Propiedad ToolBoxBitMap
Establece la imagen con la que se va a representar el nuevo control en la caja de
herramientas. Debe ser una imagen BitMap que habremos guardado previamente en el
disco.
Visual Basic - Gua del Estudiante Cap. 20
APLICACIONES CLIENTE SERVIDOR
COMUNICACIN PUERTO SERIE: EL CONTROL MSCOMM
(Captulo inacabado. Algn estudiante quiere colaborar a su terminacin?)
Hasta ahora hemos visto aplicaciones que pueden utilizarse por s solas. Pueden acceder a
bases de datos que estn en el mismo ordenador que la aplicacin o en otro, unido
mediante una red de rea local. La conexin a las bases de datos a las que accede se
realiza, bien indicndole la direccin y carpeta (\\MiServidor\BasesdeDatos\MiBase.Mdb) o
bien mapeando esa direccin (crear una unidad de disco que contienen esa direccin).
De esta forma podemos acceder a una base de datos instalada en un equipo remoto y la
aplicacin debe funcionar perfectamente, aunque al abrir o leer la base de datos origine un
trfico elevado por la red de rea local.
Con esta configuracin podemos tener problemas de lentitud, sobre todo si la red es lenta
y si hay muchos usuarios trabajando con esa aplicacin en distintos ordenadores,
accediendo todos ellos a travs de la red a un servidor que contienen la base de datos.
Esta lentitud se incrementara en una gran escala si la red a utilizar fuese Internet
mediante una conexin lenta.
Pero lo que ms se notara sera la ocupacin de los recursos de la red durante las
consultas a esa base de datos. Dependiendo de cmo se crease el recordset, podra darse
el caso de transmitir por la red todos los datos de la base de datos para que nuestra
aplicacin utilice nicamente los datos correspondientes a un registro. Pensando en una
aplicacin bancaria, por ejemplo la peticin de saldo de una cuenta desde un cajero
automtico, los nicos datos relevantes de esa operacin sern el nmero de cuenta
corriente, un cdigo para indicar que lo que se desea es el saldo, y como datos de retorno,
el nmero de esa cuenta, el saldo actual disponible y quizs un nmero de comprobacin
(Checksum) para comprobar que no ha existido error en la comunicacin. De nada nos
servira en el cajero conocer el estado de cantidades retenidas, operaciones pendientes,
etc.
Si en ese ejemplo del cajero cresemos un objeto Database, un recordset, leysemos
todos los datos del recordset y luego disemos la orden de cerrarlo, estaramos enviando
informacin innecesaria a travs de la red, con el coste de tiempo y ocupacin que ello
representa.
Casi llegamos a demostrar con esta introduccin que sera ms conveniente hacer una
aplicacin que tuviese dos partes: una, residente en el puesto de operacin, (que
llamaremos aplicacin cliente) que fuese capaz de enviar datos solicitando informacin a
otra aplicacin, instalada en el servidor donde est la base de datos. Esta segunda
aplicacin, que llamaremos aplicacin servidor, abrir la base, crear los recordsets
necesarios, filtrar la informacin, realizar con ella operaciones matemticas, y una vez
concluido todo el proceso, enviar a la aplicacin cliente los datos estrictamente
necesarios. Obviamente se necesita que ambas aplicaciones sean capaces de entenderse
entre s, es decir, que tengan un protocolo de comunicacin entre ellas previamente
definido. Esto es lo que se denomina una aplicacin cliente servidor.
659
tener las cosas claras desde el principio y saber que es lo que va a hacer nuestra aplicacin
para de esta forma poder saber dar respuesta correcta a cada uno de los dos programas. Y
para tener las cosas claras, el autor recomienda que el protocolo de comunicacin se
establezca antes de comenzar a escribir el cdigo en tanto se pueda. Y que se escriba en
un documento en el propio ordenador o mejor an, en una base de datos u hoja de
clculo, que nos permita ordenar las rdenes y avisos de nuestra aplicacin para evitar de
esta forma cualquier repeticin involuntaria.
Es muy importante a la hora de pensar el protocolo de comunicacin que este no pueda
inducir a error al programa. Si el programa tiene como funcin la transmisin de mensajes
(Tal como es nuestro caso) los mensajes no pueden estar limitados ni en su longitud ni en
su contenido por el formato del protocolo de comunicaciones. Se entiende mejor esto
analizando el protocolo del SML (fruto nicamente de la imaginacin del autor y no sujeto
a normas ni recomendaciones internacionales de ningn tipo)
661
servidor para Internet se encuentran en las RFCs, (Request For Coments) son pblicas, y
han tardado en desarrollarse varios aos a base de continuas aportaciones y correcciones
por parte de sus creadores de todo el mundo mundial. Basta con que teclee RFC en un
buen buscador y le llevar a muchas pginas donde puede ver todas las recomendaciones
para todos los servicios de Internet.
El protocolo de comunicacin debe hacerse preferentemente en ASCII puro y caracteres
que tengan representacin fsica. Esto nos permite depurar el programa analizando la
comunicacin mediante un programa externo y debidamente probado. Utilizar caracteres
sin representacin ASCII lo nico que puede hacerle es complicarle la vida a Ud. y a quien
analice su aplicacin. Cuando se enve una cifra, hgalo en decimal o en hexadecimal.
Evite en lo posible enviar cifras sustituyendo su valor por su carcter equivalente. La
mayora de los caracteres no los va a poder representar y tendr serios problemas para
depurar su programa. Esto es especialmente importante con el cheksum de un mensaje,
por ejemplo. Le recomiendo que use preferentemente numeracin Hexadecimal.
662
Un buen programador nunca oculta el protocolo de comunicacin. Esto permite que otros
mejoren su aplicacin. Slo los programadores mediocres temen que se les plagie. Y por
supuesto, nadie debera aceptar una aplicacin cliente servidor si el programador no
suministra ese protocolo.
Aspectos que debe tener siempre en cuenta cuando disee una aplicacin cliente
servidor.
Si como es normal, utiliza una red IP para la transmisin de informacin entre ambas
aplicaciones, deber poner un Winsock en la aplicacin cliente, que deber conocer la
direccin IP o el DNS de la aplicacin servidor, y el puerto en el que est escuchando. En
el servidor deber poner un Winsock que estar siempre a la escucha en el puerto
determinado para la aplicacin, y atender a todas las llamadas que reciba creando una
instancia de ese Winsock. Crear una instancia para cada comunicacin entrante desde los
clientes. La comunicacin en el servidor se mantendr abierta hasta que el cliente la
cierre. Solamente en circunstancias excepcionales, cerrar la comunicacin el servidor. Por
ejemplo, en aquellos casos en los que pase un tiempo predeterminado sin recibir ni enviar
ningn dato al cliente. Para eso se utilizar una tecnologa muy sencilla, denominada
Watch Dog consistente en un contador que se pone a cero cada vez que se recibe o se
envan datos al cliente. Ese contador incrementa su cuenta en una unidad cada cierto
tiempo. Si llega a un nmero predeterminado, prueba evidente de que ha pasado un
tiempo sin que reciba ni enve informacin, cierra la conexin del Winsock asociado. De
cualquier forma hay que tener cuidado y pensar muy bien lo que se hace antes de cerrar la
comunicacin desde el servidor.
El programa cliente debe conocer el nmero IP o direccin DNS del servidor. Pero el
servidor no tiene porque conocer la direccin ni DNS del cliente, ya que debe ser el cliente
el que inicie siempre la comunicacin.
Al cliente nunca se le debe forzar el puerto en el que emite (Propiedad LocalPort del
Winsock). El servidor contestar siempre al cliente usando la conexin abierta por ste, es
decir, usando la instancia de su Winsock correspondiente a la conexin realizada para ese
cliente)
Normalmente el servidor no podr comunicar directamente con el cliente, ya que el cliente
no est a la escucha. Solamente en algunas aplicaciones se le dota al cliente de otro
Winsock para que sea este segundo Winsock quien est a la escucha de una posible
llamada del servidor. Esto se emplea para dar una batida por todos los clientes (Hacer
Pooling) y ver los clientes que estn conectados en este momento. Solamente lo he visto
en algunas aplicaciones de seguridad. Generalmente este pooling se sustituye por llamadas
peridicas desde cada cliente para indicarle al servidor que estn activos.
La comunicacin entre cliente y servidor debe ser siempre TCP. El uso de UDP simplifica
mucho las comunicaciones, pero no sirve para salir a Internet, donde las tramas UDP son
generalmente eliminadas por los servidores. Vale ms trabajar un poco ms el cdigo y
trabajar con comunicaciones seguras aunque sea en una red de rea local que garantice la
llegada de UDP.
Los paquetes broadcast deben evitarse tambin. Solamente deben usarse en
configuraciones donde no se conocen las direcciones de los servidores. Esto ocurre cuando
la red tiene asignacin dinmica de direcciones. (Puede ocurrirle si usa una red VSAT) En
663
cualquier caso, los paquetes broadcast deben evitarse en lo posible. Los servidores de
Internet los eliminan automticamente.
Posiblemente haya ms recomendaciones relativas a la comunicacin. Veamos ahora otras
recomendaciones acerca del cdigo y de la funcionalidad.
Dado que la aplicacin cliente y la aplicacin servidor son completamente independientes,
es muy fcil realizar modificaciones en una de ellas, sobre todo en el servidor, sin que el
cliente se entere. Basta para ello mantener invariable el protocolo de comunicacin.
Pero puede llegar el caso en el que al servidor se le hayan introducido mejoras que puede
aportar al cliente si este es capaz de reconocer un nuevo protocolo. Estamos en el caso de
un servidor que debe atender a dos versiones distintas de cliente. Si el cliente tiene la
versin mejorada, usar con l un protocolo de comunicacin que permita las nuevas
prestaciones. Si el cliente tiene la versin ms antigua, deber seguir usando con l el
protocolo anterior.
Esto nos lleva a que el cliente siempre debe indicar al servidor su versin. Esto no ocupa
unos recursos excesivos y puede ser muy til cuando prevemos introducir una
modificacin. Esta prctica puede incluso servir para conocer aquellos clientes a los que
hay que realizar el cambio de versin y enviarles una nueva. En el ejemplo de este curso,
el cliente comunica al servidor su versin en el acto de conectarse mediante el acrnimo
<VER>.
El servidor tambin debera enviar su versin al cliente. No est previsto en la aplicacin
SML pero confieso que no sobrara que al identificarse el cliente y devolverle el servidor la
conformidad del registro, le devolviese tambin la versin del servidor. Se da cuenta que
segn se avanza en la definicin del protocolo aparecen nuevas necesidades?
La aplicacin cliente debe mostrar de forma clara al usuario el estado de conexin o
desconexin con el servidor. Y a ser posible, que indique la causa de la no conexin (Fallo
en la RAL, fallo en el servidor) Esta informacin se obtienen de forma muy sencilla
analizando los errores generados en el Winsock a la hora de realizar la conexin.
Cuando utilice el puerto COM para la comunicacin, bien sea directamente o a travs de
mdem, debe indicar claramente al usuario el estado de esa conexin, analizando la seal
DSR (esta seal est activa cuando el mdem est conectado, y en caso de comunicacin
directa, cuando se use, el Host debe poner a 1 esta seal para poder trabajar). Recuerde
que la comunicacin por el puerto COM es asncrona respecto a la ejecucin del programa.
En el ejemplo de aplicacin cliente servidor se han ensayado tambin los controles
avanzados de Visual Basic (Capitulo 16). La aplicacin tal como se dijo es una gua
telefnica, que presenta en un TreeView el organigrama del Organismo o empresa a la que
pertenece la gua. Esto facilita la bsqueda de una persona, hacindolo por departamento.
La gua permite tambin buscar por nombre, primer apellido, segundo apellido o
combinacin de ambos. Una vez encontrada la persona, se cubren todos los datos de la
misma, para presentarlos en la solapa de la gua propiamente dicha, y el dato de su alias
(dato que define de forma nica a cada usuario) aparece en la direccin de correo para
poder enviarle un mensaje. Para hacer una prctica con el puerto de comunicaciones
COM-1 COM-2 utilizaremos un mdem, conectado al PC a travs de uno de estos
puertos, para marcar el nmero telefnico.
Todas las operaciones de bsqueda de datos las haremos mediante consultas a la base de
datos que est en el servidor. Las consultas se realizarn siguiendo el protocolo de
comunicaciones. El organigrama se guardar en el cliente, en una base de datos, para
evitar en lo posible el envo desde el servidor. La razn para esto es que el organigrama
puede ser muy extenso, y no va a variar muy a menudo. Como esta informacin habra
664
que enviarla nada ms conectarse el cliente, y como puede ser bastante amplia, esto
podra originar un trfico intenso por la red, que es justamente lo que queramos evitar.
Solamente se va a enviar cuando haya cambiado. Cmo sabe el cliente que ha cambiado?.
Cmo sabe el servidor que el cliente tiene ya la informacin actualizada? La idea ms
sencilla para conocerlo es que el cliente enve cada vez que se registra (al comienzo de la
conexin) el nombre de la revisin del organigrama que tienen. El nombre puede ser
cualquiera. Lo que hace el servidor por defecto para poner el nombre a la revisin es
combinar una cadena de texto con el nombre de la organizacin seguido de la fecha
(da/mes/ao) en la que se realiza la revisin. De esta forma es imposible que haya dos
fichero con el mismo nombre. Al recibir ese nombre el servidor, si es igual al de la ltima
revisin, le devuelve un OK. Si no es igual, le devuelve una instruccin para que el cliente
solicite al servidor que le enve la nueva revisin. El cliente la solicita y el servidor se la
enva. Y al recibirla, el cliente reemplaza el contenido de la base de datos por los nuevos
valores recibidos.
Y razonando los procedimientos de esta misma forma, vamos completando el mecanismo
de comunicacin entre cliente y servidor, y paralelamente creando el protocolo de
comunicacin. Por eso es muy probable que el protocolo de comunicacin no est acabado
hasta que est acabada la aplicacin.
Al da de hoy (30 de Octubre de 2002) no est terminada la aplicacin. Posiblemente no lo
est nunca porque sea una aplicacin en continua ampliacin. Esto es lo bonito de los
programas ejemplo de los cursos de visual basic.
ANEXO 1
SERVIDOR DE BASES DE DATOS Y MENSAJERIA LISTATEL (SML)
PROTOCOLO DE COMUNICACIN CLIENTE SERVIDOR
La comunicacin entre cliente y servidor se realizar mediante el protocolo descrito ms
adelante, a travs de cualquier medio de comunicacin. Generalmente ser comunicacin a
travs de red IP, pero esto no debe impedir que los clientes se puedan conectar al servidor
a travs de otros medios de comunicacin, como puede ser un mdem telefnico o un
enlace va satlite.
En cualquier caso, el contenido de las rdenes y comandos de este protocolo ser siempre
en ASCII, con caracteres alfanumricos que permitan ver perfectamente el trfico entre
ambos interlocutores. El hecho de utilizar solamente caracteres legibles asegura
igualmente la comunicacin a travs de cualquier medio de telecomunicacin, incluyendo
dispositivos de cifrado on-line colocados entre cliente y servidor.
La comunicacin puede iniciarse tanto en el servidor como en cualquiera de los clientes.
Una comunicacin puede estar compuesta de:
Ordenes
Respuestas
Confirmaciones
Avisos
Ordenes: Son aquellas partes de la comunicacin que inician una operacin en el equipo
colateral.
Respuestas. Son siempre respuesta a una orden, y contendrn el resultado de la
operacin generada por la orden, o en su defecto, la notificacin de que esa orden no ha
sido ejecutada o que dio resultado nulo.
665
666
<CAT>
667
<BRC>
<BRS>
<BRA>
<VER>
<VES>
<BIP>
<DIP>
<UCC>
<MN_>
<FR_>
<IP_>
<TO_>
<SJ_>
<NX_>
<CX_>
<BX_>
<EX_>
<MSG>
<CHM>
<RTF>
<SAR>
<SAL>
669
<ABC>
<ABB>
<ABA>
<ABE>
<ABF>
<ABG>
<ABH>
670
671
Este control permite la comunicacin de una aplicacin VB con el puerto serie. Parece en
principio que los puertos serie del PC se usan para muy pocas cosas. Prcticamente para
conectarnos a Internet a travs de un mdem telefnico. Existen muchsimas aplicaciones
industriales para las cuales son fundamentales los puertos COM. Las redes de rea local
parece que han dejado obsoletos a los puertos COM1 y COM2. No es as. Deje volar su
imaginacin. Vuelva a la pgina 4 del captulo 2, y observe el panel de control de una
radio realizado en Visual Basic. La unin entre el PC y la radio, separados muchos
kilmetros, se realiz mediante el puerto COM, conectado a una lnea telefnica mediante
un mdem. El puerto COM es el gran olvido de los informticos
El control MSComm no est normalmente en la caja de herramientas, por lo que ser
necesario introducirlo mediante Proyecto | Componentes.
En el formulario solamente se le ve en tiempo de diseo. El icono que lo representa en la
caja de herramientas coincide con el que presenta en el formulario:
Indica la velocidad, paridad, nmero de bits y bits de stop (parada) que se van a usar en la
comunicacin.
Los valores posibles para velocidad son : Indica la velocidad en baudios.
50
28800
100
110
300
600
1200
2400
672
4800
9600
14400
19200
programan 5
Handshaking
Especifica el mtodo de control sobre el flujo de informacin. En una comunicacin serie se
necesita conocer si el puerto puede enviar informacin (necesita saber si el mdem est
preparado para recibirla) y necesita indicarle al mdem que l est preparado para recibir
informacin. A este proceso se le denomina Handshaking. (Handshaking = Control de
Flujo)
(Como sabr por sus conocimientos de ingls, Handshaking significa apretn de manos,
ponerse de acuerdo. Y ponerse de acuerdo entre dos terminales que van a comunicarse es
establecer las condiciones de control que uno va a tener sobre otro.)
El Control de Flujo puede hacerse de dos formas : Una mediante las seales auxiliares del
puerto (RTS, CTS, DSR, DTR), que son cables adicionales que tendrn una tensin positiva
respecto a los 0V del equipo si esa seal est activada, o una tensin negativa si no lo
est. Este tipo de control del flujo de informacin es el tpico para comunicarse el
ordenador con un mdem.
Existe otra forma de controlar el flujo de informacin : mediante seales especiales que se
envan por los dos cables que transportan la informacin. Mediante estas dos seales
podemos controlar que el ordenador enve informacin o deje de enviarla. De igual forma,
podemos indicarle al mdem que enve o no enve. Estas seales especiales se denominan
X-ON y X-OFF.
La propiedad Handshaking controla la forma de realizar este proceso. Puede tomar los
siguientes valores :
0
1
2
3
por otro carcter. ( ? predeterminado). Se puede sustituir por una cadena de caracteres
(Error, por ejemplo).
NullDiscard
Cuando se recibe el carcter nulo (00000000) puede ser que no sirva para nada a efectos
de nuestra aplicacin, o que este carcter sea un dato mas. Esta propiedad acepta los
valores True / False. Si es True se desprecia el carcter Nulo. Si es False, se toma como un
carcter mas.
CTSTimeout
Es el tiempo (en milisegundos) que permanece esperando la seal CTS (Seal CTS Dispuesto para enviar), seal de entrada al ordenador que debe estar presente antes de
que el puerto comience a enviar informacin. El tiempo se mide desde que se pone activa
la seal de salida RTS (Peticin de envo). Si se supera este tiempo entre el instante de
activacin de la seal RTS y la recepcin de la seal CTS, se produce el evento CTSTO.
Poniendo 0 en esta propiedad, se deshabilita, y en estas condiciones no se producir nunca
el evento CTSTO.
CDTimeout
Es el tiempo mximo de espera (en milisegundos) desde que se activa la seal DTR hasta
que se recibe la seal CD (Carrier Detect - Deteccin de portadora). Este tiempo
solamente tendr importancia en ciertas aplicaciones donde se espere recibir CD
continuamente. No tendr sentido cuando la aplicacin se queda en espera a recibir una
comunicacin, pero sin saber cuando la tiene que recibir. Si transcurre el tiempo
programado en esta propiedad, ocurrir el evento CDTO. Poniendo el valor 0 se deshabilita
esta propiedad y no se producir nunca el evento CDTO.
DSRTimeout
Similar a la anterior, pero en vez de esperar la seal CD se espera la seal DSR. Esta
propiedad s tiene sentido, ya que si, por ejemplo, estamos conectados con un mdem, y
nuestra aplicacin se pone a la espera de recibir alguna llamada, activa la salida DTR, y
espera recibir inmediatamente la respuesta de que el mdem est dispuesto, mediante la
lnea DSR. Si transcurre el tiempo programado sin recibir la seal DSR se producir el
evento DSRTO . Ponindola a 0, se deshabilita esta propiedad y nunca ocurrir el evento
DSRTO.
RTSEnable
Activa (Pone a 1) la seal RTS (Request To Send - Peticin de envo) Esta seal debe
ponerse a 1 para indicar al mdem (o al equipo que va a recibir nuestra comunicacin) que
deseamos enviar datos. Debe estar activada durante toda la transmisin de datos.
Cuando se pone la propiedad Handshaking a 2 (control con RTS / CTS) 3 (Control con
RTS / CTS y con X-ON / X-OFF) no debemos preocuparnos de poner a 1 la seal RTS, pues
lo hace automticamente el puerto de comunicaciones. Esta propiedad est ah para
aplicaciones donde no se emplee ese tipo de Handshaking y necesitemos activar algo
antes de transmitir. (Caso por ejemplo de transmisin de datos por radio, donde podemos
usar esta seal de salida para activar el PTT (Push To Talk - Pulse para hablar) y poner el
transmisor en marcha)
675
DTREnable
Activa (Pone a 1) la salida DTR (Data Terminal Ready - Terminal de Datos Listo). Esta
seal se emplea para decirle al mdem que el terminal (Ordenador) est preparado para
recibir datos.
Se hace la misma observacin que para la propiedad anterior respecto a los valores de la
propiedad Handshaking
Interval
Indica el tiempo (en milisegundos) del intervalo entre una y otra comprobacin del estado
de recepcin del puerto. El valor mnimo es de 55 ms.
El anlisis del puerto de comunicacin no tiene nada que ver con la generacin del evento
OnComm. Este evento se producir cuando se cumplan las condiciones para ello,
independientemente del tiempo programado en esta propiedad. La comprobacin del
puerto cada intervalo de tiempo marcado por esta propiedad solamente afecta a averiguar
el estado de las lneas auxiliares CD, DSR y CTS, y para saber el nmero de caracteres
existentes en los Buffers de transmisin y recepcin.
Las siguientes propiedades no difieren en nada respecto a otros controles :
Left, Name, Index, Top, Tag
Propiedades propias del tiempo de ejecucin
PortOpen
Abre el puerto de comunicacin. Puede tener los valores True (Para abrirlo) y False (Para
cerrarlo) Si tenemos un MSComm con Nombre (Name) MSComm1, para abrirlo
ejecutaremos la siguiente sentencia :
MSComm1.PortOpen = True
Para cerrarlo, ejecutaremos :
MSComm1.PortOpen = False
InBufferCount.
Nos permite averiguar cuantos caracteres tenemos en el Buffer de entrada. Con el mismo
MSComm anterior, comprobaremos el nmero de caracteres sin leer con la sentencia :
caracteressinleer = MSComm1.InBufferCount
OutBufferCount
Nos permite conocer cuantos caracteres quedan por transmitir en el Buffer de salida.
Emplearemos la sentencia :
caracteressinenviar = MSComm1.OutBufferCount
676
Output
Enva caracteres al Buffer de salida. Debe existir un signo igual ( = ) entre Output y lo que
se enva al Buffer. Para enviar la frase Curso de Visual Basic ejecutaremos la sentencia :
MSComm1.Output = Curso de Visual Basic
Si deseamos enviar el contenido de una variable
MSComm1.Output = variable
Input
Lee el Buffer de recepcin. El nmero de caracteres ledos depender del valor de la
propiedad InputLen. Cuando la propiedad InputLen tiene el valor 0, el Buffer se lee
completo. Si InputLen tiene un valor distinto de 0, se leer un nmero de caracteres igual
al valor de esta propiedad.
CommEvent
Devuelve el evento mas reciente que ha ocurrido para generar el evento general OnComm
(Vea mas adelante). Esta propiedad no est disponible en tiempo de diseo y es de slo
lectura en tiempo de ejecucin.
Sintaxis
NombredelMSComm.CommEvent
Break
Devuelve un valor (True / False) que indica que se ha recibido la seal Break.
variable = MSComm1.Break
CDHolding
Devuelve el estado de la lnea de control CD (Deteccin de Portadora) Si es True, esa
entrada est activada, si es False, la entrada est desactivada.
variable = MSComm1.CDHolding
CTSHolding
Devuelve el estado de la lnea de control CTS (Dispuesto para enviar) Si es True, esa
entrada est activada, si es False, la entrada est desactivada.
variable = MSComm1.CTSHolding
DSRHolding
Devuelve el estado de la lnea de control DSR (Data Set Ready ) Si es True, esa entrada
est activada, si es False, la entrada est desactivada.
variable = MSComm1.DSRHolding
del MSComm.
Esto quiere decir que para escribir el cdigo apropiado en el procedimiento del MSComm
ser necesario analizar qu evento se ha producido y colocar, mediante una sentencia If ..
Then el cdigo apropiado para cada uno de los eventos que se produzcan.
Para averiguar qu evento se ha producido puede hacerse consultando el valor de la
propiedad CommEvent. (Se toma como nombre del MsComm el de MsComm1)
If
(5)
ComEvCTS
(3)
ComEvDSR
(4)
ComEvRing ( 6 )
ComEvEOF
(7)
comEventBreak (1001)
tiempo
ComEventDSRTO
ComEventDCB
ComEventFrame
NOTA ADICIONAL
El puerto de comunicaciones.
(Potencial de 0 V.).
TxD
Transmisin de datos. Es una salida del ordenador. Por ella salen los datos en serie.
RxD Recepcin de datos. Es una entrada del ordenador. Por ella entran los datos en
serie.
679
RTS
a
Request To Send. Peticin de envo. Es una salida del ordenador. El ordenador pone
CTS
Clear To Send. Dispuesto para enviar. Es una entrada del ordenador. Si est a 1
significa que el ordenador puede enviar datos pues el mdem (o el dispositivo que
vaya a recibirlos) est preparado para hacerlo.
DSR
Data Set Ready. Dispositivo de datos preparado. Es una entrada del ordenador. Le
indica que el mdem est encendido y listo para funcionar.
DCD o CD
Carrier Detect. Deteccin de portadora. Es una entrada del ordenador. Le
indica al ordenador que el mdem est detectado seal de audio (tonos) vlida.
DTR
que
est
Data Terminal Ready. Terminal de datos listo. Es una salida del ordenador. Indica
est listo para trabajar. Suele emplearse para indicar al mdem que el ordenador
dispuesto para recibir informacin.
Otra seal (disponible slo en los ordenadores que tengan conector de 25 pines, y no en
todos) es la seal RING (timbre del telfono) Es una entrada del ordenador. Le indica que
est sonando el timbre de la lnea telefnica del mdem.
Disposicin de los pines en el ordenador
Dependiendo de si tiene conector de 9 pines o de 25, la distribucin de estas seales
fsicamente en el conector es :
Conector de 9 pines
Pin
3
2
7
8
6
5
1
4
Conector de 25 pines
Seal
Pin
TxD
RxD
RTS
CTS
DSR
GND
CD
DTR
RING
Tierra de proteccin
2
3
4
5
6
7
8
20
22
1
(La seal RING no est disponible en el conector de 9 pines. La deteccin del Ring del
telfono se realiza directamente por la lnea RxD. El mdem enva la palabra RING cuando
suena el timbre del telfono. La tierra de proteccin tampoco se usa en este conector.
680