The simplest and most comprehensive method tested by me is as follows:
In the private section of your unit, declare a global value to save the grid settings. It will be used to recover after temporarily disabling text editing while entering a checkbox column - as this is probably one of the few errors mentioned by Jordan Borisov regarding the article delphi.about.com
private GridOriginalOptions : TDBGridOptions;
In the OnCellClick event, if the field is logical, toggles and publishes changes to the database
procedure TForm1.DBGrid1CellClick(Column: TColumn); begin if (Column.Field.DataType=ftBoolean) then begin Column.Grid.DataSource.DataSet.Edit; Column.Field.Value:= not Column.Field.AsBoolean; Column.Grid.DataSource.DataSet.Post; end; end;
Drawing a flag for Boolean grid fields
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) ; begin if (Column.Field.DataType=ftBoolean) then begin DBGrid1.Canvas.FillRect(Rect) ; if (VarIsNull(Column.Field.Value)) then DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, DFCS_BUTTONCHECK or DFCS_INACTIVE) else DrawFrameControl(DBGrid1.Canvas.Handle,Rect, DFC_BUTTON, CtrlState[Column.Field.AsBoolean]); end; end;
Now the new part will disable editing cells in the boolean column. In the OnColEnter and OnColExit events:
procedure TForm1.DBGrid1ColEnter(Sender: TObject); begin if Self.DBGrid1.SelectedField.DataType = ftBoolean then begin Self.GridOriginalOptions := Self.DBGrid1.Options; Self.DBGrid1.Options := Self.DBGrid1.Options - [dgEditing]; end; end; procedure TForm1.DBGrid1ColExit(Sender: TObject); begin if Self.DBGrid1.SelectedField.DataType = ftBoolean then Self.DBGrid1.Options := Self.GridOriginalOptions; end;
Moreover, the space bar key to toggle the checkbox
procedure TForm1.DBGrid1KeyDown(Sender: TObject; var Key: Word; Shift: TShiftState); begin if ((Self.DBGrid1.SelectedField.DataType = ftBoolean) and (key = VK_SPACE)) then begin Self.DBGrid1.DataSource.DataSet.Edit; Self.DBGrid1.SelectedField.Value:= not Self.DBGrid1.SelectedField.AsBoolean; Self.DBGrid1.DataSource.DataSet.Post; end; end;
What is it!