Introduction
The System.Drawing namespace provides access to GDI+ basic graphics functionality. GDI+ resides in System.Drawing.dll assembly. All GDI+ classes resides in System.Drawing, System.Text, System.Printing, System.Internal , System.Imaging, System.Drawing2D and System.Design namespaces.
This article gives an overview to work with drawing and printing class. It explains how to use various methods in the drawing and printing class.
The Graphics classes provide methods for drawing to the display device. Classes such as Rectangle and Point encapsulate GDI+ primitives. The Pen class is used to draw lines and curves, while classes derived from the abstract class Brush are used to fill the interiors of shapes.
Before we get started we will quickly list the main namespaces you'll find in the GDI+ base classes. They are:
- System.Drawing : This class is more concerned with the basic functionality of the drawing.
- System.Drawing.Drawing2D: This class is more concerned with the specialized classes and gives more advanced effects and options in drawing on the screen.
- System.Drawing.Imaging: This class will assist in manipulation of images like creating, editing etc.
- System.Drawing.Printing: Mainly refers to printing functionality or sending a document to print to the output device.
- System.Drawing.Design: Mainly refers to styles, elements concerned with the controls which extend the design time user interface.
- System.Drawing.Text: Concerned with the manipulation related with the fonts and font families.
The Graphics Class
The Graphics class encapsulates GDI+ drawing surfaces. Before drawing any object (for example circle, or rectangle) we have to create a surface using Graphics class. Generally we use Paint event of a Form to get the reference of the graphics. Another way is to override OnPaint method.
Here is how you get a reference of the Graphics object:
private void form1_Paint(object sender, PaintEventArgs e)
{
Graphics g = e.Graphics;
}
OR:
protected override void OnPaint(PaintEventArgs e)
{
Graphics g = pe.Graphics;
}
Drawing Class
Before start working on drawing let us learn few things. A computer screen is made up of tiny dots known as Pixels. By programming you can define the color of each pixel. Of course, most of the work is available by the code that defines forms and controls.
Assume Form as a canvas, where you can draw or paint. In real canvas, everything is measured in inches or centimeters. But in form everything is measured in pixels. A system of coordinates determines where each pixel is located, with the X coordinate measuring left to right and the Y coordinate measuring top to bottom.
In every form the coordinates start from upper-left corner of the form. If you want to draw single dot 10 pixels from the left and 10 pixels down, you would express the X and Y coordinates as 10, 10.
The graphics offerings in Windows Forms fall into the following three broad categories:
- Two-dimensional (2-D) vector graphics
- Imaging
- Typography
2-D Vector Graphics
Two-dimensional vector graphics are primitives; such as lines, curves, and figures; that are specified by sets of points on a coordinate system. For example, a straight line is specified by its two endpoints, and a rectangle is specified by a point giving the location of its upper-left corner and a pair of numbers giving its width and height. A simple path is specified by an array of points that are connected by straight lines. To draw anything we need to specify some coordinates in pixels.
Imaging
Certain kinds of pictures are difficult or impossible to display with the techniques of vector graphics. For example, the pictures on toolbar buttons and the pictures that appear as icons are difficult to specify as collections of lines and curves. A high-resolution digital photograph of a crowded baseball stadium is even more difficult to create with vector techniques. Images of this type are stored as bitmaps, which are arrays of numbers that represent the colors of individual dots on the screen. GDI+ provides the Bitmap class for displaying, manipulating, and saving bitmaps.
Typography
Typography is the display of text in a variety of fonts, sizes, and styles. GDI+ provides extensive support for this complex task. One of the new features in GDI+ is sub pixel antialiasing, which gives text rendered on an LCD screen a smoother appearance.
Pen
Defines an object used to draw lines and curves. A Pen object draws a line of specified width and style. Use the Dash Style property to draw several varieties of dashed lines.
Pen pen =
new Pen(Color.Blue);
pen.DashStyle = DashStyle.DashDotDot;
The fill style depends on brush or texture that is used as the fill object.
SolidBrush brush =
new SolidBrush(Color.Red);
Pen pen = new Pen (brush,4);
The line drawn by a Pen object can be filled in a variety of fill styles, including solid colors and textures.
Pen pen =
new Pen(brush,4);
pen.PenType = PenType.PathGradient;
A Pen object has a width. The center point of this pen width is aligned relative to the line being drawn depending on the alignment value. A Pen object can be positioned to draw inside of a line or centered over the line. You can use members such as Center, Inset, Outset, Left and Right to specify the position of the pen.
pen.Alignment = PenAlignment.Center;
To specify the style of a line drawn by pen, we can use PenType enumeration. Different enumerations are HatchFill, LinearGradient, PathGradient, SolidColor and TextureFill.
pen.PenType = PenType.PathGradient;
Brush
Brush class is used to fill the interiors of graphical shapes such as rectangles, circles, polygons, ellipses etc. We can't use this class directly i.e. this class cannot be instantiated. To create a object Brush, use classes such as SolidBrush, TextureBrush and LinearGradientBrush.
SolidBrush : Defines a brush of a single color.
SolidBrush myBrush =
new SolidBrush(Color.Brown);
TextureBrush: This uses an image to fill the interior shape.
private Brush txtBrush
Image imgTxt = new Bitmap(@"C:\filename.bmp");
txtBrush = new TextureBrush(imgTxt);
LinearGradientBrush: Uses linear gradient. This class encapsulates both two-color gradients and custom multicolor gradients. All linear gradients are defined along a line specified either by the width of a rectangle or by two points.
Point p1 =
new Point(50,50);
Point p2 = new Point(100,100);
LinearGradientBrush lnBrush = new LinearGradientBrush (p1,p2,Color.Red,Color.Yellow);
Rectangle rect =
new Rectangle(50,50,100,100);
LinearGradientBrush lnBrush = new LinearGradientBrush (rect,Color.Red,Color.Yellow,LinearGradientMode.ForwardDiagonal);
PathGradientBrush: The PathGradientBrush class allows you to customize the way you fill a shape with gradually changing colors. For example, you can specify one color for the center of a path and another color for the boundary of a path. You can also specify separate colors for each of several points along the boundary of a path.
GraphicsPath path =
new GraphicsPath();
path.AddEllipse(0, 0, 140, 70);
// Use the path to construct a brush.
PathGradientBrush pthGrBrush = new PathGradientBrush(path);
// Set the color at the center of the path to blue.
pthGrBrush.CenterColor = Color.FromArgb(255, 0, 0, 255);
// Set the color along the entire boundary
// of the path to aqua.
Color[] colors = {Color.FromArgb(255, 0, 255, 255)};
pthGrBrush.SurroundColors = colors;
e.Graphics.FillEllipse(pthGrBrush, 0, 0, 140, 70);
HatchBrush: Defines a rectangular brush with a hatch style, a foreground color, and a background color.
Brush br = new HatchBrush (HatchStyle.HorizontalBrick,Color.Red,Color.Yellow);
Hatchstyle: Specifies the different patterns available for HatchBrush objects.
Color
Colors in GDI are represented by instances of the System.Drawing.Color structure. You can use system defined colors (Named Colors) or you can mention the Alpha, Red, Green and Blue (ARGB) combination. To get the general system colors, you can use SystemColors class.
Color redColor = Color.Red;
///Named Colors
Color rgbColor = Color.FromArgb(26,22,45,66);
Drawing Shapes and Lines
System.Drawing.Graphics has a large number of methods allow you to draw various lines, outline shapes, etc. Let us work with few of them.
DrawLine: Draws a line connecting the two points specified by coordinate pairs.
Pen blackPen =
new Pen(Color.Black, 3);
e.Graphics.DrawLine(blackPen, 100.0F,100.0F, 500.0F, 100.0F);
DrawRectangle: Draws a rectangle specified by a rectangle structure.
Pen blackPen = new Pen(Color.Black, 3);
/// Creats a rectangle with parameters as Start X, Start Y, Width, Height.
Rectangle rect = new Rectangle( 0, 0, 200, 200);
e.Graphics.DrawRectangle(blackPen, rect);
DrawArc: Draws an arc representing a portion of an ellipse specified by a Rectangle structure.
Pen blackPen =
new Pen (Color.Black, 3);
/// Creats a rectangle with parameters as Start X, Start Y, Width, Height.
Rectangle rect = new Rectangle (0, 0, 200, 200);
///Draws an arc by accepting parameters such as pen, rectangle, start angle, sweep angle.
e.Graphics.DrawArc(blackPen, rect, 30, 40);
DrawEllipse: Draws an ellipse specified by a bounding rectangle structure.
Pen blackPen =
new Pen(Color.Black, 3);
/// Creates a rectangle with parameters as X Position, Y Position, Width, Height.
Rectangle rect = new Rectangle( 0, 0, 200, 200);
e.Graphics.DrawEllipse(blackPen, rect);
DrawBezier: Draws a bezier spline defined by four Point structures.
Point p1 =
new Point(10, 100); // Start point
Point p2 = new Point(100, 10); // First control point
Point p3 = new Point(150, 150); // Second control point
Point p4 = new Point(200, 100); // End point
Pen pen = new Pen(Color.Black);
e.Graphics.DrawBezier(pen, p1, p2, p3, p4);
DrawString: Draws the specified text string in the specified rectangle or location with the specified Brush object and Font object using the formatting attributes of the specified StringFormat object.
StringFormat encapsulates text layout information (such as alignment and line spacing) and display manipulations. To align the text at the centre we can set the Alignment property of StringFormat to Center. To print the string in a vertical position, we can use StringFormatFlags enumerator.
System.Drawing.StringFormat drawFormat =
new System.Drawing.StringFormat (StringFormatFlags.DirectionVertical);
drawFormat.Alignment = StringAlignment.Center;
e.Graphics.DrawString("Test",new Font("Arial",7),brush,100,100, drawFormat);
FillRectangle: Fills the interior of a rectangle specified by a rectangle structure.
FillEllipse: Fills the interior of an ellipse defined by a bounding rectangle specified by a pair of coordinates, a width and a height.
DrawImage: Draws the specified portion of the Image object at the specified location at the specified image.
Image myImg;
myImg = Image.FromFile("c:\\face.jpeg");
e.Graphics.DrawImage(myImg,rect);
GraphicsPath: Represents a series of connected lines and curves. We can use this to change the shape of the form/control. We can use various methods (such as AddEllipse, AddCurve, AddLines, AddPath etc to set the shape of the form. This is a part of System.Drawing.Drawing2D namespace.
Region: Gets or sets the window region associated with the control.
System.Drawing.Drawing2D.GraphicsPath path =
new System.Drawing.Drawing2D.GraphicsPath();
path.AddEllipse(10,10, this.Width - 20, this.Height - 20);
this.Region = new System.Drawing.Region(path);
Graphics.Save Method
Saves the current state of the Graphics object and identifies the saved state with a GraphicsState object. When you call the Save method of a Graphics object, an information block that holds the state of the Graphics object is put on a stack. The Save method returns a GraphicsState object that identifies that information block. When you pass the identifying GraphicsState object to the Graphics.Restore method, the information block is removed from the stack and is used to restore the Graphics object to the state it was in at the time of the Save method call.
AntiAliasing
Using SmoothingMode of Drawing object we can specify whether we can apply antialiasing to the lines and curves and edges of filled areas. You can have various enumeration in SmoothingMode are AntiAlias, HighQuality, Default, HighSpeed, Invalid and None. This is a part of System.Drawing.Drawing2D namespace.
e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
ResetClip Method
Resets the clip region of the Graphics object to an infinite region.
Matrix Class
Encapsulates a 3-by-3 matrix that represents a Geometric transform. This is a part of System.Drawing.Drawing2D namespace. MatrixOrder can be used to specify the order for matrix transform operations. MatrixOrder gives options such as Append and Prepend. Append means old operation is applied before the new operation. Prepend means new operation is applied before old operation.
Matrix myMatrix =
new Matrix();
myMatrix.Shear(5, 5,MatrixOrder.Prepend);
e.Graphics.DrawRectangle(new Pen(Color.Green), 0, 0, 100, 50);
e.Graphics.MultiplyTransform(myMatrix);
e.Graphics.DrawRectangle(new Pen(Color.Red), 0, 0, 100, 50);
e.Graphics.DrawEllipse(new Pen(Color.Blue), 0, 0, 100, 50);
Creating a button with different shape and style
You can create a button which is different from normal non-rectangular button. Using UserControl and overriding OnPaint method, we can change the shape and style of the button.
In the OnPaint method we can use FillRectangle, FillEllipse, DrawEllipse etc to set the shape and to make style we can use Brush with HatchStyle and different background and foreground color. You need to create different usercontrol class to get different shape.
public class myControl : UserControl
{
protected override void OnPaint(PaintEventArgs e)
{
Graphics graphics = e.Graphics;
Pen myPen = new Pen(Color.Black);
Brush myBrush = new HatchBrush (HatchStyle.DottedDiamond ,Color.RosyBrown ,Color.Brown );
SolidBrush textBrush = new SolidBrush(Color.Yellow);
// Draw the button in the form of a rectangle
graphics.FillRectangle(myBrush,0, 0, 180, 45);
graphics.DrawString("Display Drawings",new Font ("Verdana",11), textBrush,10,10);
myPen.Dispose();
}
}
You can use the above control by declaring as
private
myControl btnDraw = new myControl();
Figure 1: Changing the shape and size of the button like usercontrol.
Change the shape of the Windows Form
Using GraphicsPath and Region, you can change the shape of the form. Create a GraphicsPath object and add your shape to the GraphicsPath object.
Image myImg;
myImg = Image.FromFile("c:\\mickey2.jpe");
e.Graphics.DrawImage(myImg,OuterRect);
//Creating the GraphicsPath object
System.Drawing.Drawing2D.GraphicsPath shape = new System.Drawing.Drawing2D.GraphicsPath();
// To get the shape of the Face
shape.AddEllipse(142,210,217,208);
// To get the shape of the left ear
shape.AddEllipse(110,170,80,78);
// To get the shape of the right ear
shape.AddEllipse(305,164,80,78);
// Set the region to the shape (GraphicsPath)
this.Region = new System.Drawing.Region(shape);
Figure 2: Changing the shape of the Form
Printing Class
Printing text and graphics is one of the very important and critical tasks in developing Windows application. Even though .Net provides some classes, still we need to write some code in cases like allow the user to set the printer and page to print etc.
The System.Drawing.Printing provides print-related services. To print a document/drawing, you need to create a instance of the PrintDocument class, set the properties and call the Print method to print it.
The main classes used in printing class:
- System.Drawing.Printing.PrintDocument: Defines a reusable object that sends output to a printer.
- System.Windows.Forms.PrintPreviewDialog: Represents a dialog box that contains a System.Windows.Forms.PrintPreviewControl.
- System.Windows.Forms.PrintDialog: Allows user to select a printer and choose which portions of document to print.
PrintDocument
It defines a reusable object that sends output to a printer. Steps to work with PrintDocument:
- Create an instance of the PrintDocument class.
///To initialize the PrintDocument.
PrintDocument printDocument = new PrintDocument();
-
Handle the "PrintPage" event where you specify the output to print, by using "Graphics" object included in the PrintPageEventArgs.
///Handling the PrintPageEvent.
printDocument.PrintPage += new PrintPageEventHandler(this.printDocument_PrintPage);
-
Set the properties and describe how to print.
///An event which prints a Line.
private void printDocument_PrintPage(object sender, PrintPageEventArgs e)
{
Pen blackPen = new Pen(Color.Black, 3);
e.Graphics.DrawLine(blackPen, 100.0F,100.0F, 500.0F, 100.0F);
}
-
Call the Print method to start the process.
///Print the document.
printDocument.Print();
PrintPreviewDialog
This class represents a dialog box form that contains a PrintPreviewControl. Before printing it to the actual printer, user might want to have a look at the preview of the print. Using PrintPreviewDialog class user can see the preview before printing.
When you create an instance of PrintPreviewDialog, the Document property is initialized to a null reference. You can change the value for this property at run time. Using ShowDialog() method you can initiate the print preview dialog box.
PrintPreviewDialog dlgPrintPvw =
new PrintPreviewDialog();
dlgPrintPvw.Document = printDocument;
dlgPrintPvw.ShowDialog();
PrintDialog
The Windows Forms PrintDialog component is a pre-configured dialog box used to select a printer, choose the pages to print, and determine other print-related settings in Windows applications.
Use the ShowDialog method to display the dialog at run time. This component has properties that relate to either a single print job (PrintDocument class) or the settings of an individual printer (PrinterSettings class).
PrintDialog printDialog =
new PrintDialog();
printDialog.Document = printDocument;
DialogResult dlgResult = printDialog.ShowDialog();
if (dlgResult == DialogResult.OK)
{
printDocument.Print();
}
With the help of PageSettings class we can specify the settings that can be applied to a single, printed page. Using this we can modify the way it is printed. To specify settings on a page-by-page basis, handle the PrintDocument.PrintPage or PrintDocument.QueryPageSettings event and modify the PageSettings argument included in the PrintPageEventArgs or QueryPageSettingsEventArgs, respectively.
To get or set the details of Printer, we can use PrintDocument.PrinterSettings Property. Using this we can specify several printer settings. Moreover, we can set number of copies to be printed, specify the printer name, and specify the range of pages to print.
Conclusion
This article gives the basic idea to use various methods in Drawing class. The source code contains two forms. First form explains how to use image and how to change the shape of the form. Second form tells how to use various methods such as DrawLine, FillRectangle and DrawBezier using Brush and Pen. PrintPreview and Printing options are available in both the forms.