Graphics and Windows Forms

Introduction to GDI+

The common language runtime takes advantage of an advanced version of the Windows graphics device interface (GDI) called GDI+. GDI+ is designed to provide high performance and ease of use. It supports 2-D graphics, typography, and imaging.

New 2-D features include the following:

  • Alpha blending support for all graphics primitives
  • Anti-aliasing
  • Gradient and texture fills
  • Wide lines
  • Cardinal splines
  • Scalable regions
  • Floating point coordinates
  • Compound lines
  • Inset pen
  • High quality filtering and scaling
  • Numerous line styles and end-cap options

Image support includes the following:

  • Native support for image file formats such as .jpeg, .png, .gif, .bmp, .tiff, .exif, and .icon
  • Common interfaces for encoding and decoding arbitrary raster image formats
  • Extensible architecture for dynamically adding new image file formats
  • Native image processing support for common point operations such as brightness, contrast, color balance, blur, and dissolve. Support for common transforms such as rotate, crop, and so on.

Color Management

Support for sRGB, ICM2, and sRGB64

Typographic support includes the following:

  • Native ClearType support
  • Texture and gradient filled text
  • Full Unicode support on all platforms
  • Support for all Windows 2000 scripts
  • Update to Unicode 3.0 standards
  • Text line services support for better text readability

GDI+ can be used with Windows Forms and with Web Forms. For instance, a Web Forms control can dynamcially generate a .jpeg file, using GDI+ based on user input, and reference it from a web page.

This section focuses on Windows Forms.

Differences between GDI and GDI+

The aim of this section is to help you understand the basics of using GDI+. Before you move on, it is worth pointing out the biggest difference between GDI and GDI+. GDI has a stateful programming model, but GDI+ has a stateless programming model. Using GDI, you set properties on the drawing surface, such as foreground color and background color, and then draw on it. For instance, to draw a string of black text, the code looks something like the following example.


Dim g as Graphics
g.ForeColor = Color.Black
g.BackColor = Color.White
g.Font = new Font("Times New Roman", 26)
g.DrawString("Hello, World", 0, 0)
VB

When using GDI+, you always pass the properties to be used as part of the drawing command. The previous code changes to the following.


Dim g As Graphics;
Dim foreColor As Color = Color.Black;
Dim backColor As Color = Color.White;
Dim vbFont As New Font("Times New Roman", 26);
g.FillRectangle(New SolidBrush(backColor), ClientRectangle);
g.DrawString("Hello World", vbFont, New SolidBrush(foreColor), 15, 15);
VB

GDI+ Namespaces

The GDI+ classes reside in the System.Drawing, System.Drawing.Drawing2D, System.Drawing.Imaging, and System.Drawing.Text namespaces. The namespaces are contained in the Assembly System.Drawing.DLL.

Creating a Graphics Object

A GDI+ drawing surface is represented by the Graphics class. In order to use GDI+, you first need a reference to a graphics object. Typically, you get a reference to a graphics object in the Paint event of a control or form, or in the PrintPage event of a PrintDocument.

You can handle the Paint event by creating an event handler for that event.


Public Class GdiPlusDemo : Inherits Form

    Public Sub New()
        ' Hook the paint event of the form.
        AddHandler Me.Paint, AddressOf form1_Paint
    End Sub

    Private Sub form1_Paint(sender As Object, pe As PaintEventArgs)
        Dim g As Graphics = pe.Graphics

        ' Simply fill a rectangle with red.
        g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
    End Sub
End Class
VB

More typically, you can subclass and override the OnPaint method.


Public Class GdiPlusDemo : Inherits Form

   Public Sub New()
   End Sub

   Protected Overrides Sub OnPaint(pe As PaintEventArgs)
        Dim g As Graphics = pe.Graphics
        g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
   End Sub
End Class
VB

You can also create a Graphics object instance from any derived class of Image.


