domingo, 19 de enero de 2014

El entorno Visual Basic VI

Algo a lo que están acostumbrados muchos usuarios de computadoras que dependen de mosaicos gráficos pequeños para localizar rápidamente archivos y carpetas así como para localizar y abrir rápidamente programas ejecutables son los íconos que representan carpetas, archivos y programas ejecutables, los cuales por ser fáciles de reconocer facilitan cualquier trabajo llevado a cabo a través de la interfaz gráfica:




A través de los íconos podemos reconocer de inmediato si cierto archivo es un archivo de texto .TXT, si se trata de un documento .DOC que debe ser abierto con un procesador de palabras como Microsoft Word, o si se trata de una hoja de trabajo Excel con extensión .XLS. De hecho, antes del advenimiento de los sistemas operativos basados las interfaces gráficas, la única manera de saber el tipo de archivo era examinando su extensión, por ejemplo IMAGEN.BMP, BEATLES.MP3, y CACHORRO.JPG. Hoy en día, gracias a los íconos, muchos usuarios de computadoras con el sistema operativo Windows instalado en ellas desconocen la existencia de las extensiones de archivos a menos de que le pidan al sistema operativo que muestre por escrito dichas extensiones junto con el nombre del archivo.

Cuando se construye un proyecto en un entorno de diseño como Visual Basic, se desea que al momento de compilar el proyecto a un archivo ejecutable el programa final tenga anexado un ícono que sea mostrado cuando el programa es minimizado, esto es, que posea su propio ícono con el cual pueda ser identificado visualmente y de manera fácil por el usuario. ¿Pero cómo podemos lograr tal cosa? El primer paso consiste, desde luego, en el diseño de un ícono que sea representativo y sugerente del propósito del programa.

En la entrada “El entorno Visual Basic III” ya vimos cómo desde que apareció Visual Basic 1.0 se puso a la disposición de los programadores un proyecto en Visual Basic titulado ICONWRKS.MAK el cual de manera inmediata y directa podía ser compilado al programa ejecutable ICONWRKS.EXE que a su vez podía ser usado para el diseño de íconos, agregándose que se trata de un programa bastante completo con varias funciones útiles (en realidad, la inclusión de ICONWRKS.MAK tenía la intención de demostrar las muchas cosas que se podían lograr usando el entorno de programación Visual Basic).

Una vez que tenemos elaborado un ícono para un programa, ¿cómo podemos anclar dicho ícono al programa ejecutable? Ello se tiene que llevar a cabo en la etapa de diseño, y se logra anclando el ícono a la ventana principal del programa, que en la etapa de diseño es la forma desde la cual se invoca todo lo demás. Las formas en Visual Basic tienen una propiedad, Icon, con la cual podemos definir el ícono que represente a la aplicación final (ya compilada) dentro de la interfaz gráfica Windows. El ícono que sea seleccionado para esta propiedad puede ser uno de los muchos íconos suministrados gratuitamente por Microsoft en todas sus versiones de Visual Basic, o puede ser un ícono creado dentro del mismo Visual Basic usando para ello un programa como ICONWRKS (también se puede usar un programa como Paint incluído entre los programas “Accesorios” de Windows) que nos permita crear nuestro propio ícono “hecho en casa” guardado como un archivo ICO en el disco duro.

Dependiendo de la versión de Visual Basic que sea utilizada, una vez que se ha creado un ícono (o que se ha seleccionado alguno de los íconos proporcionados por Visual Basic) los pasos para establecer un ícono como el representante de cierta aplicación son (generalmente hablando) los siguientes:

(1) Se activa la forma a la cual se le quiere anexar el ícono. Se selecciona la propiedad Icon de la lista de Propiedades de la Forma, y se hace clic en donde dice (Icon) o bien en la caja de elipses que aparece al lado derecho de la barra de Propiedades correspondiente a la propiedad Icon. Esto hará que aparezca una caja de diálogo titulada “Load Icon” (Cargar Icono).

(2) En la caja de directorios (Directories, o bien Folders), se busca el subdirectorio que contiene el ícono que se ha creado o seleccionado para la aplicación. Se selecciona el archivo de ícono en la caja de archivos (Files) y se hace clic en el botón OK para completar la selección del ícono:




Para facilitarle su labor al programador, al ser convertido un proyecto Visual Basic a un programa ejecutable el entorno permite confirmar la selección del ícono que será utilizado:




Hay desde luego otros detalles que deben atendidos, los cuales dependen de la versión del sistema operativo Windows que se esté utilizando. En Windows 95, por ejemplo, había una cosa llamada Administrador de Programas (Program Manager) que permitía al usuario organizar sus programas en grupos. Ya para Windows XP esto estaba descontinuado, y el proceso de instalación de un programa nuevo en la máquina requería meterle mano al Registro (Registry) de Windows. Pero con lo anterior, la tarea de agregarle un ícono a una aplicación está esencialmente terminada.

En aplicaciones más avanzadas que le permitan al programador dar rienda suelta a su creatividad, podemos recurrir a funciones adicionales que abren un nuevo universo de posibilidades. Tómese por ejemplo la función LoadPicture() que nos permite cargar una imagen gráfica en una forma o en un control de imagen:

 LoadPicture(expresionhilera)

Esta función produce un valor de retorno, el cual es asignado a la propiedad Picture del objeto en el cual la imagen será colocada. Por ejemplo, en el caso de un control de imagen (Picture), las siguientes expresiones son igualmente válidas:

   Picture = LoadPicture("DEX2014.BMP")

   Picture1.Picture = LoadPicture("DEX2014.BMP")

Para cargar archivos ícono .ICO al ícono de la forma, el valor de retorno de la función LoadPicture tiene que ser asignado a la propiedad Icon de la forma del proyecto:

Icon = LoadPicture("ICONODEX.ICO")

Usando la función LoadPicture(), podemos especificar el siguiente programa que crea primero un ícono en blanco para una forma con la función LoadPicture() sin usar argumento en la función, dibujando tras esto con la función QBColor() un color aleatorio de entre 16 colores posibles, en puntos de imagen también aleatorios dentro del espacio del ícono cuando la forma es minimizada, o sea cuando la propiedad WindowState adquiere el valor de 1 (la función QBColor() será explicada en mayor detalle más abajo). Obsérvese que en el código se usa el procedimiento de eventos Resize() que es lo que se requiere cuando una forma cambia de tamaño, y usamos también la propiedad WindowState que es la que se adecúa en tiempo de ejecución a un valor entero para indicar si la ventana que corresponde a la forma está en su tamaño normal (0), si está minimizada encogida a un ícono (1), o si está maximizada al tamaño máximo de la ventana (2):

   Sub Form_Resize()

      Dim X, Y

      If Form1.WindowState = 1 Then

         Form1.Icon = LoadPicture()

         Do While Form1.WindowState = 1
            Form1.DrawWidth = 10
            Form1.ForeColor = QBColor(Int(Rnd*15))
            X = Form1.Width * Rnd
            Y = Form1.Height * Rnd
            PSet(X,Y)
            Tmp = DoEvents()
         Loop

      End If

   End Sub

