Como pintar un fondo degradado en un formulario MDI

Descripción general

Este documento muestra un ejemplo de código para pintar el fondo de un formulario MDI con un color degradado

[TOC] Tabla de Contenidos


↑↑↑

Como pintar un fondo degradado en un formulario MDI


↑↑↑

A modo de introducción

En este documento (Cambiar el fondo de un formulario MDI) se analiza porqué hay que escribir el código que se muestra a continuación. Es recomendable su lectura (que además de corta, está muy bien escrita) para que comprendas el porqué de las clases que se usan


↑↑↑

Explicación del proceso

Para dibujar un color degradado en el fondo de un formulario MDI tendremos que hacer dos cosas: Una crear una imagen con el color degradada, (usando LinearGradientBrush (Clase)) y dos dibujar esa imagen en el formulario con el evento Paint del control MdiClient subyacente.

En los formularios MDI, se puede dibujar directamente sobre el fondo del formulario, pero no se vería absolutamente nada, porque como he explicado (Ver Cambiar el fondo de un formulario MDI) el control MdiClient subyacente se superpone sobre el fondo del propio formulario MDI, y observaríamos el típico color gris oscuro característico del control MdiClient.

La solución pasa por detectar el control MdiClient subyacente, y dibujar la imagen sobre su propio fondo, utilizando para ello el evento Paint del objeto MdiClient:

Para aplicar esta técnica es necesario declarar una variable objeto con eventos que referencie al objeto MdiClient subyacente existente en todos los formularios MDI principales. Será en el evento Paint del objeto MdiClient declarado, donde dibujaremos el fondo de la aplicación utilizando para ello el color degradado.

