DrawGrid/StringGridのDefaultDrawingを使ったDrawCellの使い方
11 DrawGridStringGridDrawCell-1 動作確認 Delphi2007 更新日 2007/12/04(火)

DrawGridやStringGridは表形式のコントロールです。

表に文字を入れて処理したい時はStringGridを使います。
そうではなくサムネイル画像を表にしたり
オセロゲームのマス目として使う場合はDrawGridを使います。

セルに何かを描画する為には
DrawCellイベントにコードを書くことで対応します。


今回は動作がわかりやすいように画面ではStringGridを使いました。

単なる初期化処理だけして動作を確認してみます。

────────────────────
procedure TForm1.FormCreate(Sender: TObject);
begin
  StringGridInitialize;
  StringGrid1.DefaultDrawing := True;
end;

//単なる初期化処理
procedure TForm1.StringGridInitialize;
var
  i, j: Integer;
begin
  for i := 0 to StringGrid1.RowCount - 1 do
  begin
    for j := 0 to StringGrid1.Rows[i].Count - 1 do
    begin
      StringGrid1.Cells[j, i] := IntToStr(i)+'行'+IntToStr(j)+'列';
    end;
  end;
end;
────────────────────
DefaultDrawing := True;の場合

普通の画面です。

DefaultDrawing := False;の場合

コントロールっぽく見えません。

ここでは、元々の描画を活かしたDefaultDrawing := True;の場合
固定セルを描画してくれたり文字を描画してくれたりするので
それを利用しつつ
DrawCellイベントをどのように記述すればよいかをまとめておきます。


自分で描画する処理をいれてみましょう。
1列目の文字を赤色に変え、2行目の背景をグレーにしてみる処理をいれてみます。

────────────────────
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);
begin
  with Sender as TStringGrid do begin

  if ACol=1 then
  begin
    Canvas.Font.Color := clRed;
    Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+2,
      Cells[ACol, ARow]);           //四角の中に文字列を描画
  end;

  if ARow = 2 then
  begin
    Canvas.Brush.Color := clGray;
    Canvas.FillRect(Rect);          //塗りつぶし
  end;

  end;
end;
────────────────────
これが動作画面になります。


ここで2点問題があります。
1  マウスで選択しているセルの枠が若干水色?
2  2列目のセルを四角く塗りつぶしているので文字が見えない。
    
1の問題は、Font.ColorをclRedに変更した影響が
なぜか枠描画にも現れているのでFontColorを元に戻せば直ります。
対策としてFontだけではなくCanvasの描画に必要なPenとBrushもすべて
元の値を確保しておいて、描画が終わったら正しく復帰させるコードを書いておきます。

2の問題は、の後にDrawCellイベントが発生して
FillRectしているから起きている問題なので
DefaultDrawingに頼らずに文字を自分で描画しないとだめなようです。

ということで、対策をしました。
────────────────────
procedure TForm1.StringGrid1DrawCell(Sender: TObject; ACol, ARow: Integer;
  Rect: TRect; State: TGridDrawState);

var
  PenBuffer: TPen;
  BrushBuffer: TBrush;
  FontBuffer: TFont;

  {↓パラメータを一時保存}
  procedure BufferingOn;
  begin
    with Sender as TStringGrid do
    begin
      PenBuffer.Assign(Canvas.Pen);
      BrushBuffer.Assign(Canvas.Brush);
      FontBuffer.Assign(Canvas.Font);
    end;
  end;

  {↓パラメータを復帰}
  procedure BufferingOff;
  begin
    with Sender as TStringGrid do
    begin
      Canvas.Pen.Assign(PenBuffer);
      Canvas.Brush.Assign(BrushBuffer);
      Canvas.Font.Assign(FontBuffer);
    end;
  end;

begin
  PenBuffer := TPen.Create;
  BrushBuffer := TBrush.Create;
  FontBuffer := TFont.Create;
  BufferingOn;

  with Sender as TStringGrid do begin

  if ARow = 2 then
  begin
    Canvas.Brush.Color := clGray;
    Canvas.FillRect(Rect);
    Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+2,
      Cells[ACol, ARow]);
  end;

  if ACol=1 then
  begin
    Canvas.Font.Color := clRed;
    Canvas.TextRect(Rect, Rect.Left+2, Rect.Top+2,
      Cells[ACol, ARow]);
  end;

  end;

  BufferingOff;
  PenBuffer.Free;
  BrushBuffer.Free;
  FontBuffer.Free;
end;
────────────────────
動作画面は次のようになります。


これで、文字色の変更や背景色の変更だけをする場合には
手軽に記述できるでしょう。