unit JvDBCheckBox; interface uses Windows, Messages, SysUtils, Classes, Contnrs, Controls, DB, DBCtrls; type TJvDBCheckBoxChangingEvent = procedure(Sender: TObject; var Allow: Boolean) of object; TJvDBCheckBox = class(TDBCheckBox) private FDirectEdit: Boolean; FOnChange: TNotifyEvent; FOnChanging: TJvDBCheckBoxChangingEvent; FOrgDataChange: TNotifyEvent; FDataChanging: Integer; FToggling: Integer; FOldValue: Variant; procedure CMExit(var Message: TCMExit); message CM_EXIT; function GetDataLink: TFieldDataLink; protected procedure DataChange(Sender: TObject); procedure Toggle; override; function DoChanging: Boolean; virtual; procedure DoChange; virtual; procedure KeyPress(var Key: Char); override; public constructor Create(AOwner: TComponent); override; published property DirectEdit: Boolean read FDirectEdit write FDirectEdit default True; property OnChanging: TJvDBCheckBoxChangingEvent read FOnChanging write FOnChanging; property OnChange: TNotifyEvent read FOnChange write FOnChange; end; implementation { TJvDBCheckBox } constructor TJvDBCheckBox.Create(AOwner: TComponent); begin inherited Create(AOwner); FDirectEdit := True; FOrgDataChange := GetDataLink.OnDataChange; GetDataLink.OnDataChange := DataChange; end; procedure TJvDBCheckBox.CMExit(var Message: TCMExit); begin if DirectEdit then begin if GetDataLink.Active and (Field <> nil) then FOldValue := Field.Value; DoExit // TWinControl behaviour end else inherited; end; procedure TJvDBCheckBox.DoChange; begin if Assigned(FOnChange) then FOnChange(Self); end; procedure TJvDBCheckBox.Toggle; begin if FDataChanging = 0 then begin if not DoChanging then Exit; end; Inc(FToggling); try inherited Toggle; if DirectEdit and (FDataChanging = 0) and GetDataLink.Active and GetDataLink.Editing then GetDataLink.UpdateRecord; finally Dec(FToggling); end; if FDataChanging = 0 then DoChange; end; function TJvDBCheckBox.DoChanging: Boolean; begin Result := True; if Assigned(FOnChanging) then FOnChanging(Self, Result); end; function TJvDBCheckBox.GetDataLink: TFieldDataLink; begin Result := TFieldDataLink(Perform(CM_GETDATALINK, 0, 0)); end; procedure TJvDBCheckBox.KeyPress(var Key: Char); begin case Key of #27: if (Field <> nil) and (DataSource <> nil) and (DataSource.State in [dsEdit, dsInsert]) then Field.Value := FOldValue; end; inherited KeyPress(Key); end; procedure TJvDBCheckBox.DataChange(Sender: TObject); begin if (FToggling = 0) and DirectEdit and (Field <> nil) then FOldValue := Field.Value; Inc(FDataChanging); try FOrgDataChange(Sender); finally Dec(FDataChanging); end; end; end.