轻松实现DBGrid的多表头

轻松实现DBGrid的多表头    hj0791(原作)  
  
关键字     多表头 
  


用法:
  设置DBGrid的Column的Caption属性
  例如:Column1的Caption为111|222
        Column2的Caption为111|333
        那么Column1和Column2公用一个表头111


unit ADBGrid;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  Grids, DBGrids, Math;

type
  TADBGrid = class(TDBGrid)
  private
    { Private declarations }
    //兄弟列子标题,当前列子标题
    BrerLayerTitles, CurLayerTitles: TStringList;
    SaveFont: TFont;
    //根据当前数据列号和表头的层号获取表头的区域
    function TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect; LayerID, ACol: Integer): TRect;
    //解出当前数据列标题为子标题并返回标题层数(子标题数)
    function ExtractSubTitle(LayerTitles: TStrings; ACol: Integer): Integer;
  protected
    { Protected declarations }
    procedure DrawCell(ACol, ARow: Longint; ARect: TRect; AState: TGridDrawState); override;
    procedure Paint; override;
  public
    { Public declarations }
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    { Published declarations }
  end;

procedure Register;

implementation

procedure Register;
begin
  RegisterComponents('Samples', [TADBGrid]);
end;

constructor TADBGrid.Create(AOwner: TComponent);
begin
  inherited;
  BrerLayerTitles := TStringList.Create;
  curLayerTitles := TStringList.Create;
  SaveFont := TFont.Create;
end;

destructor TADBGrid.Destroy;
begin
  BrerLayerTitles.Free;
  curLayerTitles.Free;
  SaveFont.Free;
  inherited;
end;

procedure TADBGrid.DrawCell(ACol, ARow: Integer; ARect: TRect;
  AState: TGridDrawState);
var
  SubTitleRT, CaptionRt, IndicatorRT: TRect;
  Column: TColumn;
  SubTitle: string;
  i: Integer;
begin
  if (ARow = 0) and (ACol > 0) then
  begin
    ExtractSubTitle(curLayerTitles, RawToDataColumn(ACol));
    for i := 0 to curLayerTitles.Count - 1 do
    begin
      SubTitleRT := TitleLayerRect(curLayerTitles, ARect, i, RawToDataColumn(ACol));
      CaptionRt := SubTitleRT;
      Canvas.Brush.Color := FixedColor;
      Canvas.FillRect(SubTitleRT);

      DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDINNER, BF_TOPLEFT);
      if i <> CurLayerTitles.Count - 1 then
      begin
        DrawEdge(Canvas.Handle, SubTitleRT, BDR_RAISEDOUTER, BF_BOTTOM);
        Dec(SubTitleRT.Bottom, 2);
      end else Dec(SubTitleRT.Bottom, 1);
      Canvas.Pen.Color := clWhite;
      Dec(SubTitleRT.Right, 1);
      Canvas.MoveTo(SubTitleRT.Right, SubTitleRT.Top);
      Canvas.LineTo(SubTitleRT.Right, SubTitleRT.Bottom);
      Canvas.LineTo(SubTitleRT.Left, SubTitleRT.Bottom);
      Column := Columns[RawToDataColumn(ACol)];
      SubTitle := '';
      if Assigned(Column) then
      begin
        SubTitle := CurLayerTitles[i];
        SaveFont.Assign(Canvas.Font);
        Canvas.Font.Assign(TitleFont);
        try
          InflateRect(SubTitleRT, -1, -1);
          DrawText(Canvas.Handle, PChar(SubTitle), Length(SubTitle),
            SubTitleRT, DT_CENTER or DT_SINGLELINE or DT_VCENTER);
        finally
          Canvas.Font.Assign(SaveFont);
        end;
      end;
    end;
    if dgIndicator in Options then
    begin
      IndicatorRT := Rect(0, 0, IndicatorWidth + 1, RowHeights[0]);
      Canvas.FillRect(IndicatorRT);
      IndicatorRT.Right := IndicatorRT.Right - 1;
      Canvas.Rectangle(IndicatorRT);
      IndicatorRT.Right := IndicatorRT.Right + 1;
      DrawEdge(Canvas.Handle, IndicatorRT, BDR_RAISEDOUTER, BF_RIGHT);
    end;
  end
  else begin
    inherited;
    if ACol = 0 then
      DrawEdge(Canvas.Handle, ARect, BDR_SUNKENOUTER, BF_BOTTOMRIGHT);
  end;
end;

function TADBGrid.ExtractSubTitle(LayerTitles: TStrings;
  ACol: Integer): Integer;
var L, P: Integer;
  SubTitle: string;
begin
  Result := 0;
  if Assigned(Columns[ACol]) then
    SubTitle := Columns[ACol].Title.Caption
  else Exit;
  if LayerTitles <> nil then LayerTitles.Clear;
  L := 0;
  repeat
    P := Pos('|', SubTitle);
    if P = 0 then
    begin
      if LayerTitles <> nil then LayerTitles.Add(SubTitle);
    end
    else begin
      if LayerTitles <> nil then LayerTitles.Add(Copy(SubTitle, 1, P - 1));
      SubTitle := Copy(SubTitle, P + 1, Length(SubTitle) - P);
    end;
    L := L + 1;
  until P = 0;
  Result := L;
end;