Una función nueva en el código de arriba que no habíamos visto antes y que debe llamarnos la atención es la función DoEvents(), la cual carece de argumentos. Esta función ocasiona que Visual Basic ceda ejecución al sistema operativo Windows para permitirle procesar otros eventos (activaciones del Mouse, opresiones en el teclado, etc.), pasándole el control de la máquina a Windows para ser regresado a Visual Basic cuando Windows haya terminado de procesar otros eventos pendientes en su “cola” (queue) de eventos. Este es un caso curioso en el que, además de haber una función DoEvents(), también hay un enunciado DoEvents que permite escribir algo como lo siguiente para dar una salida fuera del programa pasándole el control de la máquina al sistema operativo:

If (X > 50) Then DoEvents

Al darle más opciones al usuario cubriendo todas las posibilidades habidas y por haber y hacer todo lo que se pueda para facilitarle su uso de las computadoras, y sobre todo hablando de la comodidad intuitiva que se les quiere dar a los programas, conforme se van agregando más y más controles a una forma además de una línea de Menú y una barra de Menú, la interfaz visual en lugar de ser una ayuda puede resultar algo confusa, sobre todo para personas que padecen alguna deficiencia de lectura como la dislexia. Previendo este tipo de dificultades, Visual Basic desde su primera versión incorporó una Paleta de Colores mediante la cual es posible agregarle no sólo un color de fondo a la forma sino inclusive a los mismos controles, con la finalidad de que un programa de aplicación pueda ser de manejo más accesible. A continuación se muestra la paleta de colores típica (en la parte inferior) con una forma a la cual tanto a ella como a sus controles se les ha agregado un color de fondo:




Pero no solo se puede usar la Paleta de Colores para darle a cada objeto puesto en una forma (o inclusive a la misma forma) un color de fondo. También es posible asignar colores mediante dos funciones distintas:

QBColor(argumento)      RGB(rojoverdeazul)

La función QBColor() toma un argumento entero situado en el rango entre 0 y 15, usando un código de colores que se remonta a los tiempos previos en los que se usaba el lenguaje de programación QuickBASIC (de allí el nombre de la función). Los valores del argumento de 0 a 15 representan colores tales como el negro, azul, verde, ciano, rojo, magenta, amarillo, blanco, gris, azul claro, amarillo claro y blanco brillante, lo cual podemos resumir en la siguiente tabla:


 Número  Color  Tonalidad 
0  Negro
1  Azul
2  Verde
3  Ciano
4  Rojo
5  Magenta
6  Amarillo
7  Blanco
8  Gris
9  Azul claro
10  Verde claro
11  Ciano claro
12  Rojo claro
13  Magenta claro
14  Amarillo claro
15  Blanco brillante


Esta convención de colores se remonta a los tiempos en los que los monitores de color apenas habían hecho su aparición (remplazando a los monitores monocromáticos que usaban la tarjeta de video Hercules Graphics Card) requiriendo para su funcionamiento la instalación en el interior de la computadora de una tarjeta de video CGA (Color Graphics Adapter) que ofrecía una gama muy limitada de 16 colores y una resolución muy baja de pixeles (puntitos elementos de imagen). Posteriormente hicieron su aparición los monitores EGA (Enhanced Graphics Adapter) que ofrecían una gama más amplia de 64 colores posibles, los cuales fueron reemplazados por los monitores VGA (Video Graphics Array) y estos a su vez por los monitores SVGA (Super VGA) ofreciendo los cientos de miles de colores posibles disponibles en los monitores modernos con una mayor resolución de puntos de imagen, reflejando tarjetas de video con chips rivalizando en complejidad a la misma unidad de procesamiento central CPU instalada en las computadoras.

A continuación se presentará un programa que hará que al hacerse clic dentro de la ventana cuando el programa está corriendo el interior de la ventana sea subdividido en 16 regiones recurriendo a la propiedad ScaleHeight que adjudica un “factor de escala” para subdividir la altura de la ventana en 16 porciones, cada una de las cuales tendrá un color que corresponde en orden creciente al argumento de la función QBColor():

  Sub Form_Click()

    Dim I  ' Declaracion de variable

    Cls  ' Limpiar el interior de la ventana

    ScaleHeight = 16  ' Subdividir la forma en 16 partes

    For I = 0 To 15
      Line(0,I) - (ScaleWidth, I+1), QBColor(I), BF
    Next I

  End Sub

Obsérvese que en el programa anterior se ha utilizado un método bautizado en Visual Basic como Line, mediante el cual es posible dibujar líneas y rectángulos en un objeto, y cuya sintaxis es:

objeto Line(x1,y1) - (x2,y2),  color,  opciones

Las coordenadas (x1,y1) corresponden al punto dentro del objeto a partir de donde se traza la línea, y las coordenadas (x2,y2) corresponden al punto dentro del objeto hasta donde llega la línea, sobreentendiéndose que el punto de origen (0,0) del sistema de coordenadas está en la esquina superior izquierda del objeto. La opción B dá lugar a que en vez de una línea se especifique el trazado de una caja rectangular (Box) en lugar de la línea, mientras que la opción F (Fill) ocasiona que la caja sea rellena del mismo color utilizado para dibujar la línea.

En el programa anterior, en lugar de haber utilizado la función QBColor() podríamos haber utilizado la función RGB() que nos dá una variedad mucho más rica de opciones, porque cada uno de los tres argumentos enteros de la función RGB() que corresponden respectivamente a las intensidades del rojo, azul y verde pueden tomar desde cero hasta 255 valores posibles, ofreciendo un total de:

256 * 256 * 256 = 16,777,216 colores posibles

Con la función RGB() disponible en nuestro repertorio, el programa que se dió arriba se puede modificar del siguiente modo para dibujar en el interior de una ventana una variedad de tonalidades de color:

  Sub Form_Click ()

    Dim I   'Declaracion de variable

    Cls  ' Limpiar el interior de la ventana

    ScaleHeight = 128  ' Dividir la forma en 128 partes

    For I = 0 To 126 Step 2
     Line (0,I) - (ScaleWidth,I+2), RGB(I,64+I,128+I), BF
    Next I

  End Sub

Así pues, se cuenta con muchas opciones para añadir una gran variedad de colores de muchas maneras, lo cual ha sido explotado provechosamente (y lucrativamente) en programas multimedia y en los videojuegos.

Este alud de opciones adicionales en realidad le presenta al programador otras dificultades que no había contemplado en su elaboración de programas de uso sencillo e intuitivo. Como el tener que saber algo sobre la psicología de la percepción. Se puede desde luego prescindir de muchos adornos visuales dependiendo del tipo de usuario que estará usando una aplicación y la finalidad con la cual será utilizado un programa, pero de cualquier manera el entorno Visual Basic hace disponible este alud de opciones en caso de que los programadores así lo requieran. Quizá la consideración más importante sea el nivel del auditorio al que está dirigida una aplicación; si los usuarios van a ser niños de primaria, entonces una abundancia de colores en la aplicación será algo deseable, mientras que si se trata de algo que va a ser usado en el departamento de contabilidad de una empresa grande o en la documentación oficial de alguna agencia gubernamental quizá un estilo sobrio con pocos colores sea lo más indicado.

