Delphi DBGrid alternate row colors for all DBGrids in the project

喜欢而已 提交于 2019-12-06 14:14:37

If you put something like this in your datamodule, and assign it to the OnDrawColumnCell of every DBGrid, it seems to work (see notes that follow):

procedure TDataModule1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  RowColors: array[Boolean] of TColor = (clSilver, clDkGray);
var
  OddRow: Boolean;
begin
  // Safety check, although it really isn't needed; no other control accepts
  // this event handler definition, AFAIK, so the only way to call it with the
  // wrong Sender type would be to do so in your own code manually. In my own
  // code, I'd simply leave out the check and let the exception happen; if I
  // was stupid enough to do so, I'd want my hand slapped rudely.
  if (Sender is TDBGrid) then
  begin
    OddRow := Odd(TDBGrid(Sender).DataSource.DataSet.RecNo);
    TDBGrid(Sender).Canvas.Brush.Color := RowColors[OddRow];
    TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;

A couple of notes:

  • First, you should avoid using TDataSet.RecNo in the first place, because post-BDE datasets don't typically have this value available. Accessing it (particularly on large or query-based datasets) causes a major performance hit to your application. Of course, not using it means that you can't use this solution. A better solution would be to use a handler for the dataset's BeforeScroll or AfterScroll event that toggled a boolean available to this code instead, and use that instead of the test for Odd(RecNo), or if the dataset is only used for displaying in the DBGrid, use the TDataSet.Tag in the AfterScroll event to track the row's odd/even state using

    OddRow := Boolean(DataSet.Tag);
    DataSet.Tag := Ord(not OddRow);
    
  • Add DBGrids to the uses clause of your datamodule, and manually declare the above event in the published section so that it's available to all units that use the datamodule. You can then assign it in the Object Inspector Events tab as usual from those units.

  • This does not properly handle the TGridDrawState (nor does your initial code). You'll need to add handling for that yourself, as that wasn't what you asked here.

  • Depending on which color you want for odd and even rows, you may want to reverse the order of the colors in RowColors.

  • I prefer the repeated typecasts so that it's clear what the code is doing. If it bothers you, you can simply declare a local variable instead:

    var
      OddRow: Boolean;
      Grid: TDBGrid;
    begin
      if (Sender is TDBGrid) then
      begin
        Grid := TDBGrid(Sender);
        OddRow := Odd(Grid.DataSource.DataSet.RecNo);
        ...
      end;
    end;
    
user2231096

This works for Delphi XE7

type
  TDBGrid=Class(Vcl.DBGrids.TDBGrid)
    procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL;
  end;

procedure TDBGrid.WMVScroll(var Message: TWMVScroll);
begin
  Self.Invalidate;
  inherited;
end;

procedure TForm1. DBGrid1MouseWheel(Sender: TObject; Shift: TShiftState;
  WheelDelta: Integer; MousePos: TPoint; var Handled: Boolean);
begin
  if Sender is TDBGrid then
    (Sender as TDBGrid).Invalidate;
end;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  MyRowColors : array[Boolean] of TColor = (clLime, clMoneyGreen);
var
  RowNo  : Integer;
  OddRow : Boolean;
  S      : string;
begin
  if Sender is TDBGrid then begin
    with (Sender as TDBGrid) do  begin
      if (gdSelected in State) then begin
        // Farbe für die Zelle mit dem Focus
        // color of the focused row
        Canvas.Brush.Color := clblue;
      end   
      else  begin
        // count := trunc((Sender as TDBGrid).Height div (Rect.Bottom - Rect.Top));
        // RowNo := (Sender as TDBGrid).Height div Rect.Top;
        RowNo := Rect.Top div (Rect.Bottom - Rect.Top);
        OddRow := Odd(RowNo);
        Canvas.Brush.Color := MyRowColors[OddRow];

        // Font-Farbe immer schwarz
        // font color always black
        Canvas.Font.Color := clBlack;
        Canvas.FillRect(Rect);
        // Denn Text in der Zelle ausgeben
        // manualy output the text
        if Column.Field <> nil then begin
          S := Column.Field.AsString;
          Canvas.TextOut(Rect.Left + 2, Rect.Top + 1, S);
          //  Canvas.TextOut(Rect.Left + 2, Rect.Top + 1, 'Column.Field.AsString');
        end;
      end;
    end 
  end; 
end;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!