Использование пользовательского курсора при Drag&Drop

Применяя функцию перетаскивания Drag&Drop студия использует курсоры по умолчанию, которые не всегда подходят разработчику. В данной статье я хочу показать, как можно использовать свой курсор. Паралельно, мы кратко рассмотрим саму реализацию механизма Drag&Drop. Чтобы Drop кнопки производить с учетом координат нажатия на ней в момент перетаскивания, координаты точки нажатия можно сохранить в свойстве Tag кнопки, которое затем прочитать в обработчике события DragDrop и соответсвующим образом подкорректировать новые координаты кнопки.

Создадим в Visual Studio новый проект Windows Forms и добавим на форму две панели: panSource и panTarget. Свойство AllowDrop устанавливаем в true. Это позволит какраз и позволит применить механизм Drag&Drop:

public Form1()
{
    InitializeComponent();

    //разрешаем DragDrop
    panSource.AllowDrop = true;
    panTarget.AllowDrop = true;

    //подписываемся на события
    panSource.DragEnter += new DragEventHandler(PanelDragEnter);
    panSource.DragDrop += new DragEventHandler(PanelDragDrop);

    panTarget.DragEnter += new DragEventHandler(PanelDragEnter);
    panTarget.DragDrop += new DragEventHandler(PanelDragDrop);

    //Добавляем кнопку на панель
    Button btn = new Button();
    btn.SetBounds(10, 10, 150, 23);
    btn.Name = "btn";
    btn.Text = "Drag me";
    btn.MouseMove += new MouseEventHandler(btn_MouseMove);
    btn.GiveFeedback += new GiveFeedbackEventHandler(btn_GiveFeedback);
    panSource.Controls.Add(btn);
}

В конструкторе мы подписались на события для панелей DragEnter и DragDrop.
DragEnter вызывается, когда курсор мыши перемещается на другой элемент управления.
DragDrop – происходит по завершении операции перетаскивания.
Если Вы обратили внимание, то для обеих панелей у нас будут одни и те же обработчики событий.
Рассмотрим обработчики событий:

//проверяем тип данных на соответствие Button-у
void PanelDragEnter(object sender, DragEventArgs e)
{
    if (e.Data.GetDataPresent(typeof(Button)))
    {
        e.Effect = DragDropEffects.Move;
    }
}

 

void PanelDragDrop(object sender, DragEventArgs e)
{
    //извлекаем кнопку
    Button btn = (Button)e.Data.GetData(typeof(Button));
    Panel pan = sender as Panel;
    //получаем клиентские координаты в момент отпускания кнопки
    Point pointDrop = pan.PointToClient(new Point(e.X, e.Y));
    //извлекаем клиентские координаты мыши в момент начала перетскивания
    Point pointDrag = (Point)btn.Tag;
    //вычисляем и устанавливаем Location для кнопки в Panel
    pointDrop.Offset(-pointDrag.X, -pointDrag.Y);
    btn.Location = pointDrop;
    //установка панели в качестве родителя для нашей кнопки
    btn.Parent = pan;
}

Теперь перейдем к кнопке. Для кнопки мы подписались на два события MouseMove и GiveFeedBack.
MouseMove – именно в этом обработчике события, а не в MouseDown, начинается операция перетаскивания. Это сделано для того, чтобы осталась возможность просто кликнуть по кнопке, не инициируя при этом процедуру перетаскивания. Если клик по кнопке на момент перетаскивания не нужен, можно инициировать перетаскивание в обработчкие MouseDown. Стоит заметить, что этот обработчик вызовется только один раз при каждом перетаскивании (что собственно и нужно).

void btn_MouseMove(object sender, MouseEventArgs e)
{
    if (e.Button == MouseButtons.Left)
    {
        Button btn = sender as Button;
        btn.Tag = new Point(e.X, e.Y);
        //запоминаем координаты мыши на момент начала перетаскивания
        btn.DoDragDrop(sender, DragDropEffects.Move);
    }
}

GiveFeedBack – вызывается для элемента управления, если он допустим для конечного местоположения перетаскивания с указанным эффектом перетаскивания. Именно в этом обработчике события и задаются пользовательские курсоры. Давайте зададим пользовательский курсор:

Cursor DragCursor = new Cursor(@"Images\DragCursor.cur");

Теперь, в обработчике события GiveFeedBack зададим наш курсор:

void btn_GiveFeedback(object sender, GiveFeedbackEventArgs e)
{
    //отключаем стандартные курсоры
    e.UseDefaultCursors = false;
    try
    {
        //если происходит перетаскивание
        if ((e.Effect & DragDropEffects.Move) == DragDropEffects.Move)
        {
            //задаем свой курсор
            Cursor.Current = DragCursor;
        }
        else
        {
            //задаем курсор по умолчанию
            e.UseDefaultCursors = true;
        }
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Ошибка!", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

Ну вот и все…

  PanelDragDropCursor.rar (59,1 KiB, 1 537 закачек)

Поделиться в соц. сетях

Опубликовать в Facebook
Опубликовать в Google Plus
Опубликовать в LiveJournal
Опубликовать в Google Buzz
Опубликовать в Одноклассники
Опубликовать в Яндекс
Опубликовать в Мой Мир

Похожие статьи

Оставить комментарий