我想通过代码激活TDBGrid
中的单元格。通过“激活”我的意思是用户点击单元格内部,准备编辑单元格内容。我怎么能这样做?
编辑:这可能涉及两个步骤:更改当前活动的单元格,然后进入编辑模式。
如果您的意思是“激活当前活动单元格的编辑模式”,那么您应该这样做:
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。
我的实现基于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
也可用于根据其他标准选择单元格。)
从技术角度看,它就像魅力一样。可用性是另一个问题。