You are on page 1of 40

Formularios de interfaz múltiple (MDI)

Aplicaciones de estilo SDI


Una aplicación de tipo o estilo SDI (Single Document Interface), Interfaz de Documento Sencillo, está
compuesta fundamentalmente de un único formulario, a través del cual, el usuario realiza toda la
interacción con el programa. Como ejemplos de este tipo de aplicación tenemos el Bloc de Notas o la
Calculadora de Windows.

Un programa SDI puede tener más de un formulario, aunque no sea algo habitual. Cuando eso ocurre,
los formularios se ejecutan independientemente, sin un elemento contenedor que los organice.

Aplicaciones de estilo MDI


Una aplicación de tipo o estilo MDI (Multiple Document Interface), Interfaz de Documento Múltiple,
se compone de un formulario principal, también denominado formulario MDI, que actuará como
contenedor de otros formularios (documentos) abiertos durante el transcurso del programa,
denominados formularios hijos o secundarios MDI. Como ejemplos de este tipo de aplicación tenemos
PowerPoint o Access.

A diferencia de lo que ocurría en versiones anteriores de VB, un formulario MDI admite los mismos
controles que un formulario normal, aunque dada su orientación de formulario contenedor, se
recomienda limitar los controles en un MDI a los estrictamente necesarios. El menú es el ejemplo más
identificativo de control idóneo para un formulario MDI, ya que a través de sus opciones, podremos
abrir los formularios hijos de la aplicación.
Programación con Visual Basic .NET © Grupo EIDOS

Seguidamente describiremos el proceso de creación de un proyecto que contenga un formulario MDI y


dos formularios hijos, así como el comportamiento de estos últimos cuando son abiertos dentro del
formulario padre MDI. Este ejemplo tiene el nombre MDIPru, y se debe hacer clic aquí para acceder
al mismo.

Una vez creado el nuevo proyecto, cambiaremos el nombre del formulario por defecto a frmPrincipal.
Para conseguir que este formulario tenga el comportamiento de un contenedor MDI, debemos asignar
el valor True a su propiedad IsMdiContainer. También debemos establecer a este formulario como
inicial en las propiedades del proyecto.

Ahora pasaremos a la creación de los formularios hijos del MDI. El primero, frmCarta, permite la
escritura en un TextBox multilínea, cuyo contenido podremos grabar a un archivo en disco. La Figura
291 muestra este formulario.

Figura 291. Formulario hijo de MDI para escribir un texto largo.

El código del botón que realiza la grabación del texto lo podemos ver en el Código fuente 497.
Debemos importar el espacio de nombres System.IO, ya que en esta clase del formulario hacemos uso
de los tipos File y StreamWriter.














Código fuente 497

602
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)

El otro formulario hijo, frmInfo, muestra la fecha y hora actual; esta última es actualizada a través del
control Timer tmrTiempo. Ver la Figura 292.

Figura 292. Formulario hijo de MDI para mostrar fecha y hora actuales.

El Código fuente 498 muestra las instrucciones que se ejecutan en el evento Tick del control Timer.















Código fuente 498

El siguiente paso consiste en crear un menú para poder abrir los formularios hijos a través de sus
opciones. Ver Figura 293.

Figura 293. Menú del formulario MDI.

En las opciones Carta e Información del menú, instanciaremos un objeto del formulario
correspondiente, teniendo en cuenta que para conseguir que dichos formularios se comporten como
hijos del MDI, debemos asignar a su propiedad MdiParent, la instancia actual del formulario en
ejecución, es decir, Me. Veamos este punto en el Código fuente 499.

603
Programación con Visual Basic .NET © Grupo EIDOS
























Código fuente 499

En la Figura 294 mostramos el formulario MDI en ejecución, conteniendo a los formularios hijos
dependientes.

Figura 294. Aplicación MDI en ejecución.

Creación de menús de tipo Ventana, en formularios MDI


Es probable que el lector haya observado, en algunas aplicaciones Windows de tipo MDI, que existe
en la barra de menús de la ventana principal, un menú con el nombre Ventana o Window (depende del

604
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)

idioma del programa), que nos muestra los nombres de los formularios hijos abiertos, permitiéndonos
cambiar de formulario activo al seleccionar una de esas opciones.

En nuestras aplicaciones MDI también podemos disponer de un menú de este tipo, añadiendo una
nueva opción al menú principal del formulario MDI, y asignando a su propiedad MdiList el valor
True.

Adicionalmente, y para darle un aspecto más profesional a este menú, podemos añadir los MenuItem
correspondientes a la organización de los formularios hijos en Cascada, Mosaico Horizontal, etc. Para
organizar los formularios abiertos en la aplicación en alguno de estos modos, deberemos ejecutar el
método LayoutMdi( ) del formulario MDI, pasándole como parámetro uno de los valores
correspondiente a la enumeración MdiLayout. El Código fuente 500 muestra las opciones
correspondientes a la organización en cascada y en mosaico horizontal de nuestro ejemplo.
















Código fuente 500

La Figura 295 muestra el mencionado menú Ventana de este proyecto, en cual contiene en este caso
los nombres de los formularios abiertos que acaban de ser organizados en mosaico vertical.

Figura 295. Menú ventana en formulario MDI.

605
Programación con Visual Basic .NET © Grupo EIDOS

Bloqueo de opciones de menú en formularios MDI


En la aplicación de ejemplo que estamos desarrollando, podemos abrir tantas copias de los formularios
hijos como necesitemos.

Respecto al formulario que nos permite escribir un texto para grabar a un archivo, es útil poder tener
varios formularios de este tipo, ya que podemos trabajar con diversos archivos a la vez.

