User-Drawn Controls

The .NET Framework provides you with the ability to easily develop your own controls. You can create a user control, which is a set of standard controls bound together by code, or you can design your own control from the ground up. You can even use inheritance to create a control that inherits from an existing control and add to its inherent functionality. Whatever approach you use, the .NET Framework provides the functionality to draw a custom graphical interface for any control you create.

Painting of a control is accomplished by the execution of code in the control's OnPaint method. The single argument of the OnPaint method is a PaintEventArgs object that provides all of the information and functionality required to render your control. The PaintEventArgs provides as properties two principal objects that will be used in the rendering of your control:

  • ClipRectangle object - the rectangle that represents the part of the control that will be drawn. This can be the entire control, or part of the control depending on how the control is drawn.

  • Graphics object - encapsulates several graphics-oriented objects and methods that provide the functionality necessary to draw your control.

For more information on the Graphics object and how to use it, see How to: Create Graphics Objects for Drawing.

The OnPaint event is fired whenever the control is drawn or refreshed on the screen, and the ClipRectangle object represents the rectangle in which painting will take place. If the entire control needs to be refreshed, the ClipRectangle will represent the size of the entire control. If only part of the control needs to be refreshed, however, the ClipRectangle object will represent only the region that needs to be redrawn. An example of such a case would be when a control was partially obscured by another control or form in the user interface.

When inheriting from the Control class, you must override the OnPaint method and provide graphics-rendering code within. If you want to provide a custom graphical interface to a user control or an inherited control, you can also do so by overriding the OnPaint method. An example is shown below:

Protected Overrides Sub OnPaint(ByVal pe As PaintEventArgs)
   ' Call the OnPaint method of the base class.
   MyBase.OnPaint(pe)
      
   ' Declare and instantiate a drawing pen.
   Dim myPen As System.Drawing.Pen = New System.Drawing.Pen(Color.Aqua)
      
   ' Draw an aqua rectangle in the rectangle represented by the control.
   pe.Graphics.DrawRectangle(myPen, New Rectangle(Me.Location, Me.Size))
End Sub
protected override void OnPaint(PaintEventArgs pe)
{
   // Call the OnPaint method of the base class.
   base.OnPaint(pe);

   // Declare and instantiate a new pen.
   System.Drawing.Pen myPen = new System.Drawing.Pen(Color.Aqua);

   // Draw an aqua rectangle in the rectangle represented by the control.
   pe.Graphics.DrawRectangle(myPen, new Rectangle(this.Location, 
      this.Size));
}
protected   void OnPaint(PaintEventArgs pe)
{
   // Call the OnPaint method of the base class.
   super.OnPaint(pe);

   // Declare and instantiate a new pen.
   System.Drawing.Pen myPen =  new System.Drawing.Pen(Color.get_Aqua());

   // Draw an aqua rectangle in the ClipRectangle.
   pe.get_Graphics().DrawRectangle(myPen, pe.get_ClipRectangle());
}

The preceding example demonstrates how to render a control with a very simple graphical representation. It calls the OnPaint method of the base class, it creates a Pen object with which to draw, and finally draws an ellipse in the rectangle determined by the Location and Size of the control. Although most rendering code will be significantly more complicated than this, this example demonstrates the use of the Graphics object contained within the PaintEventArgs object. Note that if you are inheriting from a class that already has a graphical representation, such as UserControl or Button, and you do not wish to incorporate that representation into your rendering, you should not call your base class's OnPaint method.

The code in the OnPaint method of your control will execute when the control is first drawn, and whenever it is refreshed. To ensure that your control is redrawn every time it is resized, add the following line to the constructor of your control:

SetStyle(ControlStyles.ResizeRedraw, True)
SetStyle(ControlStyles.ResizeRedraw, true);
SetStyle(ControlStyles.ResizeRedraw, true);

Note

Use the Control.Region property to implement a non-rectangular control.

See Also

Tasks

How to: Create Graphics Objects for Drawing

Concepts

Constituent Controls

Varieties of Custom Controls

Reference

Region

ControlStyles

Graphics

OnPaint

PaintEventArgs