Drag and Drop

Adam Boduch

Cóż oznacza to tajemnicze pojęcie Drag and Drop (przeciągnij i upuść)? W tym artykule rozważymy przeciąganie danych z jednego komponentu do drugiego. Jako przykład, weźmy kontrolkę ListBox, w której są dane (pozycje). Po zaznaczeniu jednej z nich możemy myszką przeciągnąć ją do kolejnego komponentu ListBox. Nie jest to trudne - wystarczy oprogramować dwie procedury.

Na formularzu umieść dwa komponenty typu TListBox. W naszym przykładzie dane będzie można przemieszczać z jednego komponentu do drugiego i odwrotnie.

Do jednego z komponentów dodaj jakieś pozycje (właściwość Items). Ok, teraz oprogramuj zdarzenie OnMouseMove:

procedure TMainForm.lbSenderMouseMove(Sender: TObject; Shift: TShiftState;
  X, Y: Integer);
begin
{ jezeli podczas przesuwania kursora myszy nacisniety jest lewy przycisk myszy
  rozpocznij proces DnD }
  if ssLeft in Shift then
    TListBox(Sender).BeginDrag(FALSE);
end;

Ten kod oznacza, że jeżeli podczas przeciągania kursora nad komponentem wciśnięty jest lewy klawisz mysz (ssLeft in Shift) to rozpoczynane zostaje przeciąganie (BeginDrag).

Następnie procedura OnDragOver wykonywana zostaje wtedy gdy nad komponentem znajduje się kursor z wciśniętym klawiszem myszy. W naszym wypadku oba komponenty ListBox korzystać będą z tych samych procedur zdarzeniowych więc kod będzie wyglądał tak:

procedure TMainForm.lbSourceDragOver(Sender, Source: TObject; X,
  Y: Integer; State: TDragState; var Accept: Boolean);
begin
{ ta procedura wystepuje wtedy, gdy kursor myszy znajdzie sie nad komponentem
  - przyjecie "paczki" danych (Accept) nastepuje wtedy gdy objekty Sender oraz
  Source sa rozne }
  Accept := Sender <> Source;
end;

Parametr Accept oznacza, czy chcemy "przyjąć" pakiet przeciąganych danych. W tej procedurze nastąpi przyjęcie jeżeli parametry Sender różnią się od Source gdyż nie chcemy przenosić danych w obrębie tych samych komponentów.

Pozostaje jeszcze procedura, która obsłuży "upuszczenie" klawisza myszy i tym samym zakończenie procesu przenoszenia danych. Tą czynność dokonuje zdarzenie OnDragDrop:

procedure TMainForm.lbSourceDragDrop(Sender, Source: TObject; X,
  Y: Integer);
begin
{ ta procedura powoduje "przyjecie" danych - nowa wartosc zostaje dodana do komponentu.}
  if TListBox(Source).Items.Count > 0 then
  begin
    TListBox(Sender).Items.Add(TListBox(Source).Items[TListBox(Source).ItemIndex]);
    TListBox(Source).Items.Delete(TListBox(Source).ItemIndex);
  end;
end;

Ten kod powoduje zwyczajne dodanie nowej pozycji do komponent ListBox, nad którym kursor jest przeciągany. Powoduje dodanie pozycji, która jest zaznaczona w komponencie z którego przeciągany jest kursor. Tym samym w komponencie z którego przeciągamy pozycje zostaje ona usunięta.

4 komentarzy

Witam. Gdyby ktoś potrzebował więcej informacji o Drag&Drop - zapraszam:
http://lukashp.pl/Artykul/Programowanie/Delphi/delphi-drag_and_drop

wie ktos moze jak przeniesc dane z listboxa do czegos innego? najlepiej webbrowsera

A czy ktos zmajstrował moze wersje przeciągnięcia tak aby z kurosrem przeciągał się przeciągany tekst??? zrobiłem to z wykorzystaniem statictext ale nie bardzo mi kontrola tła tego static tekstu wychodzi.... jakiś rodzaj przezroczystosci by mi sie przydał, jakies pomysł???

Aby przenieść dane na wskazaną pozycję, to trzeba trochę inny kod w treści 'TMainForm.lbSourceDragDrop':

  if (TListBox(Source).ItemIndex >= 0) and
   (TListBox(Sender).ItemAtPos(Point(X, Y), False) >= 0) then
  begin
    TListBox(Sender).Items.Insert(TListBox(Sender).ItemAtPos(Point(X, Y), False),
     TListBox(Source).Items[TListBox(Source).ItemIndex]);
    TListBox(Source).Items.Delete(TListBox(Source).ItemIndex);
  end;

pozdrówka...