delphitdbgrid

Adding a checkbox in a grid whose OnDrawColumnCell handler is generic


Following on from this question and its very useful answer: I implemented a variation of Ken's answer in my big project where I had similar code appearing in many forms. But I noticed that I also had some forms with DrawColumnCell handlers as follows

procedure TEditDocket.DBGrid1DrawColumnCell(Sender: TObject;
           const Rect: TRect; DataCol: Integer; Column: TColumn;
           State: TGridDrawState);
var
 DrawRect: TRect;

begin
 if column.Index  = 3 then
  begin
   DrawRect:= Rect;
   drawrect.left:= rect.left + 24;
   InflateRect (DrawRect, -1, -1);
   dbgrid1.Canvas.FillRect (Rect);
   DrawFrameControl (dbgrid1.Canvas.Handle, DrawRect, DFC_BUTTON,
                 ISChecked[Column.Field.AsInteger]);
  end
 else dbgrid1.DefaultDrawColumnCell (Rect, DataCol, Column, State);
end;

How I could combine the above code with a general OnDrawColumnCell handler? Is it possible to define the general handler with an extra parameter (which would be the column index; if it were -1 then the above code would not execute)? How would I pass such a parameter to the handler?


Solution

  • Independently, I reached the following answer using the 'tag' property of the grid.

    In the client form, I write

     dbGrid1.OnDrawColumnCell:= dm.DBGrid1DrawColumnCell;
     dbGrid1.tag:= 3;  // column with checkbox
     dbGrid2.OnDrawColumnCell:= dm.DBGrid1DrawColumnCell;
     dbGrid2.tag:= $23;  // both columns 2 and 3 are checkboxes 
    

    The default handler is now

    procedure TDm.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
              DataCol: Integer; Column: TColumn; State: TGridDrawState);
    const
      IsChecked : array[0..1] of Integer =
                    (DFCS_BUTTONCHECK, DFCS_BUTTONCHECK or DFCS_CHECKED);
    
    var
     DrawRect: TRect;
     tag: integer;
     cols: set of byte;
    
    begin
     if sender is TDBGrid then
      begin
       tag:= TDBGrid (sender).tag;
       if (THackDBGrid (sender).DataLink.ActiveRecord + 1 = THackDBGrid (sender).Row)
       or (gdFocused in State) or (gdSelected in State) then
        with TDBGrid (sender) do
         begin
          canvas.Brush.Color:= clMoneyGreen;
          canvas.font.color:= clNavy;
         end;
    
       cols:= [];
       while tag > 0 do
        begin
         cols:= cols + [tag mod 16];
         tag:= tag div 16
        end;
    
       if column.Index in cols then
        begin
         DrawRect:= Rect;
         drawrect.left:= rect.left + 24;
         InflateRect (DrawRect, -1, -1);
         TDBGrid (sender).Canvas.FillRect (Rect);
         DrawFrameControl (TDBGrid (sender).Canvas.Handle, DrawRect, DFC_BUTTON,
                       ISChecked[Column.Field.AsInteger]);
        end
       else
        begin
         TDBGrid (sender).DefaultDrawColumnCell (Rect, DataCol, Column, State);
        end;
      end;
    end;
    

    This means that column 0 must never be a checkbox. Using a set allows up to four columns in the grid to be checkboxes.