如何在TDBGrid中设置活动单元?

问题描述 投票:4回答:2

我想通过代码激活TDBGrid中的单元格。通过“激活”我的意思是用户点击单元格内部,准备编辑单元格内容。我怎么能这样做?

编辑:这可能涉及两个步骤:更改当前活动的单元格,然后进入编辑模式。

delphi dbgrid
2个回答
4
投票

如果您的意思是“激活当前活动单元格的编辑模式”,那么您应该这样做:

MyDBGrid.EditorMode := True;

激活特定的单元格可以通过SelectedIndex完成:

MyDBGrid.SelectedIndex := 2;  { or maybe MyDBGrid.SelectedIndex + 1 }

或通过SelectedField

MyDBGrid.SelectedField := MyDataSet.FieldByName('Name');

要确定此刻哪个单元格位于鼠标光标下,可以使用MouseCoord,它返回一个TGridCoord记录,其中包含光标下单元格的坐标。 TGridCoord.X字段可以直接用于设置网格的活动列。

var
  Cell: TGridCoord;

...

Cell := MyDBGrid.MouseCoord(X, Y);
MyDBGrid.SelectedIndex := Cell.X;

设置行比较棘手,到目前为止,我能找到的唯一方法涉及所谓的受保护的hack,访问受保护属性的方法和类的方法。这就是我们需要“破解”的TDBGrid课程。

基本上,你声明TDBGrid的空后代,如下所示:

type
  THackDBGrid = class(TDBGrid);

然后,当您需要访问受保护的属性或方法时,只需将标准类的实例(在本例中为MyDBGrid)转换为“hacked”类型(THackDBGrid):

… THackDBGrid(MyDBGrid).protected_property_or_method

我们感兴趣的项目是Row财产。它返回活动行的Y坐标。我们需要知道它以确定活动行和光标下的行之间的差异,因此我们可以相应地移动基础数据集的记录指针。这是如何做:

MyDataSet.MoveBy(Cell.Y - THackDBGrid(MyDBGrid).Row);

Row值不是绝对值:它相对于可见的顶行,但TGridCoord.Y也是如此,因此两者之间的差异对应于基础数据集中数据行之间的差异。

我要强调的一件事是:谨慎使用这种受保护的黑客方法。受保护的物品受到保护是有原因的。所以,如果你能避免它,请这样做。如果你不能(没有其他方法或者它可以帮助你更容易地做事),请记住不要使用受保护的黑客直接改变任何东西。我的意思是,它可能没事,但通常你永远不会确定。您可以看到我只使用该方法来读取受保护的内容,我没有直接更改任何内容。对象的状态最终被改变了,但这是由MoveBy方法触发的标准机制的结果。

你可以阅读更多关于受保护的黑客here


1
投票

我的实现基于Andriy's excellent detective work

type
  TDBGridAccess = class(TDBGrid);

// Set the currently active grid cell to (DestCol, DestRow). Both values are
// relative to the currently _visible_ upper left grid cell.
procedure SelectDBGridCell(Grid: TDBGrid; DestCol, DestRow: Integer);
var
  CurrentRow: Integer;
begin
  if not Assigned(Grid.DataSource) or not Assigned(Grid.DataSource.DataSet) then
    Exit;

  CurrentRow := TDBGridAccess(Grid).Row;
  Grid.DataSource.DataSet.MoveBy(DestRow-CurrentRow);
  // check if the leftmost grid column is the indicator column which has no
  // equivalent field in the dataset
  if dgIndicator in Grid.Options then
    Grid.SelectedIndex := DestCol-1 else
    Grid.SelectedIndex := DestCol;
end;

procedure TDBGridController.HandleDBGridMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
var
  CellAtMousePos: TGridCoord;
  CurrentRow: Integer;
  DBGrid: TDBGrid;
begin
  DBGrid := Sender as TDBGrid;
  CellAtMousePos := DBGrid.MouseCoord(X, Y);
  if (CellAtMousePos.X<>-1) and (CellAtMousePos.Y<>-1)  then
    SelectDBGridCell(DBGrid, CellAtMousePos.X, CellAtMousePos.Y);
end;

(网格选择遵循鼠标光标。但SelectDBGridCell也可用于根据其他标准选择单元格。)

从技术角度看,它就像魅力一样。可用性是另一个问题。

© www.soinside.com 2019 - 2024. All rights reserved.