I am working on a little application in which I draw rectangles and move them around with the mouse.
I have some logic which has some bugs inside and I can't find them.
The first click and drag always puts the rectangle on position around (0,0), and the second click and drag will work just fine.
The third click will again put rectangle on (0,0), and with the fourth click I can drag it again.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Pr
{
public partial class Form1 : Form
{
int save=0;
Timer timer1 = new Timer();
private Point MouseDownLocation;
private List<Rectangle> rectangles;
public Form1()
{
InitializeComponent();
rectangles = new List<Rectangle>();
panel1.Paint += panel1_Paint;
this.DoubleBuffered = true;
timer1.Interval = 10;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
Refresh();
}
public void PopulateTable(int x, int y)
{
rectangles.Add(new Rectangle (500, 10, x, y));
panel1.Invalidate();
}
void panel1_Paint(object sender, PaintEventArgs e)
{
foreach( var rectangle in rectangles)
{
using (var b=new SolidBrush(Color.HotPink))
{
e.Graphics.FillRectangle(b, rectangle);
}
}
}
private void Form1_Load(object sender, EventArgs e)
{
this.WindowState = FormWindowState.Maximized;
this.MinimumSize = this.Size;
this.MaximumSize = this.Size;
}
private void panel1_MouseMove(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
for (var i = 0; i < rectangles.Count; i++)
{
if (Cursor.Position.X >= rectangles[i].X &&
Cursor.Position.X <= rectangles[i].X + rectangles[i].Width &&
Cursor.Position.Y >= rectangles[i].Y &&
Cursor.Position.Y <= rectangles[i].Y + rectangles[i].Height)
{
save = i;
Rectangle rect = rectangles[save];
rect.X = e.X - MouseDownLocation.X;
rect.Y = e.Y - MouseDownLocation.Y;
rectangles[save] = rect;
panel1.Invalidate();
break;
}
}
}
}
protected void panel1_OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
MouseDownLocation = e.Location;
}
private void panel2_Paint(object sender, PaintEventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
PopulateTable(Convert.ToInt32(textBox1.Text), Convert.ToInt32(textBox2.Text));
}
}
}
I bet my moving logic isn't so fine, so i hope someone will bring some idea.
EDIT: I just changed
rect.X = e.X - MouseDownLocation.X;
rect.Y = e.Y - MouseDownLocation.Y;
to
rect.X = e.X;
rect.Y = e.Y;
It works better, but I have one problem.
When I click, the rectangle moves so that upper left point of rectangle is at the mouse position.
I want it so that the rectangle stays at the same position, unless I move it.
EDIT 2
I changed part of code to:
rect.X = rect.X + e.X - MouseDownLocation.X;
rect.Y = rect.Y + e.Y - MouseDownLocation.Y;
But, now the rectangle moves too fast, it goes much faster than the mouse.
Could that be problem in timer?
EDIT 3
MouseDownLocatioon must be the problem. If code without it works (with rectangle moving on mouse coordinates), that means something's wrong with that.
Tried to do:
protected void panel1_OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
MouseDownLocation = panel1.PointToScreen(e.Location);
}
Didn't help.
Tried to debug, looks like Y coordinate makes problem. It just makes too big offset in Y coordinate.
I did a mouse movement from left to right (only X coordinate), and debugging showed me this:
rect.X = 500
rect.Y = 100
e.X = 848
e.Y = 216
MouseDownLocation.X = 850
MouseDownLocation.Y = 238
That means that difference for such move is for x only 2, and for y 22!
EDIT 4: Managed to solve it!
Just have to add two lines of code:
MouseDownLocation.X = e.X;
MouseDownLocation.Y = e.Y;
Because, if i held down mouse button, it wouldn't refresh new MouseDownLocation.