【Delphi】TDBGrid中的Helper定制:斑马纹、记录行号

        TDBGrid 一行代码实现斑马纹和行号显示! 

        在用 Delphi 开发数据表显示时,经常会用到TDBGrid控件,利用三方控件可以看到实现非常美观漂亮的斑马纹,那么不使用第三方的控件,可否也能方便的实现斑马纹以及数据记录行号的显示呢?当然是可以的,而且只需一行代码即可实现。

        本文介绍通过Delphi的Helper来实现通用TDBGird显示斑马纹和行号。

调用:

DBGrid.EnableZebraStriping;
//或者
DBGrid.EnableZebraStriping(clGreen,clGray,True,'ID');

使用说明如下:

功能:
    1. 通过 Helper 自动实现 GBDird 按照斑马纹显示,斑马纹奇数行和偶数行颜色可以设置
    2. 自动实现显示数据表的行号,从 1 开始,可以设置行号的标题,默认为:行号

  调用:
    1. 需要设置 DBGrid 的单元中需要引用本单元:uTDBGrid_Helper.pas
    2. 在 FormShow 事件中或者合适的试剂调用函数:EnableZebraStriping
       参数说明:
          OddRowColor  :奇数行颜色  默认白色 clWhite
          EvenRowColor :偶数行颜色  默认浅灰 $00F8F8F8
          ShowRowID    :是否自动显示数据表的行号, True表示显示, False表示不显示 默认:True
          RowIDCaption :行号的标题文字,默认:行号

       例如:
         DBGrid.EnableZebraStriping(clGreen,clGray,True,'ID');
           显示奇数行绿色,偶数行灰色,标题文字为:ID

       恢复默认显示: 不在显示斑马纹
         DBGrid.DisableZebraStriping

    3. 额外说明:选择行有焦点颜色为:clHighlight 无焦点颜色为:$00FFA940
         程序没有通过函数设置,可以通过修改这两个参数来改变选择行的颜色

    4. 正常的 DBGrid 的 OnDrawColumnCell 事件不受影响,无需在做斑马纹功能

完整的代码如下:

{
  作者: sensor  2025-08-10
  功能:
    1. 通过 Helper 自动实现 GBDird 按照斑马纹显示,斑马纹奇数行和偶数行颜色可以设置
    2. 自动实现显示数据表的行号,从 1 开始,可以设置行号的标题,默认为:行号

  调用:
    1. 需要设置 DBGrid 的单元中需要引用本单元:uTDBGrid_Helper.pas
    2. 在 FormShow 事件中或者合适的试剂调用函数:EnableZebraStriping
       参数说明:
          OddRowColor  :奇数行颜色  默认白色 clWhite
          EvenRowColor :偶数行颜色  默认浅灰 $00F8F8F8
          ShowRowID    :是否自动显示数据表的行号, True表示显示, False表示不显示 默认:True
          RowIDCaption :行号的标题文字,默认:行号

       例如:
         DBGrid.EnableZebraStriping(clGreen,clGray,True,'ID');
           显示奇数行绿色,偶数行灰色,标题文字为:ID

       恢复默认显示: 不在显示斑马纹
         DBGrid.DisableZebraStriping

    3. 额外说明:选择行有焦点颜色为:clHighlight 无焦点颜色为:$00FFA940
         程序没有通过函数设置,可以通过修改这两个参数来改变选择行的颜色

    4. 正常的 DBGrid 的 OnDrawColumnCell 事件不受影响,无需在做斑马纹功能

       如果需要改变显示的内容以及颜色等,可以在标准的 OnDrawColumnCell 事件中实现

                procedure TForm_Reagent.DBGrid_Table_stainDrawColumnCell(Sender: TObject;
                  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
                  var
                   TextRect: TRect;
                begin
                  if Column.FieldName = 'stainname' then
                    begin
                      S := Column.Field.AsString;
                      if S = '二甲苯' then
                        begin
                         S := S + ' 测试';
                          //(Sender as TDBGrid).Canvas.Brush.Color := clHighlight;
                          (Sender as TDBGrid).Canvas.Font.Color  := clRed;
                          (Sender as TDBGrid).Canvas.FillRect(Rect);
                          TextRect := Rect;
                          InflateRect(TextRect, -2, -2); // 文字边距
                          DrawText((Sender as TDBGrid).Canvas.Handle, PChar(S),
                            Length(S), TextRect, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
                        end;


                end;



}
unit uTDBGrid_Helper;

interface
uses
  Vcl.DBGrids,
  Vcl.Graphics,
  Vcl.Grids,
  System.Types,
  System.Generics.Collections,
  Winapi.Windows,
  System.SysUtils,
  System.Classes,
  Data.DB;

type
  TZebra_Color = record
    OddRowColor  : TColor;
    EvenRowColor : TColor;
    ShowRowID    : Boolean;  //是否显示行号
    RowIDCaption : string;
  end;

var
  OriginalDrawEvents: TDictionary<TDBGrid, TDrawColumnCellEvent>;
  ZebraDrawColor    : TDictionary<TDBGrid, TZebra_Color>;

type
  TDBGridHelper = class helper for TDBGrid
    procedure DrawColumnCellEvent_New(Sender: TObject; const Rect: TRect; DataCol: Integer;
              Column: TColumn; State: TGridDrawState);
    //查找是否已经包含 "行号"这一列  返回 -1 表示不存在
    function Get_RowID_Index : integer;

  public
    procedure EnableZebraStriping(OddRowColor: TColor = clWhite; EvenRowColor: TColor = $00F8F8F8; ShowRowID : Boolean = True; RowIDCaption : string = '行号');
    procedure DisableZebraStriping;
  end;

implementation

procedure TDBGridHelper.DrawColumnCellEvent_New(Sender: TObject;
  const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  Grid: TDBGrid;
  OriginalEvent: TDrawColumnCellEvent;
  Zebra_Color  : TZebra_Color;
  TextRect     : TRect;
  idText       : string;
begin
  Grid := Sender as TDBGrid;

  // 调用原始事件(如果存在)
  if Assigned(OriginalDrawEvents) then
  if not OriginalDrawEvents.TryGetValue(Grid, OriginalEvent) then Exit;


  if Assigned(ZebraDrawColor) and ZebraDrawColor.TryGetValue(Self, Zebra_Color) then
     begin
      // 如果不是选中行,则应用斑马纹
      if not (gdSelected in State) then
        begin
          if (Grid.DataSource.DataSet.RecNo mod 2) = 1 then
            Grid.Canvas.Brush.Color := Zebra_Color.OddRowColor
          else
            Grid.Canvas.Brush.Color := Zebra_Color.EvenRowColor;
        end
      else
        begin
         //if gdFocused in State then   //这一句在这里并不起作用,不知道为什么?
         if Self.Focused then
           begin
             Grid.Canvas.Brush.Color := clHighlight;
             Grid.Canvas.Font.Color  := clwhite;
           end
         else
           begin
             Grid.Canvas.Brush.Color := $00FFA940;
             Grid.Canvas.Font.Color  := clwhite;
           end;
        end;

       //如果需要显示行号
       if Zebra_Color.ShowRowID then
        begin
          if (Column.Title.Caption = Zebra_Color.RowIDCaption) and (Column.FieldName = '') and (Column.DropDownRows = 0) then
             begin
               idText :=  Grid.DataSource.DataSet.RecNo.ToString;
               Grid.Canvas.FillRect(Rect);
               TextRect := Rect;
               InflateRect(TextRect, -2, -2); // 文字边距
               DrawText(Grid.Canvas.Handle, PChar(idText),
                 Length(idText), TextRect, DT_CENTER or DT_VCENTER or DT_SINGLELINE);
               Exit;    //这里已经画好行号,直接退出
             end;
        end;


      Grid.Canvas.FillRect(Rect);
      Grid.DefaultDrawColumnCell(Rect, DataCol, Column, State);
     end;

  //调用原来的事件
  if Assigned(OriginalEvent) then
     OriginalEvent(Sender, Rect, DataCol, Column, State);




end;

procedure TDBGridHelper.EnableZebraStriping(OddRowColor, EvenRowColor: TColor; ShowRowID : Boolean; RowIDCaption : string);
var
  Zebra_Color : TZebra_Color;
begin
  if not Assigned(OriginalDrawEvents) then
    OriginalDrawEvents := TDictionary<TDBGrid, TDrawColumnCellEvent>.Create;

  if not Assigned(ZebraDrawColor) then
    ZebraDrawColor := TDictionary<TDBGrid, TZebra_Color>.Create;

  // 存储原始事件(如果尚未存储)
  if not OriginalDrawEvents.ContainsKey(Self) then
    OriginalDrawEvents.Add(Self, Self.OnDrawColumnCell);

  //存储斑马纹颜色
  Zebra_Color.OddRowColor  := OddRowColor;
  Zebra_Color.EvenRowColor := EvenRowColor;
  Zebra_Color.ShowRowID    := ShowRowID;
  Zebra_Color.RowIDCaption := RowIDCaption;

  //如果需要显示行号,则需要在DBGrid中增加一列
  if ShowRowID then
    begin
      if Get_RowID_Index = -1 then
        with Self.Columns.Add do
          begin
            Index := 0;
            Title.Caption := RowIDCaption;
            Width         := 100;
            Title.Alignment := taCenter;
            Title.Font    := Self.Columns[1].Title.Font;
            FieldName     := '';
            ReadOnly      := True;
            DropDownRows  := 0;        //作为和用户的列区分的标志,0表示不是用户列
          end;
    end;



  if not ZebraDrawColor.ContainsKey(Self) then
     ZebraDrawColor.Add(Self, Zebra_Color);

  Self.DefaultDrawing := False;

  Self.OnDrawColumnCell := DrawColumnCellEvent_New;

  //刷新显示界面
  Self.Refresh;
end;

function TDBGridHelper.Get_RowID_Index: integer;
var
  Zebra_Color : TZebra_Color;
  i,count : integer;
begin
  Result := -1;
  if Assigned(ZebraDrawColor) and ZebraDrawColor.TryGetValue(Self, Zebra_Color) then
    begin
      count := Self.Columns.Count;
      for i := 0 to count - 1  do
        begin
          if (Self.Columns[i].Title.Caption = Zebra_Color.RowIDCaption) and (self.Columns[i].FieldName = '') and (Self.Columns[i].DropDownRows = 0) then
            Exit(i);
        end;
    end;
end;

procedure TDBGridHelper.DisableZebraStriping;
var
  OriginalEvent: TDrawColumnCellEvent;
  Zebra_Color : TZebra_Color;
  i           : integer;
begin
  if Assigned(OriginalDrawEvents) and OriginalDrawEvents.TryGetValue(Self, OriginalEvent) then
  begin
    Self.OnDrawColumnCell := OriginalEvent;
    OriginalDrawEvents.Remove(Self);
  end;

  Self.DefaultDrawing := True;

  if Assigned(ZebraDrawColor) and ZebraDrawColor.TryGetValue(Self, Zebra_Color) then
    begin
      if Zebra_Color.ShowRowID then
         begin
           i := Get_RowID_Index;
           if i >= 0  then
             Self.Columns.Delete(i);
         end;
    end;


  //刷新显示界面
  Self.Refresh;
end;

// 在程序退出时释放字典
initialization

finalization
  if Assigned(OriginalDrawEvents) then
    OriginalDrawEvents.Free;
  if Assigned(ZebraDrawColor) then
    ZebraDrawColor.Free;

end.

谁用谁知道!

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海纳老吴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值