Del formulario hijo que muestra la fecha y hora actual sin embargo, tener más de una copia no parece
algo muy lógico, ya que se trata simplemente de disponer de una información visualizada, y repetirla a
través de la apertura de varios formularios iguales no tiene mucho sentido.

Para conseguir que de un determinado formulario hijo sólo podamos abrir una instancia, debemos
hacer dos cosas: en primer lugar, en el manipulador de evento correspondiente a la opción de menú
que abre dicho formulario, asignaremos False a la propiedad True de la mencionada opción de menú.
Veámoslo en el Código fuente 501.
















Código fuente 501

En segundo lugar, dentro del código del formulario hijo, en nuestro caso frmInfo, debemos escribir el
manipulador para el evento Closed del formulario. Este evento se produce cuando se ha cerrado el
formulario, por lo que desde aquí volveremos a activar la opción de menú del formulario padre, que
habíamos deshabilitado.

Para acceder desde un formulario hijo a su MDI contenedor, disponemos de la propiedad MdiParent,
que nos devuelve una referencia de dicho formulario padre. Observe el lector en el Código fuente 502,
cómo además de utilizar la mencionada propiedad, la potencia de la función CType( ) nos permite en
una sola línea de código, llevar a cabo esta acción.














606
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)






Código fuente 502

La Figura 296 muestra el resultado al ejecutar. Mientras que el formulario de información esté abierto,
su opción de menú en el MDI estará deshabilitada.

Figura 296. Opción de formulario hijo deshabilitada.

Recorrer los formularios hijos de un MDI


La clase Form tiene la propiedad MdiChildren, que devuelve un array con todos los formularios hijos
abiertos hasta el momento.

Esto nos permite recorrer todo este conjunto de formularios para realizar operaciones con alguno de
ellos o todos.

El Código fuente 503 muestra un ejemplo de uso de esta propiedad, en el que mostramos el título de
cada formulario hijo, y además, cambiamos su color de fondo.











Código fuente 503

607
Programación con Visual Basic .NET © Grupo EIDOS

Comportamiento No Modal (Modeless) de formularios


Un formulario de comportamiento no modal, permite el libre cambio de foco entre el resto de
formularios de la aplicación.

Una clara muestra la hemos visto en el proyecto de ejemplo realizado durante los últimos apartados
del texto. En dicha aplicación, podíamos abrir varios formularios hijos dentro del formulario MDI
principal, y pasar de uno a otro sin restricciones.

Otra característica de los formularios no modales reside en que una vez creados y visualizados, el resto
del código de la aplicación continúa su ejecución. Ver Código fuente 504.











Código fuente 504

Comportamiento Modal de formularios


Como contrapartida al anterior apartado tenemos los formularios de comportamiento modal, también
denominados cuadros o ventanas de diálogo.

Un formulario modal, al ser visualizado, bloquea el paso a otros formularios de la aplicación hasta que
no es cerrado (aceptado o completado) por el usuario.

Como ejemplo de estos formularios se acompaña el proyecto FormDialogos (hacer clic aquí para
acceder al ejemplo), del que pasamos a describir su proceso de creación.

Este proyecto contiene un formulario MDI llamado frmPrincipal, y uno hijo con el nombre frmHijo,
que abrimos mediante una opción de menú; la creación de este tipo de formularios se ha descrito en
apartados anteriores.

A continuación añadimos un nuevo formulario al proyecto con el nombre frmDialogo, que también
abriremos a través de la correspondiente opción de menú del formulario MDI.

Para que este formulario tenga un comportamiento modal, debemos mostrarlo ejecutando el método
ShowDialog( ) de la clase Form. En el Código fuente 505 tenemos las instrucciones necesarias.
Observe también el lector, cómo hasta que el formulario de diálogo no es cerrado, no se mostrará el
mensaje que hay a continuación de la llamada a ShowDialog( ). Si además intentamos pasar al
formulario hijo, en el caso de que esté abierto, no podremos.








608
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)










Código fuente 505

Para cerrar un formulario modal podemos, al igual que para cualquier formulario, ejecutar su método
Close( ). No obstante, un formulario de diálogo suele proporcionar, aunque esto no es obligatorio, los
típicos botones para aceptar, cancelar, reintentar, etc.; de modo que una vez cerrado el formulario,
podamos averiguar qué botón pulsó el usuario.

Podemos proporcionar este comportamiento en nuestros formularios modales, asignando a la


propiedad DialogResult de la clase Form, uno de los valores del tipo enumerado DialogResult. Esto
tendrá como efecto adicional el cierre del cuadro de diálogo.

Por lo tanto, vamos a añadir a nuestro formulario frmDialogo, dos controles Button: btnAceptar y
btnCancelar, en los que escribiremos las instrucciones del Código fuente 506.




















Código fuente 506

Como ayuda en la construcción de formularios modales de diálogo, la clase Form dispone de las
propiedades AcceptButton y CancelButton, a las que podemos asignar sendos controles Button que
serán ejecutados al pulsar las teclas [INTRO] y [ESCAPE] respectivamente.

Esto es lo que haremos en el formulario frmDialogo, asignando a AcceptButton el control btnAceptar,


y en CancelButton asignaremos btnCancelar.

Finalmente, en el evento de la opción de menú que abre este formulario modal, correspondiente a
frmPrincipal, añadiremos, tras la llamada a ShowDialog( ), el código que comprobará el resultado de
la ejecución del formulario de diálogo. Ver el Código fuente 507.

609
Programación con Visual Basic .NET © Grupo EIDOS



























Código fuente 507

