-
atruhin © (23.12.06 17:09) [0]В объекте есть свойство:
property ooFolderID : int64 read fFolderID write SetFolderID default -1;
Но данное свойство при значении -1 сохраняется а при 0 нет, т.е. default -1 не действует!
Где проблемма? Может как то связанно с типом In64? -
Были такие же траблы. Разбираться не стал, просто в конструкторе явно объявил значение.
-
Наиль © (25.12.06 07:25) [2]Для простых случаев - default.
Для сложных - stored (примеры в генофонде)
В данном случае используй [1]. -
atruhin © (25.12.06 16:41) [3]> В данном случае используй [1].
Речь не об этом. В том то и дело что в конструкторе у меня явно объявляеться:
fFolderID := -1;
При этом если в дизайнере устонавливаю значение, для данного свойства, отличное от 0,
то все сохраняется, если 0 то не сохраняется.
Про Store и т.д. я прекрасно знаю, и знаю как обойти данную проблемму, в конкретном
случае. Вопрос в том откуда у данного поведения "ноги растут", т.к. в друм случае такой эффект можно и не заметить -
Наиль © (26.12.06 09:02) [4]Не совсем внимательно прочитал [1], поэтому рекомендовал этот способ.
На самом деле я хотел сказать "не используй default" (явно объявил значение).
-1 - число особенное, так что см. генофонд.
TToolButton.ImageIndex -
atruhin © (26.12.06 15:54) [5]Спасибо за ответы, но вариант > "не используй default"
не слишком хорош, хранить абсолютно все умалчиваемые значения в ресурсе
формы не очень хорошо. -
Наиль © (26.12.06 16:30) [6]
> хранить абсолютно все умалчиваемые значения в ресурсе
> формы не очень хорошо.
А все и не надо. Только те, что равны -1. -
Slava80 (27.02.07 03:27) [7]Похожая проблема: не сохраняется свойство типа Double если в design-time задаю его равным нулю (0)
Хелп говорит:
The default and nodefault directives are supported only for ordinal types and for set types...
...For reals, pointers, and strings, there is an implicit default value of 0, nil, and '' (the empty string), respectively.
Т.е. задать значение по умолчанию можно только целочисленным переменным (свойствам). А для reals (в моем случае Double) значение по умолчанию равно нулю.
Кстати там же сказано:
Note
You can't use the ordinal value 2147483648 has a default value. This value is used internally to represent nodefault.
Вообще число 2147483648 может легко превратиться в -1 если рассматривать его как знаковое 32 битное (signed 32-bit). Может быть поэтому default -1 воспринималось для Int64 как nodefault?
Так вот, возвращаясь к Double, хотелось бы узнать как заставить сохранять свойство даже если оно равно неявному значению по умолчанию - нулю?
ПОМОГИТЕ! -
DimaBr (27.02.07 09:00) [8]property A: double read GetA write SetA stoted TRUE;
-
Slava80 © (28.02.07 02:46) [9]Позвольте возразить.
Ради эксперимента создал простую компоненту.unit JustTest;
interface
uses
SysUtils, Classes, Controls;
type
TJustTest = class(TGraphicControl)
private
FA: Double;
function GetA: double;
procedure SetA(const Value: double);
{ Private declarations }
protected
{ Protected declarations }
public
constructor Create(AOwner: TComponent); override;
{ Public declarations }
published
property A: double read GetA write SetA stored TRUE;
{ Published declarations }
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TJustTest]);
end;
{ TJustTest }
constructor TJustTest.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
function TJustTest.GetA: double;
begin
Result:=FA;
end;
procedure TJustTest.SetA(const Value: double);
begin
FA:=Value;
end;
end.
Установил и кинул на форму.
В Инспекторе Объектов у свойства A установлено значение 0. Нажимаю Alt-F12:object Form1: TForm1
Left = 213
Top = 103
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object JustTest1: TJustTest
Left = 272
Top = 152
Width = 100
Height = 41
end
end
Не сохранилось. Нажимаю Alt-F12. Задаю свойству A значение 1. Нажимаю Alt-F12:object Form1: TForm1
Left = 213
Top = 103
Width = 696
Height = 480
Caption = 'Form1'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object JustTest1: TJustTest
Left = 272
Top = 152
Width = 100
Height = 41
A = 1.000000000000000000
end
end
Сохранилось.
Извините за обилие текста.
И позвольте еще немного цитат из хелпа:
If a property has no stored directive, it is treated as if stored True were specified.
...
When saving a component's state, the storage specifiers of the component's published properties are checked. If a property's current value is different from its default value (or if there is no default value) and the stored specifier is True, then the property's value is saved. Otherwise, the property's value is not saved.
Т.е. во-первых stored TRUE является умолчанием (соглашусь, что можно и прописать лишний раз для пущей уверенности). А во-вторых stored является лишь необходимым, но не достаточным условием для сохранения значения. Т.е. (если значение свойства равно умолчанию) И (stored = true) ТОГДА сохранять. -
DimaBr (28.02.07 09:18) [10]А так ???TMyPanel = class(TCustomPanel)
private
fA: double;
protected
procedure DefineProperties(Filer: TFiler);override;
procedure LoadCompProperty(Reader: TReader);
procedure WriteCompProperty(Writer: TWriter);
published
property A: double read fA write fA stored false;
end;
implementation
procedure TMyPanel.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty('A', LoadCompProperty, WriteCompProperty, true);
end;
procedure TMyPanel.LoadCompProperty(Reader: TReader);
begin
A := Reader.ReadFloat;
end;
procedure TMyPanel.WriteCompProperty(Writer: TWriter);
begin
Writer.WriteFloat(A);
end; -
Slava80 © (01.03.07 17:27) [11]Да! Так все работает. СПАСИБО!
Значит все-таки есть возможность обойти эту проблему. А то я уже начал думать, что такое просто не возможно.
Мне бы теперь разобраться что такое Reader и Writer. :) -
DimaBr (02.03.07 10:08) [12]Это два метода, которые сохраняют и читают значения из ресурса (DFM). Записать можно любое свойство (даже private) и любым способом - главное чтобы можно было потом прочитать.
А вот
procedure DefineProperties(Filer: TFiler);override;
как раз срабатывает при записи/чтении свойств из ресурса, переопределив который можно указать чтобы ещё мы хотели сохранить и какие методы будут этим заниматься. -
Slava80 © (14.03.07 22:39) [13]Я прошу прощения, но в конце моего сообщения номер [9] закралась досадная опечатка. Я понимаю, что это не принципиально, но хочется, чтобы эта ветка помогла другим людям понять схему, по которой сохраняются свойства.
И так, в конце [9] читать:
"...ЕСЛИ (значение свойства НЕ равно умолчанию) И (Stored = TRUE) ТОГДА сохранять..."
Чтобы оправдать этот пост, еще пробегусь по нескольким интересным местам в исходниках VCL (вы их, кажется, "генофондом" называете).unit Classes;
...
procedure TWriter.WriteProperties(Instance: TPersistent);
...
begin
...
if IsStoredProp(Instance, PropInfo) then
WriteProperty(Instance, PropInfo);
...
end;
В коде выше через вызов IsStoredProp (находящийся в TypInfo.pas) проверяется: равно ли Stored TRUE, и если да, то вызывается WriteProperty из того же Classes.pas.
Посмотрим на WriteProperty:procedure TWriter.WriteProperty(Instance: TPersistent; PropInfo: PPropInfo);
...
begin
// Using IsDefaultPropertyValue will tell us if we should write out
// a given property because it was different from the default or
// different from the Ancestor (if applicable).
...
if not IsDefaultPropertyValue(Instance, PropInfo, GetLookupInfo) then
begin
...
case PropType^.Kind of
tkInteger, tkChar, tkEnumeration, tkSet:
WriteOrdProp;
...
end;
end;
...
end;
В коде выше через вызов IsDefaultPropertyValue проверяется: равно ли свойство значению по умолчанию, и если НЕТ, то в зависимости от типа свойства вызывается соответствующая подпроцедура для его сохранения. Для сокращения кода оставил только WriteOrdProp.
Посмотрим теперь на IsDefaultPropertyValue:function IsDefaultPropertyValue(Instance: TObject; PropInfo: PPropInfo;
...
function IsDefaultOrdProp: Boolean;
var
Value: Longint;
Default: LongInt;
begin
Value := GetOrdProp(Instance, PropInfo);
if AncestorValid then
Result := Value = GetOrdProp(Ancestor, PropInfo)
else
begin
Default := PPropInfo(PropInfo)^.Default;
Result := (Default <> LongInt($80000000)) and (Value = Default);
end;
end;
Функция содержит подфункции отдельно для каждого типа свойства. Выше приведена IsDefaultOrdProp, которая срабатывает для порядковых. Int64 сюда не входит!!! В общем здесь все прозрачно: условие (Default <> LongInt($80000000)) проверяет не равно ли значение по умолчанию числу 2147483648, что равнозначно директиве nodefault. Т.е. ЕСЛИ (НЕТ директивы nodefault) И (Свойство равно значению по умолчанию), то IsDefaultOrdProp возвращает TRUE.
Подфункции для типов Float и Int64 похожи:function IsDefaultFloatProp: Boolean;
var
Value: Extended;
begin
Value := GetFloatProp(Instance, PropInfo);
if AncestorValid then
Result := Value = GetFloatProp(Ancestor, PropInfo)
else
Result := Value = 0;;
end;
function IsDefaultInt64Prop: Boolean;
var
Value: Int64;
begin
Value := GetInt64Prop(Instance, PropInfo);
if AncestorValid then
Result := Value = GetInt64Prop(Ancestor, PropInfo)
else
Result := Value = 0;
end;
В них как и выше я не рассматриваю случай с предками (if AncestorValid then), потому что пока не до конца понимаю что это. Видимо это связано со свойствами взятыми у предков класса. Если кто разберется, поделитесь.
Для данной же ветки форума важна одна строчка, одинаковая как для типа Float, так и Int64:Result := Value = 0;
Т.е. в исходниках VCL для этих типов жестко прописано значение по умолчанию НОЛЬ. И никакие директивы default или nodefault при этом не учитываются!
Это собственно и является ответом на самое первое сообщение темы. Также это опровергает мои домыслы в [7] насчет числа "-1". -
Slava80 (27.02.07 3:27) [7]
Вообще число 2147483648 может легко превратиться в -1 если рассматривать его как знаковое 32 битное (signed 32-bit). Может быть поэтому default -1 воспринималось для Int64 как nodefault?
C 4.... путаешь. 2147483648 превратится в -2147483648.