浮动属性非零默认,是否可能?

时间:2010-10-20 14:04:47

标签: delphi properties floating-point components

我想在我的组件中使用float属性,但是将其设置为某个非零默认值(假设它是1000.0)。如果我尝试在Create中执行此操作,该属性开始表现得很疯狂,因为默认值为浮动它0(参见 classes.TWriter.WriteProperty.WriteFloatProp.IsDefaultValue )所以当我覆盖一些值时在表单设计器中0,delphi不保存此值(在这种情况下是默认值),但是我的Create会在下次加载compoent时将其设置为1000.0,所以实际上我有值我没有组。

问题是没有办法用'default'指令设置默认值(编译器说'默认值必须是序数,指针或小集类型')并且它也是不可能的强制存储与存储指令,它不起作用(Delphi 5)

那么有机会找到解决方法吗?

谢谢,

最高

5 个答案:

答案 0 :(得分:1)

也许您可以使用stored指令:

property MyFloat: Float read GetValue write SetValue stored IsMyFloatStored;

使用布尔函数IsMyFloatStored,如果MyFloat没有默认值,则返回True。

答案 1 :(得分:1)

我通过在TPersistent的后代中实现DefineProperties方法来解决这个问题。我想对这个问题做一个通用的解决方案,我可以在所有相关属性的所有对象中轻松实现。这是它的外观:

  TOverridePropFiler = class
    private
      FReadWritePropName: string;
      FObject: TObject;
      procedure ReadOverrideProp(Reader: TReader);
            procedure WriteOverrideProp(Writer: TWriter);
    public
      constructor Create(Filer:TFiler; Obj:TObject; Name:string);
    end;

  { TOverridePropFiler }

  constructor TOverridePropFiler.Create(Filer:TFiler; Obj:TObject; Name:string);
  begin
    FReadWritePropName:=Name;
    FObject:=obj;
    if (Name='') or not Assigned(GetPropInfo(Obj,Name)) then
      Raise Exception.CreateFmt('Property %s not found in object %s',[Name,Obj.ClassName]);
    Filer.DefineProperty(Name, ReadOverrideProp, WriteOverrideProp,
      GetPropValue(FObject,FReadWritePropName,False)<>uiFloat);
  end;

  procedure TOverridePropFiler.ReadOverrideProp(Reader: TReader);
  begin
    SetPropValue(FObject,FReadWritePropName,Reader.ReadFloat);
  end;

  procedure TOverridePropFiler.WriteOverrideProp(Writer: TWriter);
  begin
    Writer.WriteDouble(GetPropValue(FObject,FReadWritePropName,False));
  end;

我在我的DefineProperties方法中调用它,如下所示:

  procedure TMyObj.DefineProperties(Filer: TFiler);
  begin
    inherited;
    TOverridePropFiler.Create(Filer,Self,'dTOverride').Free;
  end;

为了使这一概括,我必须使用RTTI并在本地保存属性名称(不可能从TWriter中获取它,并且需要对TReader进行破解)。为了使它的线程安全(并且因为TFiler.DefineProperty想要“对象”函数),我将整个事物封装在一个对象中。

在我的情况下,我希望默认值为uiFloat。可以将此常量设置为您想要的任何值。如果您想要不同属性的不同默认值,可以轻松地将默认值作为参数添加到“创建”功能。

请注意,您仍然必须在TMyObj的构造函数中将该属性设置为默认值。

在我看来,这是解决Delphi严重限制的一种相当有效的方法。

编辑:您需要记住将“存储的假”添加到使用它的所有属性中。

答案 2 :(得分:0)

正如编译器所说,浮点值不能具有默认值。我唯一能想到的是将浮点值存储在一个缩放的整数中。例如,如果您只需要yourFloat的三位小数,则可以存储yourInt = 1000 * yourFloat。然后,默认值为yourInt := 1000000,对应yourFloat := 1000.000

当然,你可以更优雅地做到这一点,比如

  private
    FMyFloat: real;
    function GetValue: integer;
    procedure SetValue(Value: integer);

  published
    property MyInteger: integer read GetValue write SetValue default 1000000;

implementation

function TMyClass.GetValue: integer;
begin
  result := round(1000 * FMyFloat);
end;

procedure TMyClass.SetValue(Value: integer);
begin
  FMyFloat := Value / 1000;
end;

这样您仍然只能从类本身内部看到浮点字段FMyFloat。但该属性将是一个缩放的整数,因此可以完美存储。

答案 3 :(得分:0)

默认值实际上只告诉流代码默认值是什么,如果是该值,则不会流式传输。这节省了必须流式传输所有默认值。无论如何,组件必须实际设置.Create中的默认值。编译器不会为你设置默认值。

在这种情况下,无关紧要,因为您可以在.Create构造函数中设置默认值,然后在定义中省略默认值。该值将始终存储,但它将按您的意愿工作。

答案 4 :(得分:0)

只是遇到了这个问题,并通过在构造函数中将我想要的值设置为默认值并对该属性使用 nodefault 指令来解决了该问题。