Я работаю над небольшим приложением, в котором я рисую прямоугольники и перемещаю их с помощью мыши.C# ошибка в движущемся прямоугольнике с мышью
У меня есть логика, в которой есть некоторые ошибки внутри, и я не могу их найти.
Первый щелчок и перетаскивание всегда помещает прямоугольник в положение вокруг (0,0), а второй щелчок и перетаскивание будут работать нормально.
Третий щелчок снова поместит прямоугольник на (0,0), и с четвертым щелчком я смогу перетащить его снова.
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));
}
}
}
Бьюсь об заклад, моя движущаяся логика не так хороша, поэтому я надеюсь, что кто-то привнесет какую-то идею.
EDIT: Я только что изменил
rect.X = e.X - MouseDownLocation.X;
rect.Y = e.Y - MouseDownLocation.Y;
в
rect.X = e.X;
rect.Y = e.Y;
Он работает лучше, но у меня есть одна проблема.
Когда я нажимаю, прямоугольник перемещается так, что верхняя левая точка прямоугольника находится в позиции мыши.
Я хочу, чтобы прямоугольник оставался в одном и том же положении, если только не переместил его.
EDIT 2
Я изменил часть кода:
rect.X = rect.X + e.X - MouseDownLocation.X;
rect.Y = rect.Y + e.Y - MouseDownLocation.Y;
Но теперь прямоугольник движется слишком быстро, он идет гораздо быстрее, чем мышь.
Это может быть проблема с таймером?
EDIT 3
MouseDownLocatioon должно быть проблемой. Если код без него работает (с прямоугольником, движущимся по координатам мыши), это означает, что с этим что-то не так.
Пытался сделать:
protected void panel1_OnMouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
MouseDownLocation = panel1.PointToScreen(e.Location);
}
Не помогло.
Пробовал отлаживать, выглядит как координата Y, делает проблему. Он просто делает слишком большое смещение в координате Y.
Я сделал движение мыши слева направо (только X координат), и отладка показала мне это:
rect.X = 500
rect.Y = 100
Ei = 848
e.Y = 216
MouseDownLocation.X = 850
MouseDownLocation.Y = 238
Это означает, что разница для такого шага заключается только х 2, и у 22!
EDIT 4: Это удалось решить!
Просто надо добавить две строки кода:
MouseDownLocation.X = e.X;
MouseDownLocation.Y = e.Y;
Потому что, если я удерживать нажатой кнопку мыши, это не освежит новый MouseDownLocation.
Обратите внимание, что в Rectangle есть (среди прочих) хорошая функция Contains (Point)! Также обратите внимание, что Cursor.Position находится в координатах экрана, а не в относительных, которые вы получаете в Mousexxxevents! Есть функция преобразования для обоих направлений: Control.PointToClient и Control.PointToScreen – TaW
Спасибо, @TaW в вашем комментарии. Вот почему я положил панель на (0,0), поэтому мне не нужно менять – omicito
Экран действительно экран, а не форма! И лучше сделайте это правильно, вместо того, чтобы скручивать ваш макет ;-) – TaW