Ya vimos con anterioridad la manera en la cual un programador con los controles de listado de drives, listado de directorios y listado de archivos puede abrir un archivo para trabajar con dicho archivo. Esto era suficiente cuando apareció la primera versión de Visual Basic. Pero eventualmente, conforme fue evolucionando el sistema operativo Windows, dicho sistema operativo puso a la diposición del usuario varias cajas de diálogo propias del sistema operativo que le permitieron efectuar desde dichas cajas operaciones tales como el copiado de archivos. Y si tales recursos estaban disponibles para los usuarios de las computadoras, obviamente también podían ser puestos a la disposición de los constructores de programas de aplicación, mediante la adición de controles adicionales a la Caja de Herramientas. Uno de tales controles lo fue el control de Diálogo Común. A continuación tenemos un ejemplo de la manera en la cual se le agrega un control de Diálogo Común a una forma:




Para que el control de Diálogo Común pudiera funcionar, era necesario incluír como parte de los archivos del proyecto el archivo CMDIALOG.VBX. Esto se llevaba a cabo de modo automático y predeterminado en Visual Basic 3.0, la versión de Visual Basic en la cual se incluyó por vez primera este control:




El archivo CMDIALOG.VBX es un objeto implementado mediante la metodología de la programación orientada a objetos, y para que pueda funcionar requiere que el archivo COMMDLG.DLL (una biblioteca de enlace-dinámico) forme parte parte del subdirectorio Microsoft \WINDOWS\SYSTEM; esto es, al crear y distribuír aplicaciones que usan este control el programador debe proporcionar un procedimiento de instalación (Setup) que instale tanto CMDIALOG.VBX como COMMDLG.DLL en el sub-directorio \WINDOWS\SYSTEM. El control de diálogos comunes proporciona una interfaz entre Visual Basic y las rutinas contenidas en la librería de enlace-dinámico COMMDLG.DLL.

Este control de diálogos comunes le permite al programador abrir y mostrar al usuario las siguientes cajas de diálogo comúnmente usadas:
  1. Open (Abrir)
  2. Save As (Guardar como)
  3. Color
  4. Font (Fuente)
  5. Print (Imprimir)
Usamos un control de diálogos comunes añadiéndolo a una forma y ajustando sus propiedades. El diálogo mostrado por el control está determinado por los métodos del control. En tiempo de ejecución, una caja de diálogo (no los controles de Diálogo Común, los cuales el usuario final nunca llega a ver porque no hay nada en ellos que pueda manipular con algún propósito útil) propia del sistema operativo es mostrada o la maquinaria de Help (Ayuda) es ejecutada cuando el método apropiado es invocado. En la etapa de diseño, el control de diálogos comunes es mostrado como un ícono en la forma, el cual no puede ser cambiado de tamaño. El programador es el único que sabe de la existencia de dicho control en el programa y el cual es requerido en la forma para poder manipularlo a través de las propiedades de dicho objeto.

Para especificar el tipo de ventana que será abierta, es necesario fijar la selección en la propiedad Action del control de acuerdo a la siguiente tabla:


 Valor  Tipo de Caja de Diálogo
0  Ninguna acción
1  Open (Abrir)
2  Save As (Guardar como) 
3  Color
4  Font (Fuente)
5  Print (Imprimir)
6  Se invoca WINHELP.EXE


Sin embargo, después de introducir un control de Diálogo Común en una forma, en la ventana de Propiedades para dicho control no aparece por ningún lado dicha propiedad Action. Se trata de esas propiedades que aunque no aparecen listadas en la ventana de Propiedades el programador de cualquier modo debe tener conocimiento de su existencia. Y si ponemos el enfoque (en la ventana del proyecto) sobre el el control CMDIALOG.VBX, el botón “View Code” aparece inaccesible. ¿Entonces cómo y en dónde vamos a especificar el tipo de ventana que queremos que se abra? La respuesta lógica: en la forma en donde fue insertado el control. El primer control de Diálogo Común que se inserta en una forma recibe de Visual Basic el nombre predeterminado CMDialog1. El segundo control de Diálogo Común que se inserta en la misma forma recibe el nombre predeterminado CMDialog2. Y así sucesivamente.

La sintaxis para especificar el tipo de diálogo común que se abrirá es la siguiente:

[Forma.]CMDialog.Action[=valor]

Para ver la manera en la cual funciona esto, podemos abrir un proyecto nuevo y colocar en dicho proyecto tres controles de Diálogo Común, los cuales recibirán de Visual Basic los nombres predeterminados CMDialog1, CMDialog2 y CMDialog3. Asismismo, el el procedimiento para el evento Load() de la forma, ponemos el siguiente código:

   Sub Form_Load ()

      Form1.CMDialog1.Action = 1

      Form1.CMDialog2.Action = 2

      Form1.CMDialog3.Action = 3

   End Sub

Si ejecutamos este programa, veremos que al principio se abrirá una ventana como la siguiente (bajo Windows XP), que por su título en castellano “Abrir” indica claramente que es una ventana del sistema operativo Windows para la apertura de un archivo:




Si cerramos la ventana Windows haciendo clic en el botón “Cancel” aparecerá a continuación una segunda ventana como la siguiente, que por su título en castellano “Guardar como” indica claramente que es una ventana del sistema operativo Windows para guardar un archivo:




Y si cerramos la ventana haciendo clic en el botón “Cancel” aparecerá a continuación una tercera ventana como la siguiente, que es claramente una ventana para llevar a cabo la selección de algún color:




¿Y cómo le dimos a cada una de estas ventanas sus títulos en castellano? De una manera muy sencilla. En la ventana de Propiedades de cada control (recuérdese que hay tres controles, CMDialog1, CMDialog2 y CMDialog3) hay una propiedad titulada “DialogTitle”, en la cual una vez seleccionada escribimos (en la parte superior de la ventana de Propiedades) el título que le queremos dar a cada ventana, en el idioma que queramos.

Obsérvese que, al abrir un archivo, de acuerdo a la extensión del mismo (.TXT, .DOC, .XLS, .JPG, etc.) el sistema operativo invocará automáticamente el programa en el que se corren los archivos con tal extensión. Interesantemente, esto era algo que no se podía hacer en el primer sistema operativo Windows, Windows 95, en el cual era necesario abrir el programa de aplicación requerido (Word, WordPerfect, Excel, Paintbrush, Photoshop, etc.) para abrir desde dicho programa el archivo deseado. Esto fue corregido con la introducción de Windows 98, un sistema operativo robusto para computadoras de 32 bits.

Los puristas del idioma argumentarán, sin que les falte razón en ello, que en las ventanas Windows que son abiertas con el control de Diálogo Común no resulta agradable la mescolanza de idiomas en la cual el título de cada ventana aparece en español y el resto dentro de la forma aparece en inglés. Podemos, si queremos, meternos más a fondo en el código de cada ventana para especificar el titulado de cada control cambiándolo del inglés al español, aunque esto implica meternos en camisa de once varas. En realidad, esto no debe ser motivo de preocupación, ya que la gran mayoría de los sistemas operativos dominantes en el panorama mundial existen no solo en versiones en lengua inglesa sino también en muchos otros idiomas, en donde todos los títulos y textos son puestos en el idioma seleccionado. Así, además de que hay sistemas operativos Windows en inglés, también hay sistemas operativos Windows en español, y en estos últimos todo aparece en español, sin que haya mescolanza de títulos y textos en ambos idiomas. Un programa de aplicación Visual Basic elaborado para una máquina que tiene instalado un sistema operativo Windows en español también debe ser elaborado en español, y los distribuidores de un programa de aplicación deben ser lo suficientemente precavidos para elaborar su programa en varios idiomas dándole a los usuarios de varios países la opción de instalar la versión apropiada en el idioma apropiado para sus países. De cualquier modo, es posible (y de hecho, ocurre mucho) correr en un sistema operativo Windows en español programas elaborados en Visual Basic con todo en inglés, lo cual ha permitido que usuarios en lugares como Brasil o Finlandia puedan usar programas que no necesariamente tendrán títulos, textos e instrucciones en su idioma nativo.

