As mentioned, pens are used with the Graphics class to draw lines and other figures. In the examples earlier in this chapter, the SystemPens class has been used to obtain references to Pen objects initialized with the same color as client window text. In this section, we’ll examine the SystemPens class more closely and you’ll learn how to use the Pens class and the Pen class directly to create Pen objects in a variety of styles and colors.
Just like the SystemBrushes class discussed earlier in this chapter, the SystemPens class is used to create pens that match user interface components and system colors. The static properties exposed by the SystemPens class each return a reference to a shared Pen object. In earlier examples, Pen objects were created that were compatible with the window text color selected by the user. You can also create Pen objects that follow other user preferences, as shown here:
Pen highlightPen = SystemPens.HighlightText;
This example creates a Pen object that’s initialized to the user’s preferred color for highlighted text. A complete list of the static SystemPens properties used to create pens based on user preferences is provided in Table 14-7.
The properties in Table 14-7 are similar to the properties exposed by the SystemBrushes class listed in Table 14-4. They differ because pens and brushes typically are used to draw with different color schemes. Pens are often used to draw lines and shadow effects, whereas brushes are often used to fill areas with a color or a pattern. For example, there’s no Window property for the SystemPens class because pens aren’t frequently used to draw in colors that match the client area. As with the SystemBrushes class, the SystemPens class can be used to create pens based on a Color value passed as a parameter to the SystemPens.FromSystemColor method, as shown here:
Pen clientAreaPen = SystemPens.FromSystemColor(SystemColors.Window);
All the Pen references you’ll get from the SystemPens class (as well as from the Pens class, which we’ll get to shortly) have an initial width of 1 pixel. You don’t own the Pen objects, so you can’t modify them. If you need alternative widths or styles, you’ll need to create your pens using the Pen class, which will be discussed in the next section.
An alternative to passing a named color to the SystemPens class is to use the Pens class. The Pens class is organized much like the SystemPens class in that it exposes a large number of static methods that are used to create Pen objects. For example, to create a red pen, you call the static Pens.Red method, like this:
Pen warningPen = Pens.Red;
All told, there are 141 static methods in the Pens class, so again there isn’t space to list them all here. The Pens class follows the same naming convention as the Color and Brushes classes, however, so if you know the named color, you can create your Pen object directly, without extracting the color first.
The objective behind using the SystemPens and Pens classes is to obtain a reference to a Pen object. Up to now, you’ve seen the Pen class used to draw lines and figures; in this section, we’ll examine the various methods and properties exposed by the Pen class that enable you to manage the characteristics of the lines drawn using a Pen object.
In addition to using the SystemPens and Pens classes to fetch references to Pen objects, you can also create them using the Pen class directly. There are four constructors used to create Pen objects. These constructors enable you to specify a color or a brush that will be used to define the pattern drawn by the pen, as well as an optional width. The first constructor is used to create a pen of a specific color with an initial width of 1 pixel, as shown here:
Pen clearBluePen = new Pen(Color.FromArgb(40, 50, 50, 255));
You can also specify the width when constructing a Pen object with a Color value, as shown here:
Pen clearBluePen = new Pen(Color.FromArgb(40, 50, 50, 255), 20.0f);
Alternatively, you can use a Brush object to supply a pattern for your new Pen, using code such as this:
HatchBrush _horizontalBrickBrush = null; HatchBrush _diagonalBrickBrush = null; Pen _diagonalThinBricks = null; Pen _horizontalThinBricks = null; public MainForm() { _horizontalBrickBrush = new HatchBrush(HatchStyle.HorizontalBrick, Color.Gray, Color.Firebrick); _diagonalBrickBrush = new HatchBrush(HatchStyle.DiagonalBrick, Color.Gray, Color.Firebrick); _diagonalThinBricks = new Pen(_diagonalBrickBrush); _horizontalThinBricks = new Pen(_horizontalBrickBrush); }
This code creates instances of HatchBrush with the DiagonalBrick and HorizontalBrick hatch styles and then uses the brushes to create two pens that are each 1 pixel wide. Because the width of the pens is much smaller than the brick pattern, the lines drawn with these pens will have a striped appearance. The fourth version of the Pen constructor enables you to specify a width for the pen that makes the brick pattern more apparent, as shown here:
Pen_diagonalThickBricks = new Pen(_diagonalBrickBrush, 10.0f); Pen_horizontalThickBricks = new Pen(_horizontalBrickBrush, 10.0f);
Figure 14-12 shows an example using these Pen objects to draw figures in a Windows Form client area.
The Pen class exposes styles as properties that can be changed dynamically without having to re-create the Pen object each time a property needs to be altered. The most commonly used properties from the Pen class are as follows:
Alignment Specifies the position of the drawn line in relation to the curve or figure coordinates.
Brush Specifies a brush used to provide the pattern and color for this pen.
Color Specifies a color used for this pen.
EndCap Specifies the shape rendered at the end of the line or curve, using a value from the LineCap enumeration. The default value is LineCap.Flat.
LineJoin Specifies how sequences of lines are joined, using a value from the LineJoin enumeration.
MiterLimit Specifies the maximum permitted ratio between line width and miter thickness before clipping occurs. This property applies only if the LineJoin property is set to LineJoin.MiterClipped. The default value is 10.0f.
PenType Returns a value from the PenType enumeration that describes the Pen object.
StartCap Specifies the shape rendered at the start of the line, using a value from the LineCap enumeration. The default value is LineCap.Flat.
Width Specifies the width of the line drawn with the pen.
The Alignment property specifies how screen real estate is consumed by a line drawn with the pen. The default value of PenAlignment.Center draws the line centered over the line boundary. A value of PenAlignment.Inset draws the line inside the line that forms the boundary of a curve or a figure.
The LineCap enumeration is used by the StartCap and EndCap properties to draw the ends of each line. Some values in the LineCap enumeration include Anchor in their name, which indicates that the LineCap style draws an anchored end for the line. Anchor values cause the line end to be drawn wider than the line’s width. This type of LineCap style is useful when you want to emphasize the endpoints of the line. To determine whether a LineCap style is one of the anchor values, you can use AnchorMask, a value from the LineCap enumeration, as shown here:
if((clearBluePen.EndCap & LineCap.AnchorMask) > 0) { // EndCap has one of the anchor styles. }
As mentioned, the LineCap enumeration is used to specify how the ends of each line are drawn. The LineCap enumeration values are provided in Table 14-8.
Value |
Description |
AnchorMask |
A mask value used to test whether a LineCap value specifies an anchor cap. |
ArrowAnchor |
An arrow-shaped anchor is drawn for the line cap. |
Custom |
A custom end cap specified by the application is drawn. |
DiamondAnchor |
A diamond-shaped anchor is drawn for the line cap. |
Flat |
The default value; no cap is drawn. |
NoAnchor |
Same as LineCap.Flat; no anchor is drawn. |
Round |
A round line cap is drawn. |
RoundAnchor |
A large round line cap is drawn. |
Square |
A square line cap is drawn. |
SquareAnchor |
A large square anchor line cap is drawn. |
Triangle |
A triangle-shaped line cap is drawn. |
The LineJoin property uses the values from the LineJoin enumeration to control how line endpoints are joined together when drawing figures with methods such as DrawPolygon or when several lines are drawn with a single call to the DrawLines method. This property isn’t used when you’re drawing multiple lines by making multiple calls to the DrawLine method. The LineJoin enumeration values are provided in Table 14-9.
Value |
Description |
Bevel |
The lines are joined in a beveled edge. |
Miter |
The lines are joined as if mitered, with the outside edges of the lines extended until they meet. |
MiterClipped |
The lines are extended just like the LineJoin.Miter style, except that the length of the mitered join is subject to clipping if it extends past the length allowed by the Pen object’s MiterLimit property. |
Round |
The lines are joined with a rounded corner. |
The PenType property returns a value from the PenType enumeration that describes how the Pen object determines its color or pattern. This read-only value contains information about the underlying brush or color that the Pen object is currently using. The PenType enumeration values are listed in Table 14-10.
Value |
Description |
HatchFill |
The pen uses a hatch brush. |
LinearGradient |
The pen uses a linear gradient brush. |
PathGradient |
The pen uses a path gradient brush. |
SolidColor |
The pen uses a color or a SolidBrush object. |
TextureFill |
The pen uses a texture brush. |
The Pen class can be used to create pens that will draw dashed lines. There are three properties that are used to control how dashes are drawn.
DashOffset Specifies the distance from the start of the line to the start of the dash pattern
DashStyle Specifies the pattern of the dashes, using a value from the DashStyle enumeration
DashPattern Specifies an array of floating-point values that define a pattern of dots and dashes used when the DashStyle property is set to DashPattern.Custom
The DashStyle property uses values from the DashStyle enumeration to select from among predefined dash styles or to specify that a custom dash pattern is to be used. The DashStyle enumeration values are provided in Table 14-11.
The DashPattern property accepts an array of floating-point values, with each element alternatively specifying the length of each dash and space, like this:
clearBluePen.DashStyle = DashStyle.Custom; clearBluePen.DashPattern = new float [] { 0.5f, 0.3f, 1.0f, 0.5f };
The values passed to the DashPattern property are multiplied by the pen’s width to determine the actual spacing of dashes and spaces.