2016-08-15 4 views
3

Я работаю над небольшим приложением, в котором я рисую прямоугольники и перемещаю их с помощью мыши.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.

+0

Обратите внимание, что в Rectangle есть (среди прочих) хорошая функция Contains (Point)! Также обратите внимание, что Cursor.Position находится в координатах экрана, а не в относительных, которые вы получаете в Mousexxxevents! Есть функция преобразования для обоих направлений: Control.PointToClient и Control.PointToScreen – TaW

+0

Спасибо, @TaW в вашем комментарии. Вот почему я положил панель на (0,0), поэтому мне не нужно менять – omicito

+0

Экран действительно экран, а не форма! И лучше сделайте это правильно, вместо того, чтобы скручивать ваш макет ;-) – TaW

ответ

1
rect.X = e.X - MouseDownLocation.X; 
rect.Y = e.Y - MouseDownLocation.Y; 

Я не уверен, что MouseDownLocation есть, но на основе имени, когда вы первый начать движение в поле, текущее местоположение (e.X,e.Y) равно MouseDownLocation, то есть математику работает в (0,0) , Похоже, поэтому вы переходите в угол.

Технически вы также делаете это 2-е и 4-е клики, но поскольку вы УЖЕ в углу, это не очевидно.

Редактировать, что вы редактируете, что прямоугольник теперь перемещает угол в ваш курсор: Когда вы нажимаете на мышь, вам нужно будет вычислить и сохранить смещение от местоположения прямоугольников до мыши, а затем использовать это смещение в Обработчик событий MouseMove.

+0

Мне очень жаль, похоже, что я не копировал/вставлял часть код. MouseDownLocation дает местоположение курсора при нажатии – omicito

+0

@omicito Я понял, что это что-то в этом роде. Я также добавил некоторые мысли о вашем редактировании. –

+0

Да, я сделал что-то подобное, но теперь у меня есть новая проблема. Это мое новое редактирование. И спасибо @Tyler – omicito