Tag Archives: Paint

.NET and painting from an API viewpoint

When .NET is used on the windows platform it’s a layer on top  of the windows API. Understanding how this works will help you to speed up painting.

The windows API  works with messages. These message are processed by the message queue.  Often the message handler is one function with a long switch statement processing the messages required.

Messages related to painting

Messages of importance are the WM_ERASEBKGND and the WM_PAINT.

WM_ERASEBKGND   clears the background and paint it. It is called when a part of the control needs to be repainted. The default handling uses the brush assigned to the background and paints. When an API InvalidateRect is used to invalidate a rectangle the last parameter indicates whether this message is generated.

WM_PAINT paints the contents, it uses a clipping rectangle. The GDI API can clip all contents on this rectangle. Although clipping is not totally free it reduces the time to repaint significantly.

How does this translate to .NET.

.NET supports two events which map directly to the events.


Called from the WM_ERASEBKGND event unless double buffering or SetStyle is used to set the style AllPaintingInWmPaint. In that case this event will be fired from the WM_PAINT message, this may reducing some flicker since there can be some time between the two messages. It is to be assumed that setting the form property DoubleBuffered to true will also set this style implicit .


Used to paint the contents. It uses a clipping rectangle to prevent unneeded painting. It is important to remember that if you invalidate the form yourself using the Invalidate() method (equivalent to an InvalidateRect API call) using the parameter less version will invalidate the entire client area!

When using invalidate always supply an rectangle or region if needed. Multiple invalidates will be combined in one clipping rectangle. Typically the bounding rectangle.

It is also important to remember that invalidate() will not repaint directly, use the update method to redraw (the equivalent of the UpdateWindow() API call.

Double buffering

When double buffering is used the graphics drawn is first drawn on a bitmap which is then drawn on screen. Although theoretically this would be slower requiring an extra step, drawing on the bitmap (in memory) is often faster then to video memory the net result may be faster.  Since there will be less flicker since the screen buffer is accessed less often and bitmap drawing is a very efficient graphics operation double buffering is almost always a good idea .

It is still very important to use the Invalidate with rectangles even when double buffering.  Admittedly, drawing the entire bitmap is fast but when dragging a lot of bitmaps need to be painted!  Also if possible do not rely on clipping to much. Your paint handler has a parameter with the clipping rectangle. If a lot of objects are to be painted a quick check on this boundary can save precious time creating brushes, pens etc.

Lastest update in June 2011, inital post in June 2011

Scrollable panels and the Paint event.

When a panel has scrollbars ‘default’ drawing on the DC does not  work correctly when the upper-left is not at 0,0.  Graphics functions draw on the current client area, even when scrolled the upper-left posotion of the client area is still at 0,0.

Use the function TranslateTransform to offset the coordinates.


private void dc_Paint(object sender, PaintEventArgs e)
   e.Graphics.TranslateTransform(dc.AutoScrollPosition.X, dc.AutoScrollPosition.Y);
   //0,0 is now relative to the total scrollable area, not the visible part (client area).


Although this will work great for simple drawing and unnecessary drawing is limited (being clipped ), some form of optimization would speed things up considerably.

To setup a larger DC size as visible set the properties AutoScroll to  true and the property AutoScrollMinSize to a size larger then the visible area.

Lastest update in May 2011, inital post in May 2011