Formularios dependientes y fijos en primer plano

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.

© 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.

Private Sub mnuCarta_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuCarta.Click

' este formulario se abre como hijo del MDI Dim ofrmCarta As New frmCarta() ofrmCarta.MdiParent = Me ofrmCarta.Show()

End Sub

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.

Programación con Visual Basic .NET © Grupo EIDOS

Figura 306. Formulario dependiente frmBuscar.

Private Sub btnBuscar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBuscar.Click

' crear un objeto frmBuscar Dim ofrmBuscar As New frmBuscar()

' establecer dependencia entre forms Me.AddOwnedForm(ofrmBuscar) ofrmBuscar.Show()

End Sub

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.

' al pulsar este botón, buscamos en el formulario ' propietario de este dependiente Private Sub btnBuscar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBuscar.Click

Dim iResultadoBuscar As Integer ' la propiedad Owner contiene el formulario propietario iResultadoBuscar = CType(Me.Owner,

frmCarta).txtDocumento.Text.IndexOf(Me.txtBuscar.Text)

© Grupo EIDOS 34. Formularios dependientes y controles avanzados

' si encontramos el texto buscado... If iResultadoBuscar > 0 Then

' pasamos el foco al TextBox del formulario propietario ' y seleccionamos el texto encontrado CType(Me.Owner, frmCarta).txtDocumento.Focus() CType(Me.Owner, frmCarta).txtDocumento.SelectionStart = iResultadoBuscar CType(Me.Owner, frmCarta).txtDocumento.SelectionLength =

Me.txtBuscar.Text.Length

Me.lblEncontrado.Show() End If

End Sub

' al volver a teclear un valor a buscar, se oculta el Label Private Sub txtBuscar_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles txtBuscar.TextChanged

Me.lblEncontrado.Hide()

End Sub

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.

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.

Private Sub mnuUsuario_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles mnuUsuario.Click

' mostrar este formulario como un diálogo Dim ofrmUsuario As New frmDatosUsuario() ofrmUsuario.ShowDialog()

End Sub

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.

© 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.

Private Sub btnColor_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnColor.Click

' abrir el formulario para poner color al texto Dim ofrmPonerColor As New frmPonerColor(Me) ofrmPonerColor.Show()

End Sub

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.

Public Class frmPonerColor Inherits System.Windows.Forms.Form '....

Programación con Visual Basic .NET © Grupo EIDOS

' crear un constructor para establecer ' el formulario propietario Public Sub New(ByVal frmPropietario As frmCarta)

Me.New() Me.Owner = frmPropietario

End Sub

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.

' en este método ponemos el color al TextBox ' del formulario propietario Private Sub PonerColor(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rbtMadera.Click, rbtVerde.Click, rbtTurquesa.Click

Dim oColor As Color

© Grupo EIDOS 34. Formularios dependientes y controles avanzados

If sender Is Me.rbtMadera Then oColor = Color.BurlyWood End If

If sender Is Me.rbtVerde Then oColor = Color.MediumSpringGreen End If

If sender Is Me.rbtTurquesa Then oColor = Color.Turquoise End If

CType(Me.Owner, frmCarta).txtDocumento.BackColor = oColor

End Sub

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.

Private Sub btnDependientes_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnDependientes.Click

' obtener los formularios dependientes Dim oFormularios() As Form = Me.OwnedForms Dim oFormulario As Form

' si existen dependientes... If oFormularios.Length > 0 Then

' recorrer la colección y ' manipular los formularios dependientes For Each oFormulario In oFormularios

Select Case oFormulario.GetType().Name Case "frmBuscar"

CType(oFormulario, frmBuscar).lblEncontrado.Show() CType(oFormulario, frmBuscar).lblEncontrado.Text =

"¡LOCALIZADO!"

Case "frmPonerColor" CType(oFormulario, frmPonerColor).rbtTurquesa.Text = "AZULADO" CType(oFormulario, frmPonerColor).rbtTurquesa.BackColor =

Color.Blue

' con el método PerformClick() de un control, ' simulamos una pulsación CType(oFormulario, frmPonerColor).rbtTurquesa.PerformClick()

End Select

Next

End If

Programación con Visual Basic .NET © Grupo EIDOS

End Sub

Código fuente 519