using System.Drawing;
using System.Windows.Forms;

namespace CirecleCCS
{
    class CcsGo
    {
        public int ResizePinSize = 6; // 圆的直径
        int HalfRPR
        {
            get { return ResizePinSize / 2; } // 半径
        }
        private static Pen SelectRectPen, ResizePinPen;
        private float[] SelectRectDashPattern;
        private static Rectangle SelectRect;
        private static Rectangle ResizePin1, ResizePin2, ResizePin3, ResizePin4, ResizePin5, ResizePin6, ResizePin7, ResizePin8;
        private static Rectangle rect;
        private static int ActivationPinPosition;
        // selectrect 的 x, y, x1, y1
        private static int SelectX0, SelectY0, SelectX1, SelectY1;
        // 8 个角 + 点空白处 + 点中间
        private const int hitNothing = -1;
        private const int hitTopLeft = 0;
        private const int hitTopRight = 1;
        private const int hitBottomRight = 2;
        private const int hitBottomLeft = 3;
        private const int hitTop = 4;
        private const int hitRight = 5;
        private const int hitBottom = 6;
        private const int hitLeft = 7;
        private const int hitMiddle = 8;

        private void HideResizePin() // 隐藏 ResizePin
        {
            ResizePin1.Width = 0; ResizePin1.Height = 0;
            ResizePin2.Width = 0; ResizePin2.Height = 0;
            ResizePin3.Width = 0; ResizePin3.Height = 0;
            ResizePin4.Width = 0; ResizePin4.Height = 0;
            ResizePin5.Width = 0; ResizePin5.Height = 0;
            ResizePin6.Width = 0; ResizePin6.Height = 0;
            ResizePin7.Width = 0; ResizePin7.Height = 0;
            ResizePin8.Width = 0; ResizePin8.Height = 0;
        }

        void SetResizePinVal() // 实时显示 ResizePin
        {
            ResizePin1.X = X - HalfRPR;
            ResizePin1.Y = Y - HalfRPR;
            ResizePin2.X = X + Width / 2 - HalfRPR;
            ResizePin2.Y = Y - HalfRPR;
            ResizePin3.X = X + Width - HalfRPR;
            ResizePin3.Y = Y - HalfRPR;
            ResizePin4.X = X + Width - HalfRPR;
            ResizePin4.Y = Y + Height / 2 - HalfRPR;
            ResizePin5.X = X + Width - HalfRPR;
            ResizePin5.Y = Y + Height - HalfRPR;
            ResizePin6.X = X + Width / 2 - HalfRPR;
            ResizePin6.Y = Y + Height - HalfRPR;
            ResizePin7.X = X - HalfRPR;
            ResizePin7.Y = Y + Height - HalfRPR;
            ResizePin8.X = X - HalfRPR;
            ResizePin8.Y = Y + Height / 2 - HalfRPR;
        }

        private void ShowResizePin() // 显示 ResizePin
        {
            ResizePin1.X = SelectRect.X - HalfRPR;
            ResizePin1.Y = SelectRect.Y - HalfRPR;
            ResizePin2.X = SelectRect.X + SelectRect.Width / 2 - HalfRPR;
            ResizePin2.Y = SelectRect.Y - HalfRPR;
            ResizePin3.X = SelectRect.X + SelectRect.Width - HalfRPR;
            ResizePin3.Y = SelectRect.Y - HalfRPR;
            ResizePin4.X = SelectRect.X + SelectRect.Width - HalfRPR;
            ResizePin4.Y = SelectRect.Y + SelectRect.Height / 2 - HalfRPR;
            ResizePin5.X = SelectRect.X + SelectRect.Width - HalfRPR;
            ResizePin5.Y = SelectRect.Y + SelectRect.Height - HalfRPR;
            ResizePin6.X = SelectRect.X + SelectRect.Width / 2 - HalfRPR;
            ResizePin6.Y = SelectRect.Y + SelectRect.Height - HalfRPR;
            ResizePin7.X = SelectRect.X - HalfRPR;
            ResizePin7.Y = SelectRect.Y + SelectRect.Height - HalfRPR;
            ResizePin8.X = SelectRect.X - HalfRPR;
            ResizePin8.Y = SelectRect.Y + SelectRect.Height / 2 - HalfRPR;
            ResizePin1.Width = ResizePinSize; ResizePin1.Height = ResizePinSize;
            ResizePin2.Width = ResizePinSize; ResizePin2.Height = ResizePinSize;
            ResizePin3.Width = ResizePinSize; ResizePin3.Height = ResizePinSize;
            ResizePin4.Width = ResizePinSize; ResizePin4.Height = ResizePinSize;
            ResizePin5.Width = ResizePinSize; ResizePin5.Height = ResizePinSize;
            ResizePin6.Width = ResizePinSize; ResizePin6.Height = ResizePinSize;
            ResizePin7.Width = ResizePinSize; ResizePin7.Height = ResizePinSize;
            ResizePin8.Width = ResizePinSize; ResizePin8.Height = ResizePinSize;
        }

