Search code examples
delphidelphi-6

How to display NULL value as unchecked state in a TDBCheckBox descendant?


Having a nullable dataset field of a boolean type, how to display its NULL value as an unchecked state in a TDBCheckBox control descendant linked to this field. By default, TDBCheckBox displays the NULL value of the field as a grayed check box:

enter image description here

but I need it to be displayed as an unchecked state in my TDBCheckBox control descendant:

enter image description here

Modifying the original TDBCheckBox source code is not an option for me, nor I cannot override the TDBCheckBox.GetFieldState because it's a private method.

So, how can I display the NULL value as an unchecked state in my TDBCheckBox descendant ?


Solution

  • Thanks everyone for help!

    I implemented it following way:

      type
      TDBCheckBoxHack = class(TDBCheckBox)
        FDataLink: TFieldDataLink;
        procedure DataChange(Sender: TObject); virtual;
        function GetFieldState: TCheckBoxState; virtual;
      public
        constructor Create(AOwner: TComponent); override;
      end;
    

    In constructor I used message CM_GETDATALINK for retrieve DataLink to my component

      constructor TDBCheckBoxHack.Create(AOwner: TComponent);
      var
        AMessage: TMessage;
      begin
        inherited;
        FillChar(AMessage, 0, sizeof(AMessage));
        AMessage.Msg := CM_GETDATALINK;
        Dispatch(AMessage);
        FDataLink := TFieldDataLink(Pointer(AMessage.Result));
        FDataLink.OnDataChange := DataChange;
      end;
    

    and GetFieldState implementation:

      function TFsDBCheckBox.GetFieldState: TCheckBoxState;
      var
        Text: string;
      begin
        if FDatalink.Field <> nil then
          if FDataLink.Field.IsNull then
            Result := cbUnchecked
          else if FDataLink.Field.DataType = ftBoolean then
            if FDataLink.Field.AsBoolean then
              Result := cbChecked
            else
              Result := cbUnchecked
          else
          begin
            Result := cbGrayed;
            Text := FDataLink.Field.Text;
            if ValueMatch(ValueChecked, Text) then Result := cbChecked else
              if ValueMatch(ValueUnchecked, Text) then Result := cbUnchecked;
          end
       else
         Result := cbUnchecked;
     end;