La Figura 297 muestra el programa en ejecución. Como puede comprobar el lector, el formulario
modal, debido a su comportamiento, no se encuentra limitado a los bordes del formulario MDI; pero
depende de este último, ya que si intentamos pasar el foco a un formulario hijo, no podremos.

Figura 297. Formulario modal de diálogo en ejecución.

610
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)

Controles de cuadros de diálogo del sistema


Del conjunto de controles que nos ofrece la ventana Cuadro de herramientas del IDE, existe un grupo
que nos permite el acceso a los cuadros de diálogo estándar del sistema operativo, esto es, los cuadros
de selección de color, tipo de letra o fuente, apertura-grabación de archivo, etc.

Para ilustrar el uso de algunos de estos controles, vamos a crear un proyecto de ejemplo con el nombre
DialogosSistema (hacer clic aquí para acceder al ejemplo), en el que describiremos su modo de uso en
los aspectos de diseño y codificación.

Crearemos pues, un nuevo proyecto de tipo aplicación Windows, y en su formulario, insertaremos un


menú, añadiendo las siguientes opciones: Abrir, Guardar, Color y Fuente. Cada opción mostrará un
tipo de diálogo del sistema.

Seguidamente insertaremos un TextBox, que acoplaremos con la propiedad Dock a todo el espacio del
formulario, y que nos servirá como base para las operaciones a realizar mediante los controles de
diálogo. La Figura 298 muestra el aspecto de este formulario.

Figura 298. Formulario de pruebas para controles de diálogo estándar.

Una vez dibujado un control de cuadro de diálogo en el formulario, dicho control quedará ubicado en
el panel de controles especiales, al igual que sucede con los menús. Para abrir un control de este tipo
en tiempo de ejecución, emplearemos su método ShowDialog( ).

A continuación describiremos cada uno de los controles de diálogo utilizados en este ejemplo.

ColorDialog
Este control muestra el cuadro de diálogo del sistema para la selección de colores. Entre sus
propiedades podemos destacar las siguientes.

Color. Contiene un tipo de la estructura Color, que nos permite obtener el color seleccionado
por el usuario mediante este cuadro de diálogo, para poder aplicarlo sobre alguno de los
elementos del formulario.

611
Programación con Visual Basic .NET © Grupo EIDOS

AllowFullOpen. Contiene un valor lógico que permite habilitar y deshabilitar el botón que
muestra el conjunto de colores personalizados del cuadro de diálogo de selección de colores.

Al seleccionar en el formulario, la opción de menú Color, ejecutaremos el Código fuente 508 que nos
permitirá, utilizando el control dlgColor, de tipo ColorDialog, elegir un color y aplicarlo a la
propiedad BackColor, del control TextBox.










Código fuente 508

La Figura 299 muestra esta aplicación con el formulario y el cuadro de selección de color abiertos.

Figura 299. Cuadro de diálogo estándar para selección de colores.

FontDialog
Este control muestra el cuadro de diálogo del sistema para la selección del tipo de fuente. Entre sus
propiedades podemos destacar las siguientes.

Font. Contiene un tipo de la clase Font. Una vez seleccionada una fuente por el usuario en el
cuadro de diálogo, podremos cambiar el fuente de los controles del formulario.

ShowApply. Contiene un valor lógico que permite mostrar-ocultar el botón Aplicar, que nos
permitirá asignar el tipo de letra sin cerrar el diálogo. Al pulsar este botón se desencadenará el

612
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)

evento Apply de este control de diálogo, en el que podremos escribir el código necesario para
aplicar la nueva fuente seleccionada.

Al seleccionar en el formulario la opción de menú Fuente, ejecutaremos el Código fuente 509 que nos
permitirá, utilizando el control dlgFuente, de tipo FontDialog, elegir un tipo de letra, y aplicarlo a la
propiedad Font del control TextBox; con la particularidad de que el cambio de letra lo haremos tanto
al pulsar el botón Aceptar, como Aplicar del cuadro de diálogo.





























Código fuente 509

La Figura 300 muestra el cambio de fuente sobre el texto del formulario.

Figura 300. Cuadro de diálogo del sistema para selección de tipo de letra.

613
Programación con Visual Basic .NET © Grupo EIDOS

SaveFileDialog
Este control muestra el cuadro de diálogo del sistema, mediante el que escribimos un nombre de
archivo, y elegimos un directorio, sobre el cual grabaremos información.

Es importante precisar que el control no se ocupa del proceso de grabación de datos; su cometido es el
permitirnos navegar por la estructura del sistema de archivos del equipo, y la selección de un nombre
para el archivo a grabar.

Entre las propiedades del control, podemos destacar las siguientes.

Title. Contiene una cadena con el título que aparecerá en el cuadro de diálogo.

InitialDirectory. Ruta inicial que mostrará el control al abrirse.

Filter. Cadena con el tipo de archivos que mostrará el cuadro de diálogo al navegar por el
sistema de archivos. El formato de esta cadena es el siguiente: NombreArchivo
(*.Extensión)|*.Extensión; pudiendo situar varios filtros separados por el carácter de barra
vertical ( | ).

FilterIndex. Número que corresponde a alguno de los tipos de archivo establecidos en la


propiedad Filter.

FileName. Nombre del archivo en el que se realizará la escritura

DefaultExt. Cadena con la extensión por defecto a aplicar sobre el nombre del archivo.

CheckFileExists. Valor lógico que nos permite comprobar si el archivo sobre el que vamos a
grabar ya existe.

ValidateNames. Valor lógico que comprobará si el nombre de archivo proporcionado


