Permalink
Fetching contributors…
Cannot retrieve contributors at this time
127 lines (94 sloc) 12.1 KB
title ms.custom ms.date ms.prod ms.reviewer ms.suite ms.technology ms.tgt_pltfrm ms.topic dev_langs helpviewer_keywords ms.assetid caps.latest.revision author ms.author manager
Rendering a Windows Forms Control
03/30/2017
.net-framework
dotnet-winforms
article
jsharp
custom controls [Windows Forms], rendering
OnPaintBackground method, invoking in Windows Forms custom controls
custom controls [Windows Forms], graphics resources
custom controls [Windows Forms], invalidation and painting
aae8e1e6-4786-432b-a15e-f4c44760d302
12
dotnet-bot
dotnetcontent
wpickett

Rendering a Windows Forms Control

Rendering refers to the process of creating a visual representation on a user's screen. Windows Forms uses [!INCLUDEndptecgdi] (the new Windows graphics library) for rendering. The managed classes that provide access to [!INCLUDEndptecgdi] are in the xref:System.Drawing?displayProperty=nameWithType namespace and its subnamespaces.

The following elements are involved in control rendering:

  • The drawing functionality provided by the base class xref:System.Windows.Forms.Control?displayProperty=nameWithType.

  • The essential elements of the [!INCLUDEndptecgdi] graphics library.

  • The geometry of the drawing region.

  • The procedure for freeing graphics resources.

Drawing Functionality Provided by Control

The base class xref:System.Windows.Forms.Control provides drawing functionality through its xref:System.Windows.Forms.Control.Paint event. A control raises the xref:System.Windows.Forms.Control.Paint event whenever it needs to update its display. For more information about events in the .NET Framework, see Handling and Raising Events.

The event data class for the xref:System.Windows.Forms.Control.Paint event, xref:System.Windows.Forms.PaintEventArgs, holds the data needed for drawing a control — a handle to a graphics object and a rectangle object that represents the region to draw in. These objects are shown in bold in the following code fragment.

Public Class PaintEventArgs  
   Inherits EventArgs  
   Implements IDisposable  
  
   Public ReadOnly Property ClipRectangle() As System.Drawing.Rectangle  
      ...  
   End Property  
  
   Public ReadOnly Property Graphics() As System.Drawing.Graphics  
      ...  
   End Property  
   ' Other properties and methods.  
   ...  
End Class  
public class PaintEventArgs : EventArgs, IDisposable {  
public System.Drawing.Rectangle ClipRectangle {get;}  
public System.Drawing.Graphics Graphics {get;}  
// Other properties and methods.  
...  
}  

xref:System.Drawing.Graphics is a managed class that encapsulates drawing functionality, as described in the discussion of [!INCLUDEndptecgdi] later in this topic. The xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A is an instance of the xref:System.Drawing.Rectangle structure and defines the available area in which a control can draw. A control developer can compute the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A using the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A property of a control, as described in the discussion of geometry later in this topic.

A control must provide rendering logic by overriding the xref:System.Windows.Forms.Control.OnPaint%2A method that it inherits from xref:System.Windows.Forms.Control. xref:System.Windows.Forms.Control.OnPaint%2A gets access to a graphics object and a rectangle to draw in through the xref:System.Drawing.Design.PaintValueEventArgs.Graphics%2A and the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A properties of the xref:System.Windows.Forms.PaintEventArgs instance passed to it.

Protected Overridable Sub OnPaint(pe As PaintEventArgs)  
protected virtual void OnPaint(PaintEventArgs pe);  

The xref:System.Windows.Forms.Control.OnPaint%2A method of the base xref:System.Windows.Forms.Control class does not implement any drawing functionality but merely invokes the event delegates that are registered with the xref:System.Windows.Forms.Control.Paint event. When you override xref:System.Windows.Forms.Control.OnPaint%2A, you should typically invoke the xref:System.Windows.Forms.Control.OnPaint%2A method of the base class so that registered delegates receive the xref:System.Windows.Forms.Control.Paint event. However, controls that paint their entire surface should not invoke the base class's xref:System.Windows.Forms.Control.OnPaint%2A, as this introduces flicker. For an example of overriding the xref:System.Windows.Forms.Control.OnPaint%2A event, see the How to: Create a Windows Forms Control That Shows Progress.

[!NOTE] Do not invoke xref:System.Windows.Forms.Control.OnPaint%2A directly from your control; instead, invoke the xref:System.Windows.Forms.Control.Invalidate%2A method (inherited from xref:System.Windows.Forms.Control) or some other method that invokes xref:System.Windows.Forms.Control.Invalidate%2A. The xref:System.Windows.Forms.Control.Invalidate%2A method in turn invokes xref:System.Windows.Forms.Control.OnPaint%2A. The xref:System.Windows.Forms.Control.Invalidate%2A method is overloaded, and, depending on the arguments supplied to xref:System.Windows.Forms.Control.Invalidate%2A e, a control redraws either some or all of its screen area.

