2

フォーム全体ですべてのグリッドを同じように表示するにはどうすればよいですか? プロジェクトのすべてのグリッドに適用する必要がある代替行の色を実装したいと考えています。すべてのグリッドに同じ DrawColumnCell イベント コードを追加しなくても可能ですか? 各グリッドに同じコードを追加することは避けたいと考えています。私のプロジェクトには 30 個のグリッドがあり、13 行のコードを掛けると、プロジェクトに多くのコード行が追加されて「使いにくい」ものになります。プロジェクトに 390 行ではなく、13 行のコードしか追加しないソリューションを探しています。

私の書式設定コードは次のようになります(たとえば):

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;

これはできますが、送信者にアクセスできないため、データセットにアクセスして、どのレコードに色を付け、どのレコードに色を付けないか (奇数と偶数) を知ることができます。とにかく、これはすべてのフォームで行う必要があるため、貧弱なアプローチであるため、実際には解決策ではありません

何か案は?

ありがとうございました

4

2 に答える 2

4

このようなものをデータモジュールに入れ、それ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);
    
  • データモジュールの uses 句に DBGrids を追加し、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;
    
于 2014-02-28T00:29:34.757 に答える
1

これは 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;
于 2014-12-23T05:47:31.390 に答える