2005. február 24., csütörtök

How to draw checkboxes in a TDBGrid


Problem/Question/Abstract:

How to draw checkboxes in a TDBGrid

Answer:

Two procedures follow. The first is called from the OnDrawColumnCell event of any grid that has visible boolean fields, as so:

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  DrawCheckBoxes(Sender, Rect, DataCol, Column, State);
end;

Here's the procedure. Place this in your toolkit or utility unit.

procedure DrawCheckBoxes(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  MyRect: TRect;
  fld: TField;
begin
  with (Sender as TDBGrid) do
  begin
    fld := Column.Field;
    if fld is TBooleanField then
    begin
      MyRect.Top := ((Rect.Bottom - Rect.Top - 11) div 2) + Rect.Top;
      MyRect.Left := ((Rect.Right - Rect.Left - 11) div 2) + Rect.Left;
      MyRect.Bottom := MyRect.Top + 10;
      MyRect.Right := MyRect.Left + 10;
      if gdSelected in State then
        Canvas.Pen.Color := clWhite
      else
        Canvas.Pen.Color := clBlack;
      Canvas.Polyline([
        Point(MyRect.Left, MyRect.Top), Point(MyRect.Right, MyRect.Top),
          Point(MyRect.Right, MyRect.Bottom), Point(MyRect.Left, MyRect.Bottom),
          Point(MyRect.Left, MyRect.Top)]);
      if fld.AsBoolean then
      begin
        Canvas.MoveTo(MyRect.Left + 2, MyRect.Top + 4);
        Canvas.LineTo(MyRect.Left + 2, MyRect.Top + 7);
        Canvas.MoveTo(MyRect.Left + 3, MyRect.Top + 5);
        Canvas.LineTo(MyRect.Left + 3, MyRect.Top + 8);
        Canvas.MoveTo(MyRect.Left + 4, MyRect.Top + 6);
        Canvas.LineTo(MyRect.Left + 4, MyRect.Top + 9);
        Canvas.MoveTo(MyRect.Left + 5, MyRect.Top + 5);
        Canvas.LineTo(MyRect.Left + 5, MyRect.Top + 8);
        Canvas.MoveTo(MyRect.Left + 6, MyRect.Top + 4);
        Canvas.LineTo(MyRect.Left + 6, MyRect.Top + 7);
        Canvas.MoveTo(MyRect.Left + 7, MyRect.Top + 3);
        Canvas.LineTo(MyRect.Left + 7, MyRect.Top + 6);
        Canvas.MoveTo(MyRect.Left + 8, MyRect.Top + 2);
        Canvas.LineTo(MyRect.Left + 8, MyRect.Top + 5);
      end;
    end;
  end;
end;

There's a little setup involved. Select each visible boolean field in the fields editor and set the DisplayValues to ' ;'. That's space + semicolon. I like the DisplayWidth set to 2.

The next procedure is optional/ extra. It's a keystroke handler that will change the value of the field if the user presses space, T, F, Y, or N.Place it in your utility unit also and call it from your OnKeyPress event in the grid as so:

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
  CheckBoxKeyPress(Sender, Key);
end;

And here's the procedure:

procedure CheckBoxKeyPress(const Sender: TObject; var Key: Char);
var
  fld: TField;
  tbl: TDataset;
  i: integer;
begin
  if UpCase(Key) in [' ', 'T', 'F', 'Y', 'N'] then
  begin
    with (Sender as TDBGrid) do
    begin
      i := SelectedIndex;
      fld := SelectedField;
      tbl := fld.DataSet;
      if fld is TBooleanField then
      begin
        if not (tbl.State in [dsEdit, dsInsert]) then
          tbl.Edit;
        if Key = ' ' then
          fld.AsBoolean := not fld.AsBoolean
        else if (UpCase(Key) = 'T') or (UpCase(Key) = 'Y') then
          fld.AsBoolean := True
        else
          fld.AsBoolean := False;
        tbl.Post;
        Key := #0;
        Inc(i);
        if i = FieldCount then
        begin
          i := 0;
          tbl.Next;
          if tbl.EOF then
            tbl.Append;
        end;
        SelectedIndex := i;
      end;
    end;
  end;
end;

Nincsenek megjegyzések:

Megjegyzés küldése