Introduction
This article is about a simple trick to improve the drawing performance of Windows Forms. When a background image is used for a form and it has a number of controls, and especially when there are a lot of controls with a transparent background, you will definitely face an issue in rendering controls. You can individually render the controls just after loading the form. Even if you enable AllPaintingInWmPaint and do double-buffering using SetStyle, the performance will not improve.
(Double-buffering can create problems in a limited memory environment/ a terminal server environment / if you want to use OpenGL applications like VTK to draw over your window.)
This article shows you how to overcome this drawing issue without even using double-buffering
Using the code
The technique is overriding the background image property to return an image (Bitmap) which GDI can easily draw. Also, you can include the code to adjust the size. This will avoid the zoom/stretching needed while drawing and further improve performance.
property System::Drawing::Image^ BackgroundImage
{
virtual System::Drawing::Image^ BackgroundImage::get()override
{
return this->m_bmpRenderBitMap;
}
virtual void BackgroundImage::set(System::Drawing::Image ^value) override
{
if(nullptr==value)
{
m_bmpRenderBitMap = nullptr;
return;
}
this->m_bmpRenderBitMap = gcnew System::Drawing::Bitmap(value->Width,
value->Height,
System::Drawing::Imaging::PixelFormat::Format32bppPArgb);
System::Drawing::Graphics ^g =
System::Drawing::Graphics::FromImage(this->m_bmpRenderBitMap);
g->InterpolationMode = Drawing::Drawing2D::InterpolationMode::High;
g->DrawImage(value, Rectangle(0, 0, this->m_bmpRenderBitMap->Width,
this->m_bmpRenderBitMap->Height));
}
}
The same can be done in C# as well:
public override Image BackgroundImage
{
get
{
return bmpBackground;
}
set
{
if (value!=null)
{
bmpBackground = new Bitmap(value.Width,value.Height);
System.Drawing.Graphics g =
System.Drawing.Graphics.FromImage(bmpBackground);
g.InterpolationMode =
System.Drawing.Drawing2D.InterpolationMode.High;
g.DrawImage(value, new Rectangle(0, 0, bmpBackground.Width,
bmpBackground.Height));
}
else
bmpBackground = null;
}
}
After posting this article, when I searched in Google, a similar article was found in MSDN blog: http://blogs.msdn.com/mhendersblog/archive/2005/10/12/480156.aspx.