Articles - Using Drag and Drop in Delphi

'

Introduction

Due to the graphical nature of Windows the majority of operations can be performed solely with the mouse. One operation that is often useful is for the user to be able to drag an object from one position to another. Fortunately for us, Borland have made this facility easy to implement for the Delphi developer. The tutorial will show you how to do this, by explaining and providing sample code to drag items from one ListBox to another.

The Events Used

All Classes that are descendants of TControl have the following events available to us:
  OnDragDrop
  OnDragOver
  OnEndDrag
  OnStartDrag

I will explain the use of each of these events and all of their parameters, for more information on this check out the relevant help files.

OnDragDrop

This event is fired whenever an item is dropped on a control. The majority of the code needed for implementing drag and drop is entered here. The parameters are used as follows:
Parameter Type Purpose
Sender TObject The Sender parameter is the object which received the dropped item.
Source TObject This is a pointer to the actual item that is being dragged (and dropped). In the case of an item in a listbox being dragged this points to the ListBox and not the actual text being dragged, so it is up to the developer to handle which item in the ListBox the intended drag operation is to be performed on.
X,Y Integer These are the relative coordinates of where the object was dropped on the sender object.

OnDragOver

This event is fired whenever an item is dragged over a control. Its main use is to decide whether the item can be dropped here and change the cursor to reflect this. The parameters are used as follows:
Parameter Type Purpose
Sender, Source TObject Represent the same information as the onDragDrop event.
X,Y Integer Represent the same information as the onDragDrop event.
var Accept Boolean This should be set to true if the control that the drag is currently over can accept the dragged item. This is also reflected by the cursor being either the drag or the no-entry cursor (These can easily be changed to your own choice)
State TDragState This parameter tells you whether the drag operation is just entering, moving into or leaving  the Sender object.

OnEndDrag

This event is fired whenever an item is dropped. Unlike the onDrop event the use of this event is to perform the necessary operation on the object that was dragged. This is normally used for cleaning up any thing that was created in the onStartDrag event. The parameters are used as follows:
Parameter Type Purpose
Sender TObject This is the Object that was actually dragged.
Target TObject This is the Object that the drag object was dropped on. If the drag operation failed then this is set to nil.
X,Y Integer The relative coordinates of where the drag object was dropped on the target parameter.

OnStartDrag

This event is fired whenever an item first dragged. Its is mainly used to initialize any variable that are needed for the drag operation. It is not always needed and will not be used in our simple example.
Parameter Type Purpose
Sender TObject This is the Object that was actually dragged.
DragObject TDragObject This Object allows us to store and pass on a lot more information about what is being dragged. Check out the help file for further information on this, when used correctly this can add great power at low cost to your applications.

An Example

What We Will Do

In this example we will have two listboxes on a form and implement the facility to allow our users to drag items from one listbox to the other, and also reposition items in each listbox by dragging and dropping the selected strings.

Designing The Interface

As this is a very simple application demonstrating how to implement drag and drop we only need a very simple application. The code that follows assumes that you have used the default names that Delphi provides, if not adjust accordingly. The steps involved are: That is the interface complete, all we need to do now is write the actual code.

The Code

As seen in the interface section we have only created to procedure stubs. These are in fact all that we need to implement our drag and drop.

The DragOver procedure is implemented as follows:
procedure TForm1.ListBox1DragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  if Source is TListBox then Accept := True;
end;
What we are doing here is making sure that the Object being dragged onto the listbox is also another listbox (though we only use the selected item in the listbox) and setting the accept var accordingly.

Next we need to accept the dropped object and update the listboxes contents accordingly. This is done in the DragDrop procedure as follows:
procedure TForm1.ListBox1DragDrop(Sender, Source: TObject; X, Y: Integer);
var
  iTemp : integer;
  ptTemp : TPoint;
  szTemp : String;
begin
  { change the x,y coordinates into a TPoint record }
  ptTemp.x:=x;
  ptTemp.y:=y;
  
  { Use a while loop instead of a for loop due to items possible being removed from
    listboxes this prevents an out of bounds exception }
  iTemp := 0;
  While iTemp <= TListBox(Source).Items.Count-1 do
  begin
    { look for the selected items as these are the ones we wish to move } 
    if TListBox(Source).selected[iTemp] then
    begin
       { use a with as to make code easier to read }
      With Sender as TListBox do
      begin
      { need to use a temporary variable as when the item is deleted the indexing
        will change }
        szTemp := TListBox(Source).items[iTemp];
		
     { delete the item that is being dragged  }
        TListBox(Source).items.Delete(iTemp);
		
	    { insert the item into the correct position in the listbox that it was dropped on }
        items.Insert(itemAtPos(ptTemp,true),
                     szTemp);
      end;
    end;
    inc(iTemp);
  end;
end;
I have thoroughly commented this procedure, so will not explain its workings here. All that it is doing is deleting the dragged item and adding it in the correct place in the listbox that it was dropped onto.

Closing Comments

I hope this tutorial has provided enough information for you to use drag and drop in your applications. The example shown is a very simple one but provides the basic framework for more complex tasks. In a later article or tutorial I intend to dig deeper into the use of TDragObject.
Google
Web www.Delphi-Central.com
Delphi Central - Delphi Programming Tutorials, Hints and Tips