Search code examples
delphicheckboxthemesdbgrid

Delphi: Place a checkbox inside a DBGrid (themed)


I'm using the following code to show a checkbox inside a DBGrid. It works (at least was expected to) both themed and non-themed VCL style (tested in XE2, XE7 and Berlin):

uses Vcl.Themes;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
  CtrlState: Array[Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);
  CtrlStateXP: Array[Boolean] of TThemedButton = (tbCheckBoxUncheckedNormal, tbCheckBoxCheckedNormal);
var
  CheckBoxRectangle : TRect;
  Details: TThemedElementDetails;
begin
  if Column.Field.DataType = ftBoolean then
  begin
    Column.Title.Alignment := taCenter;
    Column.Alignment := taCenter;
    TDBGrid(Sender).Canvas.FillRect(Rect);

    if ThemeServices.ThemesEnabled then
    begin
      Details := ThemeServices.GetElementDetails(CtrlStateXP[Column.Field.AsBoolean]);
      ThemeServices.DrawElement(TDBGrid(Sender).Canvas.Handle, Details, Rect);
    end
    else
    begin
      CheckBoxRectangle.Left   := Rect.Left + 2;
      CheckBoxRectangle.Right  := Rect.Right - 2;
      CheckBoxRectangle.Top    := Rect.Top + 2;
      CheckBoxRectangle.Bottom := Rect.Bottom - 2;
      DrawFrameControl(TDBGrid(Sender).Canvas.Handle, CheckBoxRectangle, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]);
    end;
  end;
end;

It's working fine, except when I move over the rows, the style becomes 'strange', like bellow:

themed issue

Any help? Thanks.


Solution

  • After some attempts and research I've managed to adapt the method by myself, just adding the following lines:

      if not (gdFocused in State) then
        Grid.Canvas.Brush.Color := StyleServices.GetSystemColor(clHighlight);
    

    Here I share the complete method. It could be useful to someone :-)

    uses Vcl.Themes;
    
    procedure CheckBoxGrid(FieldName: String; ValueCheck: Variant; Grid: TDBGrid; const Rect: TRect; Column: TColumn; State: TGridDrawState);
    const
      CtrlState: Array[Boolean] of Integer = (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);
      CtrlStateXP: Array[Boolean] of TThemedButton = (tbCheckBoxUncheckedNormal, tbCheckBoxCheckedNormal);
    var
      R: TRect;
      Details: TThemedElementDetails;
    begin
      if Column.FieldName = FieldName then
      begin
        Column.Title.Alignment := taCenter;
        Column.Alignment := taCenter;
        Grid.Canvas.FillRect(Rect);
    
        if StyleServices.Enabled then
        begin
          Details := StyleServices.GetElementDetails(CtrlStateXP[Column.Field.Value = ValueCheck]);
          StyleServices.DrawElement(Grid.Canvas.Handle, Details, Rect);
    
          if not (gdFocused in State) then
            Grid.Canvas.Brush.Color := StyleServices.GetSystemColor(clHighlight);
        end
        else
        begin
          R := Rect;
          InflateRect(R, -2, -2);
          DrawFrameControl(Grid.Canvas.Handle, R, DFC_BUTTON, CtrlState[Column.Field.Value = ValueCheck]);
        end;
      end;
    end;​