drag two lines together by clicking on intersection point - c#

I have a mainPicture box that contains Two picture boxes (_pic1 , _pic2) .
I can drag _pic1 and drag _pic2 too.
But I want to when I do mouse down on intersection of two picture boxes, I could drag two lines together.
So I should get intersection position . by below code I could not.
_pic2.MouseUp += new MouseEventHandler(_pic1_MouseUp);
_pic2.MouseDown += new MouseEventHandler(_pic1_MouseDown);
Point p = new Point();
bool interSection;
private void _pic1_MouseDown(object sender, MouseEventArgs e)
{
p = e.Location;
dragging = true;
dragPoint = new Point(e.X, e.Y);
this.Cursor = Cursors.SizeAll;
Rectangle p1 = this._pic1.ClientRectangle;
p1.Offset(this._pic1.Location);
Rectangle p2 = this._pic2.ClientRectangle;
p2.Offset(this._pic2.Location);
//bool z = p1.Contains(p) it returns false
//bool zz = p2.Contains(p) it returns false too
if (p1.Contains(p) && p2.Contains(p))
{
interSection = true;
}
}
private void _pic_MouseMove(object sender, MouseEventArgs e)
{
if (interSection)
{
//drag two lines together
_pic1.Location = new Point(_pic1.Location.X + e.X - dragPoint.X, _pic1.Location.Y + e.Y - dragPoint.Y);
_pic2.Location = new Point(_pic2.Location.X + e.X - dragPoint.X, _pic2.Location.Y + e.Y - dragPoint.Y);
return;
}
if (dragging)
{
_pic_1.Location = new Point(_pic1.Location.X + e.X - dragPoint.X, _pic1.Location.Y + e.Y - dragPoint.Y);
}
}
private void _pic1_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
this.Cursor = Cursors.Default;
}
private void _pic2_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
{
_pic2.Location = new Point(_pic2.Location.X + e.X - dragPoint.X, _pic2.Location.Y + e.Y - dragPoint.Y);
}
}
image :
http://tinypic.com/view.php?pic=ix8bab&s=8

