Drag & Drop between cells in Delphi StringGrid

Posted by webmaster Guido
In Reply to: Drag and drop in Delphi stringgrid
I want to drag text from one cell to another, but not drag from or to fixed row and column.

We define two integer variables for remembering from which cell we started dragging: SourceCol and SourceRow.

Next, we create handlers for the:
- OnCreate event of the form, for setting up the StringGrid;
- OnMouseDown event of the StringGrid: start the dragging;
- OnDragOver event of the StringGrid: show the correct drag cursor during the dragging, indicates where the dragged stuff can be dropped (controlled by variable Accept);
- OnDragDrop event of the StringGrid: finally, the dragged stuff is dropped onto a cell.

Note: I changed the name of the StringGrid to SG, to make the source code a bit easier to read.

implementation

{$R *.DFM}

var
  SourceCol, SourceRow: integer;

procedure TForm1.FormCreate(Sender: TObject);
begin
  { Set DragMode to Manual, to control entire drag & drop by code }
  SG.DragMode := dmManual; 
  { For testing purposes, fill a few cells }
  SG.Cells[2, 2] := 'A';
  SG.Cells[3, 2] := 'B';
  SG.Cells[4, 2] := 'C';
end;

procedure TForm1.SGMouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: integer);
begin
  { Convert mouse coordinates X, Y to
    to StringGrid related col and row numbers }
  SG.MouseToCell(X, Y, SourceCol, SourceRow);
  { Allow dragging only if an acceptable cell was clicked
    (cell beyond the fixed column and row) }
  if (SourceCol > 0) and (SourceRow > 0) then
    { Begin dragging after mouse has moved 4 pixels }
    SG.BeginDrag(False, 4);
end;

procedure TForm1.SGDragOver(Sender, Source: TObject; X, Y: Integer;
  State: TDragState; var Accept: Boolean);
var
  CurrentCol, CurrentRow: integer;
begin
  SG.MouseToCell(X, Y, CurrentCol, CurrentRow); // convert mouse coordinates
  { Accept dragged stuff only if it came from StringGrid
    and the mouse is now over an acceptable region } 
  Accept := (Sender = Source) and
            (CurrentCol > 0) and (CurrentRow > 0);
end;

procedure TForm1.SGDragDrop(Sender, Source: TObject; X, Y: Integer);
var
  DestCol, DestRow: Integer;
begin
  SG.MouseToCell(X, Y, DestCol, DestRow); // convert mouse coord.
  { Move contents from source to destination }
  SG.Cells[DestCol, DestRow] := SG.Cells[SourceCol, SourceRow];
  if (SourceCol <> DestCol) or (SourceRow <> DestRow) then
    SG.Cells[SourceCol, SourceRow] := '';
end;