Hm, kako nisam video sinoc da si post-ao, nesto zeza i forum..? Nema veze, sad cu se raspisem :).
1) U Delphi helpu (npr. D7) ukucati "TPersistent branch"; procitati, da ne bih ja prepisivao. Poenta je da je ono sto pise BUKVALNO tacno: da bi se neki class property video u design time-u, mora biti TPersistent (izvedeno od) i imati Owner-a.
2) Zasto mora TPersistent, odnosno sta to ima ova klasa? Ima dynamic metodu GetOwner: TPersistent; svaki descendent koji pretenduje da se pojavi u OI mora da je override-uje. Poziv TPersistent.GetOwner vraca nil.
3) A sta u nasoj izvedenoj klasi da vraca GetOwner? Tu smo: nemamo owner-a. Napravimo private field fOwner: TPersistent, koji cemo da vracamo kao result poziva GetOwner. Obratite paznju na kod klasa TCollection, TComponent, bilo cega sto je izvedeno iz TPersistent i sto se vidi kao class property u OI: SVI IMAJU sopstveni fOwner field ;) .
4) A sta napucamo u fOwner? Pa upravo komponent (TPersistent ;) ) koji sadrzi (koji jeste Owner) nas(eg) class property-ja/instance.
5) Koliko mozemo ici u dubinu sa ovim GetOwner, odnosno moze li nasa instanca class property imati svoje class properties, pa ovi svoje itd.? Moze, koliko god imamo memorije :).
Cudno je sto ovo NIGDE nema napisano na jednom mestu; provalio sam ga (na tezi nacin) pre ohohoh godina. I dan danas se divim kako Delphi masinerija radi kombinujuci designtime, loadingtime, runtime. A tek da se otisnete malo dublje u pisanje komponenata, pa definisanje custom property-ja i property Designer-a... eh. :)
Evo u prilogu i kod koji ilustruje celu pricu odgore; napisao tek da se podsetim da D jos uvek radi ;)
Code:
unit SubColorsComp;
interface
uses
SysUtils, Classes, Graphics;
type
TSubPropClass = class(TPersistent)
private
fStartColor: TColor;
fEndColor: TColor;
fOwner: TPersistent;
public
function GetOwner: TPersistent; override;
published
property StartColor: TColor read fStartColor write fStartColor;
property EndColor: TColor read fEndColor write fEndColor;
end;
TSubColorsComp = class(TComponent)
private
{ Private declarations }
fSubColors: TSubPropClass;
protected
{ Protected declarations }
public
{ Public declarations }
constructor Create(aOwner: TComponent); override;
destructor Destroy; override;
procedure Assign(aSour: TPersistent); override;
published
{ Published declarations }
property SubColors: TSubPropClass read fSubColors write fSubColors;
end;
procedure Register;
implementation
procedure Register;
begin
RegisterComponents('Samples', [TSubColorsComp]);
end;
{ TSubColorsComp }
procedure TSubColorsComp.Assign(aSour: TPersistent);
begin
if aSour is TSubColorsComp then
begin
fSubColors.fStartColor := TSubColorsComp(aSour).fSubColors.fStartColor;
fSubColors.fEndColor := TSubColorsComp(aSour).fSubColors.fEndColor;
end
else
inherited;
end;
constructor TSubColorsComp.Create(aOwner: TComponent);
begin
inherited;
fSubColors := TSubPropClass.Create;
fSubColors.fOwner := self; // bitno!!!
end;
destructor TSubColorsComp.Destroy;
begin
fSubColors.Free;
inherited;
end;
{ TSubPropClass }
function TSubPropClass.GetOwner: TPersistent;
begin
result := fOwner;
end;
end.
I samo za kraj: zasto mora i metoda Assign() da se napise? Zato sto tako radi Delphi loader; sve sto se cita iz .dfm fajla (resource fajla) se ucitava u temp (privremenu) instancu date klase; tek ako prodje taj korak kreira se "prava" instanca i dodeljuju joj se (kopiraju) vrednosti temp instance. A kako se radi kopiranje? Upravo pozivom Assign() metode :). Uostalom, probajte; rem-ujte Assign, i svaki put kad zatvorite/otvorite formu imacete default vrednosti boja (clBlack), koliko god ih u designtime-u menjali.
Nadam se da sam pomogao.
Pozz
[Ovu poruku je menjao Rapaic Rajko dana 07.02.2014. u 12:49 GMT+1]