在Shift +上选择多行并在DBGrid中单击

时间:2015-10-21 12:59:15

标签: delphi delphi-7 dbgrid tdbgrid

我需要编写代码以在Shift + MouseClick上选择多行,以便我能够填充这些值。有什么办法可以吗?我的DBGrid选项如下:

 dbGrid1.Options = [dgEditing, dgAlwaysShowEditor, dgTitles, dgColLines, dgRowLines, dgTabs, dgConfirmDelete, dgCancelOnExit, dgMultiSelect]

3 个答案:

答案 0 :(得分:3)

我原本以为你可能遇到的问题是Shift + Click是由网格本身处理的,所以Grid的OnMouseUp触发时,网格已经将数据集光标移动到了那一行。按住Shift键点击。因此,将网格选择从移位点击之前的位置扩展起来并不简单,因为您将缺少ds光标之前的位置信息。

但事实证明这很简单。我在下面的代码中添加了一些注释来解释它是如何工作的。

为简单起见,我使用带有整数ID字段的ClientDataSet实现了它。使用ID字段的关键是代码使用ID的当前值和先前值,在数据集滚动时以一种手动方式执行其操作。使用书签做类似的事情会更加混乱,因为需要不断地分配和取消分配它们,所以我将其作为练习留给读者。

代码:

//  Form variables
  SettingBookmarkRange : Boolean;
  CurrentRowID,
  PreviousRowID: Integer;

procedure TForm1.CDS1AfterScroll(DataSet: TDataSet);
begin
  if SettingBookmarkRange then exit;
  PreviousRowID := CurrentRowID;
  CurrentRowID := CDS1.FieldByName('ID').AsInteger;
  Caption := Format('Current %d, prior %d', [CurrentRowID, PreviousRowID]);
end;

procedure TForm1.SetBookmarkRange;
var
  BM,
  TempBM : TBookmark;
  NewBM : TBookmarkStr;
  FoundPrevious : Boolean;
begin

  //  This code is called after the user does a Shift-Click in the grid
  //  First we set a flag to temporarily prevent the CurrrentRowID and
  //  PreviousrowID from being updated during the dataset's OnScroll event
  SettingBookmarkRange := True;

  BM := CDS1.GetBookmark;

  //  Set a flag to keep track of whether we've found the row with the PreviousRowID
  FoundPrevious := False;
  try
    CDS1.DisableControls;

    //  First, search forwards to see if we can find the the row with the PreviousRowID
    //  In other words, we're first checking that the Shift-Click was on a row *above*
    //  the previous row
    CDS1.Next;
    while not FoundPrevious and not CDS1.Eof do begin
       if CDS1.FieldByName('ID').AsInteger = PreviousRowID then begin
         FoundPrevious := True;

         //  We found the row with the PreviousRowID, so now get the Grid to add it, and
         //  all the rows back to where we started, in its SelectedRows list
         while not CDS1.Bof and (CDS1.FieldByName('ID').AsInteger <> CurrentRowID) do begin
           DBGrid1.SelectedRows.CurrentRowSelected := True;
           CDS1.Prior;
         end;
      end
       else
         CDS1.Next;
    end;
    if not FoundPrevious then begin
      //  If we get here, the Shift-Click must have been in a row further down the
      //  grid than the previously-current one
      while not FoundPrevious and not CDS1.Bof do begin
        if CDS1.FieldByName('ID').AsInteger = PreviousRowID then begin
          FoundPrevious := True;
         //  We found the row with the PreviousRowID, so now get the Grid to add it, and
         //  all the rows back to where we started, in its SelectedRows list
          while not CDS1.Eof and (CDS1.FieldByName('ID').AsInteger <> CurrentRowID) do begin
            DBGrid1.SelectedRows.CurrentRowSelected := True;
            CDS1.Next;
          end;
        end
        else
          CDS1.Prior;
      end;
    end;
  finally
    CDS1.GotoBookmark(BM);
    CDS1.FreeBookmark(BM);
    CDS1.EnableControls;
    SettingBookmarkRange := False;
  end;
end;

procedure TForm1.DBGrid1MouseUp(Sender: TObject; Button: TMouseButton; Shift:
    TShiftState; X, Y: Integer);
begin
  Caption := IntToStr(CDS1.Fields[0].Value);
  if ssShift in Shift then
    SetBookMarkRange;
end;

答案 1 :(得分:0)

多选网格的默认选择行为是Ctrl-Click,而不是Shift-Click。使用它并不需要任何特定的鼠标点击处理程序。

要实现Shift-Click,您必须否决/实现网格的鼠标单击处理程序。

答案 2 :(得分:0)

我为TDBGrid class使用了插入器。它可以使用 Ctrl + Shift 键:

type
  TDBGrid = class(Vcl.DBGrids.TDBGrid)
  private
    procedure SelectRange;
  protected
    procedure MouseDown(Button: TMouseButton; Shift: TShiftState; X: Integer; Y: Integer); override;
  end;

  {...}

implementation

  {...}
procedure TDBGrid.SelectRange;
var
  CurrentBookMark, CursorBookMark, FirstBookMark, LastBookMark: TBookmark;
  Dir: integer;
begin
  if SelectedRows.Count <= 1 then
    exit;

  DataSource.DataSet.DisableControls;
  try
    FirstBookMark := SelectedRows.Items[0];
    LastBookMark := SelectedRows.Items[SelectedRows.Count - 1];
    SelectedRows.Clear;
    CurrentBookMark := DataSource.DataSet.GetBookmark;
    Dir := DataSource.DataSet.CompareBookmarks(FirstBookMark, CurrentBookMark);

    if Dir = 0 then
      Dir := DataSource.DataSet.CompareBookmarks(LastBookMark, CurrentBookMark);

    if Dir > 0 then
      DataSource.DataSet.GotoBookmark(LastBookMark)
    else if Dir < 0 then
      DataSource.DataSet.GotoBookmark(FirstBookMark)
    else
      Exit;

    while not DataSource.DataSet.eof do
    begin
      CursorBookMark := DataSource.DataSet.GetBookmark;
      SelectedRows.CurrentRowSelected := true;

      if DataSource.DataSet.CompareBookmarks(CurrentBookMark, CursorBookMark) = 0 then
      begin
        DataSource.DataSet.FreeBookMark(CursorBookMark);
        break;
      end;
      DataSource.DataSet.FreeBookMark(CursorBookMark);

      if Dir < 0 then
        DataSource.DataSet.Next
      else
        DataSource.DataSet.Prior;
    end;

    DataSource.DataSet.FreeBookMark(CurrentBookMark);
  finally
    DataSource.DataSet.EnableControls;
  end;
end;

{ TDBGrid }


procedure TDBGrid.MouseDown(Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  inherited;
  if Shift = [ssCtrl, ssShift, ssLeft] then
    SelectRange;
end;