[Delphi] IDE забывает свойства компонента, назначеных в десигн-тайм.

kill-still

прочитал значит статью
http://www.delphikingdom.com/asp/viewitem.asp?catalogid=1344
и озадачился тем, чтобы эти объекты можно было пихать в контейнер в десигн-тайм.
написал эдитор, который в десигн-тайме вызывает форму и позволяет создавать объекты, но при запуске программы или после закрытия проекта он начисто забывает про уже лежащие в контейнере объекты.
Как его заставить сохранять их в *.dpr и загружать при запуске?
для тех кто не хочет изучать статью, но разбирается в проблеме вот суть:
 
 
TMyComponent = class(TCustomControl, ICoordConvert)
........
FObjects: TObjectList;
........
property Objects[Index: Integer]: TBaseVisualObject read Get;
........
end;
........
implementation
........
function TMetroSelector.Get(Index: Integer): TBaseVisualObject;
begin
Result := TBaseVisualObject(FObjects[Index]);
end;

вот именно это свойство он забывает
хоть убей не пойму, чем оно отличается от
    property Items: TStrings read FItems write SetItems;
у VCL'ного TListBox.

valodyr

Я попробую угадать, хотя про Дельфи ничего не знаю. В случае с параметром как среда должна угадывать, какой у него домен?
Иными словами, когда у тебя свойство "обычное", у него есть "обычное" значение, которое понятно, как сериализовать. В случае с "массивным" свойством это никакое не свойство уже в классическом понимании, так как у обсыпанных сахаром функций доступа есть параметр, про который ничего не известно.
Это вообще если предположить, что она умеет отдельные функции вызывать в как вы говорите десигн-тайм. Что маловероятно, так как вроде бы оно должно компилироваться в нейтив, а не хрен пойми куда. Короче, тут такая ересь написана, что аж страшно (=

valodyr

Чё-то я мутно написал. Короче решение в том, чтобы сослать гет для этого свойства на поле, а не на метод и убрать параметр. И это, насколько я понимаю, обязательное требование к designable свойствам. По крайней мере, я не вижу, как его можно снять во всех случаях.

kill-still

Это вообще если предположить, что она умеет отдельные функции вызывать в как вы говорите десигн-тайм.

всё что угодно за исключением обработки нажатий (только имитация). ну и трейсить естественно нельзя. что кстати очень мешало с написанием эдитора. вообще стрёмно столько работы проделать и в конце так обломаться. =(
можно конечно придумать savetofile\loadfromfile. но это уже ять не велосипед и даже не пылесос
Что маловероятно, так как вроде бы оно должно компилироваться в нейтив, а не хрен пойми куда
Вот эту фразу не понял. что есть нэйтив?

kill-still

Чё-то я мутно написал. Короче решение в том, чтобы сослать гет для этого свойства на поле, а не на метод и убрать параметр. И это, насколько я понимаю, обязательное требование к designable свойствам. По крайней мере, я не вижу, как его можно снять во всех случаях.
попробовал так сделать на пробу:
 
  

// Метакласс визуальных объектов
TVisualObjectClass = class of TBaseVisualObject;

.....

TMetroSelector = class(TCustomControl, ICoordConvert)
private
FObjectType: TVisualObjectClass;

.......
published
property ObjectType: TVisualObjectClass read FObjectType write FObjectType;
.......
end;

конструкция class of это аналог аналог генериков
эта скотина в эдиторе его даже в виде циферек не показывает (это можно поправить - едитор то я умею написать, только толку - если он его всё равно не запоминает (попробовал из другого эдитора по хэндлу поменять свойство - не сработало - после запуска nilу равно
сейчас попробую тоже самое с единичным элементом сделать - только толку - нужен всё равно массив же...

kill-still

И это, насколько я понимаю, обязательное требование к designable свойствам.
нее, тут точно не в этом проблема - могу кучу примеров привести.
тут после долгих раздумий мне кажется скорее связано с тем, что либо write не определна, либо с тем, что он не знает как такой класс сохранять - что ты там про домен говорил?

zorin29

Честно говоря, я не в курсе именно этого аспекта, но есть предположение: чтобы поле сохранялось, надо его унаследовать от TPersistent. Тогда, кажется, у него есть методы сериализации в dfm.

kill-still

А блин, домены, персистент.
Сам разобрался.
Короче надо делать так:
 

procedure ReadMetroStations(Reader: TReader);
procedure WriteMetroStations(Writer: TWriter);
procedure DefineProperties(Filer: TFiler); override;
.............

procedure TMetroSelector.DefineProperties(Filer: TFiler);
begin
inherited;
Filer.DefineProperty('MetroStations', ReadMetroStations, WriteMetroStations, true);
end;

procedure TMetroSelector.ReadMetroStations(Reader: TReader);
var Pos1,pos2: TFloatPoint;
begin
FObjects.Add(TMEclipse.Create);
Reader.ReadListBegin;
Pos1.X:=Reader.ReadInteger;
Pos1.Y:=Reader.ReadInteger;
Pos2.X:=Reader.ReadInteger;
Pos2.Y:=Reader.ReadInteger;
Objects[0].BasePoints[0]:=pos1;
Objects[0].BasePoints[1]:=pos2;
Reader.ReadListEnd;
end;

procedure TMetroSelector.WriteMetroStations(Writer: TWriter);
begin
Writer.WriteListBegin;
Writer.WriteInteger(Round(Objects[0].BasePoints[0].X;
Writer.WriteInteger(Round(Objects[0].BasePoints[0].Y;
Writer.WriteInteger(Round(Objects[0].BasePoints[1].X;
Writer.WriteInteger(Round(Objects[0].BasePoints[1].Y;
Writer.WriteListEnd;
end;

Это естественно не конечный результат, а только чтобы разобраться, как оно работает.
Оставить комментарий
Имя или ник:
Комментарий: