Mega Code Archive

 
Categories / Delphi / Ide Indy
 

Using Drag and Drop in Delphi

Title: Using Drag and Drop in Delphi Question: In this article I try to cocer Drag and Drop in Delphi applications Answer: 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 (Inprise) 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 Sender Type TObject Purpose The Sender parameter is the object which received the dropped item. Parameter Source Type TObject Purpose 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. Parameter X,Y Type Integer Purpose 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 Sender, Source Type TObject Purpose Represent the same information as the onDragDrop event. Parameter X,Y Type Integer Purpose Represent the same information as the onDragDrop event. Parameter var Accept Type Boolean Purpose 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) Parameter State Type TDragState Purpose 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 th onDrop event the use of this event is to perform the neccessary 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 Sender Type TObject Purpose This is the Object that was actually dragged. Parameter Target Type TObject Purpose This is the Object that the drag object was dropped on. If the drag operation failed then this is set to nil. Parameter X,Y Type Integer Purpose 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 Sender Type TObject Purpose This is the Object that is beginning to be dragged. Parameter DragObject Type TDragObject Purpose 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: o Start a new application. o On the main form place two TlistBox objects (from the standard page of the component palette) o For each ListBox item set the DragMode property to dmAutomatic (using the Object Inspector)- this means that we do not need to begin the drag operation manually o Next use the Object Inspector to generate the events for the onDragOver and onDragDrop for one of the listboxes, and set the corresponding events of the other listbox to match those already generated (by using the drop down list in the Object Inspector) 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 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.