【问题标题】:Delphi DBGrid alternate row colors for all DBGrids in the project项目中所有 DBGrid 的 Delphi DBGrid 交替行颜色
【发布时间】:2014-03-31 18:19:32
【问题描述】:

如何使我的所有网格在我的表单中看起来都一样? 我想实现一个替代行颜色,它必须应用于我项目的所有网格。是否可以不为每个网格添加相同的 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,但我不知道如何或如何在 google 上寻找解决方案

我试图像这样破解每个表单中的 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;

我可以这样做,但我无法访问发件人,因此我可以访问数据集并知道要着色的记录和不着色的记录(奇数和偶数)。 无论如何,这是一个糟糕的方法,因为我必须在每个表单上都这样做,所以这不是一个真正的解决方案

有什么想法吗?

谢谢

【问题讨论】:

    标签: delphi delphi-xe tdbgrid


    【解决方案1】:

    如果你把这样的东西放在你的数据模块中,并将它分配给每个 DBGrid 的OnDrawColumnCell,它似乎可以工作(见下面的注释):

    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 中显示,使用AfterScroll 事件中的TDataSet.Tag 跟踪行的奇数/偶数状态,使用

      OddRow := Boolean(DataSet.Tag);
      DataSet.Tag := Ord(not OddRow);
      
    • 将 DBGrids 添加到数据模块的 uses 子句中,并在 published 部分手动声明上述事件,以便所有使用数据模块的单元都可以使用它。然后,您可以像往常一样从这些单元在 Object Inspector Events 选项卡中分配它。

    • 这不能正确处理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;
      

    【讨论】:

      【解决方案2】:

      这适用于 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;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多