chrs
chrs

Reputation: 6106

How To Make A Selection Tool In C#

Download the project

I am trying to make a panel with a background color which should be able to be drawn in runtime when the user holds down left mouse button and moves it around. All works find when the user is starting from top left and go to bottom right just like the image shows:

But I want the user to be able to make the panel from bottom right to top left. Just like when you select something on your computer with your mouse

Le Image

Here is my code for now:

public void parent_MouseMove(object sender, MouseEventArgs e)
{
  if (e.Button == System.Windows.Forms.MouseButtons.Left)
  {
    Point tempLoc = e.Location;
    this.Location = new Point
    (
      Math.Min(this.Location.X, tempLoc.X),
      Math.Min(this.Location.Y, tempLoc.Y)
    );

    this.Size = new Size
    (
      Math.Abs(this.Location.X - tempLoc.X),
      Math.Abs(this.Location.Y - tempLoc.Y)
    );

    this.Invalidate();
  }
}

I think this is where I go wrong, and I simply can't find the right algorithm for it:

this.Size = new Size
(
  Math.Abs(this.Location.X - tempLoc.X),
  Math.Abs(this.Location.Y - tempLoc.Y)
);

But if I use a rectangle it works fine, but I want my panel to be able to do it as well.

Upvotes: 5

Views: 1905

Answers (1)

LarsTech
LarsTech

Reputation: 81655

You need to just check the minimums and maximums of your starting point versus your mousemoving point. The problem with the code is you are using the control location as a starting point, but if you move the mouse from bottom-right to top-left, your location needs to change. A control can't have a negative size.

Here is how I re-wrote it (I removed unnecessary stuff for testing):

public class SelectionTool : Panel {
  Form parent;
  Point _StartingPoint;

  public SelectionTool(Form parent, Point startingPoint) {
    this.DoubleBuffered = true;
    this.Location = startingPoint;

    //this.endingPoint = startingPoint;
    _StartingPoint = startingPoint;

    this.parent = parent;
    this.parent.Controls.Add(this);
    this.parent.MouseMove += new MouseEventHandler(parent_MouseMove);
    this.BringToFront();
    this.Size = new Size(0, 0);
  }

  public void parent_MouseMove(object sender, MouseEventArgs e) {
    if (e.Button == MouseButtons.Left) {
      int minX = Math.Min(e.Location.X, _StartingPoint.X);
      int minY = Math.Min(e.Location.Y, _StartingPoint.Y);
      int maxX = Math.Max(e.Location.X, _StartingPoint.X);
      int maxY = Math.Max(e.Location.Y, _StartingPoint.Y);
      this.SetBounds(minX, minY, maxX - minX, maxY - minY);

      this.Invalidate();
    }
  }

  protected override void OnPaint(PaintEventArgs e) {
    base.OnPaint(e);
    this.BackColor = Color.Blue;
  }
}

Here is the code I used to test it on a form:

private SelectionTool _SelectPanel = null;

private void Form1_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == System.Windows.Forms.MouseButtons.Left) {
    if (_SelectPanel == null)
      _SelectPanel = new SelectionTool(this, e.Location);
  }
}

private void Form1_MouseUp(object sender, MouseEventArgs e) {
  if (_SelectPanel != null) {
    _SelectPanel.Dispose();
    _SelectPanel = null;
  }
}

Upvotes: 3

Related Questions