Resize and reposition control based on 2 child 矩形(椭圆)图形位置

Resize and reposition control based on 2 child Rectangle (ellipse) graphics position

正如标题所说,如果我将 2 个椭圆手柄拖到我制作的自定义控件中,我只需要正确地调整大小和重新定位控件。我似乎不知道该怎么做。

在上面的 GIF 中,我的控件是黄色背景,当我开始将第二个手柄移到第四象限之外时出现问题。它需要正确地重新定位和调整控件的大小。

代码:

public partial class FlexibleLineControl : Control
{
    public FlexibleLineControl()
    {
        // transparent control: https://www.c-sharpcorner.com/uploadfile/Nildo/making-transparent-control-using-gdi-and-C-Sharp-updated-to-net-3-5/
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        this.BackColor = Color.PaleGoldenrod;

        InitializeComponent();

        this.Size = new Size(HandleSize.Width * 2, HandleSize.Height * 2);
        Handle1 = new Rectangle(new Point(0, 0), HandleSize);
        Handle2 = new Rectangle(new Point(HandleSize.Width, HandleSize.Height), HandleSize);
        GP1.AddEllipse(Handle1);
        GP2.AddEllipse(Handle2);
        DoubleBuffered = true;
    }

    private GraphicsPath GP1 = new GraphicsPath();
    private GraphicsPath GP2 = new GraphicsPath();
    private Size HandleSize = new Size(10, 10);

    public Rectangle Handle1;
    private Rectangle Handle2;

    private Point CurrMousePoint1;
    private bool DragState = false;
    private bool Handle1Dragged = false;
    private bool Handle2Dragged = false;

    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        e.Graphics.FillEllipse(Brushes.Black, Handle1);
        e.Graphics.FillEllipse(Brushes.Black, Handle2);

        // get line points to draw line
        Point p1 = new Point(Handle1.Location.X + Handle1.Width / 2, Handle1.Location.Y + Handle1.Height / 2);
        Point p2 = new Point(Handle2.Location.X + Handle2.Width / 2, Handle2.Location.Y + Handle2.Height / 2);
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.DrawLine(new Pen(Brushes.Black), p1, p2);
    }

    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (GP1.IsVisible(e.Location))
        {
            DragState = true;
            Handle1Dragged = true;
            CurrMousePoint1 = this.Parent.PointToClient(Cursor.Position);
        }
        else if (GP2.IsVisible(e.Location))
        {
            DragState = true;
            Handle2Dragged = true;
            CurrMousePoint1 = this.Parent.PointToClient(Cursor.Position);
        }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (DragState)
        {
            Point newPoint = Parent.PointToClient(Cursor.Position);
            if (Handle1Dragged)
                Handle1.Location = new Point(Handle1.X + newPoint.X - CurrMousePoint1.X, Handle1.Y + newPoint.Y - CurrMousePoint1.Y);
            else if (Handle2Dragged)
                Handle2.Location = new Point(Handle2.X + newPoint.X - CurrMousePoint1.X, Handle2.Y + newPoint.Y - CurrMousePoint1.Y);
                

            // get new control size and location
            int width = Math.Abs(Handle1.Location.X - Handle2.Location.X);
            int height = Math.Abs(Handle1.Location.Y - Handle2.Location.Y);

            this.Size = new Size(width + HandleSize.Width, height + HandleSize.Height);


            CurrMousePoint1 = newPoint;
            Invalidate();
        }
    }

    protected override void OnMouseUp(MouseEventArgs e)
    {
        DragState = false;
        if (Handle1Dragged)
        {
            GP1.Reset();
            GP1.AddRectangle(Handle1);
            Handle1Dragged = false;
        }
        else if (Handle2Dragged)
        {
            GP2.Reset();
            GP2.AddRectangle(Handle2);
            Handle2Dragged = false;
        }
    }
}

感谢评论,现在可以使用了

工作代码:

class FlexibleLineControl : Control
{
    public FlexibleLineControl()
    {
        this.Size = new Size(HandleSize.Width * 2, HandleSize.Height * 2);
        this.Location = new Point(0, 0);
        InitControl();
    }

    public FlexibleLineControl(Point p1, Point p2)
    {
        this.Location = new Point(Math.Min(p1.X, p2.X), Math.Min(p1.Y, p2.Y));
        int width = Math.Abs(p1.X - p2.X);
        int height = Math.Abs(p1.Y - p2.Y);

        this.Size = new Size(width + HandleSize.Width, height + HandleSize.Height);
        InitControl();
    }

    public Size HandleSize { get; set; } = new Size(10, 10);
    public Color HandleColor { get; set; } = Color.Black;
    public float LineWidth { get; set; } = 1;
    public Color LineColor { get; set; } = Color.Black;
    public Point LinePoint1 { get; set; }
    public Point LinePoint2 { get; set; }

    private GraphicsPath GP1 = new GraphicsPath();
    private GraphicsPath GP2 = new GraphicsPath();
    public Rectangle Handle1;
    private Rectangle Handle2;

    private Point CurrMousePoint1;
    private bool DragState = false;
    private bool Handle1Dragged = false;
    private bool Handle2Dragged = false;

    private void InitControl()
    {
        // transparent control: https://www.c-sharpcorner.com/uploadfile/Nildo/making-transparent-control-using-gdi-and-C-Sharp-updated-to-net-3-5/
        SetStyle(ControlStyles.SupportsTransparentBackColor, true);
        SetStyle(ControlStyles.ResizeRedraw, true);

        //Set style for double buffering
        SetStyle(ControlStyles.DoubleBuffer |
                    ControlStyles.AllPaintingInWmPaint |
                    ControlStyles.UserPaint, true);
        this.BackColor = Color.Transparent;
        this.DoubleBuffered = true;

        Handle1 = new Rectangle(new Point(0, 0), HandleSize);
        Handle2 = new Rectangle(new Point(this.Size.Width - HandleSize.Width, this.Size.Height - HandleSize.Height), HandleSize);
        LinePoint1 = new Point(Handle1.X + Handle1.Width / 2, Handle1.Y + Handle1.Height / 2);
        LinePoint2 = new Point(Handle2.X + Handle2.Width / 2, Handle2.Y + Handle2.Height / 2);

        GP1.AddEllipse(Handle1);
        GP2.AddEllipse(Handle2);
    }

    #region Move and Draw event overrides
    protected override void OnPaint(PaintEventArgs e)
    {
        base.OnPaint(e);

        e.Graphics.FillEllipse(new SolidBrush(HandleColor), Handle1);
        e.Graphics.FillEllipse(new SolidBrush(HandleColor), Handle2);

        // get line points to draw line
        e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
        e.Graphics.SmoothingMode = SmoothingMode.HighQuality;
        e.Graphics.DrawLine(new Pen(Brushes.Black, LineWidth), LinePoint1, LinePoint2);
    }
    protected override void OnMouseDown(MouseEventArgs e)
    {
        if (GP1.IsVisible(PointToClient(Cursor.Position)))
        {
            DragState = true;
            Handle1Dragged = true;
            CurrMousePoint1 = this.Parent.PointToClient(Cursor.Position);
        }
        else if (GP2.IsVisible(e.Location))
        {
            DragState = true;
            Handle2Dragged = true;
            CurrMousePoint1 = this.Parent.PointToClient(Cursor.Position);
        }
    }
    protected override void OnMouseMove(MouseEventArgs e)
    {
        if (DragState)
        {
            Point newPoint = Parent.PointToClient(Cursor.Position);
            if (Handle1Dragged)
                Handle1.Location = new Point(Handle1.X + newPoint.X - CurrMousePoint1.X, Handle1.Y + newPoint.Y - CurrMousePoint1.Y);
            else if (Handle2Dragged)
                Handle2.Location = new Point(Handle2.X + newPoint.X - CurrMousePoint1.X, Handle2.Y + newPoint.Y - CurrMousePoint1.Y);

            // get new control size
            int width = Math.Abs(Handle1.X - Handle2.X);
            int height = Math.Abs(Handle1.Y - Handle2.Y);

            this.Size = new Size(width + HandleSize.Width, height + HandleSize.Height);

            // get new control location
            Point p1 = Handle1.Location;
            Point p2 = Handle2.Location;

            if (!(p1.X == p2.X || p1.Y == p2.Y))
            {
                this.Location = new Point(Location.X + Math.Min(Handle1.X, Handle2.X), Location.Y + Math.Min(Handle1.Y, Handle2.Y));

                // p1 top right, p2 bottom left
                if (p1.X > p2.X && p1.Y < p2.Y)
                {
                    p1 = new Point(this.Size.Width - this.HandleSize.Width, 0);
                    p2 = new Point(0, this.Size.Height - this.HandleSize.Height);
                }
                // p1 bottom right, p2 top left
                else if (p1.X > p2.X && p1.Y > p2.Y)
                {
                    p1 = new Point(this.Size.Width - this.HandleSize.Width, this.Size.Height - this.HandleSize.Height);
                    p2 = new Point();
                }
                // p1 top left, p2 bottom right
                else if (p1.X < p2.X && p1.Y < p2.Y)
                {
                    p1 = new Point();
                    p2 = new Point(this.Size.Width - this.HandleSize.Width, this.Size.Height - this.HandleSize.Height);
                }
                // p1 bottom left, p2 top right
                else if (p1.X < p2.X && p1.Y > p2.Y)
                {
                    p1 = new Point(0, this.Size.Height - this.HandleSize.Height);
                    p2 = new Point(this.Size.Width - this.HandleSize.Width, 0);
                }
            }
                
            Handle1.Location = p1;
            Handle2.Location = p2;

            LinePoint1 = new Point(Handle1.X + Handle1.Width / 2, Handle1.Y + Handle1.Height / 2);
            LinePoint2 = new Point(Handle2.X + Handle2.Width / 2, Handle2.Y + Handle2.Height / 2);

            CurrMousePoint1 = newPoint;
            Invalidate();
        }
    }
    protected override void OnMouseUp(MouseEventArgs e)
    {
        DragState = false;
        Handle1Dragged = false;
        Handle2Dragged = false;

        GP1.Reset();
        GP1.AddRectangle(Handle1);
        GP2.Reset();
        GP2.AddRectangle(Handle2);
    }
    protected override CreateParams CreateParams
    {
        get
        {
            CreateParams cp = base.CreateParams;
            cp.ExStyle |= 0x20;
            return cp;
        }
    }
    #endregion

}