lunes, 22 de febrero de 2010

Imagen de fondo única para el MDI y sus formularios hijos

Introducción

En Visual Basic 6.0, colocar una imagen en el fondo del MDI era un poco complicado. Habian trucos como el de crear un formulario hijo sin bordes, anexarle un objeto Image y cargarle una imagen y le cambiamos la propiedad Stretch a True y este era invocado al momento de cargar el MDI. De esta forma nuestro MDI tenía un fondo o la otra forma era usando una API.

En NET es más fácil, simplemente anexamos al formulario MDI un objeto PictureBox, le colocamos una imagen en el objeto Image. Luego a la propiedad SizeMode le colocamos el valor de StretchImage. A la propiedad Dock le colocamos Fill. Luego para terminar le decimos que este objeto lo envíe al fondo del MDI en caso de haber otros objetos en el formulario. Si lo ejecutamos, funciona excelentemente, Pero llamemos un formulario hijo... podemos tener problemas o también si usamos Ensamblados de otros proveedores para NET (docking, treelist, treeview, etc.). Lo ideal sería, colocar dicha imagen de fondo en la propiedad Image del MDI y que cambiara a medida que el formulario se redimensionara y asi quitarnos el problema por una buena vez.
Viene otra pregunta: Qué sucede si necesitamos que esa misma imagen de fondo del MDI, sea el fondo de los formularios hijos? otro problema.
Bueno, a continuación vamos a hacer lo siguiente para intentar solucionar el impace:
- Vamos a cargar la imagen de fondo solamente una vez en un objeto PictureBox que va a estar en el MDI.
- Luego vamos a pasar dicha imagen a la propiedad Image del MDI y resolveremos el problema del fondo del formulario padre.
- Posteriormente si deseamos colocar el mismo fondo del MDI, en los formularios hijos, vamos a utilizar la imagen cargada en el formulario padre pero invocándola desde el hijo o hijos.
- Fuera de lo anterior, aprenderemos de pasada, como volver el formulario MDI global y asi devolver desde los hijos, valores hacia objetos colocados en el formulario padre.

Primer Paso

Iremos al formulario MDI y agregaremos un objeto PictureBox. En la propiedad Image, colocaremos la imagen que utilizaremos de fondo. Cambiaremos la propiedad SizeMode por StretchImage. Colocaremos
False en la propiedad Visible del PictureBox. También anexaremos un objeto StatusBar el cual utilizaremos más adelante para explicar la globalización del MDI.

Segundo Paso

Adicionaremos el siguiente código al formulario MDI:
    'Variables y propiedad para declarar el MDI como global ante sus hijos
    Private Shared formglo As frmmdi
    Public Shared Property gf() As frmmdi
        Get
            If formglo Is Nothing OrElse formglo.IsDisposed Then
                formglo = New frmmdi
            End If
            Return formglo
        End Get
        Set(ByVal Value As frmmdi)
            formglo = Value
        End Set
    End Property
 
    Private Sub frmmdi_Load(ByVal sender As Object, _
                            ByVal e As System.EventArgs) Handles MyBase.Load
        'Cargamos el MDI en la propiedad para indicar su globalidad
        Me.gf = Me
        'Rellenamos el picture box en todo el MDI
        Me.PictureBox1.Dock = DockStyle.Fill
        End Sub
 
        Private Sub frmmdi_Resize(ByVal sender As Object, _
                                  ByVal e As System.EventArgs) Handles MyBase.Resize
            'Tomamos la imagen del picturebox, a un objeto imagen
            Dim imagen As New Drawing.Bitmap(PictureBox1.Image, Me.Width, Me.Height)
            'La cargamos al background
            Me.BackgroundImage = imagen
        End Sub

Qué es todo esto?
El primer párrafo es una propiedad que define el MDI como unformulario global para que pueda ser invocado desde cualquier otro.
En el Evento Load, cargamos el MDI a la variable global.
Luego le indicamos al PictureBox, que se va a rellenar en todo el formulario MDI, colocando Fill en la propiedad Dock.
En el evento Resize, tomamos el valor de la propiedad Image del PictureBox, cargándolo a un objeto nuevo de tipo Image, pero con el tamaño del MDI, es decir las propiedades Width y Height.
Luego le colocamos dicha variable definida como imagen, a la propiedad BackgroundImage del MDI.

Tercer Paso

A cada formulario hijo le anexaremos el siguiente código:
    Private Sub frmhijo1_Activated(ByVal sender As Object, _
                                   ByVal e As System.EventArgs) Handles MyBase.Activated
        'Cada vez que se active el formulario hijo, indicara en la StatusBar del MDI,
        ' donde esta ubicado
        frmmdi.gf.StatusBar1.Text = "Estoy en hijo 1"
        'Redibujara el fondo de este hijo, pero teniendo como fondo la imagen del MDI
        dibujar_fondo()
    End Sub
    Private Sub frmhijo1_Resize(ByVal sender As Object, _
                                ByVal e As System.EventArgs) Handles MyBase.Resize
        'Cada vez que cambie el tamaño del formulario deberá redibujar el fondo
        dibujar_fondo()
    End Sub
    Private Sub frmhijo1_Closed(ByVal sender As Object, _
                                ByVal e As System.EventArgs) Handles MyBase.Closed
        'Al cerrar el formulario, deberá blanquear la StatusBar
        frmmdi.gf.StatusBar1.Text = String.Empty
    End Sub
    Private Sub dibujar_fondo()
        'Tomamos la imagen del picturebox
        Dim imagen As New Drawing.Bitmap(frmmdi.gf.PictureBox1.Image, Me.Width, Me.Height)
        Me.BackgroundImage = imagen
    End Sub
End Class
Qué es todo esto? en el evento Activate de cada formulario Hijo (en este caso el hijo1), mandaremos un valor a la StatusBar indicando que este formulario hijo acaba de ser activado o acaba de tomar el foco. En este mismo evento, invocamos la Sub dibujar_fondo.
En el evento Resize del formulario hijo, le indicaremos que cuando se realice este evento, vaya a la Sub dibujar_fondo.
En el evento Closed le indicamos que vacie la propiedad Text del objeto StatusBar del MDI ya que no debe mostrar nada si no hay ningún formulario hijo abierto.
Ahora si vemos la Sub dibujar_fondo. En esta Sub hacemos algo parecido a lo realizado en el evento Resize del MDI, pero tomando la imagen desde el objeto PictureBox del MDI.

A continuación procedemos a compilar y realizar las pruebas pertinentes.

Es de aclarar que podemos colocar la Sub dibujar_fondo en un módulo y enviarle los parámetros necesarios para poder hacer lo que necesitamos y nos economizaremos un poco más de código.

Espero que sea de mucha utilidad.

No hay comentarios:

Publicar un comentario