Los controles de Diálogo Común nos permiten usar de manera predeterminada como “cajas negras” algunas cajas de diálogo prefabricadas para varias de las funciones más esenciales de un programa tales como guardar un archivo o imprimir un documento en la impresora. Pero lo más probable es que un programa de aplicación deberá contener otras cajas de diálogo que ofrezcan otro tipo de opciones muy diferentes a las de las cajas de diálogo prefabricadas por el sistema operativo para ser invocadas como cajas negras. Tales cajas de diálogo hacen posible el seleccionar dos o más opciones entre una lista de opciones, o seleccionar únicamente una opción entre una lista de opciones. Para el primer objetivo, usamos los controles del tipo Cajas de Chequeo (CheckBox), los cuales son “cajitas” dentro de las cuales se puede poner una “palomita” (o una “X”, dependiendo de la versión de Visual Basic que haya sido utilizada) o quitar la “palomita” (o la “X” dentro de ella) que haya sido puesta previamente en ella. Usamos estos controles para darle al usuario una opción del tipo Falso/Verdadero o Sí/No. Usamos la propiedad Caption para poner el texto que va al lado de la cajita de chequeo, y usamos la propiedad Value para determinar el estado de la cajita, habiendo tres estados posibles: seleccionada, deseleccionada, o inhabilitada (se puede hacer una asignación previa de estos tres valores a cada cajita de chequeo al momento de arrancar el programa seleccionándolos automáticamente en la propiedad Value de la ventana de Propiedades haciendo clic sucesivamente con el botón del Mouse en dicha propiedad). Cada una de las cajitas es independiente de la otra, y podemos meter tantas opciones de cajas de chequeo como queramos dentro de una forma:




De este modo, al correr el programa, podemos tener algo como lo siguiente en lo cual podemos escoger opciones como las que se muestran (obsérvese que la última opción al fondo de la lista aparece inhabilitada):




Una opción de chequeo inhabilitada de inicio por el programador puede ser habilitada posteriormente durante la ejecución del programa de varias maneras, todas ellas fijando el valor de la propiedad Value dependiendo de lo que queramos que ocurra dentro de una cajita de chequeo:

   Check1.Value = 0   (cajita no checada)

   Check1.Value = 1   (cajita checada)

   Check1.Value = 2   (cajita inhabilitada)

Lo más probable sea que se utilice el valor de una cajita que ha sido checada para llevar a cabo una acción posterior dentro del programa, con una instrucción como:

   If Check1.Value = 1 Then

      ' Cógido a ser ejecutado

   End If

Los botones de opción trabajan en forma muy parecida a la manera en la que trabajan las cajitas de chequeo, excepto que en los botones de opción puestos dentro de una forma sólo es posible seleccionar uno de ellos a la vez.

Un problema que suele suscitarse en una ventana (forma) que tiene que tener dos o más grupos de botones de opción ofreciendo opciones distintas empieza después de que hemos introducido varios botones de opción a la forma que corresponden todos ellos a un primer grupo, y queremos meter el segundo grupo de botones de opción. El problema es que todos los botones de opción que van siendo metidos directamente a una forma van constituyendo un grupo de modo tal que en la aplicación al activar un botón de opción los demás botones de opción se “apagan” (su interior se pone en blanco) mientras que el botón de opción seleccionado se “enciende”; y si queremos meter el segundo grupo de botones de opción entonces la acción selectiva del segundo grupo se une a la del primer grupo, y en lugar de poder seleccionar dos opciones distintas seguiremos atorados con una sola opción. Para solventar este problema, se usa el <i>control de marco</i> (Frame), con el cual podemos separar botones de opción en grupos, pudiendo además darle un nombre al marco en el cual se agrupan botones de opción:




De este modo, cuando se corre el programa de aplicación, es posible seleccionar una de las seis opciones del primer grupo (8086, 80286, 80386, etc.) de manera independiente de cualquiera de las siete opciones del segundo grupo:




Para que esto funcione, es importante meter directamente cada botón de opción directamente dentro del grupo (marco) que le corresponde y no dentro de la forma pero fuera del grupo con la intención de “arrastrarlo” posteriormente con el Mouse hacia el interior del marco, ya que si se hace tal cosa el botón de opción seguirá correspondiendo al grupo que se encuentra fuera del marco ocasionando confusiones al ser ejecutado el código del programa.

Aunque lo anterior logra su propósito, una manera más elegante de lograr lo mismo consiste en poner también el primer grupo de botones de opción dentro de un marco al cual le podemos dar un nombre como “CPU” o “Procesador”, además de tener al segundo grupo de botones de opción dentro de su propio marco titulado “Sistema Operativo”.

El problema que ocurre con los botones de opción no ocurre con las cajitas de “chequeo” las cuales les ponemos una “palomita”, en virtud de que éstas últimas trabajan independientemente la una de la otra, y el usuario puede seleccionar al mismo tiempo el número de opciones que quiera.

Otra herramienta adicional para construír cajas de diálogo es el control conocido como Caja de Listado sencilla (ListBox):




Esta caja de listado muestra una lista de opciones en una caja colgante (drop-down), la cual tiene que ser especificada de antemano mediante código elaborado por el programador, código usualmente puesto en el procedimiento de evento Load() que se usa cuando la forma es abierta por el programa de aplicación, como en el siguiente ejemplo:

   Sub Form_Load()

     List1.AddItem "Doberman"
     List1.AddItem "Galgo"
     List1.AddItem "Labrador"
     List1.AddItem "Pastor Aleman"
     List1.AddItem "Pitbull"
     List1.AddItem "Pomeranio"
     List1.AddItem "San Bernardo"

   End Sub

Si se corre lo anterior en un programa de aplicación, aparecerá algo como lo siguiente (la selección Pitbull es hecha por el usuario, no por el programador):




No es necesario especificar la aparición de la barra de desplazamiento vertical cuando el número de artículos en la caja de listado excede la capacidad de renglones para exhibirlos de arriba hacia abajo, la barra de desplazamiento vertical es puesta automáticamente.

Al igual que todos los demás objetos (controles), la Caja de Listado posee propiedades, eventos y métodos. tales como Click(), el cual puede ser usado al hacer clic con el Mouse en un artículo de la lista, poniendo en movimiento acciones posteriores.

Una variante ligera a la vaja de listado sencilla es la Caja de Listado de Combinación (ComboBox), la cual combina las capacidades de una caja de texto y una caja de listado sencilla. Este control le permite al usuario hacer su selección ya sea escribiendo texto o seleccionando directamente un artículo de la lista como se hace en la caja de listado sencilla:




En la caja de listado de combinación también se tiene que especificar de antemano mediante código elaborado por el programador la lista de opciones, código usualmente puesto por el programador en el procedimiento de evento Load() que se usa cuando la forma es abierta al ejecutarse el programa, como se muestra en el siguiente ejemplo:

   Sub Form_Load()

     Combo1.AddItem "Doberman"
     Combo1.AddItem "Galgo"
     Combo1.AddItem "Labrador"
     Combo1.AddItem "Pastor Aleman"
     Combo1.AddItem "Pitbull"
     Combo1.AddItem "Pomeranio"
     Combo1.AddItem "San Bernardo"

   End Sub

