Resizing a Rectangle while dragging on Windows Form

拜拜、爱过 提交于 2019-12-13 16:14:50

问题


I have a Rectangle Drawn on top of my Windows Form and I want to resize it using one of the handles provided !

Rectangle areaRect = new Rectangle(100,100, 300, 300);
Bool dragging = false;
Point ptOld = new Point(0, 0);

protected override void OnPaint(PaintEventArgs e)
{
  Graphics dcPaint = e.Graphics;
  dcPaint.DrawRectangle(rectPen, areaRect);
}

protected override void OnMouseDown(MouseEventArgs e)
{
  ptOld = new Point(e.X, e.Y);
  dragging = true;
}

protected override void OnMouseMove(MouseEventArgs e)
{
  if(dragging = true) 
  {
    Point ptNew = new Point(e.X, e.Y);
    Int32 handleSelected = GetSelectedHandle(ptNew);

   // Lets say I want to resize this rectangle using Handle 2 now.
    if(handleSelected == 2) 
    {
      // I am resizing this rectangle Width
      areaRect.X += ptNew.X - ptOld.X;
      areaRect.Width -= ptNew .X - ptOld.X;

      this.Invalidate();
    }
  }
}

protected override void OnMouseUp(MouseEventArgs e)
{
  dragging = false;
}

It will give me an effect like this. Which is correct,

How ever I want to have a small tweak in this, I would like to change the height of this rectangle as well, When I am moving point 2, my point 7 should remain exactly as it is, Something like this... Similarly when I moving point 4, my point 5 should intact and so on for point 7 and 2 also.

Any idea, how to proceed, because if I change the height, my point 7 location also gets changed ?


回答1:


Drawing on a MouseMove like this is not going to be very smooth in WinForms.

You basically need a reference to the rectangle before you resize it.

I added the following code to keep track of the rectangle and the 8 draggable points:

private Point GetHandlePoint(int value) {
  Point result = Point.Empty;

  if (value == 1)
    result = new Point(areaRect.Left, areaRect.Top);
  else if (value == 2)
    result = new Point(areaRect.Left, areaRect.Top + (areaRect.Height / 2));
  else if (value == 3)
    result = new Point(areaRect.Left, areaRect.Bottom);
  else if (value == 4)
    result = new Point(areaRect.Left + (areaRect.Width / 2), areaRect.Top);
  else if (value == 5)
    result = new Point(areaRect.Left + (areaRect.Width / 2), areaRect.Bottom);
  else if (value == 6)
    result = new Point(areaRect.Right, areaRect.Top);
  else if (value == 7)
    result = new Point(areaRect.Right, areaRect.Top + (areaRect.Height / 2));
  else if (value == 8)
    result = new Point(areaRect.Right, areaRect.Bottom);

  return result;
}

private Rectangle GetHandleRect(int value) {
  Point p = GetHandlePoint(value);
  p.Offset(-2, -2);
  return new Rectangle(p, new Size(5, 5));
}

Here is how I reworked your form code:

private Rectangle areaRect = new Rectangle(100, 100, 300, 300);
private Rectangle oldRect;
private int dragHandle = 0;
private Point dragPoint;

public Form1() {
  InitializeComponent();
  this.DoubleBuffered = true;
}

protected override void OnMouseDown(MouseEventArgs e) {
  for (int i = 1; i < 9; i++) {
    if (GetHandleRect(i).Contains(e.Location)) {
      dragHandle = i;
      oldRect = areaRect;
      dragPoint = GetHandlePoint(i);
    }
  }
  base.OnMouseDown(e);
}

protected override void OnMouseMove(MouseEventArgs e) {
  if (dragHandle == 1) {
    // to do
  } else if (dragHandle == 2) {
    int diff = dragPoint.X - e.Location.X;
    areaRect = new Rectangle(oldRect.Left - diff, oldRect.Top, oldRect.Width + diff, oldRect.Height);
  } else if (dragHandle == 7) {
    int diff = dragPoint.X - e.Location.X;
    areaRect = new Rectangle(oldRect.Left, oldRect.Top, oldRect.Width - diff, oldRect.Height);
  }

  if (dragHandle > 0)
    this.Invalidate();

  base.OnMouseMove(e);
}

protected override void OnMouseUp(MouseEventArgs e) {
  dragHandle = 0;
  base.OnMouseUp(e);
}

protected override void OnPaint(PaintEventArgs e) {
  e.Graphics.DrawRectangle(Pens.Red, areaRect);
  for (int i = 1; i < 9; i++) {
    e.Graphics.FillRectangle(Brushes.DarkRed, GetHandleRect(i));
  }
  base.OnPaint(e);
}

The posted code only does Points #2 and #7, but that should give you some logic to work with. I'm sure this code can be improved, it's just a working example.




回答2:


Although this is a little old, this is the first (and only useful, as far as I found) result for this sort of a task.

I've used the above sample to enhance and implement a tested solution. In my case, I also wanted to have the rectangle to be strictly within another rectangle. Specifically, I was drawing it in a PictureBox and I wanted it to never get outside of the picture. This is what the max_width and max_height correspond to.

Note that it is a little funny sometimes - it re-sizes in the other direction when hitting minimum size in certain directions. I decided I like that behavior and that it should be a feature. :)

protected void pictureBox1_OnMouseMove(object sender, MouseEventArgs e)
{
        // Where I started - where I stopped
        int x_diff = dragPoint.X - e.Location.X;
        int y_diff = dragPoint.Y - e.Location.Y;

        // Minimum values
        int small_offset = 5;
        int left = small_offset;
        int top = small_offset;
        int width = small_offset;
        int height = small_offset;

        // Max values
        int max_width = this.pictureBox1.Image.Width;
        int max_height = this.pictureBox1.Image.Height;

        if (dragHandle == 1)
        {
            left = Math.Max(oldRect.Left - x_diff, left);
            top = Math.Max(oldRect.Top - y_diff, top);
            width = Math.Min(Math.Max(oldRect.Width + x_diff, width), max_width - left - small_offset);
            height = Math.Min(Math.Max(oldRect.Height + y_diff, height), max_height - top - small_offset);
        }
        else if (dragHandle == 2)
        {
            left = Math.Max(oldRect.Left - x_diff, left);
            top = oldRect.Top;
            width = Math.Min(Math.Max(oldRect.Width + x_diff, width), max_width - left - small_offset);
            height = oldRect.Height;
        }
        else if (dragHandle == 3)
        {
            left = Math.Max(oldRect.Left - x_diff, left);
            top = oldRect.Top;
            width = Math.Min(Math.Max(oldRect.Width + x_diff, width), max_width - left - small_offset);
            height = Math.Min(Math.Max(oldRect.Height - y_diff, height), max_height - top - small_offset);
        }
        else if (dragHandle == 4)
        {
            left = oldRect.Left;
            top = Math.Max(oldRect.Top - y_diff, top);
            width = oldRect.Width;
            height = Math.Min(Math.Max(oldRect.Height + y_diff, height), max_height - top - small_offset);
        }
        else if (dragHandle == 5)
        {
            left = oldRect.Left;
            top = oldRect.Top;
            width = oldRect.Width;
            height = Math.Min(Math.Max(oldRect.Height - y_diff, height), max_height - top - small_offset);
        }
        else if (dragHandle == 6)
        {
            left = oldRect.Left;
            top = Math.Max(oldRect.Top - y_diff, top);
            width = Math.Min(Math.Max(oldRect.Width - x_diff, width), max_width - left - small_offset);
            height = Math.Min(Math.Max(oldRect.Height + y_diff, height), max_height - top - small_offset);
        }
        else if (dragHandle == 7)
        {
            left = oldRect.Left;
            top = oldRect.Top;
            width = Math.Min(Math.Max(oldRect.Width - x_diff, width), max_width - left - small_offset);
            height = oldRect.Height;

        }
        else if (dragHandle == 8)
        {
            left = oldRect.Left;
            top = oldRect.Top ;
            width = Math.Min(Math.Max(oldRect.Width - x_diff, width), max_width - left - small_offset);
            height = Math.Min(Math.Max(oldRect.Height - y_diff, height), max_height - top - small_offset);
        }


        if (dragHandle > 0)
        {
            areaRect = new Rectangle(left, top, width, height);
            this.Invalidate();
        }
}


来源:https://stackoverflow.com/questions/10198381/resizing-a-rectangle-while-dragging-on-windows-form

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!