Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 30.11.06 13:53
Оценка:
Привет,

Подскажите как правильно сделать контрол, который можно перетаскивать внутри контейнера. То есть как-то реализовать DragAndDrop? В msdn я не нашел, что можно реализовывать dragandrop — методы. Я сделал через

protected override void OnMouseDown( MouseEventArgs e )
{
DownPoint = e.Location;
IsDragMode = true;
}

protected override void OnMouseUp( MouseEventArgs e )
{
IsDragMode = false;
}

protected override void OnMouseMove( MouseEventArgs e )
{
if ( IsDragMode )
{
Location = new Point( ( e.Location.X — DownPoint.X ) + Location.X, ( e.Location.Y — DownPoint.Y ) + Location.Y );
}
}

но на деле контрол вместе с панелью (на фоне которой — изображение) мерцает при перетаскивании. Что-то не так. Как реализовать правильно?? Подскажите, кто что знает.

Спасибо,
Евгений.
Re: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 30.11.06 14:55
Оценка:
Здравствуйте, rippi, Вы писали:

R>Привет,


R>Подскажите как правильно сделать контрол, который можно перетаскивать внутри контейнера. То есть как-то реализовать DragAndDrop? В msdn я не нашел, что можно реализовывать dragandrop — методы. Я сделал через


R> protected override void OnMouseDown( MouseEventArgs e )

R> {
R> DownPoint = e.Location;
R> IsDragMode = true;
R> }

R> protected override void OnMouseUp( MouseEventArgs e )

R> {
R> IsDragMode = false;
R> }

R> protected override void OnMouseMove( MouseEventArgs e )

R> {
R> if ( IsDragMode )
R> {
R> Location = new Point( ( e.Location.X — DownPoint.X ) + Location.X, ( e.Location.Y — DownPoint.Y ) + Location.Y );
R> }
R> }

R>но на деле контрол вместе с панелью (на фоне которой — изображение) мерцает при перетаскивании. Что-то не так. Как реализовать правильно?? Подскажите, кто что знает.


R>Спасибо,

R>Евгений.

Как в MSDN нет Есть же куча свойств типа AllowDrop и ивентов DragDrop, DragEnter, DragLeave, DragOver

Так и будет мерцать! А чтоб не мерцало надо реальзовать ownerdraw. У тебя контейнер внутри которого ты таскаешь какого типа ?
кто здесь ?..
Re[2]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 30.11.06 15:02
Оценка:
R>>но на деле контрол вместе с панелью (на фоне которой — изображение) мерцает при перетаскивании. Что-то не так. Как реализовать правильно?? Подскажите, кто что знает.

R>>Спасибо,

R>>Евгений.

AW>Как в MSDN нет Есть же куча свойств типа AllowDrop и ивентов DragDrop, DragEnter, DragLeave, DragOver


AW>Так и будет мерцать! А чтоб не мерцало надо реальзовать ownerdraw. У тебя контейнер внутри которого ты таскаешь какого типа ?


У меня контейнер типа Panel.
Re[3]: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 30.11.06 15:30
Оценка:
Здравствуйте, rippi, Вы писали:

R>>>но на деле контрол вместе с панелью (на фоне которой — изображение) мерцает при перетаскивании. Что-то не так. Как реализовать правильно?? Подскажите, кто что знает.


R>>>Спасибо,

R>>>Евгений.

AW>>Как в MSDN нет Есть же куча свойств типа AllowDrop и ивентов DragDrop, DragEnter, DragLeave, DragOver


AW>>Так и будет мерцать! А чтоб не мерцало надо реальзовать ownerdraw. У тебя контейнер внутри которого ты таскаешь какого типа ?


R>У меня контейнер типа Panel.


Самый простой способ для тебя — поменять на PictureBox. И задизайнить его как панель. Из плюсов — буферизованный вывод графики, а это то что надо чтоб не мерцало.
Второе место для устранения мерцания — это вызов руками метода Invalidate(Rectangle rect) в котором руками искать тот прямоугольник который надо обновить. а он как извесно меньше всего контрола. Например так.

protected override void OnMouseMove( MouseEventArgs e )
{
   if ( IsDragMode )
   {
      Point p_old = Location;
      Point p_new = new Point( ( e.Location.X — DownPoint.X ) + Location.X, ( e.Location.Y — DownPoint.Y ) + Location.Y );
      Rectangle rect = new Rectangle(Math.Min(p_old.X, p_new.X), Math.Min(p_old.Y, p_new.Y), Math.Max(p_old.X, p_new.X)+Width, Math.Max(p_old.X, p_new.X)+Heigth);
      Location = p_new;
      Invalidate(rect);
   }
}