Si se corre lo anterior en un programa de aplicación, aparecerá algo como lo siguiente:




En la lista de propiedades de una caja Combo, haciendo clic con el Mouse en la propiedad Style en la ventana de Propiedades de la caja encontramos los siguientes tres estilos válidos para una caja Combo:

   0 - Dropdown Combo

   1 - Simple Combo

   2 - Dropdown List

El primer estilo abre con lo que parece ser una simple caja de texto permitiéndole al usuario escribir (o empezar a escribir) el texto que describe el artículo que está buscando, o bien puede hacer clic con el Mouse en la flecha que aparece a la derecha de la caja de texto para abrir el listado de artículos en una lista que funciona en la modalidad de una “caja colgante”, ampliándose hacia abajo presentando la lista de opciones. Seleccionando una de las opciones de la caja colgante mete el texto del artículo en la caja de texto.

En el segundo estilo, la lista de opciones es mostrada todo el tiempo desde el momento en que se abre la ventana, pudiendo escoger el usuario el usuario su opción ya sea escribiendo en la caja de texto o seleccionando su opción de la lista mostrada, la cual tendrá una barra de desplazamiento vertical en caso de que el tamaño de la lista exceda la altura de la caja de listado de artículos.

Y en el tercer estilo, el usuario solo tiene la opción de seleccionar un artículo de la lista.

La mecánica sobre cómo trabajan todas estas cajas de diálogo es la misma a la que están acostumbrados los usuarios cuyas computadoras funcionan con alguna de las varias versiones del sistema operativo Windows, y no requieren de mayor explicación. De hecho, estas opciones de selección permanecieron sin cambio alguno hasta que fue necesario agregar métodos adicionales de selección de opciones al hacer su aparición las pantallas táctiles primero en los teléfonos inteligentes y posteriormente en los monitores de las mismas computadoras de escritorio.

Estas cajas de listado tienen algunas propiedades que resultan convenientes para el programador. Una de ellas es la propiedad Sorted (Acomodado), la cual si es cambiada de False a True hace que aunque los artículos en una lista estén desordenados alfabéticamente, de cualquier modo serán acomodados alfabéticamente cuando la caja de listado muestre su lista de opciones. Aunque en los ejemplo anteriores la lista de razas de perros estaba acomodada alfabéticamente, tal cosa no es necesaria si se hace este cambio en la propiedad Sorte, la cual resulta ventajosa cuando con el paso del tiempo se van agregando otros artículos a la lista que pueden hacer que se pierda el orden de listado alfabético.

En la siguiente entrada veremos algunos métodos para llevar a cabo dentro de una forma el trazado de varias figuras geométricas que pueden servir como el punto de arranque para añadir dibujos a una aplicación con propósitos especiales, por ejemplo una gráfica de barras que muestre el historial estadístico de algo a través de varios días o semanas. De cualquier modo, con un poco de ingenio, es posible poner en una forma líneas rectas que tengan como propósito subdividir con fines organizativos y estéticos el área interna de una forma (ventana) en varias áreas. Aquí se muestra una ilustración de esto:




La ventana de la aplicación, con el programa ejecutándose, está subdividida en lo que parecen ser tres áreas con objetivos distinos. La primera área, arriba a la izquierda, tiene un control titulado “Dibujar” que está inhabilitado, el cual seguramente será habilitado cuando el usuario seleccione algún archivo de entre la lista de opciones que haya en un sub-directorio que pueda ser procesado con fines de graficado. Dentro de esta área aparecen dos botones de opción que bajo la etiqueta “Cuñas” indicarán si la gráfica circular a ser trazada, subdividida en cuñas, tendrá cuñas diferenciadas de acuerdo a los colores puestos en el interior de cada cuña, o si usará patrones (sin color) de patrones grises punteados con distintas configuraciones que puedan distinguir una cuña de otra (este tipo de opciones se usaba mucho cuando los monitores comunes eran monocromáticos y los monitores de color aún no habían hecho su aparición o estaban sumamente caros debido a la costosa tecnología de tubos de rayos catódicos usada para fabricarlos). La segunda área, inmediatamente abajo de la primera también a la izquierda, contiene los controles de Directorio, Archivo y Drive usados para selecccionar el archivo a ser graficado. Y el área a la derecha tiene un espacio en blanco que seguramente será usado para dibujar la gráfica circular. Lo que subdivide la ventana en estas tres porciones son dos líneas rectas, una horizontal y otra vertical. ¿Y cómo podemos poner estas dos líneas en la forma? Una manera de hacerlo es mediante los métodos de graficado, pero otra manera más rápida y cómoda de lograrlo es metiendo dentro de la forma dos controles del tipo cajas de imagen (PictureBox), los cuales permiten poner una caja rectangular dentro de la forma, y he aquí el truco: si se le dá a una caja de imagen una altura lo más pequeña posible y una anchura al gusto, la caja de imagen será reducida esencialmente a una línea horizontal. Y si se le da a una caja de imagen una altura al gusto y una anchura lo más pequeña posible la caja de imagen será reducida esencialmente a una línea vertical. Este tipo de truco puede ser usado en otros entornos y en otros lenguajes de programación visual. Y por cierto, en el ejemplo proporcionado se puede apreciar que en algunos de los títulos aparece subrayada una de las letras del texto, algo indicativo de que se puede seleccionar algo con mayor rapidez oprimiendo en el teclado de la computadora la letra que corresponda a la letra subrayada al mismo tiempo que se oprime otra tecla como ALT o CTRL:

   Dibujar

   Directorio

   Archivo

   Drive

   Salir

Esto se logra fácilmente en la propiedad de título “Caption” dado a cada control anteponiendo el símbolo “&” a la letra que se desea subrayar, y en cada caso dado arriba el título Caption de cada objeto será:

   Di&bujar

   Di&rectorio

   &Archivo

   &Drive

   &Salir

He aquí otro ejemplo de una aplicación en la cual se utilizan líneas horizontales y verticales para subdividir una ventana en varias áreas que tengan información que por algún motivo debe ser manejada por separado:




En este caso, también se usan dos líneas rectas para separar en tres porciones el área disponible dentro de la ventana, una horizontal y otra vertical. Para lograr esto, en la etapa de diseño podemos poner dos cajas de imagen, y acortar al menor grosor posible ya sea la altura o la anchura, logrando obtener el efecto de una línea horizontal y una línea recta:




Al ejecutarse el programa, el usuario jamás se imaginará que detrás de esas dos líneas hay dos objetos que en principio son capacer de contener imágenes, ese será uno de los secretos que el programador guardará para sí.