        void FillResizePins(PaintEventArgs e) // 填充 ResizePinRect 颜色
        {
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin1);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin2);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin3);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin4);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin5);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin6);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin7);
            e.Graphics.FillEllipse(Brushes.SteelBlue, ResizePin8);
        }

        void DrawResizePin(Graphics g) // 绘制 ResizePin
        {
            g.DrawEllipse(ResizePinPen, ResizePin1);
            g.DrawEllipse(ResizePinPen, ResizePin2);
            g.DrawEllipse(ResizePinPen, ResizePin3);
            g.DrawEllipse(ResizePinPen, ResizePin4);
            g.DrawEllipse(ResizePinPen, ResizePin5);
            g.DrawEllipse(ResizePinPen, ResizePin6);
            g.DrawEllipse(ResizePinPen, ResizePin7);
            g.DrawEllipse(ResizePinPen, ResizePin8);
        }

        bool InELP(MouseEventArgs e, Point ElpCenter) // 是否在 ResizePin 圆内
        {
            int elpX = ElpCenter.X;
            int elpY = ElpCenter.Y;
            return !((elpX - e.X) * (elpX - e.X) + (elpY - e.Y) * (elpY - e.Y) >= HalfRPR * HalfRPR);
        }

        private int HitTest(MouseEventArgs e) // 测试哪个 ResizePin 被选中
        {
            if (InELP(e, new Point(ResizePin1.X + HalfRPR, ResizePin1.Y + HalfRPR)))
                return hitTopLeft;
            else if (InELP(e, new Point(ResizePin2.X + HalfRPR, ResizePin2.Y + HalfRPR)))
                return hitTop;
            else if (InELP(e, new Point(ResizePin3.X + HalfRPR, ResizePin3.Y + HalfRPR)))
                return hitTopRight;
            else if (InELP(e, new Point(ResizePin4.X + HalfRPR, ResizePin4.Y + HalfRPR)))
                return hitRight;
            else if (InELP(e, new Point(ResizePin5.X + HalfRPR, ResizePin5.Y + HalfRPR)))
                return hitBottomRight;
            else if (InELP(e, new Point(ResizePin6.X + HalfRPR, ResizePin6.Y + HalfRPR)))
                return hitBottom;
            else if (InELP(e, new Point(ResizePin7.X + HalfRPR, ResizePin7.Y + HalfRPR)))
                return hitBottomLeft;
            else if (InELP(e, new Point(ResizePin8.X + HalfRPR, ResizePin8.Y + HalfRPR)))
                return hitLeft;
            else if (e.X >= SelectRect.X + ResizePinSize && e.X <= SelectRect.X + SelectRect.Width - ResizePinSize
                        && e.Y >= SelectRect.Y + ResizePinSize && e.Y <= SelectRect.Y + SelectRect.Height - ResizePinSize)
                return hitMiddle;
            else
                return hitNothing;
        }

        public void Create() // 初始化参数
        {
            ResizePinPen = new Pen(Color.SteelBlue, 2);
            SelectRectDashPattern = new float[] { 3, 2, 1 };
            SelectRectPen = new Pen(Color.SteelBlue, 2.0f);
            //{
            //    DashPattern = SelectRectDashPattern,
            //};
            SelectRect = new Rectangle();
            ResizePin1 = new Rectangle();
            ResizePin2 = new Rectangle();
            ResizePin3 = new Rectangle();
            ResizePin4 = new Rectangle();
            ResizePin5 = new Rectangle();
            ResizePin6 = new Rectangle();
            ResizePin7 = new Rectangle();
            ResizePin8 = new Rectangle();
            rect = new Rectangle();
            ActivationPinPosition = hitNothing;
        }

        void StayInBoxR(PictureBox R) // 待在 box 里面别出去
        {
            if (SelectRect.X < 0)
                SelectRect.X = 0;
            if (SelectRect.Y < 0)
                SelectRect.Y = 0;
            if (SelectRect.X + SelectRect.Width > R.Width)
                SelectRect.X = R.Width - SelectRect.Width;
            if (SelectRect.Y + SelectRect.Height > R.Height)
                SelectRect.Y = R.Height - SelectRect.Height;
        }

        public void Destroy() // 释放资源
        {
            SelectRectPen.Dispose();
            ResizePinPen.Dispose();
        }

        public void StartPoint(PictureBox p, MouseEventArgs e) // 鼠标左键按下后
        {
            if (e.Button == MouseButtons.Left)
            {
                p.Invalidate(null, true);
                switch (HitTest(e))
                {
                    case hitTopLeft:
                        ActivationPinPosition = hitTopLeft;
                        SelectX1 = SelectRect.X + SelectRect.Width;
                        SelectY1 = SelectRect.Y + SelectRect.Height;
                        break;
                    case hitTop:
                        ActivationPinPosition = hitTop;
                        SelectX1 = SelectRect.Width + SelectRect.X;
                        SelectY1 = SelectRect.Height + SelectY0;
                        break;
                    case hitTopRight:
                        ActivationPinPosition = hitTopRight;
                        SelectY1 = SelectRect.Y + SelectRect.Height;
                        break;
                    case hitRight:
                        ActivationPinPosition = hitRight;
                        SelectY1 = SelectRect.Y + SelectRect.Height;
                        break;
                    case hitBottomRight:
                        ActivationPinPosition = hitBottomRight;
                        break;
                    case hitBottom:
                        ActivationPinPosition = hitBottom;
                        SelectX1 = SelectRect.X + SelectRect.Width;
                        break;
                    case hitBottomLeft:
                        ActivationPinPosition = hitBottomLeft;
                        SelectX1 = SelectRect.X + SelectRect.Width;
                        break;
                    case hitLeft:
                        ActivationPinPosition = hitLeft;
                        SelectX1 = SelectRect.X + SelectRect.Width;
                        SelectY1 = SelectRect.Y + SelectRect.Height;
                        break;
                    case hitMiddle:
                        ActivationPinPosition = hitMiddle;
                        SelectX0 = e.X - SelectRect.X;
                        SelectY0 = e.Y - SelectRect.Y;
                        SelectX1 = SelectRect.X + SelectRect.Width - e.X;
                        SelectY1 = SelectRect.Y + SelectRect.Height - e.Y;
                        break;
                    case hitNothing:
                        ActivationPinPosition = hitNothing;
                        SelectRect.Width = 0;
                        SelectRect.Height = 0;
                        SelectX0 = e.X;
                        SelectY0 = e.Y;
                        HideResizePin();
                        break;
                }
            }
        }

        public void TrackRubberBand(PictureBox p, MouseEventArgs e, bool Iskeep = false) // 鼠标左键拖动时动态显示矩形框
        {
            switch (HitTest(e))
            {
                case hitTopLeft:
                    p.Cursor = Cursors.SizeNWSE;
                    break;
                case hitTop:
                    p.Cursor = Cursors.SizeNS;
                    break;
                case hitTopRight:
                    p.Cursor = Cursors.SizeNESW;
                    break;
                case hitRight:
                    p.Cursor = Cursors.SizeWE;
                    break;
                case hitBottomRight:
                    p.Cursor = Cursors.SizeNWSE;
                    break;
                case hitBottom:
                    p.Cursor = Cursors.SizeNS;
                    break;
                case hitBottomLeft:
                    p.Cursor = Cursors.SizeNESW;
                    break;
                case hitLeft:
                    p.Cursor = Cursors.SizeWE;
                    break;
                case hitMiddle:
                    p.Cursor = Cursors.SizeAll;
                    break;
                case hitNothing:
                    p.Cursor = Cursors.Default;
                    break;
            }
            if (e.Button == MouseButtons.Left)
            {
                int TLX = e.X;
                int TLY = e.Y;

                if (e.X < 0)
                    TLX = 0;
                else if (e.X > p.Width)
                    TLX = p.Width;

                if (e.Y < 0)
                    TLY = 0;
                else if (e.Y > p.Height)
                    TLY = p.Height;

                if (!Iskeep)
                {
                    p.Invalidate(InvalidateRectangle(), false);
                }

                switch (ActivationPinPosition)
                {
                    case hitTopLeft:
                        GenerateRectangle(ref SelectRect, TLX, TLY, SelectX1, SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitTop:
                        GenerateRectangle(ref SelectRect, SelectX0, TLY, SelectX1, SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitTopRight:
                        GenerateRectangle(ref SelectRect, SelectX0, TLY, TLX, SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitRight:
                        GenerateRectangle(ref SelectRect, SelectX0, SelectY0, TLX, SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitBottomRight:
                        GenerateRectangle(ref SelectRect, SelectX0, SelectY0, TLX, TLY);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitBottom:
                        GenerateRectangle(ref SelectRect, SelectX0, SelectY0, SelectX1, TLY);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitBottomLeft:
                        GenerateRectangle(ref SelectRect, TLX, SelectY0, SelectX1, TLY);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitLeft:
                        GenerateRectangle(ref SelectRect, TLX, SelectY0, SelectX1, SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitMiddle:
                        GenerateRectangle(ref SelectRect, e.X - SelectX0, e.Y - SelectY0, e.X + SelectX1, e.Y + SelectY1);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                    case hitNothing:
                        GenerateRectangle(ref SelectRect, SelectX0, SelectY0, TLX, TLY);
                        StayInBoxR(p);
                        SetResizePinVal();
                        break;
                }
            }
        }

        public void EndPoint(PictureBox frm, MouseEventArgs e) // 鼠标左键松开后
        {
            if (e.Button == MouseButtons.Left)
            {
                frm.Invalidate(null, true);
                SelectX0 = SelectRect.X;
                SelectY0 = SelectRect.Y;
                if (HitTest(e) != hitNothing && X > ResizePinSize && Y > ResizePinSize)
                    ShowResizePin();
            }
        }

        public void DrawRubberBand(PictureBox frm, PaintEventArgs e) // 绘制矩形框
        {
            e.Graphics.DrawRectangle(SelectRectPen, SelectRect);
            FillResizePins(e);
            DrawResizePin(e.Graphics);
        }

        private void GenerateRectangle(ref Rectangle TempRectangle, int X0, int Y0, int X1, int Y1) // 根据指定两点坐标生成矩形框
        {
            if (X0 < X1)
            {
                TempRectangle.X = X0;
                TempRectangle.Width = X1 - X0;
            }
            else
            {
                TempRectangle.X = X1;
                TempRectangle.Width = X0 - X1;
            }
            if (Y0 < Y1)
            {
                TempRectangle.Y = Y0;
                TempRectangle.Height = Y1 - Y0;
            }
            else
            {
                TempRectangle.Y = Y1;
                TempRectangle.Height = Y0 - Y1;
            }
        }

        // RubberBand 的属性
        public int X
        {
            get
            {
                return SelectRect.X;
            }
        }
        public int Y
        {
            get
            {
                return SelectRect.Y;
            }
        }
        public int Width
        {
            get
            {
                return SelectRect.Width;
            }
        }
        public int Height
        {
            get
            {
                return SelectRect.Height;
            }
        }
        public Pen RectView { get => RectView; set => RectView = value; }

        public Rectangle InvalidateRectangle() // 获得无效区域,用来刷新时防止闪烁
        {
            rect.X = SelectRect.X - 8;
            rect.Y = SelectRect.Y - 8;
            rect.Width = SelectRect.Width + 16;
            rect.Height = SelectRect.Height + 16;

            return rect;
        }

        public void SetRect(int ex, int ey, int ew, int eh) // set ccs 框的位置以及尺寸
        {
            GenerateRectangle(ref SelectRect, ex, ey, ex + ew, ey + eh);
        }

        public void HideCCS() // 隐藏起来
        {
            HideResizePin();
            SetRect(0, 0, 0, 0);
        }
    }
}

代码内容解释:

这段代码是一个用于绘制矩形框的类,主要用于选中某个区域。

功能特点:

  • 使用 ResizePin 实现可拖拽、可调整大小的矩形框
  • 支持实时预览效果
  • 代码包含详细注释,易于理解和修改

使用说明:

  1. 将代码添加到您的 C# 项目中。
  2. 在 PictureBox 控件上添加鼠标事件处理程序。
  3. 在鼠标事件处理程序中调用 CcsGo 类的方法来绘制和调整矩形框。

代码示例:

private CcsGo ccsGo = new CcsGo();

private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
    ccsGo.StartPoint(pictureBox1, e);
}

private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
    ccsGo.TrackRubberBand(pictureBox1, e);
}

private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
    ccsGo.EndPoint(pictureBox1, e);
}

private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
    ccsGo.DrawRubberBand(pictureBox1, e);
}

其他说明:

  • 可以根据需要修改 ResizePinSize 属性来调整 ResizePin 的大小。
  • 可以修改 SelectRectPen 和 ResizePinPen 属性来更改矩形框和 ResizePin 的颜色。
  • 可以根据需要添加其他功能,例如将选中的区域保存到文件或进行其他操作。
C# 图形绘制:使用 ResizePin 实现可拖拽、可调整大小的矩形框

原文地址: https://www.cveoy.top/t/topic/ndzi 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录