contiene caracteres especiales, es decir, si se trata de un nombre válido.

Al seleccionar en el formulario la opción de menú Grabar, ejecutaremos el Código fuente 510, que nos
permitirá, utilizando el control dlgGrabar, de tipo SaveFileDialog, seleccionar el nombre de un
archivo, y grabar el TextBox del formulario sobre el mismo, mediante un StreamWriter.






















614
© Grupo EIDOS 33. Formularios de interfaz múltiple (MDI)




Código fuente 510

La Figura 301 muestra el cuadro de dialogo de grabación de archivo.

Figura 301. Cuadro de diálogo para la grabación de archivos.

OpenFileDialog
Este control muestra el cuadro de diálogo del sistema, mediante el que seleccionamos un archivo para
poder abrirlo posteriormente, y realizar sobre el mismo operaciones de lectura-escritura.

Al igual que en el control anterior, la lectura y escritura de información es algo que deberemos realizar
por código, una vez que hayamos elegido el archivo mediante este cuadro de diálogo

Las propiedades de este control son prácticamente las mismas que las de SaveFileDialog, con algunas
excepciones como las siguientes.

Multiselect. Contiene un valor lógico, que nos permitirá la selección de múltiples archivos.

ShowReadOnly. Permite mostrar la casilla de verificación para mostrar los archivos de sólo
lectura.

ReadOnlyChex. Permite obtener y establecer el valor para la casilla de verificación de sólo


lectura del cuadro de diálogo.

Al seleccionar en el formulario la opción de menú Abrir, ejecutaremos el Código fuente 511, que nos
permitirá, utilizando el control dlgAbrir, de tipo OpenFileDialog, seleccionar un archivo existente, y
pasar su contenido al TextBox del formulario, utilizando un StreamReader.

615
Programación con Visual Basic .NET © Grupo EIDOS





























Código fuente 511

La Figura 302 muestra este cuadro de diálogo en ejecución

Figura 302. Cuadro de diálogo de apertura de archivos.

616
Formularios dependientes y controles
avanzados

Formularios dependientes y fijos en primer plano


Un formulario dependiente, también denominado owned form, consiste en un formulario que es
abierto por otro, denominado formulario dueño (owner form), permaneciendo ambos abiertos, sin que
el formulario dependiente requiera ser cerrado, en el caso de que necesitemos pasar el foco al
formulario dueño.

No necesitamos ir muy lejos para encontrar un ejemplo de este tipo de formularios, en el propio IDE
de Visual Studio tenemos muchos casos. En la ventana del editor de código, cuando abrimos la
ventana de búsqueda de texto tecleando [CTRL + F], quedan ambas visibles en todo momento, aunque
no efectuemos ninguna búsqueda y el foco lo tengamos en el editor de código. En este caso, la ventana
Buscar es dependiente de la ventana del editor de código. Ver Figura 303.

Este comportamiento en los formularios contrasta claramente con el que tienen los formularios de
diálogo, en los cuales, hasta que no es cerrado el diálogo, no podemos retornar el foco a la ventana que
abrió el diálogo.

En versiones anteriores de VB, conseguir un formulario con tal funcionamiento era una ardua tarea,
que requería de conocimientos sobre el API de Windows; sin embargo, el nuevo motor de formularios
de la plataforma .NET, nos permite a través de una serie de propiedades, que la configuración de
formularios dependientes sea un trabajo realmente fácil y rápido de conseguir.
Programación con Visual Basic .NET © Grupo EIDOS

Figura 303. Editor de código de Visual Studio con ventana de búsqueda.

Por otra parte, un formulario fijo en primer plano, también denominado topmost form, consiste en un
formulario que siempre aparece en primer plano respecto al resto de formularios de la aplicación. Se
trata de una ligera variación de comportamiento respecto al formulario dependiente; mientras que este
último, en algunas ocasiones puede ser tapado por otros formularios del programa, un formulario
topmost siempre permanece visible en primer plano.

Para ilustrar el modo de creación y funcionamiento de este tipos de formularios, se acompaña el


proyecto de ejemplo FormDependiente (hacer clic aquí para acceder al ejemplo), del que
comentaremos los pasos principales para su creación.

Una vez creado este proyecto, eliminaremos su formulario por defecto, y añadiremos el formulario
frmPrincipal, que configuraremos como contenedor MDI, y al que añadiremos un menú que nos
permitirá abrir un formulario hijo para escribir un texto, y otro de diálogo para mostrar un literal. La
Figura 304 muestra esta ventana MDI de la aplicación.

Figura 304. Formulario MDI para el ejemplo con formularios dependientes.

618
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

El siguiente paso consistirá en crear el formulario frmCarta, que utilizaremos para abrir los
formularios dependientes que crearemos posteriormente en este proyecto. La Figura 305 muestra este
formulario.

Figura 305. Formulario para escribir un texto y abrir formularios dependientes.

El Código fuente 512 muestra el código del menú de frmPrincipal que instancia este objeto y lo
muestra como formulario hijo del MDI.












Código fuente 512

A continuación agregaremos al proyecto el formulario frmBuscar. Este formulario actuará como


dependiente de frmCarta, permitiéndonos buscar una cadena en el TextBox de este último. La Figura
306 muestra el aspecto de frmBuscar. Aunque no sería necesario, para adaptarlo mejor a su
funcionamiento, hemos variado mediante la propiedad FormBorderStyle, el estilo de su borde a
ventana de herramientas con el valor FixedToolWindow.

Para conseguir que frmBuscar se comporte como formulario dependiente, al pulsar dentro de frmCarta
el botón Buscar, instanciaremos un objeto frmBuscar, añadiéndolo a la colección de formularios
dependientes de frmCarta mediante el método AddOwnedForm( ), de la clase Form. El Código fuente
513 muestra el código del botón Buscar en el formulario frmCarta.

619
Programación con Visual Basic .NET © Grupo EIDOS

Figura 306. Formulario dependiente frmBuscar.














Código fuente 513

Podemos eliminar la asociación entre un formulario propietario y uno dependiente mediante el método
RemoveOwnedForm( ) en el formulario propietario. Esto no quiere decir que el formulario
dependiente sea eliminado, simplemente se elimina su dependencia con respecto al propietario.

En lo que respecta al código de frmBuscar, al pulsar su botón Buscar, buscamos el contenido del
control txtBuscar en el formulario propietario frmCarta.

Si la búsqueda tiene éxito, seleccionamos el texto encontrado dentro del propietario. La propiedad
Owner del formulario nos devuelve una referencia del propietario, mientras que para manipular los
controles de dicho propietario, realizaremos un moldeado de tipo o type casting sobre Owner
utilizando la función CType( ) (observe el lector de nuevo, la enorme potencia que encierra esta
función).

Además mostramos una etiqueta en el formulario dependiente, que sólo se visualizará al localizar el
texto; cuando volvamos a escribir de nuevo texto a buscar, se ocultará dicha etiqueta. El Código fuente
514 muestra los métodos de frmBuscar que llevan a cabo estas labores.












620
© Grupo EIDOS 34. Formularios dependientes y controles avanzados























Código fuente 514

La Figura 307 muestra la aplicación con ambos formularios abiertos. El formulario frmCarta tiene el
foco actualmente, pero eso no impide que frmBuscar también permanezca abierto, para poder pasar a
él en cualquier momento.

Figura 307. Formulario propietario y dependiente en funcionamiento.

Un formulario dependiente, aunque se muestra en todo momento encima de su propietario, puede ser
ocultado por otro formulario de la aplicación. Para demostrarlo, añadiremos al proyecto el formulario
frmDatosUsuario, que se mostrará como cuadro de diálogo, visualizando un Label en su interior. Ver
Figura 308.

621
Programación con Visual Basic .NET © Grupo EIDOS

Figura 308. Formulario frmDatosUsuario.

El código de la opción de menú de frmPrincipal que abre este formulario se muestra en el Código
fuente 515.











Código fuente 515

La Figura 309 muestra como este formulario oculta parcialmente al de búsqueda.

Figura 309. Formulario de diálogo ocultando parte del formulario dependiente.

622
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

Para lograr que un formulario se muestre en todo momento por encima del resto de formularios de la
aplicación, hemos de asignar el valor True a su propiedad TopMost; obtenemos de esta manera, un
formulario con estilo de visualización fijo en primer plano.

Ilustraremos este particular añadiendo un nuevo formulario al proyecto, con el nombre frmPonerColor,
en el que asignaremos a su propiedad TopMost el valor True. Ver la Figura 310.

Figura 310. Formulario de estilo TopMost.

El Código fuente 516 muestra el código del botón Color de frmCarta, en el que se crea un formulario
frmPonerColor y se visualiza.











Código fuente 516

En este momento debemos hacer dos observaciones: en primer lugar, no añadimos el formulario
frmPonerColor a la colección de formularios dependientes del propietario; en segundo lugar, al
instanciar el objeto frmPonerColor, estamos pasando al constructor de esta clase la referencia del
formulario propietario.

La explicación a este modo de proceder la encontramos dentro del código del formulario dependiente;
en donde añadimos dicho formulario, a la lista de formularios dependientes del propietario, utilizando
la propiedad Owner de la clase base Form. Esto tiene el mismo efecto que usar el método
AddOwnedForm( ). El Código fuente 517 muestra el constructor de la clase frmPonerColor, en donde
llevamos a cabo esta operación.






623
Programación con Visual Basic .NET © Grupo EIDOS








Código fuente 517

Al volver a ejecutar ahora el programa, si abrimos el formulario frmPonerColor y después el cuadro de


diálogo, será el formulario de configuración de color el que prevalezca por encima, al ser dependiente
y TopMost. Ver Figura 311.

Figura 311. El formulario TopMost siempre se sitúa encima del resto.

Este formulario será abierto también desde frmCarta, mediante su botón Color, y lo utilizaremos para
cambiar el color del control de texto de frmCarta. El Código fuente 518 muestra el procedimiento
manipulador de evento de los controles RadioButton, en el que se realiza el cambio de color en el
formulario propietario.









624
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

















Código fuente 518

Para finalizar con los formularios dependientes, debemos indicar que la clase Form dispone de la
propiedad OwnedForms, que contiene una colección con los formularios dependientes de un
formulario que actúe como propietario.

Ya que en este ejemplo es el formulario frmCarta el que se comporta como propietario, añadiremos un
botón con el nombre btnDependientes, que nos permitirá recorrer la mencionada colección, y hacer,
desde el propietario, una manipulación sobre los formularios dependientes, en el caso de que haya
alguno abierto. El Código fuente 519 muestra el código de este botón.





































625
Programación con Visual Basic .NET © Grupo EIDOS




Código fuente 519

Validación de controles
Los controles Windows vienen provistos de un potente y flexible sistema de validación, que nos
permitirá comprobar si el usuario introduce los valores adecuados en un control, de modo que le
permitiremos pasar el foco a otro control, u obligarle a permanece en el actual hasta que su valor no
sea correcto.

En este esquema de validación, los miembros principales de la clase Control que intervienen son los
siguientes.