En la última figura mostrada, se tiene lo que parece ser un “Conversor de Fechas”, algo en lo cual escribimos en las dos cajas de texto en algún formato como 15/4/92 y 31/12/99 lo que corresponde a dos fechas designadas como “Fecha #1” y “Fecha #2”, calculándose algún número serial asignado por la computadora a cada fecha, algo como 33709 y 36525, y calculándose lo que vendría siendo la diferencia en días entre ambas fechas, algo como 2816 días. Posiblemente el lector esté interesado en saber cómo funcionaría un programa de este tipo, y es lo que explicaremos en mayor detalle habido el hecho de que existen muchas aplicaciones en las cuales se recurre al reloj interno de la computadora para fijarle fecha y hora a algún dato o datos. Y si algo poseen casi todas las computadoras de escritorio e inclusive las tabletas electrónicas es un reloj interno, el cual siempre está funcionando y marcando el tiempo según transcurre mientras la batería interna que mantiene energizado el CMOS RAM de la tarjeta madre no se haya agotado.

Los datos cronológicos, consistentes en valores de fecha y tiempo, son importantes en una gran variedad de aplicaciones de negocios. Una cuenta bancaria, por ejemplo, puede mantenerle la pista a los depósitos y retiros efectuados por un cliente; para el cálculo de cosas tales como los intereses pagados o los cargos cobrados al cliente el programa llevará a cabo operaciones específicas con estas fechas y datos. Del mismo modo, el programa para una hoja del tiempo trabajado llevará el registro del tiempo que transcurre desde el momento en que el trabajador reporta su entrada hasta que el trabajador reporta su salida. Estas operaciones de este tipo involucran lo que se conoce como la aritmética de fechas y la aritmética de tiempos.

Para poder llevar a cabo operaciones aritméticas eficientes sobre valores cronológicos, un programa necesita de algún sistema para traducir (convertir) fechas y tiempos en valores numéricos representativos. Para este propósito, las fechas son consideradas como números enteros. En general, un valor dado de fecha-entero es igual al número de días que han transcurrido desde cierto punto de referencia en el pasado. Dados dos enteros que representan fechas, podemos calcular fácilmente el número de días entre ambas fechas simplemente restando el entero menor del entero mayor. Por otro lado, un valor de tiempo puede ser representado convenientemente como un valor fraccionario, expresando la porción del día de 24 horas que ha transcurrido en cierto punto temporal. A modo de ejemplo, 6:00 A.M. es representado como la fracción decimal .25, porque la cuarta parte de un día ha transcurrido ya cuando son las seis de la mañana. Por el mismo tenor, la medianoche es igual a 0 y el mediodía es igual a 0.5.

Desde el momento en que apareció la primera versión de Visual Basic se empezó a utilizar un formato práctico conocido como el número serial para representar en forma combinada y simultánea los valores de fecha y tiempo. Específicamente, un número serial es un valor de doble precisión de punto flotante que Visual Basic interpreta como una fecha y tiempo particular. La parte entera del número serial, esto es, la secuencia de dígitos colocados antes del punto decimal, representa una fecha. La parte fraccionaria, la secuencia de dígitos colocados después del punto decimal, representa el tiempo del día (lo que comúnmente se conoce como la hora).

La referencia fija que se empezó a utilizar con la aparición de Visual Basic 1.0 para calcular fechas seriales es el 30 de diciembre de 1899. Esta “fecha de inicio” tiene un valor serial igual a cero. Fechas subsecuentes, hasta el 31 de diciembre de 2078, tienen valores positivos. Todas las fechas previas al 30 de diciembre de 1899 tienen valores negativos. Combinado con la parte fraccionaria que representa la hora del día, un número serial es un valor completo que dá la fecha y hora de algún suceso.

Una función ampliamente utilizada en Visual Basic que proporciona la fecha y el tiempo actual evitándonos entrar en los detalles del número serial es la función Now, la cual se comunica directamente con el reloj interno de la computadora leyendo la fecha y la hora de dicho reloj y regresa la fecha actual y la hora actual de acuerdo con los parámetros del sistema de cómputo de fecha y tiempo. A continuación se presenta un programa breve que se encarga de proporcionar en dos cajas de mensaje (apareciendo una después de la otra) la fecha y el tiempo:

   Sub Form_Load ()

      Dim Hoy, Mensaje1, Mensaje2

      Hoy = Now

      Mensaje1 = "Hoy es " & Format(Hoy, "dddd, dd, mmmm, yyyy")

      Mensaje2 = "La hora es " & Format(Hoy, "ttttt")

      MsgBox Mensaje1

      MsgBox Mensaje2

   End Sub

Al ejecutarse el programa y cargarse en la memoria RAM, aparece primero la primera caja de mensaje dando la fecha:




Después de hacer clic en el botón OK, desaparece la primera caja de mensaje y aparece la segunda caja de mensaje dando el tiempo actual:




En el programa, el valor proporcionado por la función Now es almacenado en la variable “Hoy”, la cual es tomada por Visual Basic como un dato del tipo Date. Obsérvese que para poder extraer de dicha variable la fecha y la hora del día se hace uso intensivo de la función Format(), cuya sintaxis es:


Format(expresion ,  fmt)

en donde expresion es la expresión numérica o de hilera a ser formateada, mientras que fmt indica la manera en la cual se formatearán los caracteres tomados de la expresión. En el caso de la fecha:

Format(Hoy, "dddd, dd, mmmm, yyyy")

la hilera:


"dddd, dd, mmmm, yyyy"

le indica a Visual Basic que con la parte "dddd" se imprimirá el nombre del día, con la parte "dd" se imprimirá el día (por ejemplo, 16), con la parte "mmmm" se imprimirá el nombre del mes, y con la parte "yyyy" se imprimirá el año (year) en ese orden. Se puede alterar el orden de la impresión con la finalidad de que la fecha siga el orden que se acostumbra usar en algún país específico. El orden mostrado en el programa de ejemplo es el que se usa en los países de habla hispana. Si se quiere obtener el orden usado en países de habla inglesa como Estados Unidos y Canadá, se usa la hilera:

"dddd, mmmm, dd, yyyy"

Al leer la fecha producida por el programa anterior, se puede apreciar una mescolanza de palabras en inglés y español. Esto se debe a que el sistema operativo instalado en la máquina cuyo reloj interno proporciona los datos es un sistema operativo Windows en idioma inglés. Para que todo aparezca en español, esto ya no es cuestión de Visual Basic, es una cuestión del sistema operativo instalado en la máquina, ya sea un sistema operativo en inglés, español, alemán, francés, o lo que sea. Se puede cambiar el idioma nativo manipulando el panel de control de los ajustes de la máquina, aunque lo más fácil es suponer que en la instalación del programa se tendrá un programa elaborado en español para ser ejecutado en colaboración con un sistema operativo también en español.

En el caso de la hora del día:

Format(Hoy, "ttttt")

la hilera de control de formateo es mucho más sencilla, ya que es simplemente "ttttt". Obsérvese que podríamos habernos ahorrado unas cuantas líneas de código en el programa de arriba usando simplemente:

Format(Now, "dddd, dd, mmmm, yyyy")

