Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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 ?

like image 508
Roman Marusyk Avatar asked Oct 28 '25 07:10

Roman Marusyk


1 Answers

If your project is closed source I suggest taking a copy of DBCtrls, change that one line where it says Result := cbGrayed and add that explicitly to your project. The change will be in your entire application but did not change the original code.

However there is another way - actually a hack so be careful and I suggest putting a compiler directive preventing this to be compiled in a different Delphi version to require looking at that code again and making sure it works.

Here is the code that works in Delphi XE - it might look different in Delphi 6 but you will get the idea.

type
  TDBCheckBoxHack = class(TCustomCheckBox)
  private
    FDataLink: TFieldDataLink;
    FValueCheck: string;
    FValueUncheck: string;
    procedure DataChange(Sender: TObject);
    function GetFieldState: TCheckBoxState;
    function ValueMatch(const ValueList, Value: string): Boolean;
  end;

I leave the implementation of these methods out because they are just a copy from the original copyrighted code. You have to change one or two lines in the GetFieldState method.

The trick is to create the same memory layout as the original TDBCheckBox so you can access the private fields - that is why this code should be used with care!

Then you assign the fixed DataChange method to the datalink:

TDBCheckBoxHack(DBCheckBox1).FDataLink.OnDataChange := 
  TDBCheckBoxHack(DBCheckBox1).DataChange;

To make this easier to use you can use another trick of inheriting from the original TDBCheckBox and call your class exactly the same. You can then put this into some unit and add this after the DBCtrls in your uses. That causes calling your constructor for every TDBCheckBox you placed on your form without the need to use your own and register it to the IDE:

type
  TDBCheckBox = class(DBCtrls.TDBCheckBox)
  public
    constructor Create(AOwner: TComponent); override;
  end;

constructor TDBCheckBox.Create(AOwner: TComponent);
begin
  inherited;
  TDBCheckBoxHack(Self).FDataLink.OnDataChange := TDBCheckBoxHack(Self).DataChange;
end;
like image 169
Stefan Glienke Avatar answered Oct 30 '25 06:10

Stefan Glienke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!