Drag and Drop внутри своего приложения

Механика Drag and Drop, вопреки названию, состоит не из двух, а из трех частей. Не "потащить и бросить", а "стартовать, перетащить и бросить". 

Для примера рассмотрим перетаскивание из одного TListbox в другой.

Стартовать перетаскивание. Источником Drag&Drop-а может стать любой наследник от TControl. Добавляем первому списку ListBox1 обработчик события OnMouseDown:

procedure TTestAreaMain.ListBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  if (Button = mbLeft) and         // Если нажали левую кнопку,
     (ListBox1.ItemIndex>=0) then  //  и в LisBox1 выделен какой-то элемент,
    ListBox1.BeginDrag(false, 5);  //  стартуем перетаскивание.
end;

Первый параметр BeginDrag - начинать режим перетаскивания немедленно или после того как курсор мыши сдвинется. В нашем примере - когда сдвинется на пять пикселов.

Потом перетаскивание. Пока над контролом перетаскивается объект, ему приходят события OnDragOver. В ответ контрол должен решить, можно в него бросать перетаскиваемый объект или нет. В зависимости от ответа, курсор мыши принимает соответствующий вид. Напишем такой обработчик для второго списка ListBox2:

procedure TTestAreaMain.ListBox2DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := (Source = ListBox1);
end;

На вход мы получаем указатели на объект над которым происходит перетаскивание (Sender), исходный объект, от которого началось перетаскивание (Source), координаты события и статус перетаскивания. В ответ нужно указать, можно ли бросить объект. В нашем примере ListBox2 согласен принимать перетаскивания, только если они идут от ListBox1.

Ну и наконец, бросание объекта. Реакция на него описывается в обработчике OnDragDrop:

procedure TTestAreaMain.ListBox2DragDrop(Sender, Source: TObject; X,
  Y: Integer);
begin
  if Source is TListBox then
  begin
    (Sender as TListBox).Items.Add((Source as TListBox).Items[(Source as TListBox).ItemIndex]);
    (Source as TListBox).Items.Delete((Source as TListBox).ItemIndex);
  end;
end;

Удалим текущий элемент из списка источника и вставим его в список приёмник.

 

Метки: