【问题标题】:How to create a read-only property?如何创建只读属性?
【发布时间】:2011-04-21 02:45:36
【问题描述】:

我在运行时使用 TMS 对象检查器,但假设我的问题在设计时对 Delphi 同样有效。

我想要一个可以通过程序设置(在运行时)或硬编码(在设计时)的属性。它应该对用户可见,因为这些信息对他有用,并且它应该可以在运行时由程序更改,但不能由用户通过对象检查器更改。

我试过了

published property FileName : String read FFileName;

并且该属性是可见的,但它在对象检查器中也是可更改的(并且在更改时会引发读取地址 zer0 异常):-(

【问题讨论】:

  • 您继续假设 TMS 控件的工作方式与 Delphi 的 Object Inspector 相同。请停止这样做。它没有。这一次,不同之处在于 Object Inspector 甚至不 显示 只读属性,因此关于“读取地址 0”的内容根本不适用,并且似乎是 TMS 的错误.
  • @Rob,您可以切换一个设置以使 Delphi 对象检查器显示只读属性(或不显示)。它位于工具-> 选项对话框中的某个位置。
  • 快速解决方案:删除 TMS 属性检查器并使用 JEDI 之一。

标签: delphi


【解决方案1】:

这看起来是一个完全有效且正确的只读属性

published property FileName : String read FFileName;

如果您添加一个额外的公共属性,因此只能在运行时设置,那么您就是在做生意:

public property RuntimeFilename: string read FFileName write FFilename;
//note that two properties, one published and one public point to the same field.

但是,如果您想破解它并在设计时摆脱异常
将其更改为:

//Only writable during runtime.
private
  procedure SetFileName(Value: string);
published
  property FileName: string read FFileName write SetFileName;

....
procedure TMyClass.SetFileName(Value: string);
begin
  if csDesigning in Componentstate then {do nothing}
  else FFileName:= Value;
end;

我认为可能还会发生什么……

设计时和运行时代码之间的连接断开
为了更改代码的运行时行为,您需要更改源代码并删除属性的write ... 部分。

这将不会影响设计时代码,因为您需要重新安装组件。
如果您更改已注册组件的源代码并将更改保留在组件的privateprotected 和/或public 部分中,则通常没问题。

但是,如果您更改了组件的 published 部分并且不重新安装该组件,您将在启动时出现异常行为。

这是因为在 设计时,您仍在使用组件的旧的/未更改的二进制版本。此版本没有删除 write 部分,并允许您更改底层字符串 FFilename

runtime 初始化代码将读取表单资源 1) 并发现要写入 FFilename 的值。但是过程SetFilename 不再可用,因此在程序启动期间会发生访问冲突。

1) (.dfm 文件中的数据,现在存储在 .exe 的 dfm 资源中)

【讨论】:

    【解决方案2】:

    最简单的方法:

    private
      procedure SetFileName(Value: string);
    published
      property FileName: string read FFileName write SetFileName;
    
    ....
    procedure TMyClass.SetFileName(Value: string);
    begin
      FFileName := FFileName;
    end;
    

    【讨论】:

    • 感谢您抽出宝贵时间回复。我已经尝试过了,但用户可以通过对象检查器更改值,这是我不想要的。该属性与所有其他属性一样具有白色背景,并且可以进行编辑。我希望它具有灰色背景(如字符串网格上的固定行),并且不得允许用户更改其值。 (如果我们看不到如何做到这一点,我会将其设为私有,但宁愿将其发布)
    • 是的,Mawg,可以编辑属性。但是在编辑之后,控件是否继续显示新的、编辑的值?它不应该,因为基础字段的值没有改变。如果出现新值,那么这是 TMS 控件中的另一个错误;在真正的 Object Inspector 中,Ken 的代码将成功创建一个在设计时显示但忽略编辑它的尝试的属性。
    • @Mawg:AFAICT 无法让只读属性显示为已禁用。但是用户应该很快就会发现,试图改变它并没有什么用。正如@Rob 提到的那样,点击进入或离开属性会将其恢复为以前的(只读)值。
    【解决方案3】:

    这显然是 TMS 对象检查器中的错误,您应该向 TMS 提交错误报告。

    【讨论】:

    • 这可能是设计使然。哦等等……除了崩溃的部分。 :-)
    猜你喜欢
    • 2010-11-10
    • 1970-01-01
    • 2021-10-04
    • 2021-05-27
    • 2014-04-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    相关资源
    最近更新 更多