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.