Click here to Skip to main content
15,892,537 members
Articles / Programming Languages / C#

Moveable Resizable Objects

Rate me:
Please Sign up or sign in to vote.
4.98/5 (59 votes)
9 Oct 2009CPOL198 min read 125.7K   8.7K   178  
Here is a description of an extremely powerful mechanism that makes screen objects moveable and resizable.
using System;
using System .Collections .Generic;
using System .ComponentModel;
using System .Drawing;
using System .Windows .Forms;

using MoveGraphLibrary;

namespace Test_MoveGraphLibrary
{
    public partial class Form_CircleInRotation : Form
    {
        Mover mover;
        NRCircle circle;
        TextM info;

        bool bShowCovers = false;

        // -------------------------------------------------
        public Form_CircleInRotation ()
        {
            InitializeComponent ();
            mover = new Mover (this);

            circle = new NRCircle (Auxi_Geometry .LocationByCoefficients (ClientRectangle, 0.4, 0.4), ClientRectangle .Height / 3,
                                   new double [] { 3, 17, 8, 5, 12, 9, 2, 7, 11, 9 });
            mover .Add (circle);
            mover .Insert (0, btnCovers);

            info = new TextM (this, new Point (300, 360),
                              "Move by any inner point (L_Press)\nResize by any border point (L_Press)\nRotate by any inner point (R_Press)");
            mover .Add (info);
        }
        // -------------------------------------------------        OnMouseDown
        private void OnMouseDown (object sender, MouseEventArgs mea)
        {
            if (mover .Catch (mea .Location, mea .Button))
            {
                if (mea .Button == MouseButtons .Right && mover [mover .CaughtObject] .Source is NRCircle)
                {
                    (mover [mover .CaughtObject] .Source as NRCircle) .StartRotation (mea .Location);
                }
            }
        }
        // -------------------------------------------------        OnMouseUp
        private void OnMouseUp (object sender, MouseEventArgs e)
        {
            mover .Release ();
        }
        // -------------------------------------------------        OnMouseMove
        private void OnMouseMove (object sender, MouseEventArgs mea)
        {
            if (mover .Move (mea .Location))
            {
                Invalidate ();
            }
        }
        // -------------------------------------------------        OnPaint
        private void OnPaint (object sender, PaintEventArgs e)
        {
            Graphics grfx = e .Graphics;

            info .Draw (grfx);
            circle .Draw (grfx);
            if (bShowCovers)
            {
                mover .DrawCovers (grfx);
            }
        }
        // -------------------------------------------------        Click_btnCovers
        private void Click_btnCovers (object sender, EventArgs e)
        {
            bShowCovers = !bShowCovers;
            Invalidate ();
        }
    }

    // =====================================================
    //
    //     NCircle
    //
    // =====================================================
    public class NRCircle : GraphicalObject
    {
        PointF ptCenter;
        int radius;
        int nrSmall = 5;
        int distanceNeighbours = 9;

        double [] vals;
        double angle;
        double [] sweep;
        Color [] clrs;

        double compensation;

        int nMinRadius = 15;   // min size is set to avoid disappearence while resizing

        // -------------------------------------------------
        public NRCircle (Point center, int rad, double [] fVals)
        {
            ptCenter = center;
            radius = rad;
            angle = 0.0;
            CheckedValues (fVals);
        }
        // -------------------------------------------------        CheckedValues
        private void CheckedValues (double [] fVals)
        {
            bool bCorrect = true;
            if (fVals == null || fVals .Length < 2 || Auxi_Common .SumArray (fVals, true) == 0.0)
            {
                bCorrect = false;
            }
            else
            {
                foreach (double val in fVals)
                {
                    if (val <= 0.0)
                    {
                        bCorrect = false;
                        break;
                    }
                }
            }
            if (!bCorrect)
            {
                vals = new double [] { 1, 2, 3, 4 };
            }
            else
            {
                vals = new double [fVals .Length];
                for (int i = 0; i < vals .Length; i++)
                {
                    vals [i] = fVals [i];
                }
            }
            sweep = new double [vals .Length];
            SweepAngles ();
            clrs = new Color [vals .Length];
            for (int i = 0; i < clrs .Length; i++)
            {
                clrs [i] = Auxi_Colours .ColorPredefined (i);
            }
        }
        // -------------------------------------------------        SweepAngles
        private void SweepAngles ()
        {
            double fSum = Auxi_Common .SumArray (vals, false);
            for (int i = 0; i < vals .Length; i++)
            {
                sweep [i] = 2 * Math .PI * vals [i] / fSum;
            }
        }
        // -------------------------------------------------        Center
        public PointF Center
        {
            get { return (ptCenter); }
        }
        // -------------------------------------------------        Radius
        public int Radius
        {
            get { return (radius); }
        }
        // -------------------------------------------------        Draw
        public void Draw (Graphics grfx)
        {
            Rectangle rc = new Rectangle (Convert .ToInt32 (Center .X) - radius, Convert .ToInt32 (Center .Y) - radius, 2 * radius, 2 * radius);
            float fStartDegree, fSweepDegree;
            fStartDegree = -(float) Auxi_Convert .RadianToDegree (angle);
            for (int i = 0; i < vals .Length; i++)
            {
                fSweepDegree = -(float) Auxi_Convert .RadianToDegree (sweep [i]);
                grfx .FillPie (new SolidBrush (clrs [i]), rc, fStartDegree, fSweepDegree);
                fStartDegree += fSweepDegree;
            }
            Auxi_Drawing .DrawEllipse (grfx, Color .DarkGray, ptCenter, radius);
        }
        // -------------------------------------------------        StartRotation
        public void StartRotation (Point ptMouse)
        {
            double angleMouse = -Math .Atan2 (ptMouse .Y - Center .Y, ptMouse .X - Center .X);
            compensation = Auxi_Common .LimitedRadian (angleMouse - angle);
        }
        // -------------------------------------------------        DefineCover
        public override void DefineCover ()
        {
            int nOnPerimeter = Convert .ToInt32 ((2 * Math .PI * radius) / distanceNeighbours);
            CoverNode [] nodes = new CoverNode [nOnPerimeter + 1];
            nodes [0] = new CoverNode (0, ptCenter, radius - nrSmall + 1, Cursors .SizeAll);
            for (int i = 1; i <= nOnPerimeter; i++)
            {
                nodes [i] = new CoverNode (i, Auxi_Geometry .PointToPoint (ptCenter, 2 * Math .PI * (i - 1) / nOnPerimeter, radius), nrSmall);
            }
            cover = new Cover (nodes);
            cover .SetClearance (false);
        }
        // -------------------------------------------------
        public override void Move (int cx, int cy)
        {
            ptCenter += new Size (cx, cy);
        }
        // -------------------------------------------------        MoveNode
        public override bool MoveNode (int i, int cx, int cy, Point ptM, MouseButtons catcher)
        {
            bool bRet = false;

            if (catcher == MouseButtons .Left)
            {
                if (i == 0)
                {
                    Move (cx, cy);
                }
                else
                {
                    int nRadNew = Convert .ToInt32 (Auxi_Geometry .Distance (ptCenter, ptM));
                    if (nRadNew != radius && nRadNew >= nMinRadius)
                    {
                        radius = nRadNew;
                        bRet = true;
                    }
                }
            }
            else if (catcher == MouseButtons .Right)
            {
                double angleMouse = -Math .Atan2 (ptM .Y - Center .Y, ptM .X - Center .X);
                angle = angleMouse - compensation;  
                bRet = true;
            }
            return (bRet);
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions