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 on Google, a similar article was found in MSDN blog: http://blogs.msdn.com/mhendersblog/archive/2005/10/12/480156.aspx.