Reputation: 326
How can I draw a rectangle in all directions? Current code:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Starting point of the selection:
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
_selection.Width = e.X - _selection.X;
_selection.Height = e.Y - _selection.Y;
pictureBox1.Refresh(); // redraw picturebox
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && _selecting)
{
_selecting = false;
}
}
This allows me to MouseDown
and then draw down and to the right, but I am unable to draw in any other direction beyond the anchor point. How can I draw a rectangle in any direction like e.g. Microsoft Paint?
I first tried:
_selection.Width = Math.Abs(e.X - _selection.X);
_selection.Height = Math.Abs(e.Y - _selection.Y);
But this creates a funny mirror effect (which is not what I want). I then tried a simple shift:
_selection.X = _selection.Left - 5;
This did what I expected and moved a static rectangle 5 units left, so I thought it would be a simple matter of continuously shifting the anchor point during the Paint event:
private void UpdateRectange(Point newPos)
{
var width = newPos.X - _selection.X;
var height = newPos.Y - _selection.Y;
_selection.Width = Math.Abs(width);
_selection.Height = Math.Abs(height);
if (width < 0 && height > 0) // move down (+) and left (-)
{
//_selection.X = _selection.Left + width;
_selection.Offset(width, 0);
}
uxScreenGrab.Refresh(); // redraw picturebox
}
But this resulted in pushing a vertical line across the screen towards the left, when moving to the left of the original anchor point.The width does not properly update for some reason.
Upvotes: 1
Views: 458
Reputation: 4721
The solution proposed in the question looks good:
_selection.Width = Math.Abs(e.X - initiallySelectedX);
_selection.Height = Math.Abs(e.Y - initiallySelectedY);
...but You have to move the origin of the rectangle when (e.X - initiallySelectedX) < 0
So probably You want to add something like this to Your code:
var diffX = e.x - initiallySelectedX;
if (diffX < 0) _selection.X = initiallySelectedX - diffX;
var diffY = e.y - initiallySelectedY;
if (diffY < 0) _selection.Y = initiallySelectedY - diffY;
Where initiallySelectedX
and initiallySelectedY
are variables set onMouseDown
.
this is only a rough idea.
The idea behind is that the Width and Height of the Rectangle cannot be NEGATIVE !!
Upvotes: 2
Reputation:
Here's another snippet to draw a selection rectangle on a PictureBox
:
//...
private Point startPoint;
private Point endPoint;
private readonly Pen P1 = new Pen(Color.SteelBlue, 2) {
Alignment = PenAlignment.Center, DashStyle = DashStyle.Dash};
//...
Set the startPoint
in the MouseDown
event and reset the endPoint
variables:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
startPoint = new Point(e.X, e.Y);
endPoint = Point.Empty;
}
}
Set the endPoint
and call Invalidate()
method in the MouseMove
event:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
var p = new Point(e.X, e.Y);
if (e.Button == MouseButtons.Left &&
!p.Equals(startPoint))
{
endPoint = p;
pictureBox1.Invalidate();
}
}
Also call Invalidate()
in the MouseUp
event to remove the selection rectangle:
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
pictureBox1.Invalidate();
}
Draw the selection rectangle:
private void pictureBox1_Paint(object sender, PaintEventArgs e)
{
if(MouseButtons == MouseButtons.Left &&
!startPoint.Equals(endPoint) &&
!endPoint.Equals(Point.Empty))
{
var g = e.Graphics;
var rect = Rectangle.Empty;
if(startPoint.X < endPoint.X)
{
rect.X = startPoint.X;
rect.Width = endPoint.X - startPoint.X;
}
else
{
rect.X = endPoint.X;
rect.Width = startPoint.X - endPoint.X;
}
if(startPoint.Y < endPoint.Y)
{
rect.Y = startPoint.Y;
rect.Height = endPoint.Y - startPoint.Y;
}
else
{
rect.Y = endPoint.Y;
rect.Height = startPoint.Y - endPoint.Y;
}
g.DrawRectangle(P1, rect);
}
}
And don't forget to clean up:
private void YourForm_FormClosing(object sender, FormClosingEventArgs e)
{
P1.Dispose();
}
Keep it simple.
Related Posts
How to call a method that uses PaintEventArgs and coordinates variables
Upvotes: 2
Reputation: 326
UPDATE:
Keeping track of the starting point on the MouseDown
event allows the anchor point to correctly update:
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
// Starting point of the selection:
if (e.Button == MouseButtons.Left)
{
_selecting = true;
_selection = new Rectangle(new Point(e.X, e.Y), new Size());
_startingPoint = e.Location;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
// Update the actual size of the selection:
if (_selecting)
{
UpdateRectange(e.Location);
}
}
private void UpdateRectange(Point newPos)
{
var diffX = newPos.X - _startingPoint.X;
var diffY = newPos.Y - _startingPoint.Y;
var newSize = new Size(Math.Abs(diffX), Math.Abs(diffY));
if (diffX > 0 && diffY > 0)
{
_selection = new Rectangle(_startingPoint, newSize);
}
else if (diffX < 0 && diffY < 0)
{
_selection = new Rectangle(newPos, newSize);
}
else if (diffX > 0 && diffY < 0)
{
_selection = new Rectangle(new Point(_startingPoint.X, _startingPoint.Y + diffY), newSize);
}
else
{
_selection = new Rectangle(new Point(_startingPoint.X + diffX, _startingPoint.Y), newSize);
}
uxScreenGrab.Invalidate();
}
UPDATE 2:
Re-wrote UpdateRectangle
to simply move the anchor point, instead of instantiating at every call:
private void UpdateRectange(Point newPos)
{
var diffX = newPos.X - _startingPoint.X;
var diffY = newPos.Y - _startingPoint.Y;
var newSize = new Size(Math.Abs(diffX), Math.Abs(diffY));
if (diffX > 0 && diffY > 0)
{
_selection.Size = newSize;
}
else if (diffX < 0 && diffY < 0)
{
_selection.Location = newPos;
_selection.Size = newSize;
}
else if (diffX > 0 && diffY < 0)
{
_selection.Y = _startingPoint.Y + diffY;
_selection.Size = newSize;
}
else
{
_selection.X = _startingPoint.X + diffX;
_selection.Size = newSize;
}
uxScreenGrab.Invalidate();
}
Upvotes: 1