0

I'm trying to create a new component named CheckEdit as the following:

unit UnitName;

interface
   uses
    System.Classes, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Controls;

type
TCheckEdit = class (TCustomControl)
  private
    FCheckBox : TCheckBox;
    FEdit : TEdit;
    FEnableCaption: TCaption;
    FDisbleCaption: TCaption;
    procedure SetIsActive(const Value: Boolean);
    function GetIsActive : Boolean;
    procedure ChBoxOnClick (Sender : TObject);
    procedure SetDisbleCaption(const Value: TCaption);
    procedure SetEnableCaption(const Value: TCaption);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
      property IsActive : Boolean read GetIsActive write SetIsActive default False;
      property EnableCaption : TCaption read FEnableCaption write SetEnableCaption;
      property DisbleCaption : TCaption read FDisbleCaption write SetDisbleCaption;
      property OnClick;
end;
procedure register;

implementation

 procedure register;
 begin
   RegisterComponents('Standard', [TCheckEdit]);
 end;

{ TCheckEdit }

procedure TCheckEdit.ChBoxOnClick(Sender: TObject);
begin
  if FCheckBox.Checked then
    IsActive := True
      else
        IsActive:= False;
end;

constructor TCheckEdit.Create(AOwner: TComponent);
begin
  inherited;

  FCheckBox := TCheckBox.Create(Self);
  FCheckBox.Parent := Self;
  FCheckBox.Align := alTop;
  FCheckBox.Caption := Self.Name;
  FCheckBox.OnClick := ChBoxOnClick;
  FDisbleCaption := 'Disabled';
  FEnableCaption := 'Enabled';
  FCheckBox.Caption := FDisbleCaption;

  FEdit := TEdit.Create(Self);
  FEdit.Parent := Self;
  FEdit.Align := alTop;
  FEdit.Enabled := False;

  Self.Height := 40;
  Self.Width := 185;
  Self.AutoSize := True;
end;

destructor TCheckEdit.Destroy;
begin
  FEdit.Free;
  FCheckBox.Free;
  inherited;
end;

function TCheckEdit.GetIsActive: Boolean;
begin
  if FCheckBox.Checked then
    Result := True
      else
        Result := False;
end;

procedure TCheckEdit.SetDisbleCaption(const Value: TCaption);
begin
  FDisbleCaption := Value;
end;

procedure TCheckEdit.SetEnableCaption(const Value: TCaption);
begin
  FEnableCaption := Value;
end;

procedure TCheckEdit.SetIsActive(const Value: Boolean);
begin
  FCheckBox.Checked := Value;
  case Value of
    True :
      begin
        FEdit.Enabled := True;
        FCheckBox.Caption := FEnableCaption;
      end;
    False :
      begin
        FEdit.Enabled := False;
        FCheckBox.Caption := FDisbleCaption;
      end;
  end;
end;
end.

Everything is working fine, but I want to make EnableCaption and DisableCaption in one node as TToggleSwitch have StateCaptions property, and when I change the caption it will change it in the CheckBox too.

I try to call Invalidate; in SetEnableCaption and SetDisbleCaption procedures, but that does not work.

How can I do that?

Ilyes
  • 14,640
  • 4
  • 29
  • 55
  • You can group them in a `TPersistent` published class (persistent because of possible assignment when using your component). That's a common practice. – Victoria Dec 31 '17 at 14:48
  • @Victoria You mean as `TToggleSwitchStateCaptions`? – Ilyes Dec 31 '17 at 14:50
  • Yes, for example. There's many examples in VCL (as my memory servers e.g. `TDBGrid` has `Options` property). – Victoria Dec 31 '17 at 15:00
  • @Victoria Ok I'll try to do that, what about the caption? when I change `DisableCaption` the caption of the cackbox is not changed. – Ilyes Dec 31 '17 at 15:12

1 Answers1

1

To be honest with you, I did not want to answer this question at first because you already have the answer in one of your questions here on SO

Create a button that accepts .PNG images as Glyph

the first class to be exact it is a TPersistent that exposed the Glyph coordinates in the TNCRSpeedButton.

I'm writing this because I said I hope you benefit well from it. and I can see you did not.

So this is your solution to your problem and you are more than welcome to ask any thing about how it is implemented.

unit UnitName;;

interface
   uses
    System.Classes, Vcl.ExtCtrls, Vcl.StdCtrls, Vcl.Controls;

type
  TCheckEditCaptions = class(TPersistent)
  private
    FDisableCaption: TCaption;
    FEnableCaption: TCaption;
    FOnChange: TNotifyEvent;
    function GetDisableCaption: TCaption;
    function GetEnableCaption: TCaption;
    procedure SetDisableCaption(const Value: TCaption);
    procedure SetEnableCaption(const Value: TCaption);
  public
    procedure Assign(aValue: TPersistent); override;
  published
    property EnableCaption: TCaption read GetEnableCaption write SetEnableCaption;
    property DisableCaption: TCaption read GetDisableCaption write SetDisableCaption;
    property OnChange: TNotifyEvent read FOnChange write FOnChange;
  end;

TCheckEdit = class (TCustomControl)
  private
    FCheckBox : TCheckBox;
    FEdit : TEdit;
    FCheckEditCaptions: TCheckEditCaptions;
    procedure SetIsActive(const Value: Boolean);
    function GetIsActive : Boolean;
    procedure ChBoxOnClick (Sender : TObject);
    procedure CheckEditCaptionsChanged(Sender : TObject);
    procedure SetCheckEditCaptions(const Value: TCheckEditCaptions);
  protected
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property IsActive : Boolean read GetIsActive write SetIsActive default False;
    property CheckEditCaptions : TCheckEditCaptions read FCheckEditCaptions write SetCheckEditCaptions;
    property OnClick;
