Home > Software engineering >  Delphi FMX TStringgrid, draw a checkbox on a single cell
Delphi FMX TStringgrid, draw a checkbox on a single cell

Time:07-21

I want to put a checkbox on a single cell (not a checkcolunn) of a FMX stringgrid.

I think that I need to use 'StringGrid1.AddObject' but I do not know how to go from there.

CodePudding user response:

I don't understand you can't (but you change my code). First I want to say I am not a Stringgrid fan on Android but that's another point. Second point I focused on drawing, I also wrote some code to manage some others style containing a Tpath instead of a TStyleObject

procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject;
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
  const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var sb : TFMXObject;
    aRectF : TRectF;
    img : tfmxobject;
begin
if Assigned(Stylebook) then sb:=Stylebook.Style  else sb:=TStyleManager.ActiveStyle(Self);
if Test.find(Column.Index,Row)>=0 then
 begin
    if Test[Test.Find(Column.Index,Row)].ischecked
      then img := sb.FindStyleResource('checkcellstyle.checkboxchecked')
      else img := sb.FindStyleResource('checkcellstyle.checkboxunchecked');
    if assigned(img) then
      begin
        aRectf:=Bounds;
        arectf.Left:=arectf.Right-20; // to adapt
        TStyleObject(img).DrawToCanvas(Canvas,arectf,1);
      end
    else begin
      img:= sb.FindStyleResource('checkcellstyle');
      if assigned(img) then img:=img.FindStyleResource('checkmark');
      if assigned(img) and (img is Tpath) then
       begin
        if Test[Test.Find(Column.Index,Row)].ischecked
          then Tpath(img).Fill.Color:=TColorAnimation(Img.Children[0]).StopValue
          else Tpath(img).Fill.Color:=TColorAnimation(Img.Children[0]).StartValue;
        var bmp:=Tpath(Img).MakeScreenshot;
        aRectf:=Bounds;
        arectf.Left:=arectf.Right-20; // to adapt
        Canvas.DrawBitmap(bmp,Trectf.Create(0,0,bmp.Width,bmp.Height),aRectf,1);
       end;

    end;
    end;
end;

but this is not a problem here.

Here is two screenshots, proving my code works. First one I use transparent.style wich as a default platform

enter image description here

then I add C:\Users\Public\Documents\Embarcadero\Studio\22.0\Styles\Android\AndroidWearDarkBlue.fsf and got this one

enter image description here

What is still not clear for me on Android is the way to check/oncheck value on Android. Sometimes CellDblclick event works, sometimes not !

CodePudding user response:

You can't, because Cells[col,raw] is a string, and there is no cell selection support. But if you manage a List of selected cells somewhere and use OnDrawCellEvent, it's possible.

Here is a "dirty" sample, but you can see I use Style:

enter image description here

And how I manage this:

procedure TForm1.FormCreate(Sender: TObject);
begin
 SelectedCells:=TList<String>.Create(['0,2']);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SelectedCells.Free;
end;
procedure TForm1.StringGrid1CellDblClick(const Column: TColumn;
  const Row: Integer);
begin
 if SelectedCells.IndexOf(Format('%d,%d',[Column.Index,Row]))>=0
   then SelectedCells.Remove(Format('%d,%d',[Column.Index,Row]))
   else SelectedCells.Add(Format('%d,%d',[Column.Index,Row]));
end;

procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject;
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
  const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var sb : TFMXObject;
    aRectF : TRectF;
begin
if Assigned(Stylebook) then sb:=Stylebook.Style  else sb:=TStyleManager.ActiveStyle(Self);
if SelectedCells.IndexOf(Format('%d,%d',[Column.Index,Row]))>=0 then
 begin
    var img := sb.FindStyleResource('checkcellstyle.checkboxchecked');
    if assigned(img) then
      begin
        aRectf:=Bounds;
        arectf.Left:=arectf.Right-20; // to adapt
        TStyleObject(img).DrawToCanvas(Canvas,arectf,1);
      end;
 end;
end;

Caveats: not all styles can be used, I think.

CodePudding user response:

I reworked the answer of SergeGirard

unit Main;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes,
  System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, System.Rtti,
  FMX.Grid.Style, FMX.Grid, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Edit,
  System.Generics.Collections, FMX.Styles, FMX.Styles.Objects, FMX.StdCtrls,
  FMX.Objects;

Const
  CHECKBOX_COLUMN = 0;
  CHECKBOX_ROW    = 2;

  SYSTEM_ON  = $101;
  SYSTEM_OFF = $100;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    CurrencyColumn1: TCurrencyColumn;
    StyleBook1: TStyleBook;
    procedure FormCreate(Sender: TObject);
    procedure StringGrid1DrawColumnCell(Sender: TObject; const Canvas: TCanvas;
      const Column: TColumn; const Bounds: TRectF; const Row: Integer;
      const Value: TValue; const State: TGridDrawStates);
    procedure Grid1GetValue(Sender: TObject; const ACol, ARow: Integer;
      var Value: TValue);
    procedure FormDestroy(Sender: TObject);
    procedure StringGrid1CellClick(const Column: TColumn; const Row: Integer);
    procedure StringGrid1SelectCell(Sender: TObject; const ACol, ARow: Integer;
      var CanSelect: Boolean);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  SelectedCells: TList<string>;

implementation

{$R *.fmx}
{$R *.LgXhdpiTb.fmx ANDROID}
{$R *.LgXhdpiPh.fmx ANDROID}
{$R *.Windows.fmx MSWINDOWS}
{$R *.NmXhdpiPh.fmx ANDROID}
{$R *.SmXhdpiPh.fmx ANDROID}

procedure TForm1.FormCreate(Sender: TObject);
Var
  iRow: Integer;
  MyStyle: TFmxObject;
begin
  for iRow := 0 to 10 do
    StringGrid1.Cells[0, iRow] := iRow.ToString;

  StringGrid1.Cells[CHECKBOX_COLUMN, CHECKBOX_ROW] := SYSTEM_OFF.ToString;

  SelectedCells := TList<String>.Create
    ([CHECKBOX_COLUMN.ToString   ','   CHECKBOX_ROW.ToString]);

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  SelectedCells.Free;
end;

procedure TForm1.Grid1GetValue(Sender: TObject; const ACol, ARow: Integer;
  var Value: TValue);
Var
  i: Integer;
begin
//Fill column with some numbers
  for i := 1 to 10 do
    if (ACol = 0) AND (ARow = i - 1) then
      Value := i;
end;

procedure TForm1.StringGrid1CellClick(const Column: TColumn;
  const Row: Integer);
begin
  if (Column.Index = CHECKBOX_COLUMN) AND (Row = CHECKBOX_ROW) then
  Begin
    If StringGrid1.Cells[CHECKBOX_COLUMN, CHECKBOX_ROW] = 
      SYSTEM_OFF.ToString
    then
      StringGrid1.Cells[CHECKBOX_COLUMN, CHECKBOX_ROW] := 
       SYSTEM_ON.ToString
    else
      StringGrid1.Cells[CHECKBOX_COLUMN, CHECKBOX_ROW] := 
        SYSTEM_OFF.ToString;
  End;
  StringGrid1.Repaint;
end;

procedure TForm1.StringGrid1DrawColumnCell(Sender: TObject;
  const Canvas: TCanvas; const Column: TColumn; const Bounds: TRectF;
  const Row: Integer; const Value: TValue; const State: TGridDrawStates);
var
  sb: TFmxObject;
  aRectF: TRectF;
  img: TFmxObject;
begin
  if Assigned(Stylebook) then
    sb := Stylebook.Style
  else
    sb := TStyleManager.ActiveStyle(Self);

  if SelectedCells.IndexOf(Format('%d,%d', [Column.Index, Row])) >= 0 then
  begin
    if StringGrid1.Cells[CHECKBOX_COLUMN, CHECKBOX_ROW].ToInteger = SYSTEM_ON
    then
    Begin
      img := sb.FindStyleResource('checkcellstyle.checkboxchecked');
    End
    else
    Begin
      img := sb.FindStyleResource('checkcellstyle.checkboxunchecked');
    End;

    if Assigned(img) then
    begin
      aRectF := Bounds;
      aRectF.Left := aRectF.Right - 90; // to adapt
      TStyleObject(img).DrawToCanvas(Canvas, aRectF, 1);
      StringGrid1.Repaint;
    end;
  end;

end;

procedure TForm1.StringGrid1SelectCell(Sender: TObject;
  const ACol, ARow: Integer; var CanSelect: Boolean);
begin
  if (ACol = CHECKBOX_COLUMN) AND (ARow = CHECKBOX_ROW) then
    CanSelect := False
  else
    CanSelect := true;
end;

end.`

Column value is 256 unchecked

Column value is 257 checked

As the pictures show this works perfectly on windows 32. However not on Android. Indeed it has something to do with the style (checkcellstyle.checkboxchecked is never found). I can not find a working style for Android any suggestions?

  • Related