我在哪里可以拦截派生 TDBGrid 中的行更改? [英] Where can I intercept the row change in a derivative TDBGrid?

查看:28
本文介绍了我在哪里可以拦截派生 TDBGrid 中的行更改?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果网格正在绘制其活动行,我想知道是否覆盖了 DrawColumnCell.

I want to know on an overriding of DrawColumnCell if the grid is drawing its active row.

我想保留一个 ActiveRecno 私有变量来检查 DrawColumnCell 是否正在绘制该行.我尝试拦截数据源的 DataChange 以跟踪该 ActiveRecno.

I thought of keeping an ActiveRecno private variable to check if the DrawColumnCell is drawing that row. I tried intercepting the DataChange of the Datasource to keep track of that ActiveRecno.

TMyDBGrid = class(TDBGrid)
  protected
    OnDataChange_Original: TDataChangeEvent;
    procedure TrackPosition(Sender: TObject; Field: TField);
    procedure DrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); override;
  public
    ActiveRecno: integer;
    constructor Create(AOwner: TComponent): override;
  ...
  ...

implementation

constructor TMyDBGrid.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  OnDataChange_Original := nil;
  if Assigned(DataSource) then begin
    OnDataChange_Original := Datasource.OnDataChange;
    Datasource.OnDataChange := TrackPosition;
  end;
end;

procedure TMyDBGrid.TrackPosition(Sender: TObject; Field: TField);
begin
  ActiveRecno := Datasource.DataSet.RecNo;
  if Assigned(OnDataChange_Original) then OnDataChange_Original(Sender, Field);
end;

procedure TMyDBGrid.DrawColumnCell(const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); 
var ActiveRow: boolean;
begin
  ActiveRow := (Self.ActiveRecno = Self.DataSource.Dataset.Recno); 
  ...
  ...

  inherited DrawColumnCell(Rect, DataCol, Column, State);
end;

但 ActiveRecno 始终为 0,使 ActiveRow 始终为 False.那是因为在构造函数中Datasource仍然是nil,所以我从来没有设置TrackPosition来保留ActiveRecno.

But ActiveRecno remains always 0, making ActiveRow always False. That's because in the constructor Datasource is still nil, so I never set TrackPosition to keep the ActiveRecno.

在哪里可以为该事件设置处理程序?SetDataSource 过程是私有的,因此我无法覆盖它.

Where can I set my handler for that event ?, the SetDataSource procedure is private, so I can't override it.

你是否推荐我另一种方法来跟踪活动行,或者在 DrawColumnCell 中检测要绘制的行是否是活动行?.

Do you recommend me another way to keep track of the active row, or detect in DrawColumnCell if the row to draw is the active row ?.

谢谢.

推荐答案

我认为你想要的很简单,除了当前行DBGrid 和 OnDrawrDataCell 事件中正在绘制的行都可以在事件内轻松访问.

I think that what you want would be straightforward except for the fact that neither the current row of the DBGrid nor the row being drawn in the OnDrawrDataCell event is readily accessible inside the event.

幸运的是,使用如下所示的内插器 TDBGrid 类可以非常简单地解决这些问题.

Fortunately, it is fairly straightforward to overcome these problems using an interposer TDBGrid class as shown below.

中介层 TDBGrid 类只是将 TCustomGrid 的 Row 属性公开为 ActiveRow

THe interposer TDBGrid class simply exposes the Row property of TCustomGrid as the ActiveRow

OnDrawDataCell 事件是从 TCustomDBGrid.DrawCell 调用的,它是虚拟的,因此可以被覆盖在中介层类中.如下所示,覆盖版本首先复制使用的行号(ARow 参数)在 TCustomDBGrid.DrawCell 中放入 FRowBeingDrawn 字段,然后调用继承的 DrawDataCell,后者又调用 OnDrawDataCell 处理程序.由于这个处理程序看到中介层类,网格的 ActiveRow 和 RowBeingDrawn 都可以在内部访问OnDrawDataCell 事件.

The OnDrawDataCell event is called from TCustomDBGrid.DrawCell, which is virtual and so can be overridden in the interposer class. As you can see below, the overridden version first copies the row number (the ARow argument) used in TCustomDBGrid.DrawCell into the FRowBeingDrawn field and then calls the inherited DrawDataCell, which in turn calls the OnDrawDataCell handler. Since this handler sees the interposer class, both the grid's ActiveRow and RowBeingDrawn are accessible inside the OnDrawDataCell event.

type
  TDBGrid = class(DBGrids.TDBGrid)
  private                                   ,
    FRowBeingDrawn : Integer;
    function GetActiveRow: Integer;
  protected
    procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
    property RowBeingDrawn : Integer read FRowBeingDrawn write FRowBeingDrawn;
    property ActiveRow : Integer read GetActiveRow;
  end;

  TForm1 = class(TForm)
    DBGrid1: TDBGrid;
    ClientDataSet1: TClientDataSet;
    DataSource1: TDataSource;
    ComboBox1: TComboBox;
    DBNavigator1: TDBNavigator;
    procedure FormCreate(Sender: TObject);
    procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
      DataCol: Integer; Column: TColumn; State: TGridDrawState);
  end;

[...]

procedure TForm1.FormCreate(Sender: TObject);
var
  AField : TField;
begin
  AField := TIntegerField.Create(Self);
  AField.FieldKind := fkData;
  AField.FieldName := 'ID';
  AField.DataSet := ClientDataSet1;

  AField := TStringField.Create(Self);
  AField.FieldKind := fkData;
  AField.FieldName := 'AValue';
  AField.DataSet := ClientDataSet1;

  ClientDataSet1.CreateDataSet;
  ClientDataSet1.InsertRecord([1, 'One']);
  ClientDataSet1.InsertRecord([2, 'Two']);
  ClientDataSet1.InsertRecord([3, 'Three']);
  ClientDataSet1.InsertRecord([4, 'Four']);
  ClientDataSet1.InsertRecord([5, 'Five']);

  DBGrid1.DefaultDrawing := True;
end;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
   if (Sender as TDBGrid).RowBeingDrawn = (Sender as TDBGrid).Row then
     Caption := IntToStr((Sender as TDBGrid).RowBeingDrawn);

  DBGrid1.DefaultDrawDataCell(Rect, Column.Field, State);

end;

procedure TDBGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
  AState: TGridDrawState);
begin
  RowBeingDrawn := ARow;
  try
    inherited;
  finally
    RowBeingDrawn := -1;
  end;
end;

function TDBGrid.GetActiveRow: Integer;
begin
  Result := Row;
end;

end.

内插器类当然可以包含在一个单独的单元中,当然,前提是它出现在 DBGrids 之后的使用单元的 Uses 列表中.

The interposer class can, of course, be contained in a separate unit provided, of course, that it appears in the using unit's Uses list after DBGrids.

需要注意的一个小问题是,上面的代码没有考虑网格的标题行是否可见,如果不可见,则需要稍作调整.

One minor point to beware of is that the code above does not take account of whether the title row of the grid is visble or not, and make require minor tweaking if it is not.

这篇关于我在哪里可以拦截派生 TDBGrid 中的行更改?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