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

时间:2011-11-02 10:22:41

标签: delphi dbgrid

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

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

2 个答案:

答案 0 :(得分: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;

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

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

type
  THackDBGrid = class(TDBGrid);

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

… THackDBGrid(MyDBGrid).protected_property_or_method

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

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

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

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

您可以阅读有关受保护的黑客here的更多信息。

答案 1 :(得分: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也可用于根据其他标准选择单元格。)

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