我想在我的组件中使用float属性,但是将其设置为某个非零默认值(假设它是1000.0)。如果我尝试在Create中执行此操作,该属性开始表现得很疯狂,因为默认值为浮动它0(参见 classes.TWriter.WriteProperty.WriteFloatProp.IsDefaultValue )所以当我覆盖一些值时在表单设计器中0,delphi不保存此值(在这种情况下是默认值),但是我的Create会在下次加载compoent时将其设置为1000.0,所以实际上我有值我没有组。
问题是没有办法用'default'指令设置默认值(编译器说'默认值必须是序数,指针或小集类型')并且它也是不可能的强制存储与存储指令,它不起作用(Delphi 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 指令来解决了该问题。