【问题标题】:Unable to declare string property defaults无法声明字符串属性默认值
【发布时间】:2014-03-24 15:34:24
【问题描述】:

我正在编写一个包含许多属性的组件,这些属性将出现在 Delphi IDE 对象检查器中(已发布的属性)...

type
  TMyComponent = class(TComponent)
  private
    FMyProperty: String;
  published
    property MyProperty: String read FMyProperty write SetMyProperty default 'Something';
  end;

但是,它不允许我将默认值应用于字符串属性...

[DCC Error] MyUnit.pas(278): E2146 Default values must be of ordinal, pointer or small set type

所有其他属性默认值都可以正常工作(整数、枚举等)。

我的目标是 A) 如果字符串属性是默认值,则不将其保存到 DFM,并且 B) 如果不是默认值,则将 Object Inspector 中的值显示为 Bold,并且如果是常规的。该组件有 130 多个属性,其中大约 50 个是字符串属性,其中一些具有相当大的默认值。

为什么不允许我用默认值声明字符串属性?这是 Delphi 的一个缺点,还是无法默认字符串的技术原因?

编辑

如果您真的想知道我在做什么,我将封装 Inno Setup 并将功能包装到一个具有扩展属性/集合编辑器的组件中。本主题仅与 Setup 部分有关,它实际上包含 100 多个属性。这些属性中只有大约 20 个预计会实际用于简单实现,因此我不希望所有其余的字符串属性都增大 DFM 的大小(如果它们设置为默认值)。根据组件的设置方式,它会生成一个 Inno Setup 脚本文件。

【问题讨论】:

  • 呃,因为编译器不支持?
  • @TLama 我看到了,但为什么呢?字符串这么常见,为什么编译器会跳过string这样的常见类型?
  • 这个问题只针对编译器设计者。就我个人而言,从我的角度来看,我没有看到任何阻碍实现所有类型的东西。以类似的方式,您可以问,为什么 default 说明符给出的值不用于初始化属性值。
  • @TLama 我正在初始化构造函数中的所有默认值(超过 100 个属性)。不过这与问题无关,所以我没有包括在内。
  • 但回到你的问题。只需创建一个stored 指令方法,当属性字段等于默认值时,该方法将返回 False。 ...正如雷米在他的回答中显示的那样...

标签: delphi properties components default-value


【解决方案1】:

只有数字属性可以在属性声明中指定default 值。但是,您可以改用stored 说明符,例如:

type
  TMyComponent = class(TComponent)
  private
    FMyProperty: String;
    function MyPropertyIsStored: Boolean;
    procedure SetMyProperty(const Value: String);
  public
    constructor Create(AOwner: TComponent); override;
  published
    property MyProperty: String read FMyProperty write SetMyProperty stored MyPropertyIsStored;
end;

constructor TMyComponent.Create(AOwner: TComponent);
begin
  Inherited;
  FMyProperty := 'my default value';
end;

function TMyComponent.MyPropertyIsStored: Boolean;
begin
  Result := FMyProperty <> 'my default value';
end;

procedure TMyComponent.SetMyProperty(const Value: String);
begin
  if FMyProperty <> Value then
  begin
    FMyProperty := Value;
    // update component as needed...
  end;
end;

【讨论】:

  • +1。当我看到一个新的答案已经发布时,我正在编辑以默认添加文档(并且即将添加存储),所以我加载了它。你打败了我。 :-)
  • 现在很难决定接受哪个答案,哪个可以直接为我的问题提供解决方案,或者哪个可以详细回答我的问题?
  • @Jerry: Remy's 包含适合您的信息,他比我更胜一筹。应该是他的。 :-) 我会留下我的信息以提供其他信息以供参考(或者他可以将其添加到他的信息中,我将删除我的答案)。
  • 天哪,现在我开始实现这个,我意识到对于 53 个字符串属性,我需要 另一个 53 个函数,每个函数一个 :-) 为长代码干杯!
  • @ElDiablo 现在开心吗?
【解决方案2】:

不清楚您要做什么。将default 分配给属性有两种用途:

  • 决定是否将属性值流式传输到 DFM(用于序数或布尔属性,通常,例如 Visible - 因为默认为 True,所以没有理由编写它到 DFM,除非它是 False。(请参阅下面的注释)

  • 对于数组属性,表示该数组是该类的默认属性(如Delphi的TList.Items,其中有Items默认允许你使用List[x]而不是List.Items[x]你的代码。

如果您的意图是为字符串提供默认值以便它显示在 Object Inspector 中,只需在组件构造函数中设置该值即可。如果用户分配了不同的值,则当 DFM 内容流入时,构造函数中设置的值将被覆盖。

至于为什么不允许使用字符串默认值,这在documentation 中有明确说明(参见“存储说明符”(强调我的):

default 和 nodefault 指令仅支持序数类型和集合类型,前提是集合的基本类型的上限和下限的序数值介于 0 和 31 之间;如果这样的属性被声明为没有默认值或没有默认值,则它被视为指定了没有默认值。 对于实数、指针和字符串,分别有一个隐含的默认值 0、nil 和 ''(空字符串)。

注意:默认值与 Remy 的答案描述的存储说明符一起使用。来自上面链接和引用的相同文档(相同部分):

保存组件状态时,会检查组件已发布属性的存储说明符。 如果属性的当前值与其默认值不同(或者如果没有默认值)并且存储的说明符为 True,则保存该属性的值。否则,不会保存该属性的值。

【讨论】:

  • 如果它是默认设置,我的意图是不将其保存到 DFM,因为这是设计的。我发现很难相信这不能用字符串来完成。但是,嘿,你不能对字符串做同样的事情一定有一些技术原因。
  • @Jerry:谢谢。请参阅我对 Remy 的回答的评论(在我的编辑过程中出现,就在我正要开始输入 stored 时)。 :-) 他有时太快了。
猜你喜欢
  • 2018-12-13
  • 2012-11-03
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
  • 2020-01-30
  • 1970-01-01
  • 2020-12-16
  • 1970-01-01
相关资源
最近更新 更多