CausesValidation. Esta propiedad nos permite establecer un valor lógico, de manera que
cuando un control capture el foco, provocará la validación para otro control del formulario que
la requiera.

Validating. Este evento se produce para que podamos escribir el código de validación
oportuno en un manipulador de evento. El procedimiento manejador de evento recibe entre sus
parámetros un objeto de tipo CancelEventArgs, por lo que si la validación no es correcta,
asignaremos False a la propiedad Cancel de dicho objeto.

Validated. Este evento se produce en el caso de que la validación haya tenido éxito.

El proyecto de ejemplo ValidarControl (hacer clic aquí para acceder a este ejemplo) consta de un
formulario con tres controles TextBox. Todos tienen el valor True en su propiedad CausesValidation,
y adicionalmente, para el control txtImporte hemos escrito el procedimiento que actuará como
manipulador del evento Validating; con ello impediremos el paso desde dicho control a los demás
hasta que su contenido no sea numérico. Si pasamos la validación, se ejecutará en ese caso el código
del evento Validated. Veamos estos manipuladores de evento en el Código fuente 520.












Código fuente 520

La Figura 312 muestra esta aplicación en funcionamiento, durante la ejecución del evento de
validación.

En el control txtFecha por otro lado, podemos teclear cualquier valor, aunque no sea fecha, ya que no
proporcionamos manipuladores de evento para validar su contenido.

626
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

Cuando escribimos código de validación empleando estos miembros de la clase Control hemos de
tener presente el comportamiento, a veces no muy intuitivo, del sistema de validación para controles
en los formularios Windows.

Figura 312. Validación de un control.

Como hemos mencionado anteriormente, cuando la propiedad CausesValidation de un control


contiene True, al recibir el foco dicho control, se provocará el evento de validación para el control que
acaba de perder el foco. Pero si pasamos el foco a un control en el que CausesValidation contiene
False, la validación no se producirá sobre el control que acaba de perder el foco.

Esto lo podemos comprobar muy fácilmente sobre nuestro proyecto de ejemplo, asignando al control
txtFecha el valor False en su CausesValidation. A partir de ahora, cuando estemos situados en el
control txtImporte, si este no contiene un número, se producirá la validación si pasamos el foco a
txtNombre, pero no se validará si pasamos a txtFecha.

Controles avanzados
Los controles del Cuadro de herramientas del IDE tratados hasta el momento, son los que podríamos
considerar básicos o estándar en todas las aplicaciones; no obstante, esta ventana de herramientas
dispone de otra serie de controles avanzados o adicionales, que si bien, no son imprescindibles para
conseguir la funcionalidad elemental del programa, sirven como un magnífico complemento a la hora
de dotar a nuestras aplicaciones de un interfaz de usuario plenamente operativo.

En los siguientes apartados desarrollaremos un proyecto con el nombre ControlAvanzado (hacer clic
aquí para acceder a este ejemplo), a través del cual, realizaremos una descripción general de algunos
de estos controles adicionales y su modo de uso.

Como primer paso en este proyecto, eliminaremos el formulario por defecto, añadiendo a continuación
uno nuevo con el nombre frmPrincipal, al que daremos la característica MDI mediante la propiedad
IsMdiContainer. En este formulario crearemos un menú con un conjunto de opciones generales: Abrir,
Guardar, Salir, etc.

627
Programación con Visual Basic .NET © Grupo EIDOS

ImageList
Este control actúa como repositorio de imágenes, del que se alimentarán otros controles del formulario
que necesiten mostrar gráficos en su interior.

Una vez añadido este control en el formulario, se situará en el panel de controles especiales del
diseñador, y haciendo clic en su propiedad Images, se abrirá la ventana de la Figura 313, en la que
podremos añadir y quitar las imágenes que van a formar parte de la lista del control, así como ver en el
panel complementario, la información sobre cada imagen asignada.

Figura 313. Ventana de administración de imágenes del control ImageList.

Las imágenes que insertamos en el control tienen un tamaño por defecto, en el caso de que
necesitemos modificarlo, expandiremos la propiedad ImageSize en la ventana de propiedades y
asignaremos nuevos valores en Width y Height.

Otra ventaja de este control es que nos permite manipular las imágenes por código, por ejemplo, para
añadir nuevas imágenes, debemos usar el método Add( ) de su propiedad Images, como muestra el
Código fuente 521.




Código fuente 521

628
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

ToolBar
Este control representa la barra de herramientas o botones de acceso rápido que facilitan al usuario la
ejecución de los procesos principales del programa, evitándole la navegación por el menú del
formulario.

Al ser dibujado, este control queda acoplado a la parte superior del formulario. Después de ponerle
tbrBarra como nombre, asignaremos a su propiedad ImageList, el control de ese mismo tipo que
acabamos de crear; esto nos permitirá asignar los gráficos de la lista a los botones que vayamos
creando en el ToolBar. Para establecer el tamaño de los botones de la barra utilizaremos la propiedad
ButtonSize de este control.

Seguidamente haremos clic en la propiedad Buttons, que abrirá una ventana con la colección de
botones de la barra, en la que podremos crear y configurar dichos botones. Ver Figura 314.

Figura 314. Editor de botones del control ToolBar.

Cada botón en un ToolBar es un objeto de tipo ToolBarButton, del que podemos destacar las
siguientes propiedades.

Text. Cadena con el texto que muestra el botón.

ImageIndex. En el caso de asociar el ToolBar con un control ImageList, en esta propiedad


asignamos para un botón una de las imágenes del ImageList, indicando el número de orden de
la imagen.

Style. Permite establecer el estilo del botón: de pulsación; separador; o de tipo desplegable,
que abre un subconjunto de opciones.

629
Programación con Visual Basic .NET © Grupo EIDOS

DropDownMenu. Si asociamos el botón con una opción de la barra de menú del formulario,
y configuramos su estilo como DropDownButton, al pulsar el botón desplegable, se mostrarán
las opciones de menú; el efecto será el mismo que si hubiéramos desplegado directamente el
menú del formulario.

La Figura 315 muestra la ventana principal de la aplicación con la barra de herramientas

Figura 315. Formulario con ToolBar.

Una vez terminado el diseño del ToolBar, debemos codificar su evento ButtonClick, que será
provocado cada vez que se pulse un botón de la barra. Dentro del procedimiento de este evento,
comprobaremos qué botón ha sido pulsado y ejecutaremos las acciones oportunas. El Código fuente
522 muestra este evento. Tanto el botón Abrir como la opción de menú del mismo nombre realizan la
misma tarea, por lo que llaman al método AbrirArchivo( ), que es quien realmente muestra el
formulario necesario.





























630
© Grupo EIDOS 34. Formularios dependientes y controles avanzados








Código fuente 522

Al haber asignado al botón btnPersonal uno de los menús de la barra del formulario, no será necesario
escribir código para detectar este botón en el evento ButtonClick, ya que se ejecutará directamente el
código del evento Click de las opciones de menú. El Código fuente 523 muestra el código
perteneciente a la opción de menú Personal + Datos.











Código fuente 523

StatusBar
Para mostrar una barra informativa de estado recurriremos a este control, que al dibujarse queda
situado en la parte inferior del formulario; como nombre le daremos sbrEstado. De forma similar al
ToolBar, un control StatusBar está compuesto de una colección de objetos Panel, que iremos
añadiendo al control mediante la propiedad Panels, la cual mostrará una ventana para la creación y
configuración de tales paneles. Ver Figura 316.

Figura 316. Editor de paneles del control StatusBar.

631
Programación con Visual Basic .NET © Grupo EIDOS

Entre las propiedades destacables de un objeto Panel podemos mencionar las siguientes.

BorderStyle. Muestra el panel con efecto resaltado, hundido o normal.

Icon. Permite asociar un icono al panel.

AutoSize. Con esta propiedad podemos conseguir que el panel se redimensione ajustándose a
su contenido o que tenga un tamaño fijo.

En este ejemplo, hemos añadido dos paneles a la barra de estado del formulario. En uno mostramos un
texto fijo; mientras que en el otro, visualizamos la hora actual a través de un objeto Timer que
ponemos en marcha en el evento Load del formulario. Veamos los métodos implicados, en el Código
fuente 524.























Código fuente 524

La Figura 317 muestra el formulario con la barra de estado.

Figura 317. Formulario con StatusBar.

632
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

Finalizada la creación del StatusBar, añadiremos al proyecto un formulario con el nombre


frmDatosPersonal, en el dibujaremos un conjunto de nuevos controles que iremos describiendo
seguidamente.

DateTimePicker
Este control permite la selección e introducción de fechas en una caja de texto con capacidades
extendidas, o bien mediante un calendario desplegable que se mostrará al pulsar el botón de expansión
que contiene. Ver Figura 318.

Figura 318. Control DateTimePicker.

Para modificar la fecha en el cuadro de texto, debemos situarnos en la parte a modificar de la fecha y
teclear el nuevo valor, o bien, con las flechas de dirección arriba-abajo, cambiar esa parte de la fecha.
Si expandimos el calendario, podremos realizar la selección de un modo más gráfico.

Por defecto el control muestra la fecha actual, pero con la propiedad Text podemos cambiar la fecha
por código, cosa que hacemos al cargar el formulario, asignando una fecha distinta de la actual. Ver
Código fuente 525.










Código fuente 525

Podemos restringir el rango de fechas a mostrar por este control con las propiedades MinDate y
MaxDate. Si queremos, por otra parte, que la fecha se muestre con un formato personalizado,
aplicaremos dicho formato mediante la propiedad CustomFormat, teniendo en cuenta que no se hará
efectivo hasta que a la propiedad Format no le asignemos el valor Custom.

El botón btnCambiosFecha del formulario realiza algunas modificaciones por código sobre el control
DateTimePicker dtpFNacim del formulario, que vemos en el Código fuente 526.

633
Programación con Visual Basic .NET © Grupo EIDOS













Código fuente 526.

NumericUpDown
Control que muestra una caja de texto con un valor numérico que podremos ir aumentando-
disminuyendo al pulsar los botones para esta labor de que dispone el control. La Figura 319 muestra
este control en nuestro formulario de pruebas.

Figura 319. Control NumericUpDown.

Entre las propiedades de este control destacaremos las siguientes.

Increment. Número en el que se incrementará el valor del control cuando pulsemos sus
botones o teclas de dirección.

InterceptArrowKeys. Permite que las flechas de dirección arriba-abajo tengan el mismo


efecto que si pulsamos los botones para incrementar o disminuir, de este control.

Maximum, Minimun. Contienen los límites superior e inferior en cuanto al número que
podrá contener el control.

TextAlign. Permite alinear el número dentro la caja de texto del control.

UpDownAlign. Permite situar los botones del control a la izquierda o derecha de la caja de
texto que contiene el valor.

Entre los eventos de que dispone este control, ValueChanged se produce cada vez que cambia el valor
del control, de modo que en este caso, vamos a cambiar el color de fondo en función del número que
contenga. Veamos el Código fuente 527.












634
© Grupo EIDOS 34. Formularios dependientes y controles avanzados








