I don't know if you've ever had to draw your own shapes before WPF, but
if not, I can tell you it used to be a lot harder. You don't have to
override the OnPaint function or listen for the Paint event anymore. You
simply create a shape as if it were any other object and position it
where you want it. WPF takes care of everything else.
In order to play around with XAML and WPF, you should probably pick up a
copy of either Visual Studio 2008 or Expression Blend 2. You can
download any of the free Express Editions of Visual Studio right here.
Let's start out with an easy example to get warmed up. One of my
favorite games is Tetris, so here's a Tetris shape.
Here's all the code required to make the above application.
<Window x:Class="XAMLCustomShapes.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XAML Custom Shapes" Height="350" Width="350">
<Canvas>
<Path Canvas.Left="15" Canvas.Top="50" Stroke="Black"
Data="M 0,0 L 200,0 L 200,100 L 300,100 L 300,200 L 100,200 L 100,100 L 0,100 Z">
<Path.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="DarkBlue" />
<GradientStop Offset="1" Color="LightBlue" />
</LinearGradientBrush>
</Path.Fill>
</Path>
</Canvas>
</Window>
There's a lot of stuff here, but the only thing we care about is the
Path
object and its
Data
property. A Path has a lot of power when it comes to building custom
shapes and that's what I'll be using today to draw them.
The shape is defined by the text in the
Data
property. The syntax
might look a little weird, but once you get used to it you'll find it to
be a lot more efficient than previous methods. If you've drawn shapes
with other languages, you might be familiar with the functions named
something like lineTo
, moveTo
, arcTo
, etc. WPF replaced those
calls with one long string that contains special characters to represent
each function. In my example, "L" refers to lineTo
and "M" refers to
moveTo
. Below is an image that shows what each piece of the string
represent what piece of the shape.
As you can see, I started my shape with an "M 0,0". This places my pen
at the top-left corner of the shape. You can start the shape wherever
you like, but (0,0) worked well for my Tetris block. The next piece, "L
200,0", draws a line from my starting point, (0,0), to the point
specified after the "L", (200,0). When you draw a line the pen moves to
the new point, so any subsequent calls will start from the last
position. I simply continued using the "L" command to draw lines until
my shape was complete. The last character in my data string, "Z", tells
the path that the shape is finished.
There are a lot more commands other than "M", "L", and "Z". I'm not
going to describe all of them since MSDN has a nice article on PathMarkup Syntax
that describes them in detail.
All right, I think we've got straight lines under control. Let's look a
something a little more complicated - curves. WPF has lots of different
types of curves - Quadratic Bezier, Smooth cubic Bezier, Smooth
quadratic Bezier, and Elliptical Arc. Yep, I don't know what they are
either, but the msdn article I mentioned in the last paragraph does an
ok job of explaining them. If you really, really want to know more,
check out the Wikipedia article on BezierCurves.
Here's the same Tetris piece with some curves on the top and bottom. And
the code:
<Window x:Class="XAMLCustomShapes.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XAML Custom Shapes" Height="350" Width="350">
<Canvas>
<Path Canvas.Left="15" Canvas.Top="50" Stroke="Black"
Data="M 0,0 A 15,5 180 1 1 200,0 L 200,100 L 300,100
L 300,200 A 15,5 180 1 1 100,200 L 100,100 L 0,100 Z">
<Path.Fill>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
<GradientStop Offset="0" Color="DarkBlue" />
<GradientStop Offset="1" Color="LightBlue" />
</LinearGradientBrush>
</Path.Fill>
</Path>
</Canvas>
</Window>
For the curves, I used an EllipticalArc. Basically,
all an Elliptical Arc does is draw a curve between the current point and
the specified endpoint. The options for the arc are (in order in which
they appear in the string): ArcSize
(15, 5), RotationAngle
(180),
IsLargeArc
(1),
SweepDirection
(1), and the endpoint. The MSDN article on Elliptical Arc explains each
one of those properties, so I won't repeat them here. As you can see,
drawing curves is not that much different than drawing lines - there's
just a few more options.
I think that just about does it for custom shapes. Using straight lines
and the Elliptical Arc, you can make just about any imaginable shape. Of
course, there are lots of different path options you should definitely
explore to get your shapes exactly how you want them. Happy drawing.
Comments
Post a Comment