domingo, 19 de enero de 2014

El entorno Visual Basic III

Muchos programas de aplicación en el sistema operativo Windows (al igual que otros sistemas operativos), sobre todo aquellos con mayor presentación profesional, suelen poner en la parte superior de la ventana de trabajo una barra de Menú en la cual se presentan varias opciones que se puedan ir seleccionando conforme lo requiera el usuario.

Desde que hizo su primera aparición Visual Basic, se ofreció al programador la capacidad de poder agregarle una barra de Menú a cada programa de aplicación. Una barra de Menú no es un objeto propiamente dicho, es una capacidad que se le agrega a un objeto del tipo forma, y por lo tanto requiere de un tratamiento especial. Es por ello que para habilitar una forma con una barra de Menú Visual Basic pone a disposición una ventana para diseño de menús (Menu Design Window), la cual al tenerse abierta una forma (la forma a la cual se le va a agregar la barra de Menú) hace que se agregue una barra de Menú a la forma. Esta ventana para diseño de menús tiene el siguiente aspecto:




La palabra Caption es la que aparecerá como opción en la barra de Menú, mientras que el nombre Name es el nombre que será usado para invocar alguna acción cuando se seleccione una opción de la barra de Menú. A nombre de ejemplo, supóngase que queremos que la primera opción en la barra de Menú sea una opción titulada “Archivo”, y que el nombre que será usado en el código cuando dicha opción es seleccionada por el usuario final sea “mnuArchivo” (obsérvese que le estamos dando el mismo nombre descriptivo de la opción anexándole de acuerdo a la notación húngara el prefijo descriptivo “mnu” que significa que se trata de un artículo de menú:




Al hacer clic en el botón OK de la ventana para diseño de menús (lo cual cierra la ventana) veremos que aparece de inmediato en la forma en la que estamos trabajando una barra de Menú con la palabra de opción “Archivo”. Si corremos el programa bajo el entorno protegido de Visual Basic y seleccionamos la opción, no sucederá nada, porque no se ha elaborado aún ningún código que responda a este tipo de evento.

Con la ventana de diseño de menús, podemos no sólo crear opciones de Menú sino también sub-opciones de Menús y sub-opciones dentro de cada sub-opción de Menú, tantas como queramos. Para ello usamos el botón “Next” que nos lleva a la creación de la siguiente opción (o sub-opción), y usamos los botones con las flechas de navegación (flecha hacia la izquierda, flecha hacia la derecha, flecha hacia arriba, flecha hacia abajo) para movernos como queramos a través de toda la jerarquía de opciones y sub-opciones, subiendo y descendiendo según se requiera a lo largo de la jerarquía. De este modo podemos tener algo como lo siguiente:




Si corremos esto bajo el entorno Visual Basic, veremos que aparece una barra de Menú en la forma, en la cual al hacer una selección aparecerá una lista de sub-opciones tal y como lo hemos definido arriba:




Es común encontrar en los programas elaborados para correr bajo Windows la especificación de teclas de acceso, con las cuales al oprimir la tecla “Alt” del teclado en combinación con otra tecla (como la tecla de la letra “A”) se seleccione y se ponga en marcha la opción que aparece en la barra de Menú que tenga tal letra subrayada (esta opción resulta útil en aquellas máquinas en las cuales el Mouse no está disponible por alguna razón, y permiten trabajar sin Mouse usando simplemente el teclado). Podemos especificar teclas de acceso anteponiendo el ampersand (&) a la letra que aparecerá subrayada (no en la etapa de diseño del programa, sino cuando el programa está siendo ejecutado) en la palabra que indique la opción seleccionada. De este modo, lo anterior puede tomar el siguiente aspecto agregando teclas de acceso (obsérvese la adición del & al Caption de Correr):




Además de la posibilidad de agregar teclas de acceso para posibilitar la ejecución de un programa sin necesidad de tener que recurrir al Mouse (incómodo, desde luego, pero posible), también se pueden agregar atajos (shortcuts) para lo cual al especificar una opción o una sub-opción se selecciona el atajo deseado para la opción de menú deseada con las opciones de teclas de atajo disponibles en la ventana de diseño de menús (obsérvese que no se puede asignar una tecla de atajo a una opción principal en la barra de Menú):




Además de lo anterior, podemos agregar a cualquier lista de sub-opciones de menú una linea de separación que al ejecutarse el programa trazará una línea que separe las sub-opciones que aparecen arriba en la lista de las sub-opciones que aparecen abajo, lo cual sirve no tanto para fines de la programación en sí sino para sub-dividir las sub-opciones en bloques lógicos cuya propósito sea más entendible por el usuario final. Para agregar una línea de separación, en vez de poner algún nombre en la cajita “Caption” de la ventana de diseño de menús, ponemos simplemente un guión medio, el cual será interpretado en la ejecución del programa como una línea de separación. La siguiente figura (se recomienda ampliarla a su máximoo natural para apreciar mejor los detalles) usa como ejemplo el mismo menú de Visual Basic que en la lista de sub-opciones posee siete líneas de separación:




También podemos agregar a una sub-opción en una lista una “palomita” seleccionando para ello “Checked”, con lo cual le estamos diciendo al usuario final que esa opción es la opción predeterminada de la lista con la cual se está ejecutando el programa. Las opciones de diseño de menú “Enabled” y “Visible” sirven para habilitar y hacer visible las sub-opciones, agregándose que se puede elaborar código para deshabilitar e inclusive hacer invisible cualquier sub-opción de menú (esto es lo que se usa cuando al estarse ejecutando un programa en cierto modo se desea indicar al usuario que mientras el programa está en tal modo las demás opciones de selección están deshabilitadas).

Bien, podemos agregar una barra de Menú a una forma (y no únicamente a la forma principal con la que empieza un programa, sino también a cualquier otra forma que sea abierta por el programa). ¿Pero cómo logramos que se lleve a cabo alguna acción al hacer clic en una opción de menú o en una sub-opción? La clave radica en el hecho de que, al crear una barra de Menú, y al ir creando para dicha barra una lista de opciones (y sub-opciones) Visual Basic va creando automáticamente una lista de objetos (¿podrían ser acaso otra cosa?) dándole a cada objeto del tipo menú el nombre que se le dió con “Name” (nombre) en la ventana de diseño de menús. Para el ejemplo que se ha desarrollado arriba, al abrir (bajo Visual Basic en la etapa de diseño) la ventana que nos da un listado de los objetos para la forma, encontramos el siguiente listado de objetos:

      Form
      mnuAbrir
      mnuArchivo
      mnuAyuda
      mnuCopiar
      mnuCorrer
      mnuCortar
      mnuDetener
      mnuEditar
      mnuEmpastar
      mnuEmpezar
      mnuGuardar
      mnuSalir

Mientras que el objeto forma (Form1.frm) tiene muchos eventos posibles a los cuales puede responder, en lo que toca a estos objetos de menú si buscamos los eventos disponibles para cada uno de estos objetos encontraremos que sólo hay un evento especificado para cada uno de ellos, el evento Click(), lo cual es lógico ya que es el único evento que esperamos que ocurra con un artículo en una barra de Menú, al hacer clic con el Mouse en una opción o sub-opción. El evento para el objeto mnuArchivo tendrá espacio para su código en un procedimiento Sub:

   Sub mnuArchivo_Click()

      .........
       
   End Sub

Con este procedimiento Sub el programador puede hacer lo que quiera en respuesta a la selección de tal opción. Sin embargo, si lo que quiere es abrir un archivo de algo (por ejemplo, un archivo de imagen) lo más probable es que querrá escribir código para el evento:

   mnuAbrir_Click()

dejando a mnuArchivo_Click() sin código alguno (al hacer esto, no se ejecutará nada cuando el usuario seleccione la opción Archivo, el usuario tendrá que ir a una sub-opción como Abrir para abrir un archivo o a una sub-opción como Guardar para guardar un archivo en el que haya estado trabajando).

Habíamos visto en la entrada anterior cómo, bajo una programación orientada a objetos, existen objetos tanto dentro de un programa de aplicación como dentro del sistema operativo, y dichos objetos se pueden intercomunicar entre sí. En los sistemas operativos Windows, uno de sus objetos es el Portapapeles (Clipboard). El usuario jamás llega a ver el Portapapeles, y seguramente el programador de aplicaciones tampoco. Ambos saben de su existencia por las operaciones de cortado, copiado y empastado que deben de hacer cientos de veces durante el día al trabajar en una computadora de escritorio, pero solo lo conocen por sus efectos.

Ahora que sabemos cómo agregar una barra de Menú a la ventana principal de un programa de aplicación, usaremos este conocimiento para crear un pequeño editor de texto con el que se puede pasar texto hacia el Portapapeles así como tomar texto guardado en el Portapapeles empastándolo en el editor de texto. Para construír el pequeño editor de texto, empezaremos un proyecto con una forma nueva poniéndole por título “Mi Bloc de Notas”. Hecho esto, pondremos un control de texto dentro de la forma, ampliando sus dimensiones para que casi llene el área disponible dentro de la forma. Como siguiente paso, “limpiamos” el interior dejando en blanco la propiedad Text del control de texto. Además, le agregaremos a la caja de texto una barra de desplazamiento vertical más no una barra de desplazamiento horizontal. Al no poner una barra de desplazamiento horizontal, se forzará la característica de “enrrollamiento” (conocida como “Word wrap”) que hará que al ir escribiendo algo dentro de la caja de texto se pase a la siguiente línea cuando hayamos excedido el espacio disponible en la línea actual. Es importante, para permitir la entrada de varias líneas de texto enrrollándose cada línea nueva hacia la siguiente línea cuando se le haya agotado el espacio, fijar la propiedad Multiline de la caja de texto a True.

Hecho lo anterior, le agregamos a la forma una línea de menú con la ayuda de la ventana para el diseño de menús, con la única opción Editar y las subopciones Cortar, Copiar y Empastar, dándole a las sub-opciones los nombres mnuCortar, mnuCopiar y mnuEmpastar. Esto hace que aparezcan los objetos correspondientes, para los cuales podemos programar los siguientes tres códigos:

Para la operación de cortado de texto:

   Sub mnuCortar_Click()
      Clipboard.Clear
      Clipboard.SetText  Text1.SelText
      Text1.SelText = ""
   End Sub

Para la operación de copiado de texto:

   Sub mnuCopiar_Click()
      Clipboard.Clear
      Clipboard.SetText  Text1.SelText
   End Sub

Para la operación de empastado de texto:

   Sub mnuEmpastar_Click()
      Text1.SelText = Clipboard.GetText()
   End Sub

De este modo, en la etapa de diseño se tendrá algo como lo siguiente:




Si se hace lo anterior (habiendo borrando previamente la propiedad Text del objeto de texto para que no aparezca la hilera Text1 al empezar), se tendrá un pequeño mini-bloc de notas, que se puede usar como tal. Podemos correr el programa como si fuera un editor de texto regular, y podemos usar las funciones de cortar, copiar y empastar al objeto Clipboard sobre porciones arbitrarias de texto:




Sin embargo, aunque la caja de texto se puede ir llenando (hacia abajo) con texto hasta rebasar el borde inferior de la ventana, la barra de desplazamiento vertical no servirá para desplazarse hacia las porciones de texto que se encuentren más abajo (o más arriba), esto en virtud de que aún no se ha elaborado código alguno para que la barra de desplazamiento vertical actúe como esperamos que actúe (siendo invisible cuando hay poco texto y apareciendo cuando el hay más líneas de texto que las que caben en la ventana de texto; y cambiando el botón de la barra de desplazamiento vertical al ir metiendo una cantidad adicional de líneas, así como reposicionando el texto en la ventana siguiendo los movimientos del botón de la barra de desplazamiento). En toda programación, nada sucede mágicamente por sí solo, todos los detalles, hasta los que parecen más insignificantes, tienen que ser considerados por el programador, el cual debe incluír en su programa todas las posibilidades, incluídas aquellas en las cuales el usuario final pueda cometer algún error respondiendo el programa de manera apropiada a los errores del usuario.

Lo importante aquí es que el objeto Clipboard (Portapapeles) no es un objeto que exista dentro de ningún programa de aplicación que se pueda desarrollar con Visual Basic, no existe dentro de Visual Basic, ya que es un objeto que forma parte del sistema operativo Windows. Sin embargo, podemos accesarlo como tal mediante el operador punto, y podemos cambiar sus propiedades u obtener el valor de sus propiedades, con propiedades del objeto Clipboard como SetText y Clear. La siguiente figura ilustra la manera en la cual se ve cómo el objeto TextBox (Caja de Texto) del programa “Mi Bloc de Notas” (ya compilado a un archivo ejecutable) resaltado de color gris claro se comunica con uno de los objetos del sistema operativo, el Clipboard, resaltado de color amarillo a través de las propiedades que posee el objeto Clipboard:




Hasta este punto, solo hemos visto ejemplos de aplicaciones en las cuales se utiliza una sola ventana (además de las cajas de entrada y cajas de mensaje) creada a partir de una forma en la etapa de diseño. ¿Significa ello que estamos limitados a trabajar con una sola forma al diseñar un programa? Desde luego que no. Visual Basic permite la creación de varias formas. Sin embargo, y aunque cada forma es un objeto, no es posible incrustar una forma dentro de otra. Recuérdese en la entrada previa que se habló acerca de lo que es una jerarquía de objetos. Siempre es posible meter objetos dentro de otro objeto de mayor jerarquía, pero no es posible meter un objeto dentro de otro que está a su mismo nivel. Y en el caso de las formas, están están a la misma “altura” (por así decirlo). Sin embargo, es posible invocar desde una forma otra forma, lo cual hace que se abra una nueva ventana que puede ser utilizada para trabajar en algo hasta que es cerrada. Precisamente por el hecho de que aunque una forma es un objeto no es posible meter una forma dentro de otra, en la Caja de Herramientas de Visual Basic no encontramos nada para llevar a cabo la creación de una forma; para ello tenemos que recurrir al menú de Visual Basic en la opción File (Archivo), en donde hay dos sub-opciones para creación de formas:

   New Form

   New MDI Form

Por lo pronto trabajaremos con la primera sub-opción. Si abrimos un proyecto nuevo y si hacemos clic tres veces en la sub-opción New Form, se irán creando sucesivamente tres formas adicionales (dependiendo de la versión usada de Visual Basic para irlas viendo puede ser necesario ir tomando cada una de ellas con el Mouse y moverlas de posición ya que cada nueva forma puede ser puesta directamente encima de la otra tapándola por completo). De este modo tendremos algo como lo siguiente (se muestra también en la parte inferior la ventana de proyectos de Visual Basic, Project1):




Obsérvese que en la ventana de proyectos aparecen las cuatro formas como Form1.frm, Form2.frm, Form3.frm y Form4.frm. Podemos seleccionar la forma que queramos para ir metiendo en cada una de ellas sus propios controles que iremos tomando de la Caja de Herramientas.

¿Y cómo habremos de invocar una ventana desde otra en el programa de aplicación? Por principio de cuentas, si queremos que cuando se eche a andar una aplicación deseamos que aparezcan en la pantalla del monitor no todas las ventanas que pueda generar el programa sino solo una de ellas, podemos recurrir a la propiedades Show y Hide de cada objeto del tipo forma. Además, en el código, para “descargar” de la memoria una ventana que ya no sea necesaria, podemos usar dentro de la misma el enunciado Unload. Escogiendo a la forma Form1 como la ventana principal, podemos meter dentro de la misma tres botones de comando. Suponiendo que se haga esto, podemos meter en la etapa de diseño el siguiente código en cada uno de los eventos que corresponden a cada botón de comando:


   Sub Command1_Click()
      Form2.Show   0
   End Sub


   Sub Command2_Click()
      Form3.Hide
   End Sub


   Sub Command3_Click()
      Form4.Show   1
   End Sub


Obsérvese que al usar la propiedad Show de un objeto Form tenemos que especificar un argumento que puede ser 0 ó 1. El argumento 0 se encarga de que la forma sea Modeless, mientras que el argumento 1 se encarga de que la forma sea Modal. Si corremos lo anterior, aparecerá la primera forma (Form1) con sus tres botones de comando. Haciendo clic con el Mouse en el botón de comando Command1 de la primera ventana (Form1) se mostrará la segunda ventana (Form2) volviéndose visible. La ventana que corresponde a Form2 se puede sacar fuera con la “X” en la esquina superior derecha de dicha ventana usada por el sistema operativo para cerrar ventanas. Esto lo podemos repetir una y otra vez. Por otro lado, haciendo clic con el Mouse en el botón de comando Command2, no aparecerá la ventana que corresponde a Form3, en virtud de que el código indica que dicha ventana, si es que estaba abierta, sea ocultada. Por último, si hacemos clic con el Mouse en el botón Command3, aparecerá la cuarta ventana (Form4). Así, podemos tener algo como lo siguiente:




Al correr el programa, si hacemos que aparezca únicamente la ventana que corresponde a Form2, con los clics del Mouse podemos hacer que el enfoque cambie de manera alternada de la ventana Form1 a la ventana Form2 y viceversa cuantas veces queramos. En cambio, al hacer que aparezca la ventana Form4, dicha ventana se apodera del enfoque y no permite regresar el enfoque a la ventana Form1. Y en esto consiste precisamente en que la propiedad Show sea especificada como Modeless (con un 0) o como Modal (con un 1). ¿Pero cómo podemos regresar entonces a la primera ventana (Form1) sacando fuera a la cuarta ventana? La manera más sencilla y directa consiste en poner un botón de comando en la forma Form4 y agregar el siguiente código:

   Sub Command1_Click()
      Unload Form4
   End Sub

Haciendo clic en el botón Command1 de la ventana Form4 hará que dicha ventana sea descargada permitiendo regresar a la ventana Form1. Obsérvese que para Visual Basic no hay confusión alguna entre el objeto botón Command1 de la forma Form1 y el objeto botón Command1 de la forma Form4; ambos son objetos completamente distintos (en un programa final lo más probable es que los dos botones terminarán con nombres distintos).

Veamos ahora el otro tipo de forma que podemos crear, la forma MDI. Las formas que hemos creado hasta ahora son formas. Cualquiera que haya usado el sistema operativo Windows sabe ya que no todas las interfaces con el usuario se ven igual o se comportan igual. Hay dos estilos diferentes de interfaces: la interfaz de documento sencillo SDI (Single-Document Interface), y la interfaz de documento múltiple MDI (Multiple-Document Interface). Un ejemplo de una interfaz SDI es el procesador de texto WordPad incluído en los sistemas operativos Windows. Con WordPad solo es posible tener un documento abierto, es necesario cerrar un documento para abrir otro con el mismo WordPad. En cambio, otras aplicaciones como la hoja de trabajo Microsoft Excel y el procesador de documentos Microsoft Word usan interfaces MDI, le permiten al usuario tener abiertos varios documentos múltiples al mismo tiempo, cada uno en su propia ventana. La característica más importante de una forma MDIForm es que en el programa de aplicación final se pueden tener varias formas hijo (child form), y en este sentido la forma MDIForm actúa como el patrón a seguir.

Si abrimos un proyecto nuevo en Visual Basic y agregamos una forma MDI, aparecerá una forma MDI que se distingue de las formas que hemos estado viendo por tener un fondo obscuro en el área de trabajo en lugar de un fondo blanco. Un programa de aplicación en Visual Basic solo permite tener una forma MDI, es por ello que al haber incluído una forma MDI en un proyecto la sub-opción New MDI Form se vuelve inaccesible. Algo que puede parecer desconcertante al principio es que no es posible meter objetos en una forma MDI en la etapa de diseño tales como botones de comando o cajas de texto (sin embargo, sí es posible agregarle a una forma MDI una barra de Menú usando la ventana de diseño de menús como lo vimos arriba). Para ello es necesario crear formas hijas de la aplicación. Si queremos, lo podemos lograr yendo a la forma usual (Form1), y en dicha forma cambiamos la propiedad MDIChild a True (haciendo clic con el Mouse en el renglón que contiene el valor False de dicha propiedad). Con esto, la forma Form1 es una forma hija de la forma MDI. Podemos ir agregando otras formas al proyecto, y podemos hacerlas formas hijo de la forma MDI de la misma manera.

Una cosa que sí podemos meter en una forma MDI, además de una barra de Menú, es lo que se conoce como una barra de Herramientas, una innovación que proporciona una serie de atajos adicionales (además de las maneras que ya se tienen) para efectuar ciertas tareas tales como el guardado de archivos. La barra de Herramientas se encarga de lanzar varias aplicaciones y opciones disponibles en un programa corriendo en una máquina. Los mismos entornos de Visual Basic incorporan su propia barra de Herramientas:




Para agregar una barra de Herramientas a una forma MDI, abrimos un proyecto nuevo en Visual Basic y creamos una forma MDI, a la cual le podemos dar el título frmBarra (la forma MDI también tiene sus propiedades como Caption). Tras esto, en la Caja de Herramientas de Visual Basic hacemos clic en el control de caja de imagen (Picture Box) y dentro de la forma MDI metemos este control (el tamaño que se le dé y la posición del mismo es completamente irrelevante). Al terminar, la caja de imagen tomará de manera automática un aspecto blanco y se reposicionará estirándose horizontalmente en la parte superior de la forma MDI, tomando el aspecto de una barra en blanco que llena horizontalmente la parte superior de la forma MDI (la altura es ajustable). Esta es nuestra barra de Herramientas en la forma MDI. Dentro de esta barra de Herramientas, podemos ir colocando las imágenes íconos (imágenes gráficas) que representen los controles que queremos que sean mostrados en la barra de Herramientas. Todos los íconos deben ser de la misma altura para que queden alineados y puestos uno al lado del otro en la barra de Herramientas, y pueden ser diseñados con cualquier programa gráfico que permita el diseño de los mismos. Los íconos, que en realidad son archivos de imágenes en formato .BMP (Bitmap) son almacenados como archivos con la extensión .ICO. Para simplificar las cosas, Visual Basic desde su primera aparición puso a la disposición de los programadores un programa gráfico para la construcción de íconos llamado IconWorks, el cual curiosamente se encontraba escondido bajo la carpeta ICONWRKS y ésta a su vez dentro de la carpeta SAMPLES, proporcionado no como un programa ejecutable con extensión .EXE sino como un proyecto Visual Basic (ICONWRKS.MAK) que de cualquier modo podía ser compilado a un programa ejecutable .EXE independiente:




Además del programa IconWorks constructor de íconos, Visual Basic desde su primera aparición hizo disponible un amplio archivo de íconos en una carpeta (directorio) bajo la ruta \VB\ICONS, el cual a su vez estaba dividido en varios sub-directorios que contenían archivos .ICO organizados por temática. Por ejemplo, en el subdirectorio titulado \VB\ICONS\COMPUTER se podían encontrar íconos que representan los elementos de hardware de un sistema de cómputo tales como drives de disco duro, teclados, dispositivos de Mouse, y así por el estilo (Visual Basic 3.0 incluía ya más de 450 íconos). Como ya se dijo, los íconos son esencialmente archivos en el formato Bitmap, los cuales tienen un tamaño convencional máximo de 32 pixeles por 32 pixeles, aunque bajo Windows 95 se encuentran también en un tamaño de 16 por 16 pixeles (de hecho podemos agregar como “botones” a la barra de Herramientas con imágenes que tengan la extensión .BMP en lugar de la extensión .ICO, Visual Basic los acepta y les da entrada).

Sin embargo, el simple hecho de ir metiendo “botones” gráficos (íconos) a la barra de Herramientas no significa que sucederá algo al hacer clic con el Mouse en cada botón. El programador tiene que especificar la acción que se llevará a cabo cuando se haga clic con el Mouse dentro de cada “botón” de imagen. Siendo cada ícono en la barra de Herramientas un objeto, con propiedades y eventos, podemos especificar lo que debe ocurrir cuando el usuario final haga clic con el Mouse en cierto ícono, escribiendo código para el evento Click() que corresponda a cada ícono (“botón”) en la barra de Herramientas.

Si el programador lo juzga conveniente, puede poner en marcha programas completos (¡cualquier programa!) que esté almacenado en la computadora, al hacerse clic en los íconos que estén dentro de la barra de Herramientas, para lo cual hace uso de la función Shell() (cascarón, concha) que desde Visual Basic puede poner en marcha cualquier programa ejecutable:

Shell(ruta hacia el programa ejecutable,1)

Suponiendo que haya cuatro íconos en la barra de Herramientas, con los nombres Image1, Image2, Image3 e Image4, los códigos correspondientes pueden ser algo como los siguientes:


   Sub Image1_Click()
      X = Shell("C:\ACCOUNTS\SALESWK.EXE",1)
   End Sub


   Sub Image2_Click()
      X = Shell("C:\WINDOWS\NOTEPAD.EXE",1)
   End Sub


   Sub Image3_Click()
      X = Shell("C:\PROGS\BASIC.EXE",1)
   End Sub


   Sub Image4_Click()
      X = Shell("C:\CALC.EXE",1)
   End Sub


Con el primer botón, se ejecuta un programa SALESWK.EXE ubicado en la carpeta ACCOUNTS puesta en el disco duro de la máquina. Con el segundo botón, se echa a andar el Bloc de Notas (NOTEPAD) situado en la carpeta WINDOWS. Con el tercer botón se echa a andar el program BASIC.EXE situado en la carpeta PROGS, y con el cuarto botón se echa a andar el programa ejecutable CALC.EXE puesto directamente en el directorio raíz del disco duro. De este modo, con la barra de Herramientas añadida a la forma MDI, y al ponerse en marcha el programa principal diseñado por el programador, haciendo clic en cada ícono de la barra de Herramientas que represente el enlace hacia cierto programa específico almacenado en la computadora, dicho programa será puesto en marcha. Solo nos falta agregar un procedimiento para la forma inicial (Form1) que se encargará de hacer visible la forma MDI con la barra de Herramientas, y que se encargue de ocultar la forma inicial Form1:

   Sub Form_Load()

      frmBarra.Show

      frmFormaInicial.Hide

   End Sub

En varias versiones de Visual Basic, existen capacidades y posibilidades que no aparecen documentadas, las cuales fueron puestas allí sin intención de darles mantenimiento correctivo en caso de errores y fallos inesperados. Estas capacidades no-documentadas se dan no sólo en el entorno de Visual Basic, también en casi todos los sistemas operativos Windows de Microsoft (al igual que otros sistemas operativos), hay muchas cosas que no aparecen documentadas y de las cuales se tiene conocimiento porque en los foros de presentación a veces se les escapan estos secretos que de alguna manera encuentran su lugar en alguna publicación técnica o en algún libro. Una de tales posibilidades en Visual Basic es que, en contra de lo que generalmente se cree, es posible programar código en Visual Basic usando los números de línea que aparecen al principio de cada línea en el BASIC tradicional. Un ejemplo de este tipo de código lo podemos verificar (en Visual Basic 3.0, por ejemplo) del modo siguiente creando una forma y escribiendo el procedimiento mostrado para ser invocado con el evento Click() al hacer clic con el Mouse dentro de la ventana al ejecutarse el programa:

   Sub Form_Click ()

   10 Dim A, B, C
   20 On Error GoTo ManejadorError
   30 A = 35
   40 B = 0
   50 C = A / B
   60 Exit Sub

   ManejadorError:
      MsgBox "El error = " & Err & " ocurrio en la linea " & Erl
      Resume Next

   End Sub

Al correr lo anterior y hacer clic con el Mouse, aparece la siguiente caja de mensaje:




Este programita es un ejemplo de una rutina para manejo de errores. Si no se encuentra otro error, el enunciado Err regresa un valor numérico de 11, que corresponde a un error del tipo de división por cero; mientras que la función Erl nos devuelve el número de línea en el cual ocurrió el error, tratándose en este caso de la línea 50 en la cual se trata de dividir el número 50 entre el número cero. Y en efecto, en la línea 50 se encuentra la operación matemáticamente ilegal, el error matemático que se comete cuando se trata de llevar a cabo una división entre cero.

Independientemente de los errores y equivocaciones que pueda cometer el programador en la elaboración de sus programas, algunos de los cuales posiblemente estarán fuera del alcance de las posibilidades de detección de errores del entorno Visual Basic (errores que vayan más allá de los errores ortográficos de sintaxis y de estructuras válidas de control que sí puede detectar de manera casi inmediata Visual Basic), hay muchos otros tipos de errores y situaciones que pueden ocurrir que están fuera del control del programa de aplicación e inclusive fuera del control del sistema operativo. Un error que se puede suscitar es cuando el disco duro de una computadora está lleno hasta el tope y se trata de guardar un archivo grande en el disco duro que ya no tiene capacidad para almacenar nada más. ¿Qué se hace en una situación como ésta? Esto lo tiene que decidir el programador. O bien cuando se está tratando de guardar un archivo en un dispositivo de memoria que ya tiene otro archivo con el mismo nombre. ¿Qué se hace en una situación como ésta? También lo tiene que decidir el programador.

Para el manejo de errores, Visual Basic define lo que se conoce como errores atrapables (trappable errors), los cuales pueden ocurrir cuando se está ejecutando una aplicación, ya sea dentro del entorno de Visual Basic, o como un archivo ejecutable terminado corriendo por cuenta propia en una computadora de escritorio. Podemos probar y responder a los errores atrapables usando el enunciado On Error y la función Err(). Obsérvese que esto empieza en el programita dado arriba inmediatamente tras haber declarado las variables (en la línea 10) con la siguiente instrucción dada en la línea 20:

On Error GoTo ManejadorError

Esta instrucción especifica claramente que si ocurre un error (On Error) se lleve a cabo un salto incondicional (GoTo) al código que está contenido bajo la etiqueta proporcionada (ManejadorError, en este caso, aunque se le puede dar cualquier otro nombre), saliendo del código de ManejadorError con el enunciado Resume Next que indica que se ejecute el resto del código principal.

A continuación se presenta una lista (parcial, no exhaustiva) de algunas de las situaciones que pueden ocasionar una condición de error, el tipo de mensaje que puede ser proporcionado (en inglés) por Visual Basic así como el número de error con el que Visual Basic identifica el tipo de error, número que le es proporcionado al programa principal para llevar a cabo un manejo adecuado de la situación:


Mensajes de errores atrapables
 Error   Mensaje
 0  Sin error en tiempo de ejecucion 
 3  Return sin GoSub
 5  Llamada ilegal de funcion
 6  Sobreflujo
 7  Memoria rebasada
 9  Subscripto fuera de rango
 10  Definición duplicada
 11  División entre cero
 13  Tipos de datos no coinciden
 14  Fuera de espacio para hileras
 16  Formula de hilera muy compleja
 17  No se puede continuar
 19  No hay Resume
 20  Resume sin error
 28  Espacio en la pila agotado
 35  Sub o función no definida
 48  Error al cargar DLL
 49  Mala convención de llamado DLL 
 51  Error interno
 52  Nombre de archivo o número malo 
 53  Archivo no encontrado
 54  Modo de archivo malo
 55  Archivo ya abierto
 57  Error dispositivo I/O
 58  Ya existe el archivo
 59  Mala longitud del registro (record)
 61  Disco lleno
 62  Entrada más allá del fin de archivo
 63  Mal número de registro (record)
 64  Mal nombre de archivo
 67  Demasiados archivos abiertos
 68  Dispositivo no disponible
 70  Permiso denegado
 71  Disco no listo
 91  Variable de objeto no inicializada
 92  Bucle For no inicializado
 94  Uso no válido de Null
 321  Formato no válido de archivo
 341  Indice no válido de array de objetos


El sistema operativo (en este caso, Windows) es el supervisor que tiene su ojo puesto en los errores que puedan ir surgiendo, y cuando ocurre un error se le notifica al programa de aplicación proporcionándole el número que corresponde al error (o un mensaje al usuario notificándole lo que ha ocurrido). Un sistema operativo robusto y estable debe tener los suficientes mecanismos de protección para poder recuperarse de un error fatal cometido por un programa aunque el programador que diseñó tal programa haya hecho un mal trabajo. Y si bien es cierto que no es fácil preveer de antemano todos los errores posibles que puedan ocurrir, la falta de planificación en prevenir lo más que se pueda un mal manejo de algún error puede ocasionar que un sistema se venga abajo teniéndolo que reiniciar de nuevo apagando y encendiendo la computadora, perdiendo todo el trabajo que se haya estado haciendo al momento de ocurrir el error. Este tipo de descalabro es precisamente lo que le sucedió a Microsoft cuando, en su prisa por sacar al mercado “el sistema operativo del nuevo milenio”, Windows Me (Windows Millenium), terminó atosigada con un producto tan malo requiriendo tantos parches y remiendos que la empresa tuvo que expiar su pecado con la introducción de Windows XP.

En lo que al programa de aplicación se refiere, el programador es el que debe decidir qué tipo de situaciones podrán suceder, y meter en su programa el código necesario para poder responder a imprevistos. Como puede verse en la lista dada arriba, hay muchas cosas que pueden salirse fuera del redil, y uno supondría que para la elaboración de un programa profesional se requiere meter mucho código para el manejo de errores. Y de hecho esto es lo que ocurre en los muchos programas con los que trabaja el usuario final, el manejo de los errores posibles tiende a inflar los programas de aplicación.

El que se pueda meter código escrito en el BASIC tradicional (empleando números de línea) en rutinas y procedimientos propios de Visual Basic, esto bajo algunas versiones de Visual Basic (no todas) abre unas perspectivas interesantes. La que más nos interesa es la posibilidad de poder reciclar hacia Visual Basic muchos programas elaborados en el BASIC antigüo sin tener que reescribirlo todo desde el principio. Habrá ocasiones, desde luego, en las cuales se tendrá que hacer algunos remiendos necesarios para satisfacer la sintaxis de los procedimientos en Visual Basic, pero la penosa labor de transcripción se reduce enormemente cuando tenemos este tipo de ayuda que nos ahorra el trabajo de tener que comenzar a partir de cero.

Un ejemplo de cómo puede ser útil el poder reciclar programas elaborados en el BASIC tradicional ocurre cuando se quiere elaborar un programa práctico de naturaleza estadística para llevar a cabo un muestreo en un laboratorio de control de calidad. Muchos programas de análisis estadístico se apoyan lo que se conoce como la curva normal. En el pasado esto requería estar consultando tablas para poder efectuar los cálculos matemáticos requeridos, pero con el advenimiento de las computadoras las tablas pasaron a ser obsoletas. Aunque Visual Basic tiene algunas funciones matemáticas elementales predefinidas, no tiene nada para proporcionar los valores que corresponden a una curva normal. Siempre hay la opción de comprar “cajas negras” de software, generalmente costosas, las cuales pueden efectuar evaluaciones de funciones complicadas como las que corresponden a la curva normal, garantizando una cierta precisión en todo el rango permisible de valores. Pero si estamos trabajando con un presupuesto sumamente limitado que impide la adquisición de tales cajas negras, hay mucha literatura que se puede consultar para encontrar una variedad de algoritmos capaces de efectuar la tarea.

Un libro entre muchos otros elaborados sobre BASIC que puede servir como fuente de referencia es el libro BASIC Programs For Scientists And Engineers de Alan Miller. Consultando dicho libro, encontramos el siguiente programa para evaluar la función Gaussiana de Error:


Para la transcripción de lo anterior a Visual Basic, abrimos un nuevo proyecto, preparándonos para transcribir el código al evento Click() de la forma con la finalidad de que al ejecutarse el programa se eche a andar el código transcripto con el código puesto en el evento Form_Click().

Para la transcripción del código en sí, podemos empezar con remover las líneas de comentarios que empiezan con REM, o reemplazar REM con la comilla sencilla que usa Visual Basic al inicio de cada línea para meter comentarios. Cada instrucción INPUT se puede reemplazar con una caja de entrada, y cada instrucción PRINT se puede reemplazar con una caja de salida (hay que especificar una variable de tipo hilera a la que le podemos dar cualquier nombre como Msg, por otro lado cuando una instrucción INPUT aparece sola sin argumento alguno como en la línea 60, se puede eliminar ya que es usada en el BASIC tradicional para un “salto de carro hacia la siguiente línea”). Se reemplazan IF y THEN con If y Then, y NEXT con End If, con lo cual se transcriben las estructuras de decisión a la sintaxis de Visual Basic. El salto incondicional GOTO es reemplazado con GoTo. La función de raíz cuadrada SQR() de BASIC se substituye con la función Sqr() de Visual Basic, y la función EXP() de BASIC se substituye con la función Exp(). Para Visual Basic se declaran todas las variables numéricas como variables de tipo Single (o de tipo Double). Y el enunciado de terminación END se reemplaza con el resultado de terminación End Sub sin número de línea.

Haciendo lo anterior, llegamos al siguiente código modificado que ponemos bajo Form_Click():


Notoriamente, los números de línea presentes en el programa BASIC original siguen mostrándose en el código modificado para ejecutarse bajo Visual Basic. Si corremos el programa (bajo Visual Basic 3.0), hará su aparición en bucle perpetuo una caja de entrada pidiendo un argumento, y conforme vayamos metiendo valores irá apareciendo el resultado de la evaluación que llamaremos Φ(X). Los resultados obtenidos bajo Visual Basic son idénticos a los resultados que el autor del programa muestra como ejemplo:


X  Φ(X) con BASIC   Φ(X) con Visual Basic 
 0.0  0.0 0
 0.1 0.1125 0.112461
 0.2 0.2227 0.22270
 0.3 0.3286 0.32862
 0.4 0.4824 0.42839
 0.5 0.5205 0.52050
 0.7 0.6778 0.67780
 1.0 0.8427 0.84270
 2.0 0.9953 0.99532


La transcripción de BASIC a Visual Basic resulta pues ser una cosa sumamente rápida, ciertamente más rápida que si hubiéramos empezado a partir de cero. Estando satisfechos con la manera en la que trabaja el programa, el siguiente paso sería llevar a cabo la conversión plena del programa BASIC a la sintaxis de Visual Basic eliminando los números de línea, lo cual no representa mayores problemas si tenemos precaución en la substitución de las etiquetas que recurren a números de línea.

Hemos tratado los pormenores de las primeras versiones de Visual Basic, las cuales ofrecen una buena introducción simplificada a la manera en la cual se elabora un programa en Visual Basic. El entorno ha ido evolucionando, desde luego, hasta llegar eventualmente a lo que se conoce como Visual Basic .NET. En paquetes conteniendo más herramientas de programación, esto fue incorporado a lo que se comercializó como Visual Studio. En el fondo, Visual Basic en sus primeras versiones y Visual Basic .NET siguen siendo lo mismo, aunque la sintaxis de Visual Basic .NET es mucho más elaborada al punto de que parecen ser dos cosas completamente diferentes para muchos principiantes. La complejidad proviene del hecho de que, en un principio (cuando apareció la primera versión de Visual Basic, la versión 1.0) los programas de aplicación estaban diseñados para ejecutarse en una computadora personal de escritorio en forma prácticamente aislada; Internet estaba en pañales y los primeros navegadores Mosaic y Netscape tenían poco tiempo de haber hecho su aparición (el navegador Internet Explorer de Microsoft aún no había hecho su aparición) , y la conexión a Internet a través de módems telefónicos lentos era algo que no todas las computadoras podían llevar a cabo a menos de que tuviesen instalados los programas de comunicación requeridos para poder conectarse con un proveedor de servicios de Internet. Sin embargo, la situación empezó a cambiar con la creciente interconectividad de las computadoras dentro de un mismo edificio que permitió compartir recursos entre trabajadores de una misma empresa sin tener que salir de sus cubículos u oficinas (en esto, la empresa Novell fue de las primeras en tomar la delantera). Para responder a esta necesidad, Microsoft introdujo un sistema operativo Windows conocido como Windows NT (Windows New Technology) que entre otras cosas incorporó en los discos duros el sistema de archivos que con Windows XP empezaría a reemplazar a los sistemas de archivos FAT32. Pero esto es apenas la mitad de la historia, y ciertamente no la más importante. Se sobrevino casi al mismo tiempo el avance explosivo exponencial de la red de redes al ir aumentando las capacidades del hardware gracias a los avances en la microelectrónica y al irse simplificando los programas de aplicación volviéndose las interfaces cada vez más intuitivas y fáciles de usar. Microsoft encontró lógico y deseable incorporar las formas de navegación usadas en Internet (como los hipervínculos usados para saltar de una página a otra) a sus sistemas operativos, y mucho de lo que vemos hoy tiene su origen en esta decisión. Sin embargo, el aumento en complejidad y opciones trajo consigo como parásito indeseable la aparición de los primeros virus cibernéticos y las preocupaciones por la seguridad de las computadoras de escritorio conectadas a la red de redes. Esta fue la razón por la cual Microsoft lanzó su iniciativa .NET (la palabra inglesa net significa red). Y esto requirió dotar a Visual Basic de capacidades mucho mayores que no poseía en los tiempos de antaño, al dejar de ser las computadoras personales de escritorio un artículo desconectado del mundo exterior para terminar convirtiéndose en un apéndice de algo mucho más grandioso, Internet.