И вообще, щас набросаю пример, попробую смоделировать более четко.
кто здесь ?..
Re: Сделать контрол, который можно перетаскивать.
От: Аноним  
Дата: 30.11.06 15:48
Оценка:
Если для перетаскивания чисто внутри контрола, то, например, так:

    private Point currentMousePosition;

    private void OnMouseDown(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        control.Capture = true;
        currentMousePosition = control.PointToScreen(e.Location);
      }
    }

    private void OnMouseUp(object sender, MouseEventArgs e)
    {
      if (e.Button == MouseButtons.Left)
      {
        Point diff = CalculateDiff(e.Location);
        SetControlLocation(diff);
        control.Capture = false;
      }
    }

    private void OnMouseMove(object sender, MouseEventArgs e)
    {
      if (control.Capture)
      {
        Point diff = CalculateDiff(e.Location);
        currentMousePosition = control.PointToScreen(e.Location);
        SetControlLocation(diff);
      }
    }

    private void SetControlLocation(Point diff)
    {
      control.Location = new Point(control.Location.X + diff.X, control.Location.Y + diff.Y);
    }

    private Point CalculateDiff(Point newPoint)
    {
      newPoint = control.PointToScreen(newPoint);
      Point p = new Point(newPoint.X - currentMousePosition.X, newPoint.Y - currentMousePosition.Y);
      return p;
    }


Стоит так же добавить код, который будет обрабатывать случаи, когда курсор мыши вышел за пределы контейнера.
Re[4]: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 30.11.06 15:58
Оценка:
Вобщем переписал так.

        Point DownPoint;
        bool IsDragMode;

        private void label1_MouseDown(object sender, MouseEventArgs e)
        {
            DownPoint = e.Location;
            IsDragMode = true;
        }

        private void label1_MouseUp(object sender, MouseEventArgs e)
        {
            IsDragMode = false;
        }

        private void label1_MouseMove(object sender, MouseEventArgs e)
        {
            if ( IsDragMode )
            {
                Point p = e.Location;
                Point dp = new Point(p.X - DownPoint.X, p.Y - DownPoint.Y);
                label1.Location = new Point(label1.Location.X + dp.X, label1.Location.Y + dp.Y);
            }
        }


Никуда не дергается, никуда не бегает. "Не дымит, не пенится, не пригорает"(с) Масло какое-то

В моем примере была панель, на которую я забросил Label. К нему прикрутил три евент хендлера и все.
кто здесь ?..
Re[2]: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 30.11.06 16:01
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Если для перетаскивания чисто внутри контрола, то, например, так...


А про Capture — это верно подмечено!
кто здесь ?..
Re[5]: Сделать контрол, который можно перетаскивать.
От: Аноним  
Дата: 30.11.06 19:53
Оценка:
Здравствуйте, Alex White, Вы писали:

AW>Вобщем переписал так.


AW>
AW>        Point DownPoint;
AW>        bool IsDragMode;

AW>        private void label1_MouseDown(object sender, MouseEventArgs e)
AW>        {
AW>            DownPoint = e.Location;
AW>            IsDragMode = true;
AW>        }

AW>        private void label1_MouseUp(object sender, MouseEventArgs e)
AW>        {
AW>            IsDragMode = false;
AW>        }

AW>        private void label1_MouseMove(object sender, MouseEventArgs e)
AW>        {
AW>            if ( IsDragMode )
AW>            {
AW>                Point p = e.Location;
AW>                Point dp = new Point(p.X - DownPoint.X, p.Y - DownPoint.Y);
AW>                label1.Location = new Point(label1.Location.X + dp.X, label1.Location.Y + dp.Y);
AW>            }
AW>        }
AW>


AW>Никуда не дергается, никуда не бегает. "Не дымит, не пенится, не пригорает"(с) Масло какое-то


AW>В моем примере была панель, на которую я забросил Label. К нему прикрутил три евент хендлера и все.


Методы реализовал у панели на котором лежит Label?
Re[3]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 30.11.06 20:17
Оценка:
AW>А про Capture — это верно подмечено!

Я начинающий в .Net, а почему верно?
Re[2]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 01.12.06 06:04
Оценка:
Не понял, то есть эти обработчики реализуются в контейнере, а что такое control?
Если это двигаемый объект, то как его получить?


