f you read my DevX article "Beautify Your UIs with Perfect Pen and Brush Control
," then you know all about how to draw lines that are thick or thin; dashed, striped, or solid; beveled, mitered, or rounded; and that have standard or customized end caps. You also know how to fill areas with solid colors, hatch patterns, linear color gradients, and path color gradients.
The Pen and Brush objects that you use to draw and fill these kinds of objects correspond fairly directly to the pens and brushes that you would use to draw on a piece of paper or paint on a canvas. They allow you to produce remarkable results such as text that shades from one color to another and lines with customized arrows at their end points.
While most developers understand the connection between Pens and Brushes and pens and brushes, they don't realize there are also ways to affect the paper and canvas. Transformations allow you to move, rotate, and stretch the canvas.
Actually, you can use transformations to control each drawing operation that you perform, so you can apply different transformations to different parts of the drawing. It's as if you can make a pile of transparent canvasesall moved, rotated, and stretched in any way you like.
While this may sound a bit abstract (in fact, it would be an interesting way to make an abstract painting), transformations have some very practical applications. For example, suppose you write a bunch of code that draws a graph and a pie chart. Then you discover that you need to add some text and numbers to the form and when you do so, the picture is too big. Given enough time and caffeine, you could rewrite all of your code to make the new text fit.
But then suppose you learn that you need to put the same drawing in a printed document. The printer's page doesn't have the same size and resolution as a form on the screen so you'll need to reformat the results to fit better. You may also need to move the drawing so you can add more text to fill the page.
Transformations can simplify all of this extra work. By using a relatively simple transformation, you can easily move, stretch, and rotate the original image to make room for more text or to resize it to fit on a printed page.
This article explains how basic transformations work. It then shows how you can use them to display graphics in an area normally, centered, or sized to fit the area.
GDI+ graphics represents a transformation using a 3-by-3 matrix. I won't bore you with the details of exactly what values are in the matrix's nine entries because you probably won't find it all that interesting. (Unless you're a math major like I was. In that case, you may find it quite interesting to see how the entries represent translation, scaling, and rotation. You can learn the details in my book Visual Basic Graphics Programming
or in any other good graphics programming book.)
The Graphics object provides three methods for adding transformations to the output: TranslateTransform
, and RotateTransform
The Graphics object's TranslateTransform
method takes two parameters that specify the amount by which you want to translate the resulting drawing in the X and Y directions. For example, the following code executes in a Paint
event handler. It uses the Graphics object's DrawRectangle
method to draw a red 200 x 100
It then adds a transformation to the Graphics object to move future drawing 30 pixels to the right (in the X direction) and 50
pixels down (in the Y direction). It finishes by drawing the exact same rectangle, although this time in green:
|Figure 1. TranslateTransform Results: The TranslateTransform method moves a drawing:|
e.Graphics.DrawRectangle(Pens.Red, 10, 10, 200, 100)
e.Graphics.DrawRectangle(Pens.Green, 10, 10, 200, 100)
The output of the program TranslateRectangle
(available for download
in both Visual Basic and C# versions) in Figure 1
shows the result. Notice that the green rectangle is the same size as the red one, just moved down and to the right. (This program and the others shown in this article are available for download in Visual Basic and C# versions.)
The Graphics object's ScaleTransform
method takes two parameters that tell how much future drawing operations should be stretched in the X and Y directions. The following Paint
event handler code draws a red square. It then uses ScaleTransform
to make future drawing stretch horizontally by a factor of 1.5 and vertically by a factor of 3. It finishes by drawing the same square again, this time in green:
|Figure 2. ScaleTransform Results: The ScaleTransform method stretches a drawing vertically and horizontally:|
e.Graphics.DrawRectangle(Pens.Red, 10, 10, 50, 50)
e.Graphics.DrawRectangle(Pens.Green, 10, 10, 50, 50)
shows the result. Because the call to ScaleTransform
used different arguments for the vertical and horizontal scale factors, the green rectangle is no longer a square.
Notice also that the green rectangle's upper left corner has moved. The X and Y coordinates of all of the rectangle's corners have been stretched by the scale factors so the upper left corner has moved from (10, 10) to (10 * 1.5, 10 * 3) = (15, 30).
Finally notice that even the green rectangle's pen has been scaled. The vertical lines are scaled by a factor of 1.5 so they look the same as before. The horizontal lines, however, are scaled by a factor of 3 so they are noticeably thicker than the original lines.
When you use big scale factors, the lines are scaled greatly and may look really ugly. To compensate, you can make a custom Pen with a really thin line (for example, a width of 0.05 if you are scaling by a factor of 20). Alternatively you can make a Pen with line width 0, which GDI+ always draws one pixel wide, even when it is scaled.
You can use negative scale factors in the call to ScaleTransform
. The following code scales the drawing's X coordinate by a factor of -1. That's the same as flipping the result horizontally around the Y-axis and is exactly what you'd get if you held the drawing up to a mirror: