Working with MDI Window Backgrounds in .NET

Its not unreasonable to want to work with the background of an MDI container area; in a project I’m working on I thought it would be neat to have a custom background image in the container rather than the boring SystemColors.AppWorkspace gray. Turns out this isn’t all that straightforward, especially if you want to be a little bit cleverer than just a static image… There’s very little help floating around for this so I thought I’d document how I got it working.

The MDI parent window would be resized in infinite combinations, yet I wanted my background to remain in a consistent design, with a fixed-size (i.e. not stretching) background image and the company logo always appearing in the bottom-right corner of the window. To achieve this the background would have to be a  a composite of two images, an oversized background image anchored top-left and the company logo which would always sit in the bottom right corner. Whatever size the window was the logo should remain in the bottom corner as illustrated in the example below…

mdi_smallwindow mdi_bigwindow

What Doesn’t Work

If it wasn’t for the fact the control we are working with is an MDI Parent Form, the normal approach I’d take is to set the background image of the control, then add an PictureBox with the company logo inside it, set to Anchor right and bottom, so when the control is re-sized the logo is move accordingly. With an MDI Form though, this doesn’t work because the actual MDI window area, where child forms may exist is a hidden control which you can’t access at design time.

Setting the background colour or image of the MDI Parent form will have no effect, and any controls added in the MDI Window Area will always appear on top of any child forms. Not helpful.

What Does Work

To get a background image, you need to edit the background image property of the MDI Window area (known as the Windows.Forms.MDIClient), since this is a control added at runtime, to edit its properties and add event handlers you’ll have to catch it at runtime. The code below demonstrates adding two event handlers which we’ll use when laying the second image on top of the background. The code examples here are from Visual Basic 2008, but the same principles apply to C# or other environments using WinForms.

Finding the MDIClient Control
        Dim c As Control
        Dim mdic As MdiClient
        For Each c In Me.Controls
            mdic = TryCast(c, Windows.Forms.MdiClient)
            If Not mdic Is Nothing Then
                mdic.BackColor = 
                mdic.BackgroundImage =
                AddHandler mdic.Paint, AddressOf Mdi_Paint
                AddHandler mdic.SizeChanged, AddressOf Mdi_SizeChanged
                Exit For
            End If
        Next

Now you’ve got handles on the events for changing the size of the MDI area you can use these handlers however you want. In this case to create the second image overlay we’ll use native paint tools to simply repaint the company logo over the top of the background image each time the MDI area needs redrawing.

   Private Sub Mdi_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs)
        e.Graphics.DrawImage(Image, Left, Top, Width, Height)
    End Sub

And whenever the MDI area is resized, we’ll force it to get redrawn so our logo moves seamlessly.

    Private Sub Mdi_SizeChanged(ByVal sender As Object, ByVal e As System.EventArgs)
        CType(sender, MdiClient).Invalidate()
    End Sub

3 thoughts on “Working with MDI Window Backgrounds in .NET

  1. Ok, this is nice. But what will be if You open Dialog window and move it….?? It will flicker ?? And what with other windows when you open on it…. ???

    1. Hey,
      No the background always behaves as you expect and stays underneath dialog windows and mdi client forms. Resizing the form moves the image with no flicker.

  2. Hey,
    this solution is overwhelming! Well done! Since I´m a newbie in programming, i couldn´t realy figure out, how to translate this pieces to my code.. especially how to load the image in the code… However, could you upload an example project file or sth ?
    Regards

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.