如何使用子属性编写属性? (终极版)

时间:2010-09-28 07:36:24

标签: delphi

我确信我对my previous question得到了一个很好的答案,因为我以前在那里张贴的那些人的问题上得到了很多帮助。

但我显然做错了,因为当我复制示例代码时,对象检查器显示我的MyProp属性是单个文本输入字段。我期待看到类似于Font属性的东西,包括Pitch,字体系列等,即我期望看到树结构,但我没有看到MyProp属性的Color,Height或Width属性。

有什么想法吗?我再一次完全复制了这段代码。


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

无论如何,似乎我对Delphi的代码太愚蠢了,因为我根本无法让它工作。


编辑:TMS向我保证,如果具有“子属性”的类是TPresistent的后代,那么它将出现在具有子属性的对象检查器中,就像Font,Anchors等一样

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

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.

2 个答案:

答案 0 :(得分:4)

original versionthe demo code忽略了创建属性对象的实例。

constructor TMyControl.Create(AOwner: TComponent)
begin
  inherited;
  FMyProp := TCustomType.Create;
end;

不要忘记在析构函数中释放它。

雷米对该答案的评论指出,该物业需要以不同方式分配。该属性的write访问者不应直接写入该字段。相反,它应该有一个像这样工作的setter方法:

procedure TMyControl.SetMyProp(const Value: TCustomType);
begin
  FMyProp.Assign(Value);
end;

这也强调了实现属性类的Assign方法的要求,否则你将得到奇怪的错误消息,例如“无法将TCustomType分配给TCustomType”。一个简单的实现可能是这样的:

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;

答案 1 :(得分:2)

阅读this article 它清楚地解释了如何创建子属性。

相关问题