La siguiente tabla nos dá un resumen de las posibilidades de formateo:


 Caracter  Significado
 c  Muestra la fecha como dddd y muestra el tiempo como
 tttt, en ese orden
 d  Muestra el dia como un número sin anteponer un cero
 (1-31)
 dd  Muestra el dia anteponiendo un cero (01-31)
 ddd  Muestra el dia como una abreviatura (Dom-Sab)
 dddd  Muestra el dia como un nombre completo (Domingo
 -Sabado)
 ddddd  Muestra el número serial de fecha como una fecha
 completa (incluyendo dia, mes y año)
 w  Muestra el dia de la semana como un número (1 para
 el Domingo hasta 7 para el Sábado)
 ww  Muestra la semana del año como un número (1-53)
 m  Muestra el mes como un número sin anteponer un
 cero (1-12)
 mm  Muestra el mes como un número anteponiendo un
 cero (01-12)
 mmm  Muestra el mes como una abreviatura (Ene-Dic)
 mmmm  Muestra el mes como un nombre completo (Enero
 -Diciembre)
 q  Muestra el cuatrimestre como un número (1-4)
 y  Muestra el dia del año como un número (1-366)
 yy  Muestra el año como un número de dos dígitos
 (00-99)
 yyyy  Muestra el año como un número de cuatro dígitos
 ( 100-9999)
 h  Muestra la hora como un número sin anteponer
 ceros (0-23)
 hh  Muestra la hora como un número anteponiendo
 ceros (00-23)
 n  Muestra el minuto como un número sin anteponer
 ceros (0-59)
 nn  Muestra el minuto como un número anteponiendo
 ceros (00-59)
 s  Muestra el segundo como un número sin anteponer
 ceros (0-59)
 ss  Muestra el segundo como un número anteponiendo
 ceros (00-59)
 ttttt  Muestra el número serial de la hora como un tiempo
 completo (incluyendo hora, minuto y segundo)
 AM/PM   Usar un reloj de 12 horas mostrando un AM en
 mayúsculas para cualquier hora antes del mediodía,
 mostrar un PM en mayúsculas para cualquier hora
 entre el mediodía y las 11:59 PM
 am/pm  Usar un reloj de 12 horas mostrando un AM en
 minúsculas para cualquier hora antes del mediodía,
 mostrar un PM en minúsculas para cualquier hora
 entre el mediodía y las 11:59 PM
 A/P  Usar un reloj de 12 horas mostrando una A
 mayúscula para cualquier hora antes del mediodía,
 mostrar una P mayúscula para cualquier hora entre
 el mediodía y las 11:59 PM
 a/p  Usar un reloj de 12 horas mostrando una A
 minúscula para cualquier hora antes del mediodía,
 mostrar una P minúscula para cualquier hora entre
 el mediodía y las 11:59 PM


A continuación se muestran ejemplos para varios de los formatos dados arriba:


Formato  Se muestra como 
 m/d/yy  11/7/68
 d-mmmm-yy   7-Noviembre-68 
 d-mmmm  7-Noviembre
 mmmm-yy  Noviembre 68
 hh:mm AM/PM   09:35 PM
 hh:mm:ss a/p   09:35:27 p
 h:mm   21:35
 hh:mm:ss   19:35:27
 m/d/yy h:mm   11/7/68 21:35


Otra manera de extraer la información de fecha y tiempo de Now es usando la función Int() para obtener por ejemplo la parte entera y con ello la fecha:

Fecha = Int(Now)

De este modo, podemos reescribir el programa anterior del siguiente modo, obteniendo exactamente el mismo efecto:

  Sub Form_Load ()

    Dim Fecha, Hora, Mensaje1, Mensaje2

    Fecha = Int(Now)   ' Parte entera del numero serial

    Hora = Now - Int(Now)   ' Parte fraccionaria del numero serial

    Mensaje1 = "Hoy es " & Format(Fecha, "dddd, dd, mmmm, yyyy")

    Mensaje2 = "La hora es " & Format(Hora, "ttttt")

    MsgBox Mensaje1

    MsgBox Mensaje2

  End Sub

Hay pues varias maneras de escribir programas en Visual Basic (y en cualquier otro lenguaje de programación) para obtener exactamente lo mismo, cada programador impondrá sus propios estilos y sus propias preferencias; el usuario final jamás se dará cuenta de tales diferencias excepto en la eficiencia y velocidad con la cual funcionen los programas. Los mejores programas serán los que produzcan los mejores resultados en el menor tiempo posible.

Para la aritmética de tiempos la máquina no almacena una hora como “09:35:27” así como tal (como una expresión de hilera), y tampoco para la aritmética de fechas almacena una fecha como “7-Noviembre-68” así como tal (como una expresión de hilera) . Como ya se señaló arriba, ambos datos se almacenan como la parte entera y la parte fraccionaria de un número de punto flotante de doble precisión. Podemos obtener el número decimal que corresponde a la hora o a la fecha a partir de las hileras en cada caso mediante dos funciones, la función TimeValue() y la función DateValue() cuyas sintaxis son:

   TimeValue(expresiondehilera)

   DateValue(expresiondehilera)

Por ejemplo:

   TimeValue("18:27:15")

   DateValue("November/7/1968")

A continuación se muestra un programa que pone esto en práctica así como la caja de mensaje que se produce cuando la forma se carga y se ejecuta el código:




Obsérvese que en el código estamos declarando una variable llamada Fecha como de tipo Double (aritmética de punto flotante de doble precisión). Obsérvese también que proporcionando la hilera de fecha “December/30/1899” obtenemos una respuesta igual a cero. ¿Por qué? Pues precisamente porque el 30 de diciembre de 1899 es el punto de referencia cero para que la fecha empiece a contar de un día a otro. Si en lugar de usar la hilera “December/30/1899” usamos la hilera “April/15/1992”, obtendremos el número serial 33709. Y si usamos la hilera “December/31/1999”, obtendremos el número serial 36525. Restando el número 33709 del número 36525 obtenemos 2816. Que es precisamente el número de días que han transcurrido desde el 15 de abril de 1992 hasta el 31 de diciembre de 1999. Esta es la manera en la cual se lleva a cabo la aritmética de fechas, convirtiendo cada fecha a un número serial, y efectuando operaciones aritméticas sencillas con los números seriales obtenidos. Con esto en mente, seguramente el lector ya se puede imaginar una manera (o varias maneras) en que se puede elaborar el código para construír el “Conversor de Fechas” que se ha mostrado arriba; la obtención de los números seriales a partir de cada fecha se lleva a cabo con la función DateValue(), y la diferencia entre ambos números seriales es lo que proporciona la “Diferencia en dias” que calcula el programa.

Igual podemos usar la función TimeValue() para obtener la parte fraccionaria Tiempo que corresponde al número serial Fecha.Tiempo y usar esto para calcular, por ejemplo, a partir de la hora en la que un trabajador ingresa a laborar y la hora en la que sale de su trabajo, el tiempo extra que dicho trabajador estuvo laborando, permitiendo con ello pagarle el tiempo extra en forma justa e imparcial. Si se ejecuta el siguiente código:

   Sub Form_Load ()

      Dim Tiempo As Double

      Tiempo = TimeValue("December/31/1999")

      MsgBox "El numero del tiempo es " & Tiempo

   End Sub

se imprimirá en la pantalla el siguiente mensaje en una caja de mensajes:

El numero del tiempo es .400289351851852

En este caso, el resultado no parece tan claro, pero hay que tomar en cuenta que la hora es una fracción de un día de 24 horas. Si en vez de la hilera "9:36:25" se pone la hilera "12:00:00" se imprimirá el mensaje:

El numero del tiempo es .5

indicando correctamente que es la mitad del día, o sea el mediodía. Para un mismo día, la diferencia entre dos números de tiempo corresponden a un intervalo, el cual tiene que ser convertido a una hilera apropiada para ser legible por el usuario final como un intervalo de tiempo en minutos y segundos.