Una observación. También se puede dibujar en el evento Paint del formulario MDI, pero el código es un pelín mas enrevesado y no merece la pena (no obstante tienes un ejemplo en el código que se muestra a continuación (observa que todo el evento esta comentado)

imagen de como queda un color degradado


↑↑↑

Un Poco de código

Private Sub FormMain_Load( _
        ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles MyBase.Load


    'Degradado de fondo para un fomulario MDI
    Call EstablecerFondoDegradadoParaFormLoad()

    Call NuevoHijo()
End Sub

Private Sub NuevoHijo()
    Dim f As New Form
    f.MdiParent = Me
    f.Text = " Formulario Hijo - " & _
              Me.MdiChildren.Length.ToString()
    f.Show()
End Sub


#Region "Degradado de fondo para un formulario MDI"


''' <summary>
'''  Contendrá el control que representa al área cliente MDI
''' </summary>
''' <remarks>Se emplea por el evento Form Resize
'''  Si se declara [WithEvents] hay que escirbir 
'''  el evento [_ctlMdiClient.Paint]
'''  si no hay que asignar el manejador 
'''  [AddHandler _ctlMdiClient.Paint, AddressOf PintarFondo]
'''</remarks>
Private WithEvents _ctlMdiClient As MdiClient = Nothing

''' <summary>
'''   Esta función tiene que ser llamada 
'''   por el evento FormLoad del Form
''' </summary>
''' <remarks></remarks>
Private Sub EstablecerFondoDegradadoParaFormLoad()

    '-------------------------------------------------
    ' ATENCION
    ' Para que todo esto funcione, esta función tiene que 
    ' ser llamada desde el evento Load del formulario
    '-------------------------------------------------

    '-------------------------------------------------
    ' Estamos buscando en control que representa
     ' el área cliente MDI 
    '  La función [GetMdiContainer] comprobará si existe 
    '  un control MdiClient en el formulario indicado, 
    '  devolviendo la referencia al citado control.
    '  o el valor Nothing si no existe
    _ctlMdiClient = GetMdiContainer(Me)

End Sub



''' <summary>
'''  La función comprobará si existe un control MdiClient
'''  en el formulario indicado, devolviendo la referencia
'''  al citado control. o el valor Nothing si no existe
''' </summary>
''' <param name="frm">El formulario en el que se busca</param>
''' <returns> 
'''    La referncia al objeto 
'''    <see cref="MdiClient">[MdiClient]</see> si existe 
'''    o un valor Nothing si no existe en el formulario 
''' </returns>
Private Shared Function GetMdiContainer( _
                 ByVal frm As Form) _
             As MdiClient

    '--------------------------------------------------------
    ' La función comprobará si existe un control MdiClient
    ' en el formulario indicado, devolviendo la referencia
    ' al citado control. O el valor Nothing si no existe
    '--------------------------------------------------------
    ' Estamos buscando el control que representa 
    ' el área cliente MDI 
    Dim resultado As MdiClient = Nothing
    Dim ctl As Control
    For Each ctl In frm.Controls
        If ctl.GetType = GetType(MdiClient) Then
            ' ¿Encontrado!
            resultado = CType(ctl, MdiClient)
            ' no hace falta seguir buscando mas
            Exit For
        End If
    Next
    '
    Return resultado
End Function


''' <summary>
''' Función que pinta el fondo del área cliente
''' </summary>
Private Shared Sub PintarFondo( _
            ByVal sender As Object, _
            ByVal e As System.Windows.Forms.PaintEventArgs)

    Try
        ' Colores para el degradado
        Dim colorSuperior As Color = Color.Blue 'Color.Blue
        Dim colorInferior As Color = Color.OldLace ' Color.Black
        ' el control MdiClient
        Dim panelMdiForm As MdiClient = CType(sender, MdiClient)
        ' el degradado
        Dim GradientePanel As New Drawing2D.LinearGradientBrush( _
           New RectangleF(0, 0, panelMdiForm.Width, panelMdiForm.Height), _
               colorSuperior, _
               colorInferior, _
               Drawing2D.LinearGradientMode.Vertical)
        ' dibujarlo
        e.Graphics.FillRectangle( _
            GradientePanel, _
            New RectangleF(0, 0, panelMdiForm.Width, panelMdiForm.Height))

    Catch ex As Exception
        '--------------------------------------------------
        ' Ignoro la regla FxCop
        ' CA1031: No capturar los tipos de excepción general
        ' http://msdn.microsoft.com/es-es/library/ms182137.aspx
        ' Info: You should not catch Exception or SystemException. 
        '       Catching generic exception types can hide run-time 
        '       problems from the library user, and can complicate 
        '       debugging. You should catch only those exceptions 
        '       that you can handle gracefully.
        '--------------------------------------------------
        ' Registro el problema en el log pero 
        ' dejo que continue el proceso
        ' no se cambiara el color de fondo del formulario
        My.Application.Log.WriteEntry( _
         "Problemas en la funcion *PintarFondo* " & ex.Message, _
          System.Diagnostics.TraceEventType.Error)
    End Try
End Sub



''' <summary>
'''  Capturar el evento Paint del control [MdiClient].
'''  Evento Paint de la variable de clase que tiene la instancia
'''  del control MdiClient y que está definida como [WithEvents]
''' </summary>
Private Sub _ctlMdiClient_Paint( _
        ByVal sender As Object, _
        ByVal e As System.Windows.Forms.PaintEventArgs) _
    Handles _ctlMdiClient.Paint
    '---------
    ' Llamar a la función que hace el 
    ' trabajo de  dibujar el degradado
    Call PintarFondo(sender, e)
End Sub



''' <summary>
'''  Capturar el evento Resize del control [MdiClient].
'''  Evento Paint de la variable de clase que tiene la instancia
'''  del control MdiClient y que esta definida como [WithEvents]
''' </summary>
''' <remarks>  
'''  <para>
'''    Resuelve el problema de redibujar la imagen 
'''    cuando se cambia el tamaño del formulario
''' </para> 
'''  <para>
'''    Cuando se cambia el tamaño del formulario, la imagen 
'''    tiene problemas para dibujarse y se queda como a "capas".
'''    Con este evento forzamos a que se dibuje totalmente 
'''    y se resuelve el problema
''' </para> 
''' </remarks>
Private Sub _ctlMdiClient_Resize( _
            ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles _ctlMdiClient.Resize

    ' Llamar a la función que hace el 
    ' trabajo de  dibujar el degradado
    Call PintarFondo(sender, New PaintEventArgs( _
                Me._ctlMdiClient.CreateGraphics, _
                New Rectangle(Me._ctlMdiClient.Location, Me._ctlMdiClient.Size)))
End Sub



' ''' <summary>
' '''   Capturar el evento Resize del formulario.
' ''' </summary>
' ''' <remarks>  
' '''  <para>
' '''    Resuelve el problema de redibujar la imagen 
' '''    cuando se cambia el tamaño del formulario
' ''' </para> 
' '''  <para>
' '''    Cuando se cambia el tamaño del formulario, la imagen 
' '''    tiene problemas para dibujarse y se queda como a "capas".
' '''    Con este evento forzamos a que se dibuje totalmente 
' '''    y se resuelve el problema
' ''' </para> 
' ''' </remarks>
'Private Sub Evento_Resize( _
'            ByVal sender As Object, _
'            ByVal e As System.EventArgs) _
'        Handles MyBase.Resize
'
'    '--------------------------------------------------------
'    ' Esta pregunta evita errores en la función [PintarFondo]
'    ' cuando _ctlMdiClient Is Nothing, hecho que ocurre
'    ' cuando no se llama la función[TrabajoParaFormLoad] 
'    ' desde el evento "Load del formulario
'    '--------------------------------------------------------
'
'    If Not (Me._ctlMdiClient Is Nothing) Then
'        ' llamar a la función que pinta el 
'        ' degradado del fondo del form
'        '------------------
'        ' Observa la *trampa* al llamar
'        ' a la función [PintarFondo]  
'        ' El objeto [Sender] no es el formulario sino que se  
'        ' cambia al control [MdiClient].  
'        ' De la misma forma el evento [EventArgs] se cambia  
'        ' al evento [PaintEventArgs] y se vuelve a usar para  
'        ' ello al control [MdiClient] en lugar del formulario.
'        '------------------
'        Call PintarFondo( _
'            Me._ctlMdiClient, _
'            New PaintEventArgs( _
'                Me._ctlMdiClient.CreateGraphics, _
'                New Rectangle(Me._ctlMdiClient.Location, _
'                              Me._ctlMdiClient.Size)))
'    End If
'End Sub


#End Region

↑↑↑

A.2.Enlaces

[Para saber mas]
[Grupo de documentos]
[Documento Index]
[Documento Start]
[Imprimir el Documento]