Альтернативные цвета строк Delphi DBGrid для всех DBGrid в проекте

Как сделать так, чтобы все мои сетки выглядели одинаково во всех формах? Я хочу реализовать альтернативный цвет строки, который должен применяться ко всем сеткам моего проекта. Возможно ли это без добавления одного и того же кода события DrawColumnCell для каждой сетки? Я хочу избежать добавления одного и того же кода для каждой из моих сеток. У меня в проекте около 30 сеток, и умноженное на 13 строк кода, это просто добавляет много строк кода в мой проект, что делает его «недружественным». Я ищу решение, которое добавит в проект только 13 строк кода, а не 390 строк.

Мой код форматирования выглядит так (например):

procedure TDBGrid.DBGrid1DrawColumnCell(Sender: TObject;const Rect: TRect;DataCol: Integer;Column: TColumn;State: TGridDrawState) ;
var
   grid : TDBGrid;
   row : integer;
begin
   grid := sender as TDBGrid;
   row := grid.DataSource.DataSet.RecNo;
   if Odd(row) then
     grid.Canvas.Brush.Color := clSilver
   else
     grid.Canvas.Brush.Color := clDkGray;
   grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
end;

Вероятно, мне нужно было бы как-то расширить DBGrid, но я не знаю, как именно и как искать решение для этого в гугле.

Я пытался взломать DBGRid внутри каждой формы следующим образом:

type
  TDBGrid = class(DBGrids.TDBGrid)
  protected
    procedure DrawColumnCell(const Rect: TRect; DataCol: Integer;Column: TColumn; State: TGridDrawState); override;
  end;
...
procedure TDBGrid.DrawColumnCell(const Rect: TRect; DataCol: Integer;Column: TColumn; State: TGridDrawState) ;
var
       grid : TDBGrid;
       row : integer;
begin
       row := 2;//grid.DataSource.DataSet.RecNo;
       if Odd(row) then
         Canvas.Brush.Color := clSilver
       else
         Canvas.Brush.Color := clDkGray;
       DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
end;

Я могу это сделать, но я не могу получить доступ к отправителю, поэтому я могу получить доступ к набору данных и узнать, какую запись окрашивать, а какую нет (четную и нечетную). И в любом случае это плохой подход, так как мне придется делать это в каждой форме, так что на самом деле это не решение.

Любые идеи?

Спасибо


person user1137313    schedule 28.02.2014    source источник


Ответы (2)


Если вы поместите что-то подобное в свой модуль данных и назначите его OnDrawColumnCell каждой DBGrid, это, похоже, сработает (см. примечания ниже):

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;

Пара замечаний:

  • Во-первых, вам следует избегать использования TDataSet.RecNo в первую очередь, потому что наборы данных после BDE обычно не имеют этого значения. Доступ к нему (особенно к большим наборам данных или наборам данных на основе запросов) приводит к серьезному снижению производительности вашего приложения. Конечно, неиспользование означает, что вы не можете использовать это решение. Лучшим решением было бы использовать обработчик для события BeforeScroll или AfterScroll набора данных, который вместо этого переключал бы логическое значение, доступное для этого кода, и использовать его вместо теста для Odd(RecNo), или, если набор данных используется только для отображения в DBGrid, используйте TDataSet.Tag в событии AfterScroll для отслеживания нечетного/четного состояния строки с помощью

    OddRow := Boolean(DataSet.Tag);
    DataSet.Tag := Ord(not OddRow);
    
  • Добавьте DBGrids в раздел uses вашего модуля данных и вручную объявите указанное выше событие в разделе published, чтобы оно было доступно для всех модулей, использующих модуль данных. Затем вы можете назначить его на вкладке «События» инспектора объектов, как обычно, из этих блоков.

  • Это неправильно обрабатывает TGridDrawState (как и ваш исходный код). Вам нужно будет добавить обработку для этого самостоятельно, так как это не то, о чем вы просили здесь.

  • В зависимости от того, какой цвет вы хотите для нечетных и четных строк, вы можете изменить порядок цветов в RowColors.

  • Я предпочитаю повторяющиеся приведения типов, чтобы было понятно, что делает код. Если вас это беспокоит, вы можете просто вместо этого объявить локальную переменную:

    var
      OddRow: Boolean;
      Grid: TDBGrid;
    begin
      if (Sender is TDBGrid) then
      begin
        Grid := TDBGrid(Sender);
        OddRow := Odd(Grid.DataSource.DataSet.RecNo);
        ...
      end;
    end;
    
person Ken White    schedule 28.02.2014

Это работает для 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;
person user2231096    schedule 23.12.2014