【问题标题】:How to set two properties as a node and change the caption in design mode?如何将两个属性设置为节点并在设计模式下更改标题?
【发布时间】:2017-12-31 14:41:06
【问题描述】:

我正在尝试创建一个名为 CheckEdit 的新组件,如下所示:

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.

一切正常,但我想在一个节点中创建EnableCaptionDisableCaption,因为TToggleSwitch 具有StateCaptions 属性,当我更改标题时,它也会在CheckBox 中更改它。

我尝试在SetEnableCaptionSetDisbleCaption 程序中调用Invalidate;,但这不起作用。

我该怎么做?

【问题讨论】:

  • 您可以将它们分组到TPersistent 已发布的课程中(由于在使用您的组件时可能进行分配而持续存在)。这是一种常见的做法。
  • @Victoria 你的意思是TToggleSwitchStateCaptions?
  • 是的,例如。 VCL 中有很多示例(因为我的内存服务器,例如 TDBGrid 具有 Options 属性)。
  • @Victoria 好的,我会尝试这样做,标题呢?当我更改 DisableCaption 时,cackbox 的标题不会更改。

标签: delphi delphi-10-seattle


【解决方案1】:

说实话,一开始我不想回答这个问题,因为你已经在 SO 上的一个问题中找到了答案

Create a button that accepts .PNG images as Glyph

确切地说,第一类是TPersistent,它暴露了TNCRSpeedButton 中的字形坐标。

我写这篇文章是因为我说过我希望你能从中受益。我可以看出你没有。

所以这是您解决问题的方法,非常欢迎您询问有关如何实施的任何问题。

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.

【讨论】:

  • TPersistentOnChange 事件吗?如果你能描述一下你做了什么以及为什么会这样,那就太好了。
  • @Sami 根据我在西雅图 D10 的版本,它确实有 OnChange 没有,我认为这样做不是一个好的决定(许多代码在继承时会中断)。
  • 我更改了ChBoxOnClick 的分配,这里只有两种可能,你为什么要检查它们。我的意思是它要么是真要么是假,所以直接将它分配给.Checked 属性。 (SetIsActiveGetIsActive 也一样)
  • 回到OnChange 事件,我将此事件添加到所有TPersistent 子类中,并使用此事件来更新UI 或通知Master 类(在您的情况下是TCheckEditCaptions ) 某事发生了变化,必须采取行动来适应它。在此示例中,SetIsActive(GetIsActive); 负责更新标题。
  • @Sami 这样就够了,还是您还有其他问题?
猜你喜欢
  • 2022-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 2021-05-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多