Recipe 9.8. Drawing Lines One Pixel Wide Regardless of Scaling


Problem

You need to draw a one- pixel-wide line, but this becomes problematic when the graphics scaling mode is changed.

Solution

Sample 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.

Discussion

The 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





Visual Basic 2005 Cookbook(c) Solutions for VB 2005 Programmers
Visual Basic 2005 Cookbook: Solutions for VB 2005 Programmers (Cookbooks (OReilly))
ISBN: 0596101775
EAN: 2147483647
Year: 2006
Pages: 400

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net