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