end;
procedure register;

implementation

 procedure register;
 begin
   RegisterComponents('Samples', [TCheckEdit]);
 end;

{ TCheckEdit }

procedure TCheckEdit.ChBoxOnClick(Sender: TObject);
begin
  IsActive := FCheckBox.Checked;
end;

procedure TCheckEdit.CheckEditCaptionsChanged(Sender: TObject);
begin
  SetIsActive(GetIsActive);
end;

constructor TCheckEdit.Create(AOwner: TComponent);
begin
  inherited;

  FCheckBox := TCheckBox.Create(Self);
  FCheckBox.Parent := Self;
  FCheckBox.Align := alTop;
  FCheckBox.OnClick := ChBoxOnClick;

  FCheckEditCaptions := TCheckEditCaptions.Create;
  FCheckEditCaptions.FDisableCaption := 'Disabled';
  FCheckEditCaptions.FEnableCaption := 'Enabled';
  FCheckEditCaptions.OnChange := CheckEditCaptionsChanged;

  FCheckBox.Caption := CheckEditCaptions.DisableCaption;

  FEdit := TEdit.Create(Self);
  FEdit.Parent := Self;
  FEdit.Align := alTop;
  FEdit.Enabled := False;

  Self.Height := 40;
  Self.Width := 185;
  Self.AutoSize := True;
end;

destructor TCheckEdit.Destroy;
begin
  FEdit.Free;
  FCheckBox.Free;
  FCheckEditCaptions.Free;
  inherited;
end;

function TCheckEdit.GetIsActive: Boolean;
begin
  Result := FCheckBox.Checked ;
end;

procedure TCheckEdit.SetCheckEditCaptions(const Value: TCheckEditCaptions);
begin
  FCheckEditCaptions.Assign(Value);
end;

procedure TCheckEdit.SetIsActive(const Value: Boolean);
begin
  FCheckBox.Checked := Value;
  FEdit.Enabled := Value;
  if Value then
    FCheckBox.Caption := CheckEditCaptions.EnableCaption
  else
    FCheckBox.Caption := CheckEditCaptions.DisableCaption;
end;
{ TCheckEditCaptions }

procedure TCheckEditCaptions.Assign(aValue: TPersistent);
begin
  if aValue is TCheckEditCaptions then begin
    FEnableCaption := TCheckEditCaptions(aValue).FEnableCaption;
    FEnableCaption := TCheckEditCaptions(aValue).FDisableCaption;
    if Assigned(FOnChange) then
       FOnChange(self);
  end else
    inherited;
end;

function TCheckEditCaptions.GetDisableCaption: TCaption;
begin
  result := FDisableCaption;
end;

function TCheckEditCaptions.GetEnableCaption: TCaption;
begin
  result := FEnableCaption;
end;

procedure TCheckEditCaptions.SetDisableCaption(const Value: TCaption);
begin
  FDisableCaption := Value;
  if Assigned(FOnChange) then
       FOnChange(self);
end;

procedure TCheckEditCaptions.SetEnableCaption(const Value: TCaption);
begin
  FEnableCaption := Value;
  if Assigned(FOnChange) then
       FOnChange(self);
end;

end.
Nasreddine Galfout
  • 2,550
  • 2
  • 18
  • 36
  • Is `TPersistent` has `OnChange` event? It will be great if you descride what chages you made and why. – Ilyes Jan 03 '18 at 17:34
  • @Sami Based on the version I have in D10 Seattle no it does have `OnChange` not and I do not think it will be a good decision to do so (many code will break when inheriting). – Nasreddine Galfout Jan 03 '18 at 18:42
  • I Changed the assignment in `ChBoxOnClick`, there is only two possibilities here so why would you check for them. I mean it is either True or False so assign it directly to the `.Checked` property. (the same thing for `SetIsActive` and `GetIsActive`) – Nasreddine Galfout Jan 03 '18 at 18:46
  • Returning to the `OnChange` event, I add this event to all `TPersistent` sub classes and use this event to update the UI or to inform the Master class (in your case it is `TCheckEditCaptions`) that something has changed and an action must take place to accommodate to it. In this example `SetIsActive(GetIsActive);` does the job of updating the caption. – Nasreddine Galfout Jan 03 '18 at 18:56
  • @Sami would this be enough or do you have more questions? – Nasreddine Galfout Jan 03 '18 at 23:18
  • Dunno, I need to learn more about components creation (practice), I just need to find the guid. – Ilyes Jan 04 '18 at 00:09
  • I do not think it is component creation what you need to learn specifically. it is OOP. the only difference I can see is the `published` key word and how would you interact with IDE, other wise it is the same thing. [here](https://stackoverflow.com/a/42389971/7579632) you will find a free component set try to modify it and learn from it. It was my start to the component writing world. also If you have any question I'm always here and you can ask me any thing you want. you may want to unfrozen the chat room for this. – Nasreddine Galfout Jan 04 '18 at 00:16
  • The room is frozen for inactivity, it will automatically frozen. (not me) – Ilyes Jan 04 '18 at 00:38
  • @Sami I know I tried to unfreeze it but I could not. If you can do something about it or maybe create another one so we could chat about components writing. – Nasreddine Galfout Jan 04 '18 at 00:45