Dim newBitmap As Bitmap = New Bitmap(600,400,PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(newBitmap)
g.FillRectangle(New SolidBrush(Color.Red), 40, 40, 140, 140)
newBitmap.Save("c:\temp\TestImage.jpg", ImageFormat.Jpeg)
VB

After creating a Graphics object, you can use it to draw lines, fill shapes, draw text, and so on. The major objects that you use in association with the Graphics object are the following.
Brush

Used to fill enclosed surfaces with patterns, colors, or bitmaps.

Pen

Used to draw lines and polygons, including rectangles, arcs, and pies.

Font

Used to describe the font used to render text.

Color

Used to describe the color used to render a particular object. In GDI+, the color can be alpha blended.

Alpha Blending
Colors can be alpha blended, which makes it is easy to create effects that are based on overlays of colors. For instance, the following example paints a red rectangle, overlayed with a yellow rectangle, without obscuring the underlying red rectangle.


Dim g As Graphics = pe.Graphics
g.FillRectangle(new SolidBrush(Color.Red), 600, 350, 100, 100)
g.FillRectangle(new SolidBrush(Color.FromArgb(180, Color.Yellow)), 650, _
                               400, 100, 100)
VB

Using Brushes
You use a brush to fill the interior of shapes and paths. For instance, to create a red rectangle, see the following example.


Dim g As Graphics = pe.Graphics
g.FillRectangle(new SolidBrush(Color.Red), 600, 350, 100, 100)
VB

Brushes can either be solid, hatched, textured, or gradiated. A hatched brush is simply a brush that paints using a pattern.


Dim g As Graphics = pe.Graphics
HatchBrush hb = new HatchBrush(HatchStyle.ForwardDiagonal, Color.Green, _
                               Color.FromArgb(100, Color.Yellow))
g.FillEllipse(hb, 250, 10, 100, 100)
VB

A textured brush uses a bitmap to paint. For instance, the following code uses a texture brush to paint the background of a form and applies a white "wash" over it to tone down the colors in the bitmap.


Dim g As Graphics = pe.Graphics
Dim colorbars As Image = new Bitmap("colorbars.jpg")
Dim backgroundBrush As Brush = new TextureBrush(colorbars)
g.FillRectangle(backgroundBrush, ClientRectangle)
g.FillRectangle(new SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)
VB

A LinearGradientBrush uses two colors to paint. It fills the given shape, gradually changing from one color to the other, according to the attributes set on the brush. For instance, you can create the following fill with the code that follows.




Dim r As Rectangle = new Rectangle(500, 300, 100, 100);
Dim lb As LinearGradientBrush = new LinearGradientBrush(r, Color.Red, Color.Yellow, _
                                                       LinearGradientMode.BackwardDiagonal);
e.Graphics.FillRectangle(lb, r);
VB

A PathGradient brush allows for the creation of much more complex effects, such as the following shape.

It was created with the following code.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(backgroundBrush, ClientRectangle)
    e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)

    Dim path As New GraphicsPath(New Point() { _
        New Point(40, 140), _
        New Point(275, 200), _
        New Point(105, 225), _
        new Point(190, 300), _
        new Point(50, 350), _
        new Point(20, 180), _
        }, New Byte() { _
            CType(PathPointType.Start, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Bezier, Byte), _
            CType(PathPointType.Line, Byte), _
            CType(PathPointType.Line, Byte), _
            })

    Dim pgb As New PathGradientBrush(path)
    pgb.SurroundColors = new Color() { _
        Color.Green, _
        Color.Yellow, _
        Color.Red, _
        Color.Blue, _
        Color.Orange, _
        Color.White, _
    }

    e.Graphics.FillPath(pgb, path)
End Sub
VB



 
VB Brush Sample

[Run Sample] | [View Source]

Using Pens

You use a pen to draw lines and curves. You can set properties, such as PenType, DashStyle, Width, Color, and EndCap to control how a Pen draws.

The following code draws a curve.


Dim g As Graphics
' Create a pen 20 pixels wide that is and purple and partially transparent.
Dim penExample As New Pen(Color.FromArgb(150, Color.Purple), 20)
' Make it a dashed pen.
Dim penExample.DashStyle As Pen = DashStyle.Dash
' Make the ends round.
Dim penExample.StartCap As Pen = LineCap.Round
Dim penExample.EndCap As Pen= LineCap.Round

' Now draw a curve using the pen
g.DrawCurve(penExample, New Point() { _
            New Point(200, 140), _
            New Point(700, 240), _
            New Point(500, 340), _
            New Point(140, 140), _
            New Point(40, 340), _
})
VB

It is also possible to use a texture as the fill for a pen by using a textured brush.


Dim g As Graphics
Dim textureBrush As New TextureBrush(New Bitmap("Boiling Point.jpg"))
Dim penExample As New Pen(textureBrush, 25)
penExample.DashStyle = DashStyle.DashDotDot
penExample.StartCap = LineCap.Triangle
penExample.EndCap = LineCap.Round
g.DrawLine(penExample, 10,450,550,400)
VB



 
VB Pen Sample

