Results 1 to 16 of 16

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

  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! --

  2. #2
    Master Of Orion ForumAccount's Avatar
    Join Date
    Jan 2009
    Location
    Canada
    Posts
    2,802

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

    Very cool.

    Two quick things I saw were when you try to click a shape it doesn't account for Z-Order. For example if I have a huge triangle behind a smaller square, I can't select the square. Also, when you change the location's/size's of shapes in the designer it should tell the property editor to refresh their values.

  3. #3

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

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

    Yes, the Z-order selection was something I was going to implement but decided to leave it for now because it wasn't working out the way I wanted it. I forgot to mention it in my post.
    I don't think the Visual Studio designer even does that, right? I think the only way you can select a control behind another control in VS is to rightclick and select it from the context menu. I was going to do it differently, where each successive click selects the next control in the z-order. So if you have 4 controls stacked on top of each other (at least partly) and you click in the part where they all overlap, each time you click you will select a different control (one next up in the z-order). I'm not sure how to implement that though.

    For updating the property grid, do you mean when you move/resize a shape with the mouse? I suppose I could do that, but I'd do that on the form level, by letting the form handle the Move / Resize events of the shapes. Since the shapes don't have those events yet, I didn't implement it yet

  4. #4
    Freelancer akhileshbc's Avatar
    Join Date
    Jun 2008
    Location
    Trivandrum, Kerala, India
    Posts
    7,652

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

    That's cool. But I like to see the VB version of it.

    If my post was helpful to you, then express your gratitude using Rate this Post.
    And if your problem is SOLVED, then please Mark the Thread as RESOLVED (see it in action - video)
    My system: AMD FX 6100, Gigabyte Motherboard, 8 GB Crossair Vengance, Cooler Master 450W Thunder PSU, 1.4 TB HDD, 18.5" TFT(Wide), Antec V1 Cabinet

    Social Group: VBForums - Developers from India


    Skills: PHP, MySQL, jQuery, VB.Net, Photoshop, CodeIgniter, Bootstrap,...

  5. #5

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

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

    I am actually working on the library some more (although I don't know if I will bring out another example project like this), mainly by adding snap lines and things like that. I doubt I will translate it to VB completely as that would be quite a lot of work after all with no gain for me at all.

    Can't you try converting it yourself? Using this converter you can probably get a very long way, and anything you can't get you can always ask here, I'll be glad to help.

  6. #6
    Freelancer akhileshbc's Avatar
    Join Date
    Jun 2008
    Location
    Trivandrum, Kerala, India
    Posts
    7,652

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

    Ok...

    If my post was helpful to you, then express your gratitude using Rate this Post.
    And if your problem is SOLVED, then please Mark the Thread as RESOLVED (see it in action - video)
    My system: AMD FX 6100, Gigabyte Motherboard, 8 GB Crossair Vengance, Cooler Master 450W Thunder PSU, 1.4 TB HDD, 18.5" TFT(Wide), Antec V1 Cabinet

    Social Group: VBForums - Developers from India


    Skills: PHP, MySQL, jQuery, VB.Net, Photoshop, CodeIgniter, Bootstrap,...

  7. #7

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

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

    Finally I got around to creating another test project for my updated library.

    Updates (at least those I can remember):
    • Multiple selections
    • Snapping and aligning shapes to shapes
    • Snapping shapes to the edge of the canvas
    • Z-order selection (clicking multiple times on the same spot will select each underlying shape in turn)
    • Updated grab handles to look more like Visual Studio IDE (rounded and smaller)
    • Locked shapes can no longer move and also display locked grab handles


    Multiple selections work just like in Visual Studio: one shape is the 'main selection' (white grab handles), all other selected shapes are secondary selections (black grab handles). Clicking a secondary selection will make it the main selection. Snapping happens only on the main selected shape, not on any secondary shapes.

    I think that's about it.

    Unfortunately, I no longer have VS2008 so I did not create a VS2008 compatible version. The files should all work in VS2008 though, so you can add them to a new project manually if you cannot use VS2010.


    New screenshots:

    Aligning an ellipse to a rectangle and triangle:


    Snapping a shape towards another shape (so they keep a fixed distance):


    Multiple selections:



    Known bugs:
    - When snapping two shapes the snapline might not appear in the middle correctly. It just looks a bit strange but it still works.



    A solution including two projects (the ShapeEditorLibrary and a test project) is attached (build or run before viewing the form).

    Enjoy!
    Attached Files Attached Files

  8. #8
    New Member
    Join Date
    Jul 2012
    Posts
    2

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

    hello @NickThissen!

    can you help me about rotate rectangle in your code please!

  9. #9
    New Member
    Join Date
    May 2012
    Posts
    14

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

    How to add text on a shape ????

    I've added this property to base class shape _

    private string _Texto = String.Empty;
    public string Texto
    {
    get { return _Texto; }
    set
    {
    if (value.Trim() == String.Empty)
    throw new ArgumentException("Texto cannot be empty.");
    _Texto = value;
    }
    }

    But i need to extend to (for example Rectangle )...how ??

    Thanks for your great work !!

  10. #10

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

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

    Quote Originally Posted by dtanh View Post
    hello @NickThissen!

    can you help me about rotate rectangle in your code please!
    Rotation of shapes is not supported. You could however create a new shape that has a Rotation property, and draw your rotated rectangle accordingly inside the current bounds. That would require a little trigonometry to figure out the locations of the four corners.

    Quote Originally Posted by magefesa View Post
    How to add text on a shape ????

    I've added this property to base class shape _




    But i need to extend to (for example Rectangle )...how ??

    Thanks for your great work !!
    You could create your own class that inherits RectangleShape (or just Shape), add the Text property in that class (instead of the base class), and then override the Draw method and use Graphics.DrawString to draw the text.

  11. #11
    New Member
    Join Date
    May 2012
    Posts
    14

    Smile Re: Add text to shapes !

    I've achieved !!!
    HEre is the code !

    On RectangleShapes.Cs :

    public override void Draw(System.Drawing.Graphics g)
    {
    using (var b = new SolidBrush(this.BackColor))
    {
    g.FillRectangle(b, this.Bounds);
    g.DrawRectangle(Pens.Black, this.Bounds);

    AfegirText(g,Texto );
    }
    }

    private void AfegirText(System.Drawing.Graphics g,string s)
    {
    Font font2 = new Font("Calibri", 18, FontStyle.Bold, GraphicsUnit.Point);
    g.DrawString(s, font2, Brushes.Black, this.Bounds);

    }
    On Shape.cs (add this property)

    private string _Texto = String.Empty;
    public string Texto
    {
    get { return _Texto; }
    set
    {
    if (value.Trim() == String.Empty)
    throw new ArgumentException("Texto cannot be empty.");
    _Texto = value;
    }
    }

    How to call it ?? Example, on the sample project :

    private void AddShape(Shape s)
    {
    s.Texto = " sdf sd fsd fsdf sd fsfsdf";
    canvas1.Shapes.Add(s);
    canvas1.Invalidate();
    }

  12. #12
    New Member
    Join Date
    Jul 2012
    Posts
    2

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

    Quote Originally Posted by NickThissen View Post
    Rotation of shapes is not supported. You could however create a new shape that has a Rotation property, and draw your rotated rectangle accordingly inside the current bounds. That would require a little trigonometry to figure out the locations of the four corners.
    Thanks for your reply! i have been tried to rotate my rectangle, but not good. My rectangle is the current bound.

  13. #13
    Lively Member
    Join Date
    Mar 2015
    Posts
    104

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

    Nice.

    Perhaps Add polygon could possibly be next?

    Codeproject also has an example of rotating, shifting and resizing objects by attaching adorners over here:
    w w w.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part

    Also a skew class is mentioned here:
    w w w.codeproject.com/Messages/3295560/Skew-Class-as-addition-to-this-nice-article.aspx

    Please change w w w to www in the above links.

    Keep up the good work.
    Last edited by CreativeDreamer; Mar 12th, 2015 at 07:51 AM.

  14. #14
    Fanatic Member coolcurrent4u's Avatar
    Join Date
    Apr 2008
    Location
    *****
    Posts
    993

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

    Thanks for such a wonderful work.
    Last edited by coolcurrent4u; Sep 29th, 2018 at 06:55 PM.
    Programming is all about good logic. Spend more time here


    (Generate pronounceable password) (Generate random number c#) (Filter array with another array)

  15. #15
    Junior Member
    Join Date
    Jan 2019
    Posts
    26

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

    Hi all,
    Before I start, I apologize for answering the old post.
    The source code of NickThissen was excellent.I want to use part of these codes in other programing languages like vb6.
    Can anyone help me to convert a small part of this source code?

    I just want to convert these codes into one of the following.
    1-winapi functions
    2-vb6 syntax

    I hope that the professors of this forum can help me.
    Thanks.

    Code:
     var oldBounds = new List<Rectangle>();
                    if (this.SelectedShape != null)
                    {
                        if (hitStatus == Shape.HitStatus.Drag)
                        {
                            // 1. Store the relative locations of all other selected shapes, if any
                            var relativeLocations = new List<Point>();
                            for (var i = 1; i < this.SelectedShapes.Count; i++)
                            {
                                var shape = this.SelectedShapes[i];
                                relativeLocations.Add(this.SelectedShape.Location.Subtract(shape.Location));
                                oldBounds.Add(shape.GrabHandles.TotalBounds);
                            }
    
                            // 2. Move the main selected shape
                            oldBounds.Add(this.SelectedShape.GrabHandles.TotalBounds);
                            var newLocation = e.Location.Subtract(moveStart);
                            if (this.SnapMode == SnapModes.SnapToGrid) newLocation = newLocation.Floor(10);
                            this.SelectedShape.Move(newLocation);
                            this.InvalidateShape(this.SelectedShape);
    
                            // 3. Move the remaining selected shapes back to their relative positions
                            for (var i = 1; i < this.SelectedShapes.Count; i++)
                            {
                                var shape = this.SelectedShapes[i];
                                oldBounds.Add(shape.GrabHandles.TotalBounds);
                                shape.Location = this.SelectedShape.Location.Subtract(relativeLocations[i - 1]);
                               this.InvalidateShape(shape);
                            }
                        }

  16. #16
    New Member
    Join Date
    Apr 2021
    Posts
    1

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

    This shape editor is good even after 11 years. Unfortunately, rotation is not implemented, it is not easy (coordinate transformation) to rotate at the center of the shape so that the grip points and the cursor arrows are at the same angle.

    Hopefully after all these years, there will be an entrepreneurial C# guru who will do the rotation of the shapes, I think a few would be happy for him.
    Last edited by deeronb; Apr 30th, 2021 at 06:45 AM.

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