Tal vez asombre al lector que para obtener la fecha y el día de un número serial existen además las siguientes dos funciones en Visual Basic:

   DateSerial(año, mes, dia)

   TimeSerial(hora, minutos, segundos)

Todos los argumentos pasados a estas dos funciones son numéricos, y deben darse en el orden indicado. La primera función DateSerial() regresa un número almacenado internamente como un número de doble precisión que representa una fecha entre el primero de enero del año 100 y el 31 de diciembre del año 9999, en donde el primero de enero de 1900 es igual a 2 y los números negativos representan fechas anteriores al 30 de diciembre de 1899. La segunda función TimeSerial() regresa un número fraccionario almacenado internamente como un número fraccionario de doble precisión entre 0 y .99999 que representa un tiempo entre 0:00:00 y 23:59:59.

Un ejemplo del uso de DateSerial es el siguiente:

   Sub Form_Load ()

      Dim Fecha As Double

      Fecha = DateSerial(1992, 4, 15)

      MsgBox "El numero de la fecha es " & Fecha

   End Sub

Si se ejecuta el programa anterior, se imprimirá en la pantalla el siguiente mensaje:

El numero de la fecha es 33709

Por otro lado, un ejemplo del uso de TimeSerial es el siguiente:

   Sub Form_Load ()

      Dim Tiempo As Double

      Tiempo = TimeSerial(9,36,25)

      MsgBox "El numero del tiempo es " & Tiempo

   End Sub

Si se ejecuta el programa anterior, se imprimirá en la pantalla el siguiente mensaje:

El numero del tiempo es .400289351851852

PROBLEMA: ¿Cuál es, en Visual Basic, el número serial que describe las 9:36:25 horas del 15 de abril de 1992?

La respuesta se obtiene simplemente combinando los dos resultados que se acaban de obtener arriba:

Fecha.Tiempo = 33709 + .400289351851852

Fecha.Tiempo = 33709.400289351851852

Hemos visto la manera en la cual podemos leer de la máquina valores que son mantenidos por el hardware de la misma, cosas tales como la fecha y el tiempo de los cuales el reloj del sistema lleva la cuenta aún cuando la máquina está apagada. Sin embargo, cabe formularse una pregunta un poco más audaz: ¿es posible, mediante Visual Basic, cambiar valores que son mantenidos por el hardware de la máquina? Aquí nos estamos metiendo en un terreno más truculento en el que hay que tomar en consideración otros detalles que con los que no nos habíamos topado antes. Tómese, por ejemplo, la hora del día, la cual es mantenida actualizada por el reloj del sistema en una memoria CMOS RAM. Además de la función Time que nos regresa la hora del día, y cuya salida es equivalente a:

Format$(Now, "hh:mm:ss")

existe un nunciado Time usado para fijar la hora del sistema. La sintaxis del enunciado Time es la siguiente:

Time = expresion

en donde expresion es la hilera usada para describir lo que sera cambiado, pudiendo ser simplemente hh para fijar únicamente la hora (los minutos y los segundos son fijados de modo automático a 00), hh:mm para fijar la hora y los minutos (los segundos son fijados de modo automático a 00) y hh:mm:ss.

El siguiente ejemplo de código nos muestra la manera en la cual se usa el enunciado Time para reajustar la hora del día que es marcada por el sistema (el reloj interno de la computadora):

   Sub Form_Click ()

      Dim Msg, TiempoNuevo

      Msg = "Dame un tiempo nuevo en el formato hh:mm:ss"

      TiempoNuevo = InputBox(Msg, "", Time)

      If Len(TiempoNuevo) > 0 Then

         Time = TiempoNuevo

         Msg = "El tiempo del sistema está puesto a "

         Msg = Msg & Time & "."

      Else

         Msg = "No pusiste un tiempo valido"

      End If

     MsgBox Msg

   End Sub

Si para ejecutar este código usamos una de las primeras versiones de Visual Basic, por ejemplo Visual Basic 2.0, la cual podía producir programas ejecutables capaces de funcionar bajo el viejo sistema operativo MS-DOS (dentro de Windows cuando Windows aún no era un sistema operativo, cuando Windows apenas era una interfaz visual), en versiones previas al sistema operativo MS-DOS 3.3 el cambio efectuado con el enunciado Time permanecía en efecto únicamente hasta se apagaba la computadora, porque eran los tiempos en los que algunas computadoras caseras aún no tenían un reloj operado continuamente por una batería interna, cada vez que se encendía esas máquinas había que poner la fecha y la hora a tiempo. Y en las máquinas que sí tenían una memoria CMOS RAM apoyada con una batería interna, el cambio no se llevaba a cabo usando el programa anterior. Sin embargo, el programa dado arriba funcionaba bien en el sistema operativo Windows 95, un sistema operativo de 32 bits. Pero al hacer su aparición otros sistemas operativos de 32 bits como Windows XP, el programa deja de funcionar, no sirve para producir cambios en el sistema. En rigor de verdad, para poder efectuar este tipo de cambios, se requiere la elaboración de programas con el mismo propósito pero usando otro tipo de lenguaje, como el lenguaje C. Y para cada tipo de sistema operativo se requiere una versión apropiada del programa ejecutable. De este modo, para sistemas operativos de 32 bits (como Windows XP), se requiere elaborar programas ejecutables capaces de correr en máquinas de 32 bits. Y para sistemas operativos de 64 bits (como Windows 8) se requiere elaborar programas ejecutables capaces de correr en máquinas de 64 bits. Podemos elaborar dos versiones diferentes, y concebir alguna manera de detectar el tipo de sistema operativo instalado en una máquina, con el fin de que se transfiera la tarea a la versión requerida para poder ejecutar el programa.

No hemos agotado las funciones disponibles en Visual Basic para llevar a cabo la aritmética de tiempos y fechas. Existen además otras funciones como:

    Year(número)

    Month(número)

    Weekday(número)

    Hour(número)

    Minute(número)

    Second(número)

En cada función, el número debe ser obvio. En el caso de Year, el número debe ser un entero de cuatro dígitos como 2015. En el caso de Minute, el número debe ser un entero como 48 (un entero entre 0 y 59, inclusive), y en el caso de Weekday el número debe ser un entero entre 1 y 7 con 1 representando a Domingo y 7 representando al Sábado.

La única manera de poder estar al tanto de todas las funciones disponibles en la versión de Visual Basic que se tenga a la mano así como las propiedades de los objetos (controles) que estén disponibles en el Visual Basic que estemos usando es consultando el Manual del Programador que se incluye en cada versión que es puesta a la venta. O bien consultar sitios de Internet que proporcionen una explicación sobre las propiedades de cada objeto. Aquí se ha tratado de dar un común denominador que es válido para la mayoría de las versiones de Visual Basic desde que apareció Visual Basic 1.0. Afortunadamente, se puede esperar que todas las versiones posteriores de Visual Basic que vayan apareciendo incorporen este común denominador, por la simple y sencilla razón de que existe una enorme cantidad de documentación conteniendo millones de líneas de código que perderían su utilidad si se implementaran cambios drásticos en la sintaxis o en la forma de trabajar. Este requerimiento de que haya una compatibilidad hacia atrás (backward compatibility) le garantiza a los programadores de hoy que mucho de lo que están aprendiendo y desarrollando les será útil en el futuro, y buena parte de sus esfuerzos podrá ser reciclada de maneras insospechadas.