Search code examples
c#graphicsgdi+

how to draw multiple draggable and selectable circle?


i wrote somecode to draw circles on a panel by mouse click, i need to add some feature like selecting and dragging this circles , help me to complete my code please, thanks

Screenshot of running code

CircleItem class:

public class CircleItem
    {
        public bool Selected { get; set; }
        public Color CircleColor { get; set; }
        public Point StartPoint { get; set; }
        public int LineWidth { get; set; }
        public String Caption { get; set; }

        public CircleItem(String caption, Color circleColor,Point startPoint,int lineWidth)
        {
            CircleColor = circleColor;
            StartPoint = startPoint;
            LineWidth = lineWidth;
            Caption = caption;
        }
        public void Draw(Graphics G)
        {
            using (var pen = new Pen(Color.DimGray, LineWidth))
            {
                G.FillEllipse(new SolidBrush(CircleColor), StartPoint.X, StartPoint.Y, 25, 25);
                G.DrawEllipse(pen, StartPoint.X, StartPoint.Y, 26, 26);
                G.DrawString(Caption, new Font("Arial", 9), Brushes.Green, StartPoint.X + 6, StartPoint.Y + 6);
            }
        }
        public bool HitTest(Point Pt)
        {

            return true;
        }

Main code:

public partial class Form1 : Form
    {
        public int circleNumber;
        private Point positionCursor;
        private List<Components.CircleItem> circleItems = new List<CircleItem>();

        public Form1()
        {
            InitializeComponent();
            typeof(Panel).InvokeMember("DoubleBuffered", BindingFlags.SetProperty
            | BindingFlags.Instance | BindingFlags.NonPublic, null,
            picCanvas, new object[] { true });
            picCanvas.Paint += PicCanvas_PaintEventHandler;
        }
        private void PicCanvas_PaintEventHandler(object sender, PaintEventArgs e)
        {
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            foreach (CircleItem cItem in circleItems) cItem.Draw(e.Graphics);
        }

        private void Form1_Load(object sender, EventArgs e)
        {

        }

        private void picCanvas_MouseDoubleClick(object sender, MouseEventArgs e)
        {

        }

        private void picCanvas_MouseClick(object sender, MouseEventArgs e)
        {
            positionCursor = this.PointToClient(new Point(Cursor.Position.X - 25, Cursor.Position.Y - 25));
            if (e.Button == MouseButtons.Left)
            {
                circleItems.Add(new CircleItem(circleItems.Count.ToString(), Color.White, positionCursor, 4));
            }
            else
            {
                foreach (CircleItem cirTag in circleItems)
                    cirTag.CircleColor = cirTag.HitTest(e.Location) ? Color.Red : Color.White;
            }
            picCanvas.Invalidate();
        }

        private void picCanvas_MouseDown(object sender, MouseEventArgs e)
        {

        }
}

Thanks for attention :)

I try to wrote some code to done this, i don't have any good result, circle collision routin needed


Solution

  • i solve selecting circles problem by GraphicPath(),just working on drag and drop circles now

    public class CircleItem
    {
        private bool Selected { get; set; }
        public Color FillColor { get; set; }
        private int LineWidth { get; set; }
        private String Caption { get; set; }
        private Point Center { get; set; }
        private int Radious { get; set; }
    
        private GraphicsPath path;
        public CircleItem(String caption, Color fillColor,Point startPoint,int lineWidth,int radious)
        {
            FillColor = fillColor;
            LineWidth = lineWidth;
            Caption = caption;
            Center = new Point(startPoint.X-radious,startPoint.Y - radious);
            Radious = radious;
        }
        public void Draw(Graphics G)
        {
            path = new GraphicsPath();
            using (var pen = new Pen(Color.DimGray, LineWidth))
            {
                G.FillEllipse(new SolidBrush(FillColor), Center.X, Center.Y, Radious-1, Radious-1);
                G.DrawEllipse(pen, Center.X, Center.Y, Radious,Radious);
                G.DrawString(Caption, new Font("Arial", 9), Brushes.Green, Center.X + 6, Center.Y + 6);
                path.AddEllipse(Center.X, Center.Y, Radious, Radious);
            }
        }
        public bool HitTest(Point Pt)
        {
            bool result = false;
            result = (bool)path.IsVisible(Pt);
            return result;
        }
    }