Código fuente 527

DomainUpDown
Este control nos permite desplazarnos por una lista de valores, al mismo estilo que el control anterior.
Dicha lista de valores la crearemos mediante la propiedad Items, en tiempo de diseño o ejecución.

El Código fuente 528 muestra como al cargar el formulario frmDatosPersonal, con la propiedad Items
y su método AddRange( ), añadimos los valores que seleccionaremos en el control en tiempo de
ejecución.












Código fuente 528

La Figura 320 muestra el control dudCategoría, de este tipo al ser utilizado en el formulario. En el
caso de que necesitemos los valores ordenados, asignaremos True a su propiedad Sorted.

Figura 320. Control DomainUpDown.

MonthCalendar
Este control muestra en modo gráfico un calendario por el que podemos desplazarnos para seleccionar
una fecha. El control DateTimePicker utiliza internamente un MonthCalendar para mostrar su
calendario desplegable.

Por defecto se visualiza un mes, pero si asignamos a su propiedad CalendarDimensions un objeto Size,
podemos expandir el tamaño del calendario para que muestre varios meses. El Código fuente 529
muestra el código de un botón del formulario mediante el que cambiamos el tamaño del calendario.





635
Programación con Visual Basic .NET © Grupo EIDOS





Código fuente 529

En la Figura 321 vemos el resultado de expandir el tamaño del control.

Figura 321. Control MonthCalendar con el tamaño ampliado.

Para detectar la selección de una fecha utilizaremos el evento DateChanged. Debido a que en un
control MonthCalendar podemos seleccionar un rango de fechas, las propiedades que tenemos que
manipular para averiguar la fecha/s seleccionada/s son: SelectionStart, SelectionEnd y
SelectionRange, aunque en muchas ocasiones sólo será necesario utilizar una de ellas. Veamos el
Código fuente 530.











Código fuente 530

LinkLabel
Este control permite tener en un formulario Windows un enlace hacia una página de Internet, con un
comportamiento similar al que encontramos en un hiperenlace de una página web.

636
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

Su propiedad Text muestra un literal, de modo que al hacer clic sobre el mismo, se provocará el evento
LinkClicked en el que escribiremos el código a ejecutar.

En nuestro formulario de ejemplo, hemos creado un control de este tipo con el nombre lnkEidos, que
tiene el aspecto de la Figura 322, ya que además del enlace, le hemos asignado una imagen.

Figura 322. Conrol LinkLabel.

Para conseguir que al hacer clic en este enlace, se abra Internet Explorer y navegue hacia una
determinada página, vamos a utilizar la clase Process, que como su nombre indica, nos permite la
gestión de procesos del sistema, tales como su inicio y finalización.

En este caso, el método compartido Start( ), de Process, va a ejecutar el navegador al pasarle como
parámetro una dirección web en forma de cadena. Veamos el Código fuente 531.










Código fuente 531

Creación y manipulación de elementos en ejecución


El conjunto de controles que acabamos de ver, al igual que los básicos permiten ser creados no sólo
mediante el diseñador de formularios, sino también desde código. Como muestra de ello, la opción de
menú Varios + Añadir botón y panel, añade dos imágenes al control ImageList del formulario
frmPrincipal, creando un nuevo botón para el ToolBar y un panel para el StatusBar Ver el Código
fuente 532.
















637
Programación con Visual Basic .NET © Grupo EIDOS









Código fuente 532

Para detectar la pulsación del nuevo botón de la barra de herramientas, añadimos el siguiente código
en su evento ButtonClick, que vemos en el Código fuente 533.










Código fuente 533

La Figura 323 muestra este formulario en ejecución tras añadir los nuevos elementos.

Figura 323. Nuevos controles añadidos al formulario en tiempo de ejecución.

NotifyIcon
Este control permite añadir un icono asociado con nuestra aplicación en el panel de iconos del sistema
(Windows System Tray) situado en la parte derecha de la barra de tareas de Windows.

Tales iconos suelen utilizarse por aplicaciones que permanecen ocultas, y al hacer clic derecho sobre
su icono en este panel, aparece un menú contextual que permite mostrar la aplicación.

En nuestro caso vamos a utilizar este control para ejecutar y parar la calculadora del sistema
empleando la clase Process, comentada en un apartado anterior.

638
© Grupo EIDOS 34. Formularios dependientes y controles avanzados

Después de agregar un control de este tipo al formulario, asignaremos un icono a su propiedad Icon y
una cadena a su propiedad Text, que será mostrada al situar el ratón encima de este control en tiempo
de ejecución.

Crearemos después un menú contextual con las opciones Abrir y Cerrar, que asignaremos a la
propiedad ContextMenu del control NotifyIcon.

Para poder controlar la calculadora de Windows cuando esté en ejecución, declararemos una variable
de tipo Process a nivel de la clase. Al ejecutar la calculadora mediante el método Start( ) de la clase
Process, obtendremos un objeto de dicho tipo, que pasaremos a esta variable, y nos permitirá
posteriormente, cerrar el proceso en el que se está ejecutando la calculadora mediante el método Kill(
). Veamos esta parte en el Código fuente 534.


























Código fuente 534

Al ejecutar el programa, se mostrará un nuevo icono en la lista del panel de iconos del sistema de la
barra de tareas, como muestra la Figura 324.

Figura 324. Control NotifyIcon en el panel de iconos del sistema de la barra de tareas.

639
Programación con Visual Basic .NET © Grupo EIDOS

Como puede comprobar el lector, la clase Process amplía enormemente nuestra capacidad de
manipulación de los procesos del sistema.

640

You might also like