TEMA 3. APLICACIONES CON MÚLTIPLES FORMULARIOS 3.1. INTRODUCCIÓN Ya conocemos los fundamentos del diseño de formularios Windows simples. Sabemos, además, que nuestras aplicaciones pueden tener múltiples formularios o ventanas, que se abrirán desde la ventana inicial de la aplicación bajo demanda del usuario o al darse determinadas condiciones durante la ejecución. En este tema vamos a aprender a crear formularios capaces de contener a otros formularios al estilo de las llamadas aplicaciones de interfaz de múltiples documentos, conocidas como aplicaciones MDI. Ejemplos de este tipo de interfaz son muchos procesadores de textos bajo Windows, o en general, aplicaciones que permiten abrir múltiples documentos a la vez. Esta clase de aplicaciones tiene típicamente un menú para que el usuario navegue cómodamente entre las ventanas secundarias, por lo que también aprenderemos a crear un menú para el formulario principal. Programación .NET (II). Aplicaciones con múltiples formularios 3.1 3.2. PREPARACIÓN DE LA VENTANA PRINCIPAL Las aplicaciones de múltiples formularios se componen de un formulario principal o primario, que será el contenedor MDI (padre), y de uno o varios formularios secundarios (hijos) que se mostrarán siempre contenidos en el principal. Supongamos que tenemos creado un nuevo proyecto de Windows Forms tal y como hemos hecho en anteriores ocasiones. Por ello contamos en nuestra aplicación con un único formulario “Form1” que se comporta como una ventana estándar. ¿Cómo transformar esta ventana estándar en una ventana contenedora MDI? Es muy sencillo, basta con poner a la propiedad IsMDIContainer del formulario el valor “True”. Tras hacer esta modificación observamos que el aspecto del formulario ha cambiado, su fondo ahora es más oscuro. 3.2 Programación .NET (II). Aplicaciones con múltiples formularios Desde el momento que establecemos la propiedad IsMDIContainer de un formulario a true éste podrá contener tantos formularios como se desee. También podremos añadir en él controles, como hemos hecho con formularios estándar. La peculiaridad de estos controles es que permanecerán visibles siempre por encima de los formularios secundarios que podamos agregar. Veamos a continuación cómo añadir formularios secundarios al principal. Programación .NET (II). Aplicaciones con múltiples formularios 3.3 3.3. CREACIÓN DE VENTANAS SECUNDARIAS Los formularios secundarios de un formulario MDI tienen el aspecto de una ventana estándar. Durante la ejecución será posible variar su tamaño (maximizarlas, minimizarlas…) y moverlas, pero todo esto estará siempre limitado al cuerpo de la ventana principal que las contiene. Es decir, en ningún caso podremos “sacar” una ventana secundaria de la principal. Igualmente, la vida de la ventana secundaria está ligada a la de la principal y no al revés, por ello, si cerramos la ventana principal, se cerrarán con ella todas sus ventanas secundarias. Si cerramos una ventana secundaria, la principal y otras posibles ventanas secundarias no se verán afectadas. 3.4 Programación .NET (II). Aplicaciones con múltiples formularios Ahora supongamos que tenemos creado un nuevo proyecto de Windows Forms, con un formulario vacío llamado “Form1”, como ya viene siendo habitual. Además, hemos convertido este formulario en un formulario contenedor MDI (Recuerda: hemos establecido IsMDIContainer a true en la ventana de propiedades del formulario). Añadimos un segundo formulario llamado “Form2” (Menú “Proyecto” y “Agregar Windows Forms…”) ¿Cómo hacer que “Form2” sea un formulario secundario de “Form1”? En esta ocasión no hay una propiedad en tiempo de diseño que establezca el “parentesco” de “Form2” respecto a “Form1”. Debemos crear el formulario hijo en tiempo de ejecución. ¿En qué momento creamos el formulario secundario? En este primer ejemplo lo haremos al iniciar el formulario principal, usaremos el evento Load de “Form1”. Este evento es el evento principal de los formularios, luego basta un doble clic sobre el diseño de form1 para crearlo. Observa el código que hemos añadido en el evento: Ejemplo: Private Sub Form1_Load(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles MyBase.Load 'Declaramos una variable de la clase Form2 Dim formulario_hijo As New Form2 'Indicamos quién es el contenedor MDI del formulario formulario_hijo.MdiParent = Me formulario_hijo.Show() End Sub Programación .NET (II). Aplicaciones con múltiples formularios 3.5 El código anterior realiza lo siguiente: Declara una variable de la clase Form2. Este formulario nos sirve de modelo al crear el formulario “formulario_hijo”. Determina quién es el contenedor MDI padre del formulario a través de la propiedad MdiParent. Como ya hemos dicho, esta propiedad no está disponible en tiempo de diseño. En este caso, el fomulario cintenedor es “Form1”, pero al estar implementado Form1_Load dentro de la declaración de la clase “Form1” nos referimos a él con “Me”. Finalmente mostramos el formulario. “Form2” ha servido de molde para crear un nuevo formulario durante el evento Load. Por ello, el formulario creado (“formulario_hijo”) tiene las mismas propiedades que “Form2”, así como los manejadores de eventos y otros métodos que hayamos podido implementar en “Form2”. Esto es útil si pretendemos ir añadiendo formularios secundarios iguales al formulario principal. Partimos de un formulario que hace de modelo (en nuestro ejemplo “Form2”), cuyos métodos y propiedades modificamos según necesitemos. Después solo habrá que crear nuevos formularios secundarios de la clase del formulario modelo (“Form2”). El sencillo ejemplo que acabamos de ver crea la ventana secundaria directamente al cargar la principal. Lo normal es crear los formularios secundarios bajo demanda del usuario. Bastará elegir el evento que provocará la creación de una nueva ventana. Veremos cómo hacerlo. A continuación vamos a añadir al formulario principal un menú de opciones que servirá para que el usuario abra nuevas ventanas secundarias y navegue entre ellas con facilidad. 3.6 Programación .NET (II). Aplicaciones con múltiples formularios 3.4. CREACIÓN DE UN MENÚ DE OPCIONES El menú es un elemento típico de las aplicaciones de tipo MDI. Facilita que el usuario tenga siempre visibles y a mano sus opciones dado que, colocado en la ventana principal, el menú permanece siempre por encima de ventanas secundarias. En la sección “Menús y barras de herramientas” del cuadro de herramientas de nuestro entorno de desarrollo podemos ver diversos controles de gran utilidad. Nosotros vamos a prestar especial atención a los controles MenuStrip y ToolStrip. En la siguiente imagen puedes ver todos estos controles tal y como aparecen en el cuadro de herramientas de Visual Basic Express. Programación .NET (II). Aplicaciones con múltiples formularios 3.7 Veamos una pequeña descripción de cada uno de ellos: ContextMenuStrip Este control es un menú contextual. Se puede asociar a cualquier control, lo que provocará que se abra al hacer clic con el botón secundario del ratón sobre él. Sustituye al control ContextMenu. Este menú es útil para presentar las opciones específicas o más habituales de cierto control de forma rápida y accesible. MenuStrip MenuStrip representa el menú que habitualmente vemos en las ventanas de las aplicaciones Windows. Frecuentemente se coloca en la parte superior de la ventana, aunque podemos ubicarlo en cualquier otra zona. Sirve para agrupar opciones y comandos de la aplicación por su funcionalidad. 3.8 Programación .NET (II). Aplicaciones con múltiples formularios StatusStrip Representa la barra de estado que frecuentemente vemos al pie de la ventana de las aplicaciones para Windows. Sustituye y amplia al control StatusBar. Permite mostrar en la barra de estado controles como barras de progreso, etiquetas o listas desplegables entre otros. Su principal utilidad consiste en mostrar información al usuario. ToolStrip Este control es una barra de herramientas. En ella podremos alojar diversos controles como botones, listas desplegables, cajas de texto, barras de progreso… ToolStripContainer Como su nombre indica, este control es un contenedor de barras de herramientas. También puede contener controles MenuStrip y StatusStrip. Es útil cuando nuestra aplicación cuenta con varias barras de herramientas que nos interesa agrupar y organizar. Veamos cómo funciona el control MenuStrip. Volvemos al ejemplo anterior y añadimos un control MenuStrip al formulario principal arrastrándolo desde el cuadro de herramientas. Programación .NET (II). Aplicaciones con múltiples formularios 3.9 Hemos añadido dos elementos al menú: Ventanas y Salir. Serán controles de la clase ToolStripMenuItem. Con el carácter & indicamos cuál será la letra del método abreviado de cada opción. Queremos que el elemento del menú "Ventana" muestre una lista de las ventanas secundarias abiertas. La propiedad MdiWindowListItem del control MenuStrip nos ofrece la posibilidad de hacerlo de forma automática. Sólo hay que asignar a esta propiedad el elemento del menú a partir del cual queremos que se muestre la lista. La opción "Salir" cerrará el formulario principal. El evento principal de un elemento del menú es el evento click. Hacemos doblle clic con el ratón para acceder a su manejador y añadimos el código necesario: Private Sub SalirToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SalirToolStripMenuItem.Click Me.Close() End Sub 3.10 Programación .NET (II). Aplicaciones con múltiples formularios _ Añadimos ahora nuestro ejemplo una barra de herramientas o ToolStrip. La colocamos justo debajo del menú. Añadimos un botón (Button), será un objeto de la clase ToolStripButton. Este botón nos va servir para crear nuevas ventanas secundarias. ¿Cómo lo hacemos? En primer lugar, tenemos que crear el manejador para el evento click de botón. Al igual que ocurría con los elementos del menú MenuStrip, bastará con hacer doble clic sobre el elemento para crear el manejador del evento click, dado que es su evento predeterminado. Ya hemos visto qué código haría falta para crear una ventan secundaria. En el ejemplo realizado se creaba una ventana secundaria durante carga del formulario principal (evento Load). Usamos el mismo código en el manejador que acabamos de crear: Programación .NET (II). Aplicaciones con múltiples formularios 3.11 Private Sub ToolStripButton1_Click(ByVal sender As System.Object, _ ByVal e As System.EventArgs) Handles ToolStripButton1.Click Dim formulario_hijo As New Form2 formulario_hijo.MdiParent = Me formulario_hijo.Show() End Sub Así, cada vez que el usuario haga clic en el botón de nuestra barra de herramientas, se creará una nueva ventana hija de la clase Form2. Dentro del menú "Ventana" debería aparecer un listado con las ventanas actualmente abiertas 3.12 Programación .NET (II). Aplicaciones con múltiples formularios Con este menú podremos navegar facilmente entre las ventanas secundarias. El listado de ventanas activas se mantendrá actualizado automáticamente. Programación .NET (II). Aplicaciones con múltiples formularios 3.13