.
GDI+ FAQ
Skip Navigation LinksWelcome : GDI+ FAQ : Scaling the Pen object

Scaling the Pen object

GDI+ is resolution independent which can be a good thing but oftentimes confusing, especially in regard to getting a line of a specific width.

The current page-unit settings will affect the way a pen draws so that a pen of unit width will draw 1 pixel, 1 millimeter, 1 point, 1 inch or 1 300th of an inch thick lined depending on the way the Graphics object is set-up.

To ensure that the pen draws a specific thickness of line for example, is not always straightforward. There is a cheat that you can use, setting the line width to any negative value which works for single pixel lines but to get lines of a specific thickness, say 5 pixels, the only reliable method is to scale the pen. The examples below show the pen drawn with unit width and at several different page-unit settings.

Figure 1. A unit pen in several page-unit settings.

The code that produced this is shown below.

C#

      //create a unit pen.

      Pen p=new Pen(Color.Black,1.0f);

 

      e.Graphics.PageUnit=GraphicsUnit.Pixel;

      e.Graphics.DrawLine(p,10,10,300,10);

 

      e.Graphics.PageUnit=GraphicsUnit.Point;

      e.Graphics.DrawLine(p,10,72,300,72);

 

      e.Graphics.PageUnit=GraphicsUnit.Millimeter;

      e.Graphics.DrawLine(p,10,20,100,20);

 

      e.Graphics.PageUnit=GraphicsUnit.Inch;

      e.Graphics.DrawLine(p,0.25f,2,6,2);

 

VB

      'create a unit pen.

      Dim p As new Pen(Color.Black,1.0f)

 

      e.Graphics.PageUnit=GraphicsUnit.Pixel

      e.Graphics.DrawLine(p,10,10,300,10)

 

      e.Graphics.PageUnit=GraphicsUnit.Point

      e.Graphics.DrawLine(p,10,72,300,72)

 

      e.Graphics.PageUnit=GraphicsUnit.Millimeter

      e.Graphics.DrawLine(p,10,20,100,20)

 

      e.Graphics.PageUnit=GraphicsUnit.Inch

      e.Graphics.DrawLine(p,0.25f,2,6,2)

You can see that the same pen draws quite differently depending upon the graphics unit set. The pen is also affected by other graphical scaling operations as shown in figure 2.

Figure 2. Scaled and transformed graphics object.

C#

      Pen p=new Pen(Color.Black, 1.0f);

 

      e.Graphics.PageScale=5f;

      e.Graphics.DrawLine(p,10,10,100,10);

 

      e.Graphics.PageScale=0.5f;

      e.Graphics.DrawLine(p,10,10,100,10);

 

      //when the pen is set to the cheat value we get a 1 pixel line

      p.Width=-1;

      p.Color=Color.Blue;

 

      e.Graphics.PageScale=5f;

      e.Graphics.DrawLine(p,10,14,100,14);

 

      e.Graphics.PageScale=0.5f;

      e.Graphics.DrawLine(p,10,14,100,14);

 

      //even if we change the transform of the page.

      e.Graphics.PageScale=1f;

      e.Graphics.Transform=new Matrix(5,0,0,5,0,0);

 

      p.Color=Color.Red;

      e.Graphics.DrawLine(p,10,16,100,16);

 

VB

      Dim p As new Pen(Color.Black,1.0f)

 

      e.Graphics.PageScale=5f

      e.Graphics.DrawLine(p,10,10,100,10)

 

      e.Graphics.PageScale=0.5f

      e.Graphics.DrawLine(p,10,10,100,10)

 

      'when the pen is set to the cheat value we get a 1 pixel line

      p.Width=-1

      p.Color=Color.Blue

 

      e.Graphics.PageScale=5f

      e.Graphics.DrawLine(p,10,14,100,14)

 

      e.Graphics.PageScale=0.5f

      e.Graphics.DrawLine(p,10,14,100,14)

 

      'even if we change the transform of the page.

      e.Graphics.PageScale=1f

      e.Graphics.Transform=new Matrix(5,0,0,5,0,0)

 

      p.Color=Color.Red

      e.Graphics.DrawLine(p,10,16,100,16)

 

Getting a specific thickness of line is more tricky. Perhaps your CAD program needs to lay out in millimeters but display lines that are 3 pixels thick. To do this you can scale the pen using a value based upon the display DPI settings. Figure 3 shows a 1 inch square with 3 pixel thick lines.

Figure 3. Graphics unit in inches. Lines in pixels.

The code that generated this is shown in the following listings.

C#

      e.Graphics.PageUnit=GraphicsUnit.Inch;

      float dpix=e.Graphics.DpiX;

      float dpiy=e.Graphics.DpiY;

 

      Pen p=new Pen(Color.Black,3);

 

      Matrix mx=new Matrix(1f/dpix,0,0,1f/dpiy,0,0);

      p.Transform=mx;

 

      e.Graphics.DrawRectangle(p,0.5f,0.5f,1,1);

VB

      e.Graphics.PageUnit=GraphicsUnit.Inch

      Dim dpix As Single = e.Graphics.DpiX

      Dim dpix As Single = e.Graphics.DpiY

 

      Dim p As new Pen(Color.Black,3)

 

      Dim mx As new Matrix(1f/dpix,0,0,1f/dpiy,0,0)

      p.Transform=mx

 

      e.Graphics.DrawRectangle(p,0.5f,0.5f,1,1)

Scaling for effect.

The Pen can also be scaled to create visual effects such as the appearance of drawing with a calligraphy pen by scaling it to be larger in one direction than another. Figure 3 shows this effect in action.

Figure 3. Asymmetric scaling.

The code that produced the calligraphy-pen ellipse is shown below.

C#

      Pen p=new Pen(Color.Black,2f);

      Matrix mx=new Matrix(4,0,0,1,0,0);

      p.Transform=mx;

 

      e.Graphics.DrawEllipse(p,20,20,400,300);

VB

      Dim p As new Pen(Color.Black,2f)

      Dim mx As new Matrix(4,0,0,1,0,0)

      p.Transform=mx

 

      e.Graphics.DrawEllipse(p,20,20,400,300)

BUG WARNING.

There is a bug in the Pen object that prevents pens of size 1.5 and below scaling correctly. It is for this reason I'm sure that all the Microsoft examples pertaining to pen scaling all have a pen width of 2.

Return to the GDI+ FAQ.

Copyright � Bob Powell 2004. All rights reserved

Sponsored By
DaraizeTechnologies.com

&
Proteus Groupe

Bob Powell

Create your badge

Copyright © Bob Powell 2000-2012.  All rights reserved.