Modifying all items in a list of Points - c#

List<Point> pointList;
public int pickedIndexRight = -1;
public int diffX = 0;
public int diffY = 0;
public Form1()
{
InitializeComponent();
pointList = new List<Point>();
}
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
Point myPoint = new Point(e.X, e.Y);
if (e.Button == MouseButtons.Left)
{
if (pickedIndex == -1)
{
if (pointList.Contains(myPoint) == false)
{
pointList.Add(myPoint);
}
}
}
else if (e.Button == MouseButtons.Right)
{
//if right click near a point then pickedIndexRight is index of that point in list
pickedIndexRight = pointList.FindIndex(delegate(Point point) { return Distance(point, myPoint) < 10; });
}
Invalidate();
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right && pickedIndexRight != -1)
{
for (int i = 0; i < pointList.Count - 1; i++)//(int i = pointList.Count - 1; i > 0; i--)
{
diffX = pointList[i].X + (e.X - pointList[i].X);
diffY = pointList[i].Y + (e.Y - pointList[i].Y);
pointList[i] = new Point(diffX, diffY);
Invalidate();
}
}
}
private void Form1_MouseUp(object sender, MouseEventArgs e)
{
pickedIndexRight = -1;
Invalidate();
}
private double Distance(Point p1, Point p2) //calculate distance between two points
{
double d = Math.Sqrt((p2.X - p1.X) * (p2.X - p1.X) + (p2.Y - p1.Y) * (p2.Y - p1.Y));
return d;
}
private void Form1_Paint(object sender, PaintEventArgs e)
{
foreach (Point myPoint in pointList)
{
e.Graphics.DrawRectangle(Pens.Black, myPoint.X, myPoint.Y, 1, 1);
}
}
Ok, so I need my app to draw points on a form with every left click - that works just fine. All the points are stored in a list pointList and then the Paint form draws them each one by one.
The thing is, i need the program to have another functionality - moving all points in parallel by dragging one of the points with the right mouse button - I already wrote the function for that but I can't figure out why my code doesn't work properly - it seems to screw up the entire list when i right click.
I'm all out of ideas, I'd be thankful for any hints.

In this line:
diffX = pointList[i].X + (e.X - pointList[i].X);
The pointList[i].X terms cancel out. So it's just:
diffX = e.X;
You're assigning the current mouse position to every point. If you want to move all the points by the distance that the mouse has moved, but keep their positions relative to each other, you need to remember the previous position of the mouse, so you can compare it with the new position. The difference between new and old mouse positions is the correct amount to add to each point.
So add a field such as:
Point oldMousePosition;
And initialise it when the button-down occurs. In each move event:
pointList[i] = new Point(pointList[i].X + (e.X - oldMousePosition.X),
pointList[i].Y + (e.Y - oldMousePosition.Y))

Related

How to draw a Rectangle in any direction after MouseDown using C#?

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.
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
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 !!
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();
}

How do I move the Image inside the picturebox?

I want an Image to move inside the picturebox. It shouldn't be possible that you can drag it out. I found an answer with the Padding and tried it out but it drags in the opposite direction. So I tried out to switch it with Right and down, but it is not getting dragged. Also I found an answer where the picturebox get moved but then it can be moved out of the form and isn't there anymore. So I need something that can just move the picture inside the picturebox or something that moves the picturebox but not out of the form.
private bool Dragging;
private Point lastLocation;
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
Dragging = true;
lastLocation = e.Location;
}
}
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (Dragging == true)
{
int dx = e.X - lastLocation.X;
int dy = e.Y - lastLocation.Y;
pictureBox1.Padding = new Padding(0, 0, Padding.Right - dx, Padding.Bottom - dy);
pictureBox1.Invalidate();
}
}
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
Dragging = false;
}
Do this
pictureBox1.Padding = new Padding(Padding.Left + dx, Padding.Top + dy, Padding.Right - dx, Padding.Bottom - dy);
instead of this
pictureBox1.Padding = new Padding(0, 0, Padding.Right - dx, Padding.Bottom - dy);
I have done it by creating a panel and inserted image box inside of it.It's working in my side.Please find the code blow .
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
int moveLeftRight = e.X + pictureBox1.Left - MouseDownLocation.X;
int moveUpDown = e.Y + pictureBox1.Top - MouseDownLocation.Y;
int panlTopLocation = panel1.Location.Y;
int panlbottomLocation = panel1.Location.Y + panel1.Height - pictureBox1.Height;
int panlLeftLocation = panel1.Location.X;
int panlRightLocation = panel1.Location.X + panel1.Width - pictureBox1.Width ;
if (panlLeftLocation < moveLeftRight)
{
if (panlRightLocation > moveLeftRight)
{
pictureBox1.Left = moveLeftRight;
}
else
{
pictureBox1.Left = panlRightLocation;
}
}
else
{
pictureBox1.Left = panlLeftLocation;
}
if (panlTopLocation < moveUpDown)
{
if (panlbottomLocation > moveUpDown)
{
pictureBox1.Top = moveUpDown;
}
else
{
pictureBox1.Top = panlbottomLocation;
}
}
else
{
pictureBox1.Top = panlTopLocation;
}
}
}

