I just want to draw an ellipse dynamically when running . mouseclick then mousemove and then mouse release that's it . But, confused of detecting point(x,y).Can someone help me out of this
You basically just need to record the starting point from the MouseDown event, so that you can make the ellipse with the point recorded from the MouseUp event.
Simple demo:
public partial class Form1 : Form {
private Point _StartPoint;
private List<Rectangle> _Ovals = new List<Rectangle>();
public Form1() {
InitializeComponent();
this.MouseDown += new MouseEventHandler(Form1_MouseDown);
this.MouseUp += new MouseEventHandler(Form1_MouseUp);
this.Paint += new PaintEventHandler(Form1_Paint);
}
void Form1_Paint(object sender, PaintEventArgs e) {
foreach (Rectangle r in _Ovals)
e.Graphics.FillEllipse(Brushes.Red, r);
}
void Form1_MouseDown(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left)
_StartPoint = e.Location;
}
void Form1_MouseUp(object sender, MouseEventArgs e) {
if (e.Button == MouseButtons.Left) {
_Ovals.Add(MakeRectangle(_StartPoint, e.Location));
this.Invalidate();
}
}
private Rectangle MakeRectangle(Point p1, Point p2) {
int x = (p1.X < p2.X ? p1.X : p2.X);
int y = (p1.Y < p2.Y ? p1.Y : p2.Y);
int w = Math.Abs(p1.X - p2.X);
int h = Math.Abs(p1.Y - p2.Y);
return new Rectangle(x, y, w, h);
}
}
Related
class Cycle : Form1
{
public void Draw(Graphics G,Brush b, float x, float y, float w, float h)
{
G.FillEllipse( b, x, y, w, h);
}
}
This is my Cycle class that inherits from Form1.
List<Point> star = new List<Point>();
List<Point> endd = new List<Point>();
private void Panel1_MouseDown(object sender, MouseEventArgs e)
{
moving = true;
Start = e.Location;
star.Add(e.Location);
}
private void Panel1_MouseMove(object sender, MouseEventArgs e)
{
if (moving)
{
End = e.Location;
Panel1.Invalidate();
}
}
private void Panel1_MouseUp(object sender, MouseEventArgs e)
{
endd.Add(e.Location);
moving = false;
}
These are my mouse event args that keeps locations.
private void Panel1_Paint(object sender, PaintEventArgs e)
{
Cycle c = new Cycle();
if (End.Y > Start.Y && End.X > Start.X)
{
foreach (Point pt in star)
{
foreach(Point p in endd)
c.Draw(e.Graphics, brush, pt.X - (p.X - pt.X) / 2 - (p.Y - pt.Y) / 2, pt.Y - (p.Y - pt.Y) / 2 - (p.X - pt.X) / 2, ((p.X - pt.X) + (p.Y - pt.Y)), ((p.X - pt.X) + (p.Y - pt.Y)));
}
}
}
And this code draws ellipses in panel. However the first ellipse has been drawn perfect but other ellipses got so big that covered all the panel.
I want to keep locations because after drawing 3-4 ellipses I will try to save the points into .txt. After that I will load it to draw again. But there is this problem in drawing :/
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;
}
I am having the user click a point on screen, and until they choose the second point, the line will follow the cursor. Once the second point is drawn it will stay. I am using a double buffer like so:
public void EnableDoubleBuffering()
{
this.SetStyle(ControlStyles.DoubleBuffer | ControlStyles.UserPaint | ControlStyles.AllPaintingInWmPaint, true);
}
I will call that function in the Form_Load();
I am doing the draw like so:
void draw(int x1, int y1, int x2, int y2)
{
Graphics formGraphics = pictureEdit1.CreateGraphics();
Pen myPen = new Pen(Color.Red, 3);
formGraphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
formGraphics.DrawLine(myPen, x1, y1, x2, y2);
myPen.Dispose();
formGraphics.Dispose();
}
I repetatively call that function from the MouseMove event;
void pictureEdit1_MouseMove(object sender, MouseEventArgs e)
{
if (click == 1 && !rightClicked)
{
pictureEdit1.Invalidate();
trail.X = e.X;
trail.Y = e.Y;
draw(p1.X, p1.Y, trail.X, trail.Y);
}
else if (click != 1)
{
draw(p1.X, p1.Y, trail.X, trail.Y);
}
}
There is a very slight flicker that occurs and it is driving me insane! Please help, thanks.
This code will do what you want, without any flicker. Keep in mind, I don't know what you want to do after the line is drawn, so it will vanish. But this should give you a pretty good idea of how to do this:
public partial class Form1 : Form
{
private Point _firstPoint;
private Point _secondPoint;
private bool _hasClicked;
public Form1()
{
InitializeComponent();
_hasClicked = false;
_firstPoint = new Point();
_secondPoint = new Point();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void pictureEdit1_MouseMove(object sender, MouseEventArgs e)
{
_secondPoint.X = e.X;
_secondPoint.Y = e.Y;
pictureEdit1.Refresh();
}
private void pictureEdit1_MouseUp(object sender, MouseEventArgs e)
{
if (!_hasClicked)
{
_firstPoint.X = e.X;
_firstPoint.Y = e.Y;
}
_hasClicked = !_hasClicked;
pictureEdit1.Refresh();
}
private void pictureEdit1_Paint(object sender, PaintEventArgs e)
{
if (_hasClicked)
e.Graphics.DrawLine(Pens.Red, _firstPoint, _secondPoint);
}
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;
}
}
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.