Здравствуйте, Аноним, Вы писали:

А>Если для перетаскивания чисто внутри контрола, то, например, так:


А>
А>    private Point currentMousePosition;

А>    private void OnMouseDown(object sender, MouseEventArgs e)
А>    {
А>      if (e.Button == MouseButtons.Left)
А>      {
А>        control.Capture = true;
А>        currentMousePosition = control.PointToScreen(e.Location);
А>      }
А>    }

А>    private void OnMouseUp(object sender, MouseEventArgs e)
А>    {
А>      if (e.Button == MouseButtons.Left)
А>      {
А>        Point diff = CalculateDiff(e.Location);
А>        SetControlLocation(diff);
А>        control.Capture = false;
А>      }
А>    }

А>    private void OnMouseMove(object sender, MouseEventArgs e)
А>    {
А>      if (control.Capture)
А>      {
А>        Point diff = CalculateDiff(e.Location);
А>        currentMousePosition = control.PointToScreen(e.Location);
А>        SetControlLocation(diff);
А>      }
А>    }

А>    private void SetControlLocation(Point diff)
А>    {
А>      control.Location = new Point(control.Location.X + diff.X, control.Location.Y + diff.Y);
А>    }

А>    private Point CalculateDiff(Point newPoint)
А>    {
А>      newPoint = control.PointToScreen(newPoint);
А>      Point p = new Point(newPoint.X - currentMousePosition.X, newPoint.Y - currentMousePosition.Y);
А>      return p;
А>    }
А>


А>Стоит так же добавить код, который будет обрабатывать случаи, когда курсор мыши вышел за пределы контейнера.
Re[3]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 01.12.06 06:18
Оценка:
Я реализовал все именно так. Результат тот же.
У меня контейнер унаследован от Panel, на фоне лежит тяжелая картинка, около 2.5 мб. Свой контрол я унаследовал от Control. Это просто прозрачный прямоугольник.

R>Не понял, то есть эти обработчики реализуются в контейнере, а что такое control?

R>Если это двигаемый объект, то как его получить?
Re[6]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 01.12.06 07:06
Оценка:
AW>>Никуда не дергается, никуда не бегает. "Не дымит, не пенится, не пригорает"(с) Масло какое-то

AW>>В моем примере была панель, на которую я забросил Label. К нему прикрутил три евент хендлера и все.


А>Методы реализовал у панели на котором лежит Label?


Ну если картинки на фоне нет, то у меня тоже не мерцает. Если на фоне тяжелая картинка, то появляется мерцание. Видимо перерисовывается вся картинка, короче неоптимально, достаточно перерисовать открывшиеся области.
Re[7]: Сделать контрол, который можно перетаскивать.
От: Аноним  
Дата: 01.12.06 10:56
Оценка:
Здравствуйте, rippi, Вы писали:

AW>>>Никуда не дергается, никуда не бегает. "Не дымит, не пенится, не пригорает"(с) Масло какое-то


AW>>>В моем примере была панель, на которую я забросил Label. К нему прикрутил три евент хендлера и все.


А>>Методы реализовал у панели на котором лежит Label?


R>Ну если картинки на фоне нет, то у меня тоже не мерцает. Если на фоне тяжелая картинка, то появляется мерцание. Видимо перерисовывается вся картинка, короче неоптимально, достаточно перерисовать открывшиеся области.


Лучше не использовать BackgroundImage свойство, а отрисовывать самостоятельно необходимые части изображения на котроле.
Re[3]: Сделать контрол, который можно перетаскивать.
От: Аноним  
Дата: 01.12.06 11:03
Оценка:
Здравствуйте, rippi, Вы писали:

R>Не понял, то есть эти обработчики реализуются в контейнере, а что такое control?

R>Если это двигаемый объект, то как его получить?

Обработчики можно можно разместить как в контейнере, так и в коде вашего контрола, если вы создали дочерний класс от базового контрола.

control — это именно тот самый котнтрол. Можно в начале методов OnMouseDown, OnMouseUp, OnMouseMove добавить строку:

Control control = (Control)sender;


и в метод SetControlLocation добавить мараметр:


private void SetControlLocation(Control control, Point diff)
{
  control.Location = new Point(control.Location.X + diff.X, control.Location.Y + diff.Y);
}




R>Здравствуйте, Аноним, Вы писали:


А>>Если для перетаскивания чисто внутри контрола, то, например, так:


