Results 1 to 16 of 16

Thread: Shape Editor, including many shapes, Resize and more

Threaded View

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Shape Editor, including many shapes, Resize and more

    -- Updated, see below! --


    Hi there,

    This is codebank submission loosely based on jmcilhinney's Manipulate GDI+ Drawings. It mimics a simple "Shape Editor" much like the Windows Forms Editor in Visual Studio.

    So, first of all, credits to jmcilhinney for his excellent base sample.



    Here's a screenshot:
    -- Updated, see below! --

    As you can see, this shape editor includes:
    • Different shapes, easily extensible with your own shapes,
    • Resizing using drag handles,
    • Each Shape has properties you can edit, even during run-time using a PropertyGrid.

    -- Updated, see below! --

    I think a very brief explanation is in order.

    The attached example solution contains two projects: the ShapeEditorLibrary, containing the basic shape editor classes, and the ShapeEditorExampleVs2008 project, containing the form you see in the screenshot, including the property grid + selection combobox logic. As you can see, this is separated from the ShapeEditorLibrary so you can implement it completely differently if you want.

    The most important classes in the ShapeEditorLibrary are the Shape, Canvas and ShapeCollection classes.

    The Shape class is an abstract class and implements most of the basic methods and properties that every Shape will have. In order to create your own Shapes, you can create a class that inherits Shape, and override the Draw method to provide your own drawing. If you want a Triangle shape, you implement the drawing such that it looks like a triangle. There is a RectangleShape and EllipseShape already included in the example so you can take a look how you do that. You usually won't have to do anything else except provide your own drawing. All the moving and resizing and even the drawing of the drag handles is implement automatically.

    The Canvas class is the panel the Shapes live in. It is the control you put on your Form. It has the properties you'll most likely need: a collection of Shapes and a SelectedShape property. In addition, it has useful events such as the SelectedShapeChanged and ShapesCollectionChanged events.

    The ShapeCollection class represents a collection of Shapes. The Canvas class has an instance of this class to keep track of the Shapes. It behaves exactly like any other strongly typed collection (such as a List(Of Shape)), except that it raises the CollectionChanged event when an item in the collection is changed, added or removed.
    Also, the ShapeCollection class has a method that uses a rather complicated (to explain anyway) algorithm to determine the name that a new Shape should have. For example, if you have four RectangleShapes on your form called RectangleShape1, RectangleShape3, Xyz and Hello, then when you add a new RectangleShape (with a blank name), it will be named RectangleShape2, as that is the next available name.

    The names are used, in my example, in the 'selection combobox' and the property grid, just like in Visual Studio.


    Well, that's it for the explanation for now, on to the facts...

    There are a few things that aren't completed yet, but I'm planning to add them as soon as I find some time:
    • There is no 'live drawing' to add shapes yet. Shapes are added via code at the moment.
    • There is no docking or anchoring or anything like that.



    Finally, here's a very short 'tutorial' on how to create your own shapes. Let's suppose you want to create a triangular shape.

    1. Create a new class called TriangleShape in the Shapes folder.

    2. Edit the class declaration so that it inherits Shape.
    csharp Code:
    1. public class TriangleShape : Shape

    3. Override the Draw method and provide your own drawing. In our case, we want to draw a triangle. We need to draw within the Bounds rectangle, because that defines the location and size of our shape.
    csharp Code:
    1. public override void Draw(System.Drawing.Graphics g)
    2.         {
    3.             float middle = this.Bounds.X + this.Bounds.Width / 2f;
    4.  
    5.             PointF left = new PointF(this.Bounds.Left, this.Bounds.Bottom);
    6.             PointF right = new PointF(this.Bounds.Right, this.Bounds.Bottom);
    7.             PointF top = new PointF(middle, this.Bounds.Top);
    8.  
    9.             using (var b = new SolidBrush(this.BackColor))
    10.             {
    11.                 g.FillPolygon(b, new PointF[] { left, right, top });
    12.             }
    13.         }

    4. Finally, we need to add a non-default constructor because each Shape should accept a Point (its location) in the constructor. All you need to do is call the base constructor and pass the point on to let it handle it:
    csharp Code:
    1. public TriangleShape(Point location)
    2.             : base(location)
    3.         {
    4.         }

    Final code:
    csharp Code:
    1. using System.Drawing;
    2.  
    3. namespace ShapeEditorLibrary.Shapes
    4. {
    5.     public class TriangleShape : Shape
    6.     {
    7.         public TriangleShape(Point location)
    8.             : base(location)
    9.         {
    10.         }
    11.  
    12.         public override void Draw(System.Drawing.Graphics g)
    13.         {
    14.             float middle = this.Bounds.X + this.Bounds.Width / 2f;
    15.  
    16.             PointF left = new PointF(this.Bounds.Left, this.Bounds.Bottom);
    17.             PointF right = new PointF(this.Bounds.Right, this.Bounds.Bottom);
    18.             PointF top = new PointF(middle, this.Bounds.Top);
    19.  
    20.             using (var b = new SolidBrush(this.BackColor))
    21.             {
    22.                 g.FillPolygon(b, new PointF[] { left, right, top });
    23.             }
    24.         }
    25.     }
    26. }


    5. Finally, we need some way to add the Shape so we can test it. If you are still using my example project, you can very easily edit, for example, the 'addRectangle' toolstrip button. Instead of creating a new RectangleShape, just create a new TriangleShape:
    csharp Code:
    1. private void addRectangle_Click(object sender, EventArgs e)
    2.         {
    3.             Shape s = new TriangleShape(new Point(rnd.Next(0, canvas1.Width), rnd.Next(0, canvas1.Height)));
    4.             s.ContextMenuStrip = shapeContextMenu;
    5.             canvas1.Shapes.Add(s);
    6.         }
    Nevermind the fact that the names don't match up, this is just for testing...

    So test it! This is what you should get:

    A fully functional triangular shape.

    That wasn't very hard was it?


    Enjoy!


    -- Updated, see below! --

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width