Here is how to achieve shift-click (contiguous) select on TDBGrid lazarus / 16-Databases ---------------------------------------------------------------------- grandehombre · 2013-08-11 12:45 Code: [Select]{ Usage: in the form that needs this functionality, add var     previousGridBookmark: TBookmark; ... ... ... procedure TfrmTest.DBGrid1CellClick(Column: TColumn); begin DBGridShiftSelect(DBGrid1, previousGridBookmark);   // save last selected bookmark   previousGridBookmark := DBGrid1.DataSource.DataSet.GetBookmark; end; // Don't forget to clear the above bookmark when you clear or re- populate the grid // // Example code //if assigned(previousGridBookmark) then begin //        DBGrid1.DataSource.DataSet.FreeBookmark(previousGridBookmark); //        previousGridBookmark := nil; //    end; } Add this code to a unit of its own (or in the form itself, though  it would be best on its own, so it can be reused!) // Allow shift-Ckick marking of a contiguous block procedure DBGridShiftSelect(Sender: TObject; existingBookmarks: TBookmark); var curPos: TBookmark; limiter: integer; grid: TDBGrid; dSet: TDataSet; rFrom, rTo, rTmp: integer; begin grid := (Sender as TDBGrid); dSet := grid.DataSource.DataSet; // Get the current position (bookmark) and record number (the row we shift-clicked on) curPos := dSet.GetBookmark; rTo := dSet.RecNo; dSet.DisableControls; try         // dummy loop that allows multiple exits to a single point repeat if not (ssShift in GetKeyShiftState) then begin         exit; end; if (existingBookmarks = nil) then begin exit; end; // go to the last bookmark before we shift- clicked dSet.GotoBookmark(existingBookmarks); rFrom := dSet.RecNo; if rTo = rFrom then begin exit; end; // we want to only mark moving forward, so if need be, swap the bookmarks if rTo < rFrom then begin rTmp := rTo; rTo := rFrom; rFrom := rTmp; grid.SelectedRows.CurrentRowSelected := True; dSet.GotoBookmark(curPos); end; // stop after marking 255 rows (just in case recNo is not a reliable method of doing this. // This is probably no longer an issue but it doesn't hurt to leave it here :-) limiter := 255; repeat // highlight current row grid.SelectedRows.CurrentRowSelected := True; dset.Next; rFrom := dSet.recNo; limiter := limiter - 1; // keep going until we reach the shift-clicked row until (limiter < 0) or (rFrom = rTo); until true; finally dSet.FreeBookmark(curPos); dSet.EnableControls; end; end; UPDATE: Added note on clearing the bookmark when clearing/repopulating the grid ---------------------------------------------------------------------- rfwoolf · 2020-07-13 00:34 Well done! I just tested this and it works pretty well. One thing that needs improvement: If you want to use shift-click twice: Example: 1. You select row 10. 2. You use shift-click to select row 20.   Rows 10-20 are now selected 3. You use shift-click to select row 30.   Expected behaviour:   It should select rows 10-30.   Actual behaviour:   It selects rows 20-30 I made some minor tweaks to the code, but essentially it's the same as you wrote: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i //Declare a global variable //Used for special function on TDBGrids: the ability to use Shift to select multiple rows//(See DBGridShiftSelect)var  DBGridPriorBookmark : TBookmark; //Don't forget to clear the above bookmark when you clear or re-populate the grid//Example, place this in Dataset.AfterRefresh://begin//  if assigned(DBGridPriorBookmark) then//  begin//    DataSet.FreeBookmark(DBGridPriorBookmark);//    DBGridPriorBookmark := nil;//  end;//end; //Add this code to a unit of its own (or in the form itself, though it would be best on its own, so it can be reused!)// In a DBGrid, allow Shift-Click marking of a contiguous blockprocedure DBGridShiftSelect(Sender: TObject; existingBookmarks: TBookmark);var  curPos: TBookmark;  limiter: integer;  aDBGrid: TDBGrid;  aDataset: TDataSet;  iFrom,  iTo,  iTmp: integer;begin   //Validation  if not (ssShift in GetKeyShiftState) then    exit;   if (existingBookmarks = nil) then    exit;   //Initiliasation  aDBGrid := (Sender as TDBGrid);  aDataset := aDBGrid.DataSource.DataSet;   // Get the current position (bookmark) and record number (the row we shift-clicked on)  curPos := aDataset.GetBookmark;  iTo := aDataset.RecNo;   aDataset.DisableControls;  try    //dummy loop that allows multiple exits to a single point    repeat      //go to the last bookmark before we shift-clicked      aDataset.GotoBookmark(existingBookmarks);      iFrom := aDataset.RecNo;       if iTo = iFrom then        exit;       //we want to only select moving forward, so if need be, swap the bookmarks      if iTo < iFrom then      begin        iTmp := iTo;        iTo := iFrom;        iFrom := iTmp;        aDBGrid.SelectedRows.CurrentRowSelected := True;        aDataset.GotoBookmark(curPos);      end;       //Stop after marking 255 rows (just in case recNo is not a reliable method of doing this.    //This is probably no longer an issue but it doesn't hurt to leave it here :-)      limiter := 255;       repeat        //highlight current row        aDBGrid.SelectedRows.CurrentRowSelected := True;      aDataset.Next;         iFrom := aDataset.recNo;        limiter := limiter - 1;         //keep going until we reach the shift-clicked row      until        (limiter < 0) or (iFrom = iTo);    until      true;  finally    aDataset.FreeBookmark(curPos);    aDataset.EnableControls;  end;end;  //Add this to the DBGrid's onCellClick method: procedure TfrmTest.DBGrid1CellClick(Column: TColumn); begin   DBGridShiftSelect(DBGrid1, DBGridPriorBookmark);   // save last selected bookmark   DBGridPriorBookmark := DBGrid1.DataSource.DataSet.GetBookmark; end; ---------------------------------------------------------------------- emilt · 2020-07-15 14:27 That is very nice, but it made me wonder - is there any special reason why the shift+click functionality is not built-in into the TDBGrid component by default? After all, you can use shift+arrows to do the same with the keyboard, why not with the mouse too?