Friday, March 13, 2009

C# MDI control with backcolor

Stumble del.icio.us Reddit MyWeb! Facebook Google bookmark

When designing an MDI form one comes across a limitation of having to accept the default gray background of the mdi control. Here is a way out :). MDI control is just like another windows control which has a default backcolor defined. One can change the backcolor if we handle the events properly. I have tried to demonstrate one such way in the OnLoad method of the form.

The code here is just a a small part of a form class with its IsMdiContainer property set to true.

You will need to add the following using directives so as to be able to run the code after placing it in your form class file.


using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;



And here goes the main code:



/// The brush used to paint the background.
private LinearGradientBrush m_bgndBrush;

// *********************************************************************
/// <summary>
/// Raises the System.Windows.Forms.Form.Load event
/// </summary>
/// <param name="e">An <see cref="System.EventArgs"/> that contains the
/// event data.</param>
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);

// Now set the background color for the mdi client
foreach (Control control in this.Controls)
{
if (control is MdiClient)
{
control.Paint += new PaintEventHandler(
this.PaintMdiClientBackground);
control.SizeChanged += new EventHandler(
this.ReSizeMdiClientBackground);
ControlEventHandler eh =
new ControlEventHandler(HandleMdiChildAddRemove);
control.ControlAdded += eh;
control.ControlRemoved += eh;
break;
}
}

} // end OnLoad


// *********************************************************************
/// <summary>
/// Paints the background of MdiClient.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="System.Windows.Forms.PaintEventArgs"/>
/// object that contains the event data.</param>
private void PaintMdiClientBackground(object sender, PaintEventArgs e)
{
// Check to see if the window is just being restored from
// minimised state.
if (this.Height <= 0 || this.Width <= 0) return; // Do not call the base.OnPaintBackground because it will just keep
// repainting the whole area since the backcolor is supposed to be
// transparent.
//base.OnPaintBackground(e);
m_bgndBrush = this.GetDisplayBgndBrush( m_bgndBrush, this.ClientRectangle);
e.Graphics.FillRectangle(m_bgndBrush, this.ClientRectangle); return; }
// end PaintMdiClientBackground

// *********************************************************************
/// <summary>
/// Paints the background of MdiClient.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="System.Windows.Forms.PaintEventArgs"/>
/// object that contains the event data.</param>
private void ReSizeMdiClientBackground(object sender, EventArgs e)
{
((MdiClient) sender).Invalidate();
}


// *********************************************************************
/// <summary>
/// Handles the <see cref="Control.ControlAdded"/> and
/// <see cref="Control.ControlRemoved"/>
/// events to enable or disable the windows mdilist menu item.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">An <see cref="EventArgs"/> object that contains
/// the event data.</param>
private void HandleMdiChildAddRemove(object sender, ControlEventArgs e)
{
// One could just show a Mdi window menu for example
//m_windowsMenu.Visible = this.MdiChildren.Length > 0;
}

//**********************************************************************
/// <summary>
/// Gets a brush used to paint the background area in the viewer's
/// middle (display) area.
/// </summary>
/// <remarks>
/// <para>This method optimizes creation of the brush by checking if
/// the brush's rectangle still matches <paramref name="rect"/>. If so,
/// the existing brush is returned. If they do not match or
/// <paramref name="brush"/> is <see langword="null"/>, a new brush
/// will be created and returned.</para>
/// </remarks>
/// <param name="brush">An existing brush previously returned by
/// this method or <see langword="null"/>.</param>
/// <param name="rect">The rectangular region that defines the starting
/// and ending points of the gradient.</param>
/// <returns>A <see cref="System.Drawing.Brush"/>.</returns>
/// <seealso cref="GetDisplayBgndBrush(Rectangle)"/>
/// <seealso cref="System.Drawing.Drawing2D.LinearGradientBrush"/>
private LinearGradientBrush GetDisplayBgndBrush
(
LinearGradientBrush brush,
Rectangle rect
)
{
if ((brush == null) ||
(brush.Rectangle.Width != (float) rect.Width) ||
(brush.Rectangle.Height != (float) rect.Height))
{
brush = this.GetDisplayBgndBrush(rect);
}
return (brush);
} // end GetDisplayBgndBrush (LinearGradientBrush, Rectangle)

//**********************************************************************
/// <summary>
/// Gets a brush used to paint the background area in the viewer's
/// middle (display) area.
/// </summary>
/// <remarks>
/// <para>This is a gradient brush whose primary use is to draw the
/// display area of the viewer window.</para>
/// </remarks>
/// <param name="rect">The rectangular region that defines the starting
/// and ending points of the gradient.</param>
/// <returns>A <see cref="System.Drawing.Brush"/>.</returns>
/// <seealso cref="GetDisplayBgndBrush(LinearGradientBrush,Rectangle)"/>
/// <seealso cref="System.Drawing.Drawing2D.LinearGradientBrush"/>
private GetDisplayBgndBrush(Rectangle rect)
{
LinearGradientBrush brush = new LinearGradientBrush(rect,
Color.FromArgb(33, 62, 153), // dark skyblue
Color.FromArgb(0, 172, 238), // light skyblue
90.0f, true);
brush.SetBlendTriangularShape(0.5f);
return (brush);
}


Now enjoy your colored mdicontrol. :)

1 comment:

  1. http://www.codeproject.com/KB/debug/WinDBGAndSOS.aspx

    ReplyDelete

Please leave your opinion...