You can test two Rectangles for Intersection like this:
if (_pic1.Bounds.IntersectsWith(_pic2.Bounds) ) // do stuff
And you can get the intersection like this:
Rectangle R = _pic1.Bounds;
R.Intersect(_pic2.Bounds);
Now you can test it again:
if (R != Rectangle.Empty)
Or find the Center:
Point center = new Point(R.X + R.Width / 2, R.Y + R.Height / 2);
Or test whether the Mouse was clicked on the intersection:
if (R.Contains(e.Location) // ..

Related

MouseKeyHook c# path of relocation of a mouse

How to receive a path of relocation of a mouse between the 1st clicking and the 2nd?
private void OnMouseDown(object sender, MouseEventArgs e)
{
Log(string.Format("MouseDown \t\t {0}\n", e.Button));
LogMousePosition(string.Format("\n\nx={0:0000}\ny={1:0000}", e.X, e.Y));
if (lastX != -100 && lastY != -100)
{
shortestDistanse = Convert.ToInt64(Math.Sqrt((Math.Pow(e.X - lastX, 2)) + (Math.Pow(e.Y - lastY, 2))));
LogMousePosition(string.Format("\nshortDistanse\t\t {0}\n", shortestDistanse));
}
lastX = e.X;
lastY = e.Y;
}
If you just want the distance between the two points use pythagora.
Example:
private double GetDistance(Point p1, Point p2) {
int x = Math.Abs(p1.X - p2.X);
int y = Math.Abs(p1.Y - p2.Y);
return Math.Sqrt( Math.Pow(x, 2) + Math.Pow(y, 2));
}
You may try something like
// form fields
bool pressed;
List<Point> path;
private void Form1_MouseDown(object sender, MouseEventArgs e)
{
if (!pressed)
{
pressed = true;
path = new List<Point>();
path.Add(e.Location);
}
else
{
pressed = false;
// calculate distance from List
// log distance
}
}
private void Form1_MouseMove(object sender, MouseEventArgs e)
{
if (pressed)
{
path.Add(e.Location);
}
}
However, the MouseMove event will be triggered only above the form. If the mouse is outside of it - distance is not taken into account. It also doesn't work when moving over other controls, but we can add to them MouseMove handlers too.
I could make
string pathMList = "C:\\logs/testMList.txt";`
private void HookManager_MouseMove(object sender, MouseEventArgs e)
{
labelMousePosition.Text = string.Format("x={0:0000}; y={1:0000}", e.X, e.Y);
if (mouseDownMove == 2)
{
LogMList(string.Format("\nx={0:0000} y={1:0000}", e.X, e.Y));
}
}
private void OnMouseDown(object sender, MouseEventArgs e)
{
Log(string.Format("MouseDown \t\t {0}\n", e.Button));
LogMousePosition(string.Format("\n\nx={0:0000}\ny={1:0000}", e.X, e.Y));
if (lastX != -100 && lastY != -100)
{
shortestDistanse = Convert.ToInt64(Math.Sqrt((Math.Pow(e.X - lastX, 2)) + (Math.Pow(e.Y - lastY, 2))));
LogMousePosition(string.Format("\nshortDistanse\t\t {0}\n", shortestDistanse));
LogMList(string.Format("\n\n NEW CLICK\n\nx={0:0000} y={1:0000}", e.X, e.Y));
}
lastX = e.X;
lastY = e.Y;
mouseDownMove = 2;
}

DragDrop to move a picture box at run time

I have a PictureBox called pic, placed inside another PictureBox called picTrack.
My goal is to be able to let the user, at run time, change the position of pic by draging it.
This is what I have so far:
int x_offset = 0; // any better to do this without having a global variable?
int y_offset = 0;
void pic_MouseDown(object sender, MouseEventArgs e)
{
PictureBox me = (PictureBox)sender;
x_offset = me.Left - e.X;
y_offset = me.Top - e.Y;
}
void pic_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
PictureBox me = (PictureBox)sender;
me.Left = e.X + x_offset;
me.Top = e.Y + y_offset;
picTrack.Invalidate();
}
}
This code only works at a very basic level. I have 2 problems with it:
1.) picTrack is not updated if the user does not let go of the mouse button. Ghost images of pic can be seen while pic is getting moved around (it's like pic is having a tail).
2.) pic is "giggling" (i.e. rapidly shaking left and right, up and down, around its location).
How should I solve these 2 problems and create a more smooth drag & drop? Thanks.
Here this actually works, I've written quite a few dragging things before.. it may not be perfect but this should give you something to work with.
Point dragPoint = Point.Empty;
bool dragging = false;
private void pic_MouseDown(object sender, MouseEventArgs e)
{
dragging = true;
dragPoint = new Point(e.X, e.Y);
}
private void pic_MouseMove(object sender, MouseEventArgs e)
{
if (dragging)
pic.Location = new Point(pic.Location.X + e.X - dragPoint.X, pic.Location.Y + e.Y - dragPoint.Y);
}
private void pic_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
}
See, if you were dragging a local picture that you were just rendering yourself, this wouldn't be right.. but since you are moving a control after you move it, the new move coordinates are relative to the control. Therefore, you do not need to update dragPoint to the last position on move. If you were just moving a shape/image you were rendering OnPaint, you'd have to do update the drag point each movement.
There's one improvement you could make, if desired, which is to only start dragging if the user moves the cursor a certain distance D. For example, something like this:
Point dragPoint = Point.Empty;
bool dragging = false;
bool mouseDown = false;
private void pic_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
dragPoint = new Point(e.X, e.Y);
}
private void pic_MouseMove(object sender, MouseEventArgs e)
{
int deltaX = e.X - dragPoint.X;
int deltaY = e.Y - dragPoint.Y;
if (!dragging && mouseDown && deltaX * deltaX + deltaY * deltaY > 100)
dragging = true;
if (dragging)
pic.Location = new Point(pic.Location.X + deltaX, pic.Location.Y + deltaY);
}
private void pic_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
mouseDown = false;
}
Which checks if the user has moved the mouse 10 pixels (sqrt of 100).
If you don't want a global, you could try implementing your own behavior system and creating a reusable piece of code that you can attach to things you want to move. Something like this:
public class Behavior<T> where T : class
{
public T AssociatedObject
{
get;
private set;
}
public Behavior(T associatedObject)
{
this.AssociatedObject = associatedObject;
}
public virtual void Attach() { }
public virtual void Detach() { }
}
public class DragBehavior : Behavior<Control>
{
Point dragPoint = Point.Empty;
bool dragging = false;
bool mouseDown = false;
public DragBehavior(Control c) : base(c)
{
}
public override void Attach()
{
AssociatedObject.MouseDown += new MouseEventHandler(control_MouseDown);
AssociatedObject.MouseMove += new MouseEventHandler(control_MouseMove);
AssociatedObject.MouseUp += new MouseEventHandler(control_MouseUp);
}
private void control_MouseUp(object sender, MouseEventArgs e)
{
dragging = false;
mouseDown = false;
}
private void control_MouseMove(object sender, MouseEventArgs e)
{
int deltaX = e.X - dragPoint.X;
int deltaY = e.Y - dragPoint.Y;
if (mouseDown && deltaX * deltaX + deltaY * deltaY > 100)
dragging = true;
if (dragging)
AssociatedObject.Location = new Point(AssociatedObject.Location.X + deltaX, AssociatedObject.Location.Y + deltaY);
}
private void control_MouseDown(object sender, MouseEventArgs e)
{
mouseDown = true;
dragPoint = new Point(e.X, e.Y);
}
public override void Detach()
{
AssociatedObject.MouseDown -= new MouseEventHandler(control_MouseDown);
AssociatedObject.MouseMove -= new MouseEventHandler(control_MouseMove);
AssociatedObject.MouseUp -= new MouseEventHandler(control_MouseUp);
}
}
public partial class Form1 : Form
{
DragBehavior dragger;
public Form1()
{
InitializeComponent();
DoubleBuffered = true;
dragger = new DragBehavior(pic);
dragger.Attach();
}
}
Maybe that is better than "creating a global variable" (or more like creating a member variable in your form. =)
Try this
int x_offset = 0; // any better to do this without having a global variable?
int y_offset = 0;
private void pic_MouseDown(object sender, MouseEventArgs e)
{
PictureBox me = (PictureBox)sender;
x_offset = e.X;
y_offset = e.Y;
}
private void pic_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
PictureBox me = (PictureBox)sender;
me.Left = e.X + me.Left - x_offset;
me.Top = e.Y + me.Top - y_offset;
}
}

How to get the x, y, on a specific form.

I'v been making a program where the user clicks, and wherever they drag their mouse, it draws a line to. It works, but it draws the lines in the wrong place. I think its because I am getting the x y of the whole form, not my panel. Heres the code:
private void panel2_MouseDown(object sender, MouseEventArgs e)
{
vars.x = MousePosition.X;
vars.y = MousePosition.Y;
label1.Text = vars.x + ", " + vars.y;
vars.isDrawing = true;
}
private void panel2_MouseMove(object sender, MouseEventArgs e)
{
if (vars.isDrawing == true)
{
if (e.Button == MouseButtons.Left)
{
int x2 = MousePosition.X;
int y2 = MousePosition.Y;
Random randomGen = new Random();
Color randomColor = Color.FromArgb(randomGen.Next(255), randomGen.Next(255), randomGen.Next(255));
Pen line = new Pen(randomColor, 1);
System.Drawing.Graphics formGraphics = panel2.CreateGraphics();
formGraphics.DrawLine(line, vars.x, vars.y, x2, y2);
}
}
}
Use e.X and e.Y instead of MousePosition.X and MousePosition.Y

How can i check on pictureBox1 mouse leave event if the user is in mouse down event?

What i mean is that i want to activate the mouse leave event only when the user is moving the mouse pointer out of the pictureBox1 client area. This happens only if he presses down the left mouse button but not if the user doesn't press the left mouse button, i.e he can move the mouse around free and the event wont do anything.
I have a variable in the top of Form1 called mouseLeave type bool.
In constructor i made it to be false;
In the pictureBox1 mouse down event i did the mouseLeave variable to be true.
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
label1.Visible = true;
label4.Visible = true;
// find the index that is closest to the current mouse location
float t = wireObject1.GetIndexByXY(e.X, e.Y, 5);
if (t == -1)
{
button3.Enabled = false;
}
else
{
button3.Enabled = true;
{
selectedIndex = t;
mouseMove = true;
mouseLeave = true;
In the pictureBox1 mouse move event i check if mouseMove is true then move the point drag it around:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseMove == true)
{
Point NewPoint = e.Location;
{
wireObject1.MovePoint(selectedIndex, NewPoint, NewPoint); // when moving a point dragging the other point is vanished deleted. To check why !
label1.Text = "{X = " + NewPoint.X + "}" + " " + "{Y = " + NewPoint.Y + "}";
pictureBox1.Refresh();
}
}
else
{
label19.Text = "{X = " + e.X + "}" + " " + "{Y = " + e.Y + "}";
}
}
So when the user click on the mouse left button without leave it and drag the point then the point will move aorund the pictureBox1 client area.
Now in the pictureBox1 mouse leave event i did:
private void pictureBox1_MouseLeave(object sender, EventArgs e)
{
if (mouseLeave == true)
{
mouseMove = false;
}
}
But it dosent work. I add a point drag it move it around but this event activate do something only when i move the mouse pointer out of the pictureBox1 area without dragging the point only when im not clicking down the left mouse button.
What i want is that only when i click down the mouse left button and move it around like in the mouse move event only then this leave event will do something in this case will make mouseMove to be false.
So the user will not be able to drag the point out of the pictureBox1 area. What should i do in the mouse leave event then ?
EDITED**
This the button1 click where i add each time a new point to the pictureBox1 area.
And the paint event where i draw the points.
Maybe this will help to solve the problem where it stop but not in the right places when drag out of bounds of pictureBox.
private void button1_Click(object sender, EventArgs e)
{
halfX = pictureBox1.ClientRectangle.Width / 2;
halfY = pictureBox1.ClientRectangle.Height / 2;
Random rnd = new Random();
offsetX = rnd.Next(-10, 10);
offsetY = rnd.Next(-10, 10);
wireObject1.addPoint(halfX + offsetX, halfY + offsetY);
if (wireObjectCoordinates1 == null)
wireObjectCoordinates1 = new WireObjectCoordinates() { FrameNumber = currentFrameIndex };
wireObjectCoordinates1.Point_X.Add(halfX + offsetX);
wireObjectCoordinates1.Point_Y.Add(halfY + offsetY);
wireObjectAnimation1._coordinatesList.Add(wireObjectCoordinates1);
pictureBox1.Refresh();
numberOfPoints++;
label5.Text = "{X = " + (halfX + offsetX) + "}" + " " + "{Y = " + (halfY + offsetY) + "}";
label5.Visible = true;
label7.Visible = true;
label16.Text = numberOfPoints.ToString();
label16.Visible = true;
label15.Visible = true;
buttonLockMode = true;
button8.Enabled = true;
button4.Enabled = true;
}
private void pictureBox1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
Point connectionPointStart;
Point connectionPointEnd;
Graphics g = e.Graphics;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
SolidBrush brush = new SolidBrush(Color.Red);
Pen p = new Pen(brush);
for (int idx = 0; idx < wireObject1._point_X.Count; ++idx)
{
Point dPoint = new Point((int)wireObject1._point_X[idx], (int)wireObject1._point_Y[idx]);
dPoint.X = dPoint.X - 5; // was - 2
dPoint.Y = dPoint.Y - 5; // was - 2
Rectangle rect = new Rectangle(dPoint, new Size(10, 10));
g.FillEllipse(brush, rect);
// g.FillEllipse(brush, rect);
}
for (int i = 0; i < wireObject1._connectionstart.Count; i++)
{
int startIndex = wireObject1._connectionstart[i];
int endIndex = wireObject1._connectionend[i];
connectionPointStart = new Point((int)wireObject1._point_X[startIndex], (int)wireObject1._point_Y[startIndex]);
connectionPointEnd = new Point((int)wireObject1._point_X[endIndex], (int)wireObject1._point_Y[endIndex]);
p.Width = 4;
g.DrawLine(p, connectionPointStart, connectionPointEnd);
}
}
I think i solved it by changing the if in the mouse move to this:
if (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X + 5,NewPoint.Y) || (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X - 5,NewPoint.Y) ||
!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X, NewPoint.Y + 5)) || (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X, NewPoint.Y - 5)))
So the move event should look like this:
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
if (mouseMove == true)
{
mouseDrag = true;
Point NewPoint = e.Location;
if (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X + 5,NewPoint.Y) || (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X - 5,NewPoint.Y) ||
!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X, NewPoint.Y + 5)) || (!((PictureBox)sender).ClientRectangle.Contains(NewPoint.X, NewPoint.Y - 5)))
{
if (mouseDrag)
{
mouseMove = false;
return;
}
}
{
wireObject1.MovePoint(selectedIndex, NewPoint, NewPoint); // when moving a point dragging the other point is vanished deleted. To check why !
label1.Text = "{X = " + NewPoint.X + "}" + " " + "{Y = " + NewPoint.Y + "}";
pictureBox1.Refresh();
}
}
else
{
label19.Text = "{X = " + e.X + "}" + " " + "{Y = " + e.Y + "}";
}
}
Instead of using the MouseLeave event you can check to see if the Mouse Location is in your PictureBox's Client Rectangle in your MouseMove Event, something like this.
private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
{
{
if (mouseMove == true)
{
Point NewPoint = e.Location;
if (!((PictureBox)sender).ClientRectangle.Contains(NewPoint))
{
if (mouseLeave)
{
mouseMove = false;
return;
}
}
wireObject1.MovePoint(selectedIndex, NewPoint, NewPoint); // when moving a point dragging the other point is vanished deleted. To check why !
label1.Text = "{X = " + NewPoint.X + "}" + " " + "{Y = " + NewPoint.Y + "}";
pictureBox1.Refresh();
}
else
{
label19.Text = "{X = " + e.X + "}" + " " + "{Y = " + e.Y + "}";
}
}
}
Do something like this:
private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
{
pictureBox1.MouseMove -= OnMouseMove;
}
private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
pictureBox1.MouseMove += OnMouseMove;
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
Debug.WriteLine(e.Location);
}
Where "OnMouseMove" is not attached to pictureBox event by default.

Move the rectangle with the mouse

I wrote this code:
private struct MovePoint
{
public int X;
public int Y;
}
private void Image_MouseDown(object sender, MouseEventArgs e)
{
FirstPoint = new MovePoint();
FirstPoint.X = e.X;
FirstPoint.Y = e.Y;
}
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if(e.Button == MouseButtons.Left)
{
if(FirstPoint.X > e.X)
{
Rectangle.X = FirstPoint.X - e.X;
//Rectangle.Width -= FirstPoint.X - e.X;
} else
{
Rectangle.X = FirstPoint.X + e.X;
//Rectangle.Width += FirstPoint.X + e.X;
}
if(FirstPoint.Y > e.Y)
{
Rectangle.Y = FirstPoint.Y - e.Y;
//Rectangle.Height -= FirstPoint.Y - e.Y;
} else
{
Rectangle.Y = FirstPoint.Y + e.Y;
//Rectangle.Height += FirstPoint.Y + e.Y;
}
Image.Invalidate();
}
}
private void Image_Paint(object sender, PaintEventArgs e)
{
if(Pen != null) e.Graphics.DrawRectangle(Pen, Rectangle);
}
Rectangle moves, but with inversion (it should not be). Can you help?
The mathematics in your mouse-move handler for moving the rectangle based on the mouse-movements seems quite off; I think you want something like this:
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
int initialX = 0, initialY = 0; // for example.
Rectangle.X = (e.X - FirstPoint.X) + initialX;
Rectangle.Y = (e.Y - FirstPoint.Y) + initialY;
Image.Invalidate();
}
}
This way, the rectangle's upper left corner will follow the mouse by tracking the delta between the initial mouse-down location and the current mouse location. Note however that each time you re-click and drag, the rectangle will move back to its original location.
If, instead, you want the Rectangle to 'remember' its position across multiple click-and-drag operations (i.e. not to be reinitialized to its initial location on mouse-down) you can do:
private void Image_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
// Increment rectangle-location by mouse-location delta.
Rectangle.X += e.X - FirstPoint.X;
Rectangle.Y += e.Y - FirstPoint.Y;
// Re-calibrate on each move operation.
FirstPoint = new MovePoint { X = e.X, Y = e.Y };
Image.Invalidate();
}
}
One other suggestion: There's no need to create your own MovePoint type when there's already the System.Drawing.Point type. Also, in general, try not to create mutable structs.

Categories

Resources