[Run Sample] | [View Source]

Drawing Text

The Graphics object's DrawString methods render the text to the drawing surface. You pass the font and color to be used to the DrawString method. For instance, the following code displays the text "Hello World" by using the form's font and a black brush.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Dim g As Graphics = e.Graphics
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)
    g.DrawString("Hello World", Me.Font, New SolidBrush(Color.Black), 10,10)
End Sub
VB

Because DrawString takes a brush, it is possible to render text using any brush. This includes a texture brush. For instance, the following code renders the text with a marbled effect and a background shadow.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    Dim titleBrush As New TextureBrush(New Bitmap("marble.jpg"))
    Dim backgroundBrush As New TextureBrush(New Bitmap("colorbars.jpg"))
    Dim titleShadowBrush As New SolidBrush(Color.FromArgb(70, Color.Black))
    Dim titleFont As New Font("Lucida Sans Unicode", 60)
    Dim titleText As String = "Graphics  Samples"

    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(backgroundBrush, ClientRectangle)
    e.Graphics.FillRectangle(New SolidBrush(Color.FromArgb(180, Color.White)), ClientRectangle)

    e.Graphics.DrawString(titleText, titleFont, titleShadowBrush, 15, 15)
    e.Graphics.DrawString(titleText, titleFont, titleBrush, 10, 10)

End Sub
VB

If you supply DrawString with a Rectangle, the text will wrap to fit in the rectangle.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 12)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    e.Graphics.FillRectangle(New SolidBrush(Color.Gainsboro), rectangle)
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle)
End Sub
VB

You can control how the text is drawn by using the StringFormat object. For instance, the following code allows you to draw text that is centered in a particular area.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 8)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    e.Graphics.FillRectangle(new SolidBrush(Color.Gainsboro), rectangle)
    Dim format As New StringFormat()
    format.Alignment = StringAlignment.Center
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle,format)
End Sub
VB

If you want to find out how long a string will be when it is drawn, you can use MeasureString. For instance, to center a string on a form, use the following code.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Dim textToDraw As String ="Hello Symetrical World"

    Dim textFont As New Font("Lucida Sans Unicode", 8)
    Dim windowCenter As Double = this.DisplayRectangle.Width/2
    Dim stringSize As SizeF = e.Graphics.MeasureString(textToDraw, textFont)
    Dim startPos As Double = windowCenter-(stringSize.Width/2)

    e.Graphics.DrawString(textToDraw, textFont, new SolidBrush(Color.Blue), startPos, 40)
End Sub
VB

MeasureString can also be used to determine how many lines and characters will be rendered. For instance, we can determine how many lines and characters will be rendered in the previous flowed text example.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Dim textFont As New Font("Lucida Sans Unicode", 12)
    Dim rectangle As New RectangleF(100, 100, 250, 350)
    Dim lines As Integer
    Dim characters As Integer
    Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
        & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
        & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
        & "language runtime." & ControlChars.CrLf _
        & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
        & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
        & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
        & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
        & "written in Windows Forms." & ControlChars.CrLf _
        & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
        & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
        & "control and container classes. This significantly reduces" & ControlChars.CrLf _
        & "control-container interoperability issues." & ControlChars.CrLf
    Dim whatRenderedText As String

    e.Graphics.FillRectangle(New SolidBrush(Color.Gainsboro), rectangle)

    e.Graphics.MeasureString(flowedText, textFont, rectangle.Size, _
                    new StringFormat(), characters, lines)
    whatRenderedText = "We printed " & characters & " characters and " & lines & " lines"

    e.Graphics.DrawString(flowedText, textFont, New SolidBrush(Color.Blue), rectangle)

    e.Graphics.DrawString(whatRenderedText, Me.Font, New SolidBrush(Color.Black), 10,10)
End Sub
VB

GDI+ has full Unicode support. This means that it is possible to render text in any language. For instance, the following code draws a string in Japanese (you must have the Japanese language pack installed).


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.TextRenderingHint = TextRenderingHint.AntiAliased
    e.Graphics.FillRectangle(new SolidBrush(Color.White), ClientRectangle)

    Try
        Dim japaneseFont As New Font("MS Mincho", 32)
        Dim japaneseText As New String(new char() {CType(31169, Char), CType(12398, Char), _
                    CType(21517, Char), CType(21069, Char), CType(12399, Char), _
                    CType(12463, Char), CType(12522, Char), CType(12473, Char), _
                    CType(12391, Char), CType(12377, Char), CType(12290, Char)})
        e.Graphics.DrawString(japaneseText, japaneseFont, new SolidBrush(Color.Blue), 20, 40)
    Catch ex As Exception
         MessageBox.Show("You need to install the Japanese language pack to run this sample")
         Application.Exit()
    End Try
End Sub
VB


 
VB Text Sample

[Run Sample] | [View Source]

Using Images

GDI+ has full support for a range of image formats, including .jpeg, .png, .gif, .bmp, .tiff, .exif, and .icon files.

Rendering an image is simple. For instance, the following renders a .jpeg image.


Protected Overrides Sub OnPaint(e As PaintEventArgs)
    e.Graphics.FillRectangle(New SolidBrush(Color.White), ClientRectangle)
    e.Graphics.DrawImage(New Bitmap("sample.jpg"), 29, 20, 283, 212)
End Sub
VB

Using a a bitmap as a rendering surface is also simple. The following code renders some text and lines to a bitmap, and then saves the bitmap to disk as a .png file.


Dim newBitmap As New Bitmap(800,600,PixelFormat.Format32bppArgb)
Dim g As Graphics = Graphics.FromImage(newBitmap)
g.FillRectangle(New SolidBrush(Color.White), new Rectangle(0,0,800,600))

Dim textFont As New Font("Lucida Sans Unicode", 12)
Dim rectangle As New RectangleF(100, 100, 250, 350)
Dim Lines As Integer
Dim Characters As Integer
Dim flowedText As String ="Simplicity and power: Windows Forms is a programming model for" & ControlChars.CrLf _
    & "developing Windows applications that combines the simplicity of the Visual" & ControlChars.CrLf _
    & "Basic 6.0 programming model with the power and flexibility of the common" & ControlChars.CrLf _
    & "language runtime." & ControlChars.CrLf _
    & "Lower total cost of ownership: Windows Forms takes advantage of the versioning and" & ControlChars.CrLf _
    & "deployment features of the common language runtime to offer reduced deployment" & ControlChars.CrLf _
    & "costs and higher application robustness over time. This significantly lowers the" & ControlChars.CrLf _
    & "maintenance costs (TCO) for applications" & ControlChars.CrLf _
    & "written in Windows Forms." & ControlChars.CrLf _
    & "Architecture for controls: Windows Forms offers an architecture for" & ControlChars.CrLf _
    & "controls and control containers that is based on concrete implementation of the" & ControlChars.CrLf _
    & "control and container classes. This significantly reduces" & ControlChars.CrLf _
    & "control-container interoperability issues." & ControlChars.CrLf

g.FillRectangle(new SolidBrush(Color.Gainsboro), rectangle)
g.DrawString(flowedText, textFont, new SolidBrush(Color.Blue), rectangle)
Dim penExample As New Pen(Color.FromArgb(150, Color.Purple), 20)
penExample.DashStyle = DashStyle.Dash
penExample.StartCap = LineCap.Round
penExample.EndCap = LineCap.Round
g.DrawCurve(penExample, new Point() { _
            new Point(200, 140), _
            new Point(700, 240), _
            new Point(500, 340), _
            new Point(140, 140), _
            new Point(40, 340), _
})

newBitmap.Save("TestImage.png", ImageFormat.Png)
VB



 
VB Image Sample

[Run Sample] | [View Source]

Other Information
Standard Pens and Brushes

The Pen and Brush classes include a set of standard solid pens and brushes for all of the known colors.

Anti-Aliasing
Setting Graphics.SmoothingMode to SmoothingMode.AntiAlias will result in sharper text and graphics.
Scope of the Graphics Object
The graphics object that is contained in the arguments to the Paint event (PaintEventArgs) is disposed upon return from the Paint event handler. Therefore, you should not keep a reference to this Graphics object that has scope outside the Paint event. Attempting to use this Graphics object outside the Paint event will have unpredictable results.
Handling Resize

By default, the Paint event is not raised when a control or form is resized. If you want the Paint event to be raised when a form is resized, you need to set the control style appropriately.


Public Sub MyForm()
    SetStyle(ControlStyles.ResizeRedraw,True)
End Sub
VB


Copyright 2001 Microsoft Corporation. All rights reserved.