А>>
А>>    private Point currentMousePosition;

А>>    private void OnMouseDown(object sender, MouseEventArgs e)
А>>    {
А>>      if (e.Button == MouseButtons.Left)
А>>      {
А>>        control.Capture = true;
А>>        currentMousePosition = control.PointToScreen(e.Location);
А>>      }
А>>    }

А>>    private void OnMouseUp(object sender, MouseEventArgs e)
А>>    {
А>>      if (e.Button == MouseButtons.Left)
А>>      {
А>>        Point diff = CalculateDiff(e.Location);
А>>        SetControlLocation(diff);
А>>        control.Capture = false;
А>>      }
А>>    }

А>>    private void OnMouseMove(object sender, MouseEventArgs e)
А>>    {
А>>      if (control.Capture)
А>>      {
А>>        Point diff = CalculateDiff(e.Location);
А>>        currentMousePosition = control.PointToScreen(e.Location);
А>>        SetControlLocation(diff);
А>>      }
А>>    }

А>>    private void SetControlLocation(Point diff)
А>>    {
А>>      control.Location = new Point(control.Location.X + diff.X, control.Location.Y + diff.Y);
А>>    }

А>>    private Point CalculateDiff(Point newPoint)
А>>    {
А>>      newPoint = control.PointToScreen(newPoint);
А>>      Point p = new Point(newPoint.X - currentMousePosition.X, newPoint.Y - currentMousePosition.Y);
А>>      return p;
А>>    }
А>>


А>>Стоит так же добавить код, который будет обрабатывать случаи, когда курсор мыши вышел за пределы контейнера.
Re[8]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 01.12.06 11:16
Оценка:
А>Лучше не использовать BackgroundImage свойство, а отрисовывать самостоятельно необходимые части изображения на котроле.

Изображение отрисовывать прост в цикле? например

    for (uint i=0; j<PicHeight; j++)
        for (uint j=0; j<PicWidth; j++)
        {
            Canvas[i, j] = Img[i*IW+j]
            Canvas[i, j] = Img[i*IW+j+1]
            Canvas[i, j] = Img[i*IW+j+2]
        }


здесь Canvas — это полотно контейнера (пока я не знаю как получить).
И это будет лучше? А может есть способ сразу в память скопировать блок изображения?
Re[4]: Сделать контрол, который можно перетаскивать.
От: rippi  
Дата: 01.12.06 11:18
Оценка:
А>Обработчики можно можно разместить как в контейнере, так и в коде вашего контрола, если вы создали дочерний класс от базового контрола.

А>control — это именно тот самый котнтрол. Можно в начале методов OnMouseDown, OnMouseUp, OnMouseMove добавить строку:


А>
А>Control control = (Control)sender;
А>


Понял, спасибо.

Хотя я все-таки расзместил обработчики в самом контроле.
Re[6]: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 01.12.06 11:23
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Методы реализовал у панели на котором лежит Label?


Методы реальзовал как EventHandler-ы для соответствующих эвентов класса Label

this.label1.MouseDown += new System.Windows.Forms.MouseEventHandler(this.label1_MouseDown);
this.label1.MouseMove += new System.Windows.Forms.MouseEventHandler(this.label1_MouseMove);
this.label1.MouseUp += new System.Windows.Forms.MouseEventHandler(this.label1_MouseUp);
кто здесь ?..
Re[4]: Сделать контрол, который можно перетаскивать.
От: Alex White Украина  
Дата: 01.12.06 11:27
Оценка:
Здравствуйте, rippi, Вы писали:

AW>>А про Capture — это верно подмечено!


R>Я начинающий в .Net, а почему верно?


Потому что пока Capture == true контрол отлавливает любые мышиные евенты, даже если мышь вышла за пределы окна. Это спасает от багов, например еслы вытянуть контрол за окно и бросить его там, он потом будет за мышой бегать постоянно (во всяком случае у меня так воспроизводится)
кто здесь ?..
Re: Сделать контрол, который можно перетаскивать.
От: Аноним  
Дата: 01.12.06 12:28
Оценка:
Здравствуйте, rippi, Вы писали:

R>Привет,


R>Подскажите как правильно сделать контрол, который можно перетаскивать внутри контейнера. То есть как-то реализовать DragAndDrop? В msdn я не нашел, что можно реализовывать dragandrop — методы. Я сделал через


R>Спасибо,

R>Евгений.

Посмотри у DevExpress XtraLayoutControl мне он понравился.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.