Delphi 如何使用子属性对属性进行编码?(重复)

Delphi 如何使用子属性对属性进行编码?(重复),delphi,Delphi,我确信我得到了一个很好的答案,因为我以前在其他问题上得到了很多来自那些在那里发帖的人的帮助 但我显然做错了什么,因为当我复制示例代码时,对象检查器为MyProp属性向我显示的是单个文本输入字段。我希望看到一些类似于字体属性的东西,包括间距、字体系列等,也就是说,我希望看到一个树结构,但我没有看到MyProp属性的颜色、高度或宽度属性 有什么想法吗?同样,我完全复制了代码 编辑:我忘了提到(在这个问题中)我使用的是TMS scripter pro,它允许用户在运行时设计表单,并提供自己的对象检查

我确信我得到了一个很好的答案,因为我以前在其他问题上得到了很多来自那些在那里发帖的人的帮助

但我显然做错了什么,因为当我复制示例代码时,对象检查器为MyProp属性向我显示的是单个文本输入字段。我希望看到一些类似于字体属性的东西,包括间距、字体系列等,也就是说,我希望看到一个树结构,但我没有看到MyProp属性的颜色、高度或宽度属性

有什么想法吗?同样,我完全复制了代码


编辑:我忘了提到(在这个问题中)我使用的是TMS scripter pro,它允许用户在运行时设计表单,并提供自己的对象检查器,但我想这可能是从标准的Delphi中派生出来的

无论如何,我似乎太笨了,无法编写Delphi代码,因为我根本无法让它工作


编辑:TMS向我保证,如果具有“子属性”的类是从TPresistent派生的,那么它将出现在具有子属性的对象检查器中,就像字体、锚定等一样

使用此代码时,“Warning”属性在对象检查器中显示为文本字段,并且没有子属性

unit IntegerEditBox;
  // An edit box which only accepts integer values and warns if the value is not in a certain range

interface

uses
  SysUtils, Classes, Controls, StdCtrls,
  EditBox_BaseClass;

type

  TWarning = Class(TPersistent)
    private
      FWarningBelowValue   : Integer;
      FWarningAboveValue   : Integer;
      FWarningEmailTo : String;
      FWarningSmsTo   : String;
    published
      property WarningBelowValue   : Integer read FWarningBelowValue   write FWarningBelowValue;
      property WarningAboveValue   : Integer read FWarningAboveValue   write FWarningAboveValue;
      property WarningEmailTo      : String  read FWarningEmailTo      write FWarningEmailTo;
      property WarningSmsTo        : string  read FWarningSmsTo        write FWarningSmsTo;
  end;


  TIntegerEditBox = class(TEditBox_BaseClass)
    private
      FWarning : TWarning;
      procedure WriteValue(const newValue : Integer);


    protected
      // The new property which w/e introduce in this class
      FValue : Integer;   

    public { Public declarations }
      Constructor Create(AOwner: TComponent); override;   // This constructor uses defaults
      property Text;

    published  { Published declarations - available in the Object Inspector at design-time }
      property Hint;

      // Now our own properties, which we are adding in this class
      property Value : Integer read FValue write WriteValue;
      property Warning  : TWarning read FWarning write FWarning ;
  end;  // of class TIntegerEditBox()

procedure Register;

implementation

uses
  Dialogs;

  procedure Register;
  begin
    RegisterComponents('Standard', [TIntegerEditBox]);
  end;

  Constructor TIntegerEditBox.Create(AOwner: TComponent);
  begin
    inherited;  // Call the parent Create method
    Hint := 'Only accepts a number|Only accepts a number'; // Tooltip | status bar text
    Mandatory := True;
    Value := 0;
    Text := IntToStr(Value);
  end;

  procedure TIntegerEditBox.WriteValue(const newValue : Integer);
  begin
    Text := IntToStr(newValue);
  end;

end.
忽略创建属性对象实例的

constructor TMyControl.Create(AOwner: TComponent)
begin
  inherited;
  FMyProp := TCustomType.Create;
end;
别忘了在析构函数中释放它

Remy对该答案的评论指出,需要以不同的方式分配属性。属性的
write
访问器不应直接写入字段。相反,它应该具有如下工作方式的setter方法:

procedure TMyControl.SetMyProp(const Value: TCustomType);
begin
  FMyProp.Assign(Value);
end;
procedure TCustomType.Assign(Source: TPersistent);
begin
  if Source is TCustomType then begin
    Color := TCustomType(Source).Color;
    Height := TCustomType(Source).Height;
    Width := TCustomType(Source).Width;
  end else
    inherited;
end;
这还强调了实现属性类的
Assign
方法的要求,否则您将收到奇怪的错误消息,如“无法将TCustomType分配给TCustomType”。简单的实现可以如下所示:

procedure TMyControl.SetMyProp(const Value: TCustomType);
begin
  FMyProp.Assign(Value);
end;
procedure TCustomType.Assign(Source: TPersistent);
begin
  if Source is TCustomType then begin
    Color := TCustomType(Source).Color;
    Height := TCustomType(Source).Height;
    Width := TCustomType(Source).Width;
  end else
    inherited;
end;

您接受的答案中的代码至少有一个问题-有关详细信息,请参阅Remy Lebeau对接受答案的评论“另一个讨论中的代码只显示声明,它没有显示任何实际的实现代码,因此很可能您错过了重要的步骤。我已经编辑了前面的代码来显示现在的实现。+1我完全同意。那是我非常糟糕的表现。我唯一的借口是,我出差了,这使我无法尝试,而且两位添加了一些评论的@RRUZ@Remy从未误导过我——只要看看他们的代表就知道了。不幸的是,这几乎迫使你接受某些东西,只是任何东西;没有选择说“我没有得到一个满意的答案”,所以有时候我只是把它给那些付出最大努力的人。还有什么办法?@Mawg:你可以选择暂时不回答这个问题。到目前为止,我发布了一个独特的问题,我得到了一个非常好的答案,但它并不完美,而且还没有被标记为接受。我想得到正确的代码,我愿意合作以达到正确的结果。这个问题询问上一个问题的代码有什么问题。上一个问题有一个公认的答案,表明它现在没有问题。对于这个问题,您希望得到什么进一步的答案?这些详细信息已在其他讨论中添加到代码中。