The base xref:System.Windows.Forms.Control class defines another method that is useful for drawing — the xref:System.Windows.Forms.Control.OnPaintBackground%2A method.

Protected Overridable Sub OnPaintBackground(pevent As PaintEventArgs)  
protected virtual void OnPaintBackground(PaintEventArgs pevent);  

xref:System.Windows.Forms.Control.OnPaintBackground%2A paints the background (and thereby the shape) of the window and is guaranteed to be fast, while xref:System.Windows.Forms.Control.OnPaint%2A paints the details and might be slower because individual paint requests are combined into one xref:System.Windows.Forms.Control.Paint event that covers all areas that have to be redrawn. You might want to invoke the xref:System.Windows.Forms.Control.OnPaintBackground%2A if, for instance, you want to draw a gradient-colored background for your control.

While xref:System.Windows.Forms.Control.OnPaintBackground%2A has an event-like nomenclature and takes the same argument as the OnPaint method, xref:System.Windows.Forms.Control.OnPaintBackground%2A is not a true event method. There is no PaintBackground event and xref:System.Windows.Forms.Control.OnPaintBackground%2A does not invoke event delegates. When overriding the xref:System.Windows.Forms.Control.OnPaintBackground%2A method, a derived class is not required to invoke the xref:System.Windows.Forms.Control.OnPaintBackground%2A method of its base class.

GDI+ Basics

The xref:System.Drawing.Graphics class provides methods for drawing various shapes such as circles, triangles, arcs, and ellipses, as well as methods for displaying text. The xref:System.Drawing?displayProperty=nameWithType namespace and its subnamespaces contain classes that encapsulate graphics elements such as shapes (circles, rectangles, arcs, and others), colors, fonts, brushes, and so on. For more information about [!INCLUDEndptecgdi], see Using Managed Graphics Classes. The essentials of [!INCLUDEndptecgdi] are also described in the How to: Create a Windows Forms Control That Shows Progress.

Geometry of the Drawing Region

The xref:System.Windows.Forms.Control.ClientRectangle%2A property of a control specifies the rectangular region available to the control on the user's screen, while the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A property of xref:System.Windows.Forms.PaintEventArgs specifies the area that is actually painted. (Remember that painting is done in the xref:System.Windows.Forms.Control.Paint event method that takes a xref:System.Windows.Forms.PaintEventArgs instance as its argument). A control might need to paint only a portion of its available area, as is the case when a small section of the control's display changes. In those situations, a control developer must compute the actual rectangle to draw in and pass that to xref:System.Windows.Forms.Control.Invalidate%2A. The overloaded versions of xref:System.Windows.Forms.Control.Invalidate%2A that take a xref:System.Drawing.Rectangle or xref:System.Drawing.Region as an argument use that argument to generate the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A property of xref:System.Windows.Forms.PaintEventArgs.

The following code fragment shows how the FlashTrackBar custom control computes the rectangular area to draw in. The client variable denotes the xref:System.Windows.Forms.PaintEventArgs.ClipRectangle%2A property. For a complete sample, see How to: Create a Windows Forms Control That Shows Progress.

[!code-csharpSystem.Windows.Forms.FlashTrackBar#6] [!code-vbSystem.Windows.Forms.FlashTrackBar#6]

Freeing Graphics Resources

Graphics objects are expensive because they use system resources. Such objects include instances of the xref:System.Drawing.Graphics?displayProperty=nameWithType class as well as instances of xref:System.Drawing.Brush?displayProperty=nameWithType, xref:System.Drawing.Pen?displayProperty=nameWithType, and other graphics classes. It is important that you create a graphics resource only when you need it and release it soon as you are finished using it. If you create a type that implements the xref:System.IDisposable interface, call its xref:System.IDisposable.Dispose%2A method when you are finished with it in order to free resources.

The following code fragment shows how the FlashTrackBar custom control creates and releases a xref:System.Drawing.Brush resource. For the complete source code, see How to: Create a Windows Forms Control That Shows Progress.

[!code-csharpSystem.Windows.Forms.FlashTrackBar#5] [!code-vbSystem.Windows.Forms.FlashTrackBar#5]

[!code-csharpSystem.Windows.Forms.FlashTrackBar#4] [!code-vbSystem.Windows.Forms.FlashTrackBar#4]

[!code-csharpSystem.Windows.Forms.FlashTrackBar#3] [!code-vbSystem.Windows.Forms.FlashTrackBar#3]

See Also

How to: Create a Windows Forms Control That Shows Progress