A Graphics Drawing Tool by using C# and Winforms
Introduction
This is a drawing tool I developed at spare time, it can draw rectangle,circle, and other shapes, you can also move, resize, even rotate some of the shapes. It will be useful start point of a compliated graphics project.
Background
To fulled undertand this code, user has to understand some of the C# concepts, reflection, interfaces, inheritance, etc. There is another version of this drawing tool by using WPF, you can find it on http://www.codeproject.com/KB/cs/GraphicsDrawingToolWPF.aspx
Using the code
I have defined several basic shapes, the LeShape is basic class, in order to serialize the shapes I have created, I have redefined LeColor structure, like following:
public struct LeColor { public int A; public int R; public int G; public int B; public LeColor(Color color) { this.A = color.A; this.R = color.R; this.G = color.G; this.B = color.B; } public static LeColor FromColor(Color color) { return new LeColor(color); } public Color ToColor() { return Color.FromArgb(A, R, G, B); } }
As we can't serialize C# Font and Color class to XML, therefore I created their equivalent structures and used them everywhere.
This drawing tool's basic class is LeShape:
public abstract class LeShape : IShape { private bool showBorder = true; public bool ShowBorder { get { return showBorder; } set { showBorder = value; LeCanvas.self.Canvas.Invalidate(); } } private LeColor borderColor = new LeColor(Color.Black); public LeColor LeBorderColor { get { return borderColor; } set { borderColor = value; LeCanvas.self.Canvas.Invalidate(); } } [XmlIgnore] public Color BorderColor { get { return LeBorderColor.ToColor(); } set { LeBorderColor = new LeColor(value); } } private int borderWidth = 1; public int BorderWidth { get { return borderWidth; } set { borderWidth = value; LeCanvas.self.Canvas.Invalidate(); } } private Rectangle bounds; [XmlIgnore] public Rectangle Boundary { set { bounds = value; Rect =new LeRect(value); } get { return bounds; } } ... public LeShape() { path = new GraphicsPath(); objectsInPath = new ArrayList(); }
As you can see, this LeShape class is abstract class, as we don't want user instantialize it at any time. Instead we create ZoneShape, Rectangle shape classes based on this LeShape, then we instantialize them, it makes more sense.
In order to let user move, resize shapes, I made another class BoundaryShape, it inherit from LeShape, which contains all the properties, while this BoundaryShape only handle user's mouse movement, and it won't be serialized to xml file.
Basically all the shapes will be inherited from BoundaryShape, and BoundaryShape inherited from LeShape.
public class RoundRectShape : BoundaryShape { private int radius = 10;
We can have corner radius shape, by default radius is 10 px.
We used following paint method draw this cornered Rectangle shape.
public override void Paint(object sender, Graphics g) { Point[] pt = new Point[8]; path = new GraphicsPath(); path.AddLine(pt[4], pt[5]); path.AddArc(new Rectangle(pt[6], new Size(radius, radius)), 90, 90); path.AddLine(pt[6], pt[7]); if (path != null) { g.FillPath(new System.Drawing.Drawing2D.LinearGradientBrush( Boundary, FromColor, ToColor, LightAngle), path); } }
This paint method has a copy in BoundaryShape, we don't want to use it, therefore we put override as modifier.
You will also see the LeShape implemented IShape interface.
I made LeShape's IShape implementation virtual method. Then at its inherited classes selectively rewrite these virtual methods.
ZoneShape has a text field, the idea is when ZoneShape moves, text field moves as well. This is achieved when user has finished move zoneshape, then raise a event at BoundaryShape, ZoneShape accept this event then process this event, move the text field parameters.
User's mouse movement was handled by LeCanvas class, LeCanvas class then pass this event to all its on screen shapes. Each shape then decide its actions. Either it's a drawing start, or move a shape or resize a shape.
.
Points of Interest
Did you learn anything interesting/fun/annoying while writing the code? Did you do anything particularly clever or wild or zany?
History
In oder to contribute to the computer world, which I always enjoyed to learn from others, or for others maybe think of my work is useful.
发表评论
7lekOa I truly appreciate this blog.Much thanks again. Awesome.
3Gos9w Very good article post.Much thanks again. Awesome.
5ivr1M This is one awesome article.Really thank you! Keep writing.
2Qq2WS Fantastic blog post.Really looking forward to read more. Really Cool.
bIUxAW Awesome blog article. Really Great.