Dragging of the form moves the form down

I have a Windows Form, My task is to add drag function to the form. "VendorMasterList" is a label. I have added mouse move, mouse down and mouse up events to that label.
If i tried to drag, the form moves down and then only able to drag the way i want. My question is why its going down?This is my code
private Point startPoint = new Point(0, 0);
private bool isDragging = false;
private void lblHeader_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true; // _dragging is your variable flag
startPoint = new Point(e.X, e.Y);
}
private void lblHeader_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
private void lblHeader_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
Point p = PointToScreen(e.Location);
this.Location = new Point(p.X - this.startPoint.X, p.Y - this.startPoint.Y);
}
}
Is there any way to fix this?
Newly added image
I haven' tried your code, but what I see is only partially correct :-)
You save the initial coordinate, which is relative to the upper left corner of the control that's clicked, but you need to save screen coordinates.
Then the mouse is moved and again you get a point relative to that corner. You're missing a few relevant things:
You need to calculate a delta between the two points based on the screen coordinates, otherwise moving the window underneath the cursor gives you wrong values.
You need to add this delta to the form's current location
You need to save the new mouse position to calculate the next delta correctly
The current mouse position based on screen coordinates can be obtained through Cursor.Position.
So your code should read:
private void lblHeader_MouseDown(object sender, MouseEventArgs e)
{
isDragging = true; // _dragging is your variable flag
startPoint = Cursor.Position;
}
private void lblHeader_MouseUp(object sender, MouseEventArgs e)
{
isDragging = false;
}
private void lblHeader_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
Point p = Cursor.Position;
int deltaX = p.X - startPoint.X;
int deltaY = p.Y - startPoint.Y;
startPoint = p;
this.Left += deltaX;
this.Top += deltaY;
}
}
I just placed a panel on a form and implented the above, which worked.
#IInspector is right when he says that this approach is actually not very good, as it doesn't take into account that Windows can actually handle all this for you.
An alternative approach (and the better one) I'd take is:
Override the WndProc method as shown below
Done. No more mouse handling
The following is an example of how you could override WndProc to do what you need:
protected override void WndProc(ref Message m)
{
const UInt32 WM_NCHITTEST = 0x0084;
const UInt32 HTCAPTION = 0x2;
bool handled = false;
if (m.Msg == WM_NCHITTEST)
{
if (<cursor is within the caption area>)
{
m.Result = (IntPtr)HTCAPTION;
handled = true;
}
}
if (!handled)
base.WndProc(ref m);
}
To restrict the area in which the window can be moved, you could use the following. Of course, #IInspectable will disagree, but you went this road :-)
private void lblHeader_MouseMove(object sender, MouseEventArgs e)
{
if (isDragging)
{
Point p = Cursor.Position;
int deltaX = p.X - startPoint.X;
int deltaY = p.Y - startPoint.Y;
startPoint = p;
int fX = this.Left + deltaX;
int fY = this.Top + deltaY;
if (fX >= 0 && fX + this.Width < Area.Width) this.Left = fX;
if (fY >= 0 && f> + this.Height < Area.Height) this.Top = fY;
}
}

Set location of mouse

I cannot fix my mistake : /
if (Cursor.Position = new Point(x, y)
I have an error on x,y, and I want to change to 50,99 for example
First of all you should trig mouseClick event. It's quite simple:
this.MouseClick += new System.Windows.Forms.MouseEventHandler(this.Form1_MouseClick);
Then you should handle the event. Suppose your desired position is (x,y)=(100,100):
private void Form1_MouseClick(object sender, MouseEventArgs e)
{
int xDesired = 100;
int yDesired = 100;
if (e.X == xDesired && e.Y == yDesired)
MessageBox.Show("Certain point clicked.");
}

Stop dragging picturebox c #

I have a picturebox and movement just right and to the left, but when moving it to the left or right edge of the picturebox appears in the middle of the form , as the picture below
This thus
what I want is when moving left or right when the board of picturebox were in the same position of the board form the image can not be more moves , just to the other lado.Conforme the image below
Follows the script:
private void imagemPictureBox_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button==MouseButtons.Left)
{
x = e.X;
//y = e.Y;
}
}
private void imagemPictureBox_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
imagemPictureBox.Left += (e.X - x);
//imagemPictureBox.Top += (e.Y - y);
}
}
Try something like this:
// the point in the PB where we grab it:
Point mDown;
void imagemPictureBox_MouseDown(object sender, MouseEventArgs e)
{
// grab the pb
mDown = e.Location;
}
void imagemPictureBox_MouseMove(object sender, MouseEventArgs e)
{
// new position:
int x = imagemPictureBox.Left + e.X - mDown.X;
int y = imagemPictureBox.Top + e.Y - mDown.Y;
// limit to form size:
x = Math.Min(Math.Max(x, 0), this.ClientSize.Width - imagemPictureBox.Width);
y = Math.Min(Math.Max(y, 0), this.ClientSize.Height - imagemPictureBox.Height);
// move the pb:
imagemPictureBox.Location = new Point(x, y);
}
void imagemPictureBox_MouseUp(object sender, MouseEventArgs e)
{
//release it (optional)
mDown = Point.Empty;
}

Categories