ProblemYou need to draw a one- pixel-wide line, but this becomes problematic when the graphics scaling mode is changed. SolutionSample code folder: Chapter 09\ PenWidth Set the pen's width to -1. Although this approach is not formally documented in the GDI+ references, it does cause the thinnest line possible to be drawn no matter what the scaling is set to. DiscussionThe Graphics object's PageUnit property allows you to set the scaling to standard units such as inches or millimeters. This can be very handy for some types of graphics-drawing tasks, but it alters the way lines are drawn. The DrawLine() method accepts a pen that defines the color and width of the drawn line. By default the pen's width is always set to 1 unit wide, and as long as the PageUnit is left at its default setting of Pixels, all is well: a 1-unit-wide line will be drawn as 1 pixel wide. However, when PageUnit is set to Inches, for example, a 1-unit-wide line is rendered as 1 inch wide, which is likely not what you want at all. To demonstrate this in action, and to show the workaround, this recipe's code first draws a line diagonally across the form with a red pen set to a width of 1, then draws another line on the other diagonal using a green pen set to a width of -1. Create a new Windows Forms application, and place three RadioButton controls on the form, named UsePixels, UseMillimeters, and UseInches. Set their Text properties appropriately. Then add the following code to the form's code template: Private Sub RadioButton_CheckedChanged( _ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles UsePixels.CheckedChanged, _ UseMillimeters.CheckedChanged, _ UseInches.CheckedChanged ' ----- Change the scaling system. Me.Refresh() End Sub Private Sub Form1_Paint(ByVal sender As Object, _ ByVal e As System.Windows.Forms.PaintEventArgs) _ Handles Me.Paint ' ----- Draw contrasting lines. Dim xCorner As Single Dim yCorner As Single Dim canvas As Graphics canvas = e.Graphics xCorner = Me.ClientSize.Width yCorner = Me.ClientSize.Height If (UseMillimeters.Checked = True) Then canvas.PageUnit = GraphicsUnit.Millimeter xCorner /= canvas.DpiX yCorner /= canvas.DpiY xCorner *= 25.4 yCorner *= 25.4 ElseIf (UseInches.Checked = True) Then canvas.PageUnit = GraphicsUnit.Inch xCorner /= canvas.DpiX yCorner /= canvas.DpiY Else canvas.PageUnit = GraphicsUnit.Pixel End If ' ----- Clear any previous lines. canvas.Clear(Me.BackColor) ' ----- Draw a one-unit line. canvas.DrawLine(New Pen(Color.Red, 1), 0, 0, _ xCorner, yCorner) ' ----- Draw a one-pixel line. canvas.DrawLine(New Pen(Color.Green, -1), xCorner, _ 0, 0, yCorner) End Sub As this code shows, the graphics PageUnit property is set appropriately for these units, and the red line will show the obvious difference in the line width. Figure 9-12 shows the results when the red line is drawn 1 inch wide (it's black and white here, obviously, but imagine it's red). The green line is drawn 1 pixel wide, no matter which scaling mode is selected. In addition to the PageUnit mode, the ScaleTransform() method can customize the scaling of your graphics. This transform affects all coordinates, and all pen widths too; a pen width of 1 draws a 1-unit-wide line at whatever scale is set. Again, the workaround is to set the pen's width to 1 to get a consistent 1- pixel-wide line. Figure 9-12. A one-inch-wide line and a one-pixel-wide line |