1. Home
  2. Computing & Technology
  3. Delphi Programming
Drag and drop operations with Delphi's DBGrid
Learn how to enable dragging and dropping from and to a TDBGrid component.
 Join the Discussion
"Post your views, comments, questions and doubts to this article."
Discuss!
 Related Resources
• Using TDBGrid
• Dragging and dropping

Dragging and dropping is a convenient way for users to manipulate data. You can let users drag an entire control, or let them drag items from one control to another, or drag and drop nodes of a tree view (for example).

Each Delphi control exposes several events (OnDragOver, OnDragDrop) and properties (DragMode) you use to program drag and drop operations in your applications.

In order to start a drag operation for a control, you either have to set the DragMode property to dmAutomatic, or leave it to dmManual (default) and manually call the BeginDrag method. BeginDrag starts the dragging of a control. When we have started the drag operation we need to have a component that will act as a drop target.
To enable a control to accept an object being draged you have to code two events: OnDragOver (to signal that the control can accept a dragged object) and OnDragDrop (to specify what happens when the user drops an object).

In Delphi database applications, where TDBGrid is used to enable a user to view and edit data in a tabular grid, dragging and dropping can come quite handy. Let's see how to add drag and drop capabilities to DBGrid.

Dragging FROM a DBGrid
Let's say you have a DBGrid attached to some Dataset object displaying some data from a database. Here's what needs to be coded if you want to enable a user to drag the selected record to a TMemo control, for example.

1. Handle the OnCellClick event of a DBGrid (Name := 'DBGrid1') to start the drag operation:

procedure TForm1.DBGrid1CellClick(Column: TColumn);
begin
  DBGrid1.BeginDrag(true);
end;

2. Specify that a Memo control (Name := 'Memo1') can accept data from a DBGrid, using the OnDragDrop event of a Memo:

procedure TForm1.Memo1DragOver(
  Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := Source IS TDBGrid;
end;

3. Finally, handle the OnDragDrop of a Memo control to process data being dropped. We'll add the code to add the values of all the fields of the current record to a Memo control:

procedure TForm1.Memo1DragDrop(
  Sender, Source: TObject; 
  X, Y: Integer);
var i : integer;
begin
  Memo1.Clear;

  for i := 0 to -1 + DBGrid1.FieldCount do
  begin
    Memo1.Lines.Add(DBGrid1.Fields[i].AsString);
  end;
end;

Dragging from a DBGrid

Once you have a running application, click on a row in a DBGrid (to make the row/record active) then click inside the Memo control: Memo gets filled with the values of the fields from the selected (dragged record).

Dragging TO a DBGrid
While dragging FROM a DBGrid turns to be easy to program, dragging TO a DBGrid is quite a tricky task.

Suppose you have a ListBox filled with items, and want to enable a user to drag an item to a particular cell (e.g. to edit one particular field) of a DBGrid - to change the value of a specific field. How do you determine the exact row and the exact cell of a DBGrid where the user has finished the drag operation?

As discussed in the "accessing protected members of a component" article, many Delphi components have useful properties and methods that are marked invisible ("protected") to a Delphi developer.

When a user finishes the drag operation and drops a value over a cell in a DBGrid, we have to set the active record, place the underlying dataset into edit mode, and assign a value to a particular field.

Here's the code needed to handle dragging to a DBGrid:

1. Since we are dropping items from a ListBox control, by handling the OnDragOver of a DBGrid we specify that only items from a ListBox are acceptable to be dropped on a DBGrid:

procedure TForm1.DBGrid1DragOver(
  Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
begin
  Accept := Source IS TListBox;
end;

2. The tricky part goes in the OnDragDrop event handler for DBGrid:

procedure TForm1.DBGrid1DragDrop(
  Sender, Source: TObject; X, Y: Integer);
var
  gc : TGridCoord;
  s : string;
begin
  gc := THackDBGrid(DBGrid1).MouseCoord(X,Y);
  if (gc.X > 0) AND (gc.Y > 0) then
  begin
    if ListBox1.ItemIndex = -1 then Exit;
    s := ListBox1.Items[ListBox1.ItemIndex];

    with THackDBGrid(DBGrid1) do
    begin
      DataSource.DataSet.MoveBy (gc.Y - Row);
      DataSource.DataSet.Edit;
      Columns.Items[-1 + gc.X].Field.AsString := s;
    end;
  end;
end;

Dragging to a DBGrid

Note: We first use the protected hack to get our hands on the protected MouseCoord method to access the row and column of a DBGrid. This technique is explained in the Selecting and highlighting a row in a DBGrid - "OnMouseOverRow" article. If the target is not the first row (where column titles are by default) and not the first column (where row indicator is by default) we set the current row using the MoveBy method and the Row property. Next, dataset is put into edit mode. Finally, the value of the target field is assigned using the selected item from the ListBox.

That's it. If you are looking for more DBGrid related article, check the "TDBGrid to the MAX" collection. More drag and drop ideas can be found here: dragging and dropping with Delphi.

Explore Delphi Programming
About.com Special Features

Holiday Central

What to eat, where to go, fun things to do and how to save money on the perfect gifts. More >

Family Tech Center

Stay connected and entertained with reviews on tips on the latest HDTVs, cellphones and more. More >

  1. Home
  2. Computing & Technology
  3. Delphi Programming

©2009 About.com, a part of The New York Times Company.

All rights reserved.