procedure TADBGrid.Paint;
var
  i, MaxLayer, Layer: Integer;
  TM: TTextMetric;
begin
  if ([csLoading, csDestroying] * ComponentState) <> [] then Exit;
  MaxLayer := 0;
  //获取表头最大层数
  for i := 0 to Columns.Count - 1 do
  begin
    Layer := ExtractSubTitle(nil, i);
    if Layer > MaxLayer then MaxLayer := Layer;
  end;
  SaveFont.Assign(Canvas.Font);
  Canvas.Font.Assign(TitleFont);
  try
    GetTextMetrics(Canvas.Handle, TM);
    //调整DBGrid的标题行高度
    RowHeights[0] := (TM.tmHeight + TM.tmInternalLeading + 3) * MaxLayer;
  finally
    Canvas.Font.Assign(SaveFont);
  end;
  inherited;
end;

function TADBGrid.TitleLayerRect(LayerTitles: TStrings; TitleRect: TRect;
  LayerID, ACol: Integer): TRect;
var
  SubTitle: string;
  i, j: Integer;
  bBrer: Boolean;
begin
  Result := TitleRect;
  if Assigned(Columns[ACol]) then
    SubTitle := Columns[ACol].Title.Caption
  else Exit;
  ExtractSubTitle(LayerTitles, ACol);
  //联合左边的兄弟列
  for i := ACol - 1 downto 0 do
  begin
    ExtractSubTitle(BrerLayerTitles, i);
    bBrer := False;
    //判断是否为兄弟列
    if (BrerLayerTitles.Count = LayerTitles.Count) then
    begin
      for j := 0 to LayerID do
      begin
        bBrer := BrerLayerTitles[j] = LayerTitles[j];
        if not bBrer then
          Break;
      end;
    end;
    if bBrer then
    begin
      Result.Left := Result.Left - Columns[i].Width;
      if dgColLines in Options then
        Result.Left := Result.Left - 1;
    end
    else Break;
  end;
  //联合右边的兄弟列
  for i := ACol + 1 to Columns.Count - 1 do
  begin
    ExtractSubTitle(BrerLayerTitles, i);
    bBrer := False;
    //判断是否为兄弟列
    if BrerLayerTitles.Count = LayerTitles.Count then
    begin
      for j := 0 to LayerID do
      begin
        bBrer := BrerLayerTitles[j] = LayerTitles[j];
        if not bBrer then
          Break;
      end;
    end;
    if bBrer then
    begin
      Result.Right := Result.Right + Columns[i].Width;
      if dgColLines in Options then
        Result.Right := Result.Right + 1;
    end
    else Break;
  end;
  //调整表头区域
  Result.Top := (RowHeights[0] div LayerTitles.Count) * LayerID;
  Result.Bottom := (RowHeights[0] div LayerTitles.Count) * (LayerID + 1);
end;

end.
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: DBGrid 是一种用于显示和编辑数据库表格数据的列表控件,常用于数据库应用程序的开发中。通过 DBGrid,用户可以方便地查找、显示和编辑数据库中的数据。 在 DBGrid 中进行数据查找操作十分简便。首先,用户可以使用DBGrid自带的搜索功能进行查找。用户只需在DBGrid的搜索框中输入关键词,点击搜索按钮,即可显示与关键词匹配的记录。这样,用户可以快速找到所需的数据。 另外,DBGrid 也支持在表头中提供过滤条件,用户可以在表头区域输入不同的条件进行查找。比如,用户可以在某一列的表头输入特定的值,DBGrid 会将输入的条件应用到该列,只显示满足条件的记录。这样,用户可以根据自己的需求灵活地筛选出符合条件的数据。 此外,DBGrid 还支持多列的排序功能,用户可以通过点击表头中不同的列来对数据进行升序或降序排列。这样,用户可以根据需要将数据按照不同的列排序,方便查找和比对。 综上所述,DBGrid 是一个功能强大、操作简便的列表控件,用户可以通过自带的搜索功能、过滤条件以及排序功能,方便地进行数据查找操作。无论是在列表中还是在数据库中,DBGrid 都能为用户提供便捷和高效的数据查找体验。 ### 回答2: DBGrid 是一个数据列表控件,常用于数据库应用程序中的数据展示和管理。它可以将数据库中的数据以表格的形式显示出来,并且支持对数据进行排序、筛选、编辑等操作。 在 DBGrid 中进行列表查找,可以通过以下几种方式实现: 1. 根据关键字查找:用户可以在 DBGrid 的搜索框中输入关键字,然后程序根据该关键字进行模糊匹配,将符合条件的数据显示出来。这样用户就能快速找到自己想要的数据。 2. 使用筛选功能:DBGrid 提供了筛选功能,用户可以点击标题栏上的下拉箭头,选择筛选条件进行筛选。只有符合筛选条件的数据才会被显示出来,这样用户就可以按照自己的需求对列表进行过滤显示。 3. 利用排序功能:DBGrid 的列表头部可以点击进行排序。用户可以点击列表头部,实现对某个列的升序或降序排序。通过排序功能,用户可以将数据按照自己的需求进行整理,方便查找。 总之,DBGrid 提供了多种功能,可以帮助用户实现列表查找。无论是根据关键字查找、使用筛选功能还是利用排序功能,都能够提高用户在数据库应用程序中的数据查找效率和体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值