3. Vytvß°enφ vlastnostφ

Vlastnosti jsou nejviditeln∞j╣φ Φßstφ komponent. V²vojß° aplikace je vidφ a manipuluje s nimi p°i nßvrhu a zφskßvß bezprost°ednφ zp∞tnou vazbu reakcφ komponenty na NßvrhovΘm formulß°i. Vlastnosti jsou takΘ d∙le╛itΘ, nebo╗ usnad≥ujφ pou╛φvßnφ komponent. Vlastnosti poskytujφ v²znamnΘ v²hody a to jak pro tv∙rce komponent, tak i pro jejich u╛ivatele. Nejz°ejm∞j╣φ v²hodou je, ╛e vlastnost m∙╛e b²t v dob∞ nßvrhu zobrazena v Inspektoru objekt∙. To zjednodu╣uje na╣e programovßnφ, nebo╗ namφsto zadßvßnφ n∞kolika parametr∙ p°i vytvß°enφ objektu, zpracujeme hodnoty p°i°azenΘ u╛ivatelem.
K zaji╣t∞nφ bezpeΦnΘho pou╛itφ vlastnostφ v na╣ich komponentßch, musφme pochopit:

Kdy vytvß°et vlastnosti?

Pro u╛ivatele komponent se vlastnosti podobajφ prom∞nn²m. U╛ivatel m∙╛e nastavovat nebo Φφst hodnoty vlastnostφ, jako kdyby tyto vlastnosti byly slo╛kami t°φd. Rozdφl je pouze v tom, ╛e vlastnost nem∙╛e b²t pou╛ita jako parametr volan² odkazem.
Vlastnosti poskytujφ vφce mo╛nostφ ne╛ slo╛ky t°φd nebo╗: P°φkladem je vlastnost Top v╣ech komponent. P°i°azenφ novΘ hodnoty vlastnosti Top, neznamenß jenom zm∞nu n∞jakΘ ulo╛enΘ hodnoty, ale zp∙sobφ i p°emφst∞nφ a p°ekreslenφ komponenty samotnΘ. Efekt nastavenφ vlastnosti nenφ omezen na n∞jakou komponentu. Nastavenφ vlastnosti Down komponenty SpeedButton na true, zp∙sobφ nastavenφ Down v╣ech ostatnφch tlaΦφtek ve skupin∞ na false.

Typy vlastnostφ

Vlastnost m∙╛e b²t libovolnΘho typu. D∙le╛it²m aspektem volby typu pro na╣i vlastnost je to, ╛e r∙znΘ typy jsou r∙zn∞ zobrazovßny v Inspektoru objekt∙. Inspektor objekt∙ pou╛φvß typ vlastnosti k urΦenφ co u╛ivatel chce zobrazit. P°i registraci komponenty m∙╛eme specifikovat r∙znΘ editory vlastnostφ. V nßsledujφcφ tabulce je uvedeno jak vlastnost je zobrazena v Inspektoru objekt∙.
 
Typ vlastnosti  Zachßzenφ s vlastnostφ v Inspektoru objekt∙
Jednoduch² ╚φselnΘ, znakovΘ a °et∞zcovΘ vlastnosti se zobrazujφ v Inspektoru objekt∙ jako Φφsla, znaky nebo °et∞zce. U╛ivatel m∙╛e zadßvat a editovat hodnotu vlastnosti p°φmo.
V²Φtov² Vlastnosti v²Φtov²ch typ∙ (vΦetn∞ bool) zobrazujφ hodnotu tak, jak je definovßna ve zdrojovΘm k≤du. U╛ivatel m∙╛e cyklicky prochßzet mo╛n²mi hodnotami dvojit²m kliknutφm ve sloupci hodnot. Hodnotu m∙╛eme takΘ vybφrat ze seznamu obsahujφcφho v╣echny mo╛nΘ hodnoty v²ΦtovΘho typu.
Mno╛ina Vlastnosti typu mno╛ina se zobrazujφ v Inspektoru objekt∙ jako mno╛iny. Roz╣φ°enφm mno╛iny, u╛ivatel m∙╛e zachßzet s ka╛d²m prvkem mno╛iny jako s logickou hodnotou: true, jestli╛e prvek je obsa╛en v mno╛in∞ nebo false nenφ-li.
Objekt Vlastnost, kterß je sama objektem, Φasto mß sv∙j vlastnφ editor vlastnostφ. NicmΘn∞, jestli╛e t°φda, kterß je vlastnostφ mß takΘ zve°ej≥ovanΘ vlastnosti, pak Inspektor objekt∙ umo╛≥uje u╛ivateli roz╣φ°it seznam vlastnostφ objektu a editovat je samostatn∞. Tyto vlastnosti musφ b²t odvozeny od TPersistent.
Pole Pole vlastnostφ musφ mφt sv∙j vlastnφ editor vlastnostφ. Inspektor objekt∙ nemß zabudovßnu podporu pro editaci pole vlastnostφ.

Zve°ej≥ovßnφ zd∞d∞n²ch vlastnostφ

V╣echny komponenty d∞dφ vlastnosti od sv²ch p°edk∙. Kdy╛ odvozujeme novou komponentu od existujφcφ komponenty, pak na╣e novß komponenta d∞dφ v╣echny vlastnosti ze t°φdy p°edka. Jestli╛e odvozujeme komponentu od jednoho z abstraktnφch typ∙, pak zd∞d∞nΘ vlastnosti jsou chrßn∞nΘ nebo ve°ejnΘ, ale ne zve°ej≥ovanΘ.
Aby chrßn∞nß nebo ve°ejnß vlastnost byla p°φstupnß pro u╛ivatele komponenty v Inspektoru objekt∙, musφme ji op∞tovn∞ deklarovat jako zve°ej≥ovanou. To provedeme p°idßnφm deklarace zd∞d∞nΘ vlastnosti do deklarace t°φdy potomka.
Jestli╛e odvozujeme komponentu od TWinControl, komponenta nap°. zd∞dφ vlastnost Ctl3D, ale tato vlastnost je chrßn∞nß a u╛ivatel komponenty nem∙╛e k Ctl3D b∞hem nßvrhu ani p°i b∞hu programu p°istupovat. Op∞tovnou deklaracφ Ctl3D v na╣φ novΘ komponent∞, m∙╛eme zm∞nit ·rove≥ ochrany na ve°ejnou nebo zve°ej≥ovanou. Nßsledujφcφ k≤d ukazuje op∞tnou deklaraci Ctl3D jako zve°ej≥ovanou, co╛ ji zp°φstupnφ b∞hem nßvrhu:
class PACKAGE TPrikladKomponenty : public TWinControl
{
__published:
  __property Ctl3D;
}
Op∞tovnou deklaracφ m∙╛eme pouze zmφrnit omezenφ p°φstupu a nelze je zv∞t╣it. Chrßn∞nou vlastnost lze zm∞nit na ve°ejnou, ale nelze zm∞nit ve°ejnou vlastnost na chrßn∞nou. P°i opakovanΘ deklaraci, specifikujeme pouze jmΘno vlastnosti (typ a dal╣φ informace se neuvßdφ). M∙╛eme takΘ deklarovat novou implicitnφ hodnotu nebo specifikovat, zda vlastnost uklßdat.

Definovßnφ vlastnosti komponenty

V tΘto Φßsti je uvedeno jak deklarovat novΘ vlastnosti a jsou zde uvedeny n∞kterΘ konvence pou╛φvanΘ ve standardnφch komponentßch. Jsou zde body:

Deklarace vlastnosti

Deklarace vlastnosti a jejφ implementace je snadnß. P°idßme deklaraci vlastnosti k deklaraci t°φdy na╣φ komponenty. V deklaraci vlastnosti specifikujeme t°i v∞ci: jmΘno vlastnosti, typ vlastnosti a metody pro Φtenφ a nastavovßnφ hodnot vlastnosti.
Vlastnosti komponent minimßln∞ musφme deklarovat ve ve°ejnΘ Φßsti deklarace typu objektu komponenty, co╛ umo╛nφ Φφst a nastavovat vlastnosti z vn∞j╣ku komponenty p°i b∞hu programu. K vytvo°enφ editovateln²ch komponent b∞hem nßvrhu musφme deklarovat vlastnost ve zve°ej≥ovanΘ Φßsti deklarace t°φdy komponenty. Zve°ej≥ovanΘ vlastnosti jsou automaticky zobrazovßny v Inspektoru objekt∙. Ve°ejnΘ vlastnosti jsou p°φstupnΘ pouze za b∞hu programu.
Nßsleduje typickß deklarace vlastnosti Pocet:
class PACKAGE TNaseKomponenta : public TComponent
{
private:
  int FPocet;                            // slo╛ka pro ulo╛enφ vlastnosti
  int __fastcall GetPocet();             // Φtecφ metoda
  void __fastcall SetPocet(int APocet);  // zßpisovß metoda
public:
  __property int Pocet={read=GetPocet,write=SetPocet} //deklarace vlastnosti
}

Internφ ulo╛enφ dat (vlastnostφ)

Nenφ ╛ßdnΘ omezenφ na to jak uklßdat data vlastnosti. Komponenty C++ Builderu ale pou╛φvajφ tyto konvence: Zßkladnφm principem t∞chto konvencφ je, ╛e pouze p°φstupovΘ metody vlastnosti mohou p°istupovat k dat∙m tΘto vlastnosti. Jestli╛e metoda nebo jinß vlastnost pot°ebuje zm∞nit tato data, musφ to provΘst prost°ednictvφm vlastnosti a ne p°φm²m p°φstupem k ulo╛en²m dat∙m. To zaji╣╗uje, ╛e implementaci zd∞d∞nΘ metody m∙╛eme m∞nit bez vlivu na potomky komponenty.

P°φm² p°φstup

Nejjednodu╣╣φ mo╛nostφ zp°φstupn∞nφ dat je p°φm² p°φstup. Tj. Φßsti read a write deklarace vlastnosti specifikujφ, ╛e p°i°azenφ nebo Φtenφ hodnoty vlastnosti probφhß p°φmo se slo╛kou vnit°nφho ulo╛enφ bez volßnφ p°φstupovΘ metody. P°φm² p°φstup je u╛iteΦn², kdy╛ vlastnost nemß vedlej╣φ efekty a chceme ji zp°φstupnit v Inspektoru objekt∙. ╚asto pou╛φvßme p°φm² p°φstup pro Φßst read deklarace vlastnosti a p°φstupovou metodu pro Φßst write nebo╗ obvykle aktualizujeme stav komponenty na zßklad∞ novΘ hodnoty vlastnosti.
Nßsledujφcφ deklarace typu komponenty ukazuje vlastnost, kterß pou╛φvß p°φm² p°φstup pro Φtenφ i zßpis:
class PACKAGE TPrikladKomponenty : public TComponent
{
private:
  bool FPouzeProCteni; //vnit°nφ ulo╛enφ dat je soukromΘ
__published:           //umo╛≥uje p°φstup k vlastnosti b∞hem nßvrhu
  __property bool PouzeProCteni={read=FPouzeProCteni,write=FPouzeProCteni};
}

P°φstupovΘ metody

Syntaxe deklarace vlastnosti umo╛≥uje, aby Φßsti read a write deklarace vlastnosti specifikovaly p°φstupovΘ metody mφsto slo╛ky t°φdy. P°φstupovΘ metody musφ b²t soukromΘ a jsou obvykle deklarovanΘ jako virtußlnφ. To umo╛≥uje potomk∙m p°episovat implementaci a u╛ivatelΘ komponent nemohou tyto metody volat k modifikaci vlastnosti.
P°φstupovΘ metody by nem∞ly b²t ve°ejnΘ. Tφm zabra≥ujeme v²vojß°i aplikace v nedovolenΘ modifikaci vlastnosti volßnφm n∞kterΘ z t∞chto metod.
Nßsleduje t°φda, kterß deklaruje t°i vlastnosti pou╛φvajφcφ indexov² specifikßtor, co╛ umo╛≥uje aby v╣echny t°i vlastnosti m∞ly stejnΘ Φtecφ a zßpisovΘ metody.
class PACKAGE TPrikladKalendar : public TCustomGrid
{
private:
  int __fastcall GetDatumovyPrvek(int Index);
  void __fastcall SetDatumovyPrvek(int Index, int Hodnota);
public:
  __property int Den = {read=GetDatumovyPrvek, write=SetDatumovyPrvek, index=3, nodefault};
  __property int Mesic = {read=GetDatumovyPrvek, write=SetDatumovyPrvek, index=2, nodefault};
  __property int Rok = {read=GetDatumovyPrvek, write=SetDatumovyPrvek, index=1, nodefault};
};
Proto╛e ka╛d² prvek datumu (den, m∞sφc a rok) je typu int a proto╛e nastavovßnφ ka╛dΘho vy╛aduje zak≤dovßnφ datumu p°i nastavenφ, k≤d zabra≥uje duplikacφm sdφlenφm Φtecφch a zßpisov²ch metod pro v╣echny t°i vlastnosti. M∙╛eme mφt tedy pouze jednu metodu pro Φtenφ datumovΘho prvku a dal╣φ pro zßpis datumovΘho prvku.
Nßsleduje Φtecφ metoda, kterß zφskßvß datumov² prvek:
int __fastcall TPrikladKalendar::GetDatumovyPrvek(int Index)
{
  unsigned short ARok, AMesic, ADen;
  int vysledek;
  FDate.DecodeDate(&ARok, &AMesic, &ADen); // rozlo╛enφ datumu do prvk∙
  switch (Index)
  {
    case 1: vysledek = ARok;   break;
    case 2: vysledek = AMesic; break;
    case 3: vysledek = ADen;   break;
    default: vysledek = -1;
  }
  return vysledek;
}
Toto je zßpisovß metoda, kterß nastavuje p°φslu╣n² datumov² prvek:
void __fastcall TPrikladKalendar::SetDatumovyPrvek(int Index, int Hodnota)
{
  unsigned short ARok, AMesic, ADen;
  if (Hodnota > 0)        // v╣echny prvky musφ b²t kladnΘ
  {
    FDate.DecodeDate(&ARok, &AMesic, &ADen); // zφskßnφ datumov²ch prvk∙
    switch (Index)
    {
      case 1: ARok = Hodnota;   break;
      case 2: AMesic = Hodnota; break;
      case 3: ADen = Hodnota;   break;
      default: return;
    }
 }
 FDate = TDateTime(ARok, AMesic, ADen);  // zak≤dovßnφ modifikovanΘho datumu
 Refresh();                              // aktualizace viditelnΘho kalendß°e
}
╚tecφ metoda pro vlastnost je funkce, kterß nemß parametry a vracφ hodnotu stejnΘho typu jako mß vlastnost. Podle konvencφ, jmΘno funkce zaΦφnß Get a pokraΦuje jmΘnem vlastnosti. Nap°. Φtecφ metoda pro vlastnost nazvanou Pocet by se m∞la jmenovat GetPocet. V²jimkou je p°φpad vlastnosti typu pole, kterß p°edßvß indexy jako parametry Φtecφ metod∞.
╚tecφ metoda pracuje s vnit°nφm ulo╛enφm dat a vytvß°φ hodnotu vlastnosti p°φslu╣nΘho typu. Je-li vlastnost typu ?pouze pro zßpis, nenφ nutnΘ deklarovat Φtecφ metodu. Vlastnosti, urΦenΘ pouze pro zßpis se pou╛φvajφ velmi z°φdka a obecn∞ nejsou moc u╛iteΦnΘpis?,
Zßpisovß metoda pro vlastnost je v╛dy funkce typu void s jednφm parametrem, kter² je stejnΘho typu jako vlastnost. Parametr m∙╛e b²t p°edßvßn odkazem nebo hodnotou a jeho jmΘno m∙╛e b²t libovolnΘ. Podle konvencφ jmΘno funkce je Set nßsledovanΘ jmΘnem vlastnosti. Nap°. zßpisovß metoda pro vlastnost nazvanou Pocet by se m∞la jmenovat SetPocet. Hodnota p°edanß v parametru je pou╛ita k nastavenφ novΘ hodnoty vlastnosti a zßpisovß metoda musφ provΘst operace pot°ebnΘ k vytvo°enφ p°φslu╣nΘ hodnoty ve vnit°nφm formßtu.V²jimkou k pravidlu jednoho parametru jsou vlastnosti typu pole a vlastnosti pou╛φvajφcφ specifikßtor indexu (zde je p°edßvßna hodnota indexu jako dal╣φ parametr).
Je-li vlastnost typu pouze pro Φtenφ, nenφ nutnΘ deklarovat zßpisovou metodu. Aby zve°ej≥ovanΘ vlastnosti mohly b²t pou╛ity b∞hem nßvrhu musφ b²t definovßny jako Φtecφ i zßpisovΘ.
Je vhodnΘ testovat, zda se novß hodnota li╣φ od souΦasnΘ hodnoty p°ed jejφm p°i°azenφm. Nap°. nßsleduje p°φklad zßpisovΘ metody pro vlastnost typu int nazvanou Pocet, kterß uklßdß svou aktußlnφ hodnotu v polo╛ce FPocet:
void __fastcall TMojeKomponenta::SetPocet(int Hodnota)
{
  if (Hodnota != FPocet) {
    FPocet = Hodnota;
    Update();
  }
}

Implicitnφ hodnota vlastnosti

Kdy╛ deklarujeme vlastnost, m∙╛eme pro nφ voliteln∞ deklarovat implicitnφ hodnotu. Implicitnφ hodnota vlastnosti komponenty je hodnota nastavenß pro tuto vlastnost konstruktorem komponenty. C++ Builder pou╛φvß deklarovanou implicitnφ hodnotu k urΦenφ, zda uklßdat vlastnost v souboru formulß°e. Jestli╛e implicitnφ hodnotu pro vlastnost nespecifikujeme, pak C++ Builder vlastnost v╛dy uklßdß. Nap°. kdy╛ umφstφme komponentu z Palety komponent na formulß°, pak C++ Builder vytvß°φ komponentu volßnφm konstruktoru komponenty, kter² urΦuje poΦßteΦnφ hodnoty vlastnostφ komponenty.
K deklarovßnφ implicitnφ hodnoty pro vlastnost p°ipojφme klauzuli default k deklaraci (nebo op∞tovnΘ deklaraci) nßsledovanou implicitnφ hodnotou. Nap°.
__property bool JePravda = {default=true};
Poznßmka: Deklaracφ implicitnφ hodnoty v deklaraci vlastnosti nenastavujeme aktußln∞ vlastnost na tuto hodnotu. Jako tv∙rce komponenty musφme zajistit, ╛e konstruktor komponenty nastavφ vlastnost na tuto hodnotu. Jeliko╛ objekty v╛dy inicializujφ svΘ datovΘ slo╛ky na 0, nenφ nutno v konstruktoru nastavovat celoΦφselnΘ hodnoty na 0, ukazatele na NULL a logickΘ vlastnosti na false.
Kdy╛ opakovan∞ deklarujeme vlastnost, m∙╛eme specifikovat, ╛e vlastnost nemß implicitnφ hodnotu, i kdy╛ zd∞d∞nß vlastnost ji mß. K urΦenφ, ╛e vlastnost nemß implicitnφ hodnotu, p°ipojφme klauzuli nodefault k deklaraci vlastnosti. Nap°.
__property int NoveCislo = {nodefault};
Kdy╛ deklarujeme vlastnost poprvΘ, nenφ nutno specifikovat nodefault, proto╛e absence deklarace implicitnφ hodnoty znamenß totΘ╛.
Nßsleduje deklarace komponenty, kterß obsahuje vlastnost JePravda typu bool s implicitnφ hodnotou true a konstruktor nastavujφcφ implicitnφ hodnotu:
class PACKAGE TPrikladKomponenty : public TComponent
{
private:
  bool FJePravda;
public:
  virtual __fastcall TPrikladKomponenty(TComponent* Owner);
__published:
  __property bool JePravda = {read=FJePravfa, write=FJePravda, default=true};
};
__fastcall TPrikladKomponenty::TPrikladKomponenty(TComponent * Owner)
  : TComponent(Owner)
{
  FJePravda = true;   //nastavenφ implicitnφ hodnoty
}
Pokud by implicitnφ hodnota pro JePravda m∞la b²t false, potom ji nenφ nutno explicitn∞ nastavovat v konstruktoru, nebo╗ v╣echny t°φdy (a tedy i komponenty) v╛dy inicializujφ v╣echny svΘ polo╛ky na nulu a ?nulovß logickß ß? logickß false.

Vytvß°enφ pole vlastnostφ

N∞kterΘ vlastnosti mohou b²t indexovanΘ, podobn∞ jako pole. Majφ vφce hodnot, kterΘ rozli╣ujeme indexem. P°φkladem ve standardnφch komponentßch je vlastnost Lines komponenty Memo. Lines je indexovan² seznam °et∞zc∙, kterΘ tvo°φ text komponenty a m∙╛eme k n∞mu p°istupovat jako k poli °et∞zc∙. V tomto p°φpad∞, vlastnost typu pole dßvß u╛ivateli p°irozen² p°φstup k jistΘmu prvku (°et∞zci - °ßdku) ve v∞t╣φ mno╛in∞ dat (textu komponenty).
Vlastnost typu pole pracuje stejn∞ jako ostatnφ vlastnosti a deklarujeme ji v∞t╣inou stejn∞ (jsou zde pouze tyto rozdφly): Deklarace vlastnosti obsahuje jeden nebo vφce index∙ urΦitΘho typu. Indexy mohou b²t libovolnΘho typu. ╚ßsti read a write deklarace vlastnosti, jsou-li specifikovßny, pak musφ b²t metodami. Nelze zde specifikovat polo╛ky t°φdy.
P°φstupovΘ metody pro Φtenφ a zßpis hodnoty vlastnosti p°ibφrajφ dal╣φ parametry, kterΘ odpovφdajφ indexu nebo index∙m. Parametry musφ b²t ve stejnΘm po°adφ a stejnΘho typu jako indexy specifikovanΘ v deklaraci vlastnosti. Na rozdφl od indexu pole, typ indexu pro vlastnost typu pole nemusφ b²t celoΦφselnΘho typu. Nap°. jako index vlastnosti typu pole m∙╛e b²t i °et∞zec. M∙╛eme se odkazovat pouze na jednotlivΘ prvky pole a ne na celΘ pole.
Nßsleduje deklarace vlastnosti, kterß vracφ na zßklad∞ celoΦφselnΘho indexu °et∞zec:
Class PACKAGE TPrikladKomponenty : public TComponent
{
private:
  System::AnsiString __fastcall GetJmenoCisla(int Index);
public:
  __property System::AnsiString JmenoCisla[int Index] = {read=GetJmenoCisla};
};
Toto je metoda GetJmenoCisla v CPP souboru:
System::AnsiString __fastcall TPrikladKomponenty::GetJmenoCisla(int Index)
{
  System::AnsiString Vysledek;
  switch (Index){
    case 0:
      Vysledek = "Nula";
      break;
    case 100:
      Vysledek = "MalΘ";
      break;
    case 1000:
      Vysledek = "VelkΘ";
      break;
    default Vysledek = "NeznßmΘ";
  }
  return Vysledek;
}

Uklßdßnφ a zavßd∞nφ vlastnostφ

C++ Builder uklßdß formulß°e a jejich komponenty v DFM souborech. Tyto soubory jsou binßrnφ reprezentacφ vlastnostφ formulß°e a jeho komponent. Komponenta p°idanß na formulß° je zapsßna do formulß°e a tedy komponenta musφ mφt schopnost zapisovat svΘ vlastnosti do souboru formulß°e p°i ulo╛enφ. Obdobn∞, p°i zavßd∞nφ ze souboru formulß°e se komponenta musφ sama obnovit. Schopnost uklßdat a obnovovat svou reprezentaci je zd∞d∞nΘ chovßnφ komponenty. N∞kdy ale m∙╛eme pot°ebovat v tomto mechanismu provΘst n∞jakou zm∞nu a pot°ebuje se tedy s nφm seznßmit. Nßsledujφ body:

Pou╛φvßnφ uklßdacφho a zavßd∞jφcφho mechanismu

Popis formulß°e obsahuje seznam vlastnostφ formulß°e spoleΦn∞ s popisem v╣ech komponent vlo╛en²ch na formulß°. Ka╛dß komponenta vΦetn∞ samotnΘho formulß°e zodpovφdß za uklßdßnφ a zavßd∞nφ svΘho vlastnφho popisu.
Implicitn∞ (p°i uklßdßnφ sama sebe) komponenta zapisuje hodnoty v╣ech sv²ch ve°ejn²ch a zve°ej≥ovan²ch vlastnostφ, kterΘ se li╣φ od sv²ch implicitnφch hodnot a to v po°adφ jejich deklarace. P°i zavßd∞nφ, komponenta nejprve vytvo°φ sama sebe, nastavφ v╣echny vlastnosti na jejich implicitnφ hodnoty a potom Φte neimplicitnφ ulo╛enΘ hodnoty vlastnostφ.
Tento mechanismus vyhovuje v∞t╣in∞ komponent a nevy╛aduje ╛ßdnou akci od tv∙rce komponenty. Je ale n∞kolik zp∙sob∙ jak p°izp∙sobit uklßdacφ a zavßd∞cφ proces pot°ebn² pro n∞kterΘ komponenty.

Specifikovßnφ implicitnφch hodnot

Komponenty uklßdajφ svΘ vlastnosti pouze tehdy, kdy╛ se jejich hodnoty li╣φ od implicitnφch hodnot. Pokud nespecifikujeme jinak, pak C++ Builder p°edpoklßdß, ╛e vlastnost nemß implicitnφ hodnotu, co╛ znamenß, ╛e komponenta vlastnost uklßdß.
Vlastnost jejφ╛ hodnota nenφ nastavena konstruktorem mß nulovou hodnotu. Nulovß hodnota znamenß, ze oblast pam∞ti rezervovanß pro vlastnost je vynulovßna. Pokud pot°ebujeme n∞co jinΘho, pak implicitnφ hodnotu specifikujeme explicitn∞. Nap°.
__property Alignment = {default=taCenter};
Implicitnφ hodnotu lze takΘ specifikovat p°i op∞tovnΘ deklaraci vlastnosti. V²znamem op∞tovnΘ deklarace vlastnosti je urΦit jinou implicitnφ hodnotu.
Poznßmka: Nezapome≥te, ╛e specifikacφ implicitnφ hodnoty nenφ automaticky p°i°azena tato hodnota vlastnosti p°i vytvß°enφ objektu. P°i°azenφ hodnoty je nutno provΘst v konstruktoru komponenty.
Nßsledujφcφ k≤d ukazuje deklaraci komponenty, kterß specifikuje implicitnφ hodnotu pro vlastnost Align a implementaci konstruktoru komponenty, kter² nastavuje implicitnφ hodnotu. V na╣em p°φpad∞, novß komponenta je specißlnφ p°φpad standardnφho panelu, kter² je pou╛it jako stavov² °ßdek v okn∞ (implicitn∞ je umφst∞n u spodnφho okraje svΘho vlastnφka).
class PACKAGE TMujStavovyRadek : public TPanel
{
public:
  virtual __fastcall TMujStavovyRadek(TComponent* AOwner);
__published:
  __property Align = {default=alBottom};
};
Konstruktor TMujStavovyRadek v CPP souboru:
__fastcall TMujStavovyRadek::TMujStavovyRadek (TComponent* AOwner)
  : TPanel(AOwner)
{
   Align = alBottom;
}

UrΦovßnφ co uklßdat

M∙╛eme urΦovat, zda C++ Builder uklßdß v╣echny vlastnosti komponenty. Implicitn∞ v╣echny vlastnosti ze zve°ej≥ovanΘ Φßsti deklarace t°φdy jsou uklßdßny. M∙╛eme zvolit, ╛e danß vlastnost nebude uklßdßna nebo m∙╛eme navrhnout funkci, kterß bude urΦovat za b∞hu, zda vlastnost uklßdat.
K urΦenφ zda uklßdat vlastnost pou╛φvßme specifikßtor stored nßsledovan² znakem = a true, false nebo jmΘnem metody vracejφcφ logickou hodnotu.
Nßsledujφcφ k≤d ukazuje komponentu, kterß deklaruje t°i novΘ vlastnosti. Jedna je v╛dy uklßdßna, druhß nenφ nikdy uklßdßna a t°etφ je uklßdßna na zßklad∞ hodnoty metody Ulozit:
class PACKAGE TPrikladKomponenty : public TComponent
{
protected:
  bool __fastcall Ulozit();
public:
  __property int Ukladana = {stored=true};    // v╛dy uklßdßna
   ...
__published:
  __property int Neukladana = {stored=false}; // nikdy uklßdßna
  __property int Nekdy = {stored=Ulozit};     // ulo╛enφ zßvisφ na hodnot∞ funkce
};

Inicializace po zavedenφ

Po p°eΦtenφ v╣ech hodnot vlastnostφ komponenty z jejφho ulo╛enΘho popisu, je volßna virtußlnφ metoda nazvanß Loaded, kterß provßdφ po╛adovanΘ inicializace. Volßnφ Loaded nastane d°φve ne╛ formulß° a jeho ovladaΦe jsou zobrazeny a tedy inicializace nezp∙sobφ blikßnφ na obrazovce.
K inicializaci komponenty po zavedenφ jejich hodnot vlastnostφ, p°epφ╣eme metodu Loaded.
Poznßmka: Prvnφ v∞cφ, kterou v tΘto metod∞ musφme provΘst je volat zd∞d∞nou metodu Loaded. Tφm zajistφme, ╛e zd∞d∞nΘ vlastnosti jsou sprßvn∞ inicializovßny p°ed inicializacφ na╣ich vlastnφch vlastnostφ.

  1. P°ejd∞me ke konkrΘtnφmu p°φkladu. Budeme modifikovat standardnφ komponentu Memo k vytvo°enφ komponenty, kterß implicitn∞ neprovßdφ lßmßnφ slov a mß ╛lutΘ pozadφ. Je to velmi jednoduch² p°φklad, ale ukazuje v╣e, co je zapot°ebφ provΘst k modifikaci existujφcφ komponenty. Implicitn∞ hodnota vlastnosti WordWrap komponenty Memo je true. Jestli╛e pou╛φvßme n∞kolik t∞chto komponent u nich╛ nechceme provßd∞t lßmßnφ slov (automatick² p°echod na dal╣φ °ßdek p°i dosa╛enφ konce °ßdku) m∙╛eme snadno vytvo°it novou komponentu, kterß implicitn∞ lßmßnφ slov neprovßdφ (implicitnφ hodnotu vlastnosti WordWrap nastavφme na false). Modifikace existujφcφ komponenty probφhß ve dvou krocφch: vytvo°enφ a registrace komponenty a modifikace objektu komponenty.

  2. Zßkladnφ proces je ale v╛dy stejn², ale u slo╛it∞j╣φch komponent budeme muset provΘst vφce krok∙ pro p°izp∙sobenφ novΘ t°φdy. Vytvß°enφ ka╛dΘ komponenty zaΦφnß stejn∞: vytvo°φme programovou jednotku, odvodφme t°φdu komponenty, registrujeme ji a instalujeme ji na Paletu komponent.
    V na╣em p°φklad∞ pou╛ijeme uveden² obecn² postup s t∞mito specifikami: jednotku komponenty nazveme Memos, od TMemo odvodφme nov² typ komponenty nazvan² TWrapMemo a registrujeme TWrapMemo na strßnce Samples Palety komponent. V²sledek na╣i prßce je tento (nejd°φve je uveden v²pis hlaviΦkovΘho souboru):
    #ifndef MemosH
    #define MemosH
    #include <vcl\sysutils.hpp>
    #include <vcl\controls.hpp>
    #include <vcl\classes.hpp>
    #include <vcl\forms.hpp>
    #include <vcl\StdCtrls.hpp>
    class PACKAGE TWrapMemo : public TMemo
    {
    private:
    protected:
    public:
    __published:
    };
    #endif
    Nßsleduje CPP soubor:
    #include <vcl.h>
    #pragma hdrstop
    #include "Memos.h"
    #pragma package(smart_init)
    static inline TWrapMemo *ValidCtrCheck()
    {
      return new TWrapMemo(NULL);
    }
    namespace Memos
    {
      void __fastcall PACKAGE Register()
      {
        TComponentClass classes[1] = {__classid(TWrapMemo)};
        RegisterComponents("Samples", classes, 0);
      }
    }
    Poznßmka: V tomto p°φpad∞ jsme nepou╛ili k vytvo°enφ komponenty Experta komponent, ale vytvo°ili jsme ji manußln∞. Pokud bychom pou╛ili Experta komponent, pak by byl do vytvo°enΘ t°φdy automaticky p°idßn konstruktor.
    V╣echny komponenty nastavujφ svΘ hodnoty vlastnostφ p°i vytvß°enφ. Kdy╛ umφstφme komponentu b∞hem nßvrhu na formulß° nebo kdy╛ spustφme aplikaci vytvß°ejφcφ komponentu a p°eΦteme jejφ vlastnosti ze souboru formulß°e, je nejprve volßn konstruktor komponenty k nastavenφ implicitnφch hodnot komponenty. V p°φpad∞ zavedenφ komponenty ze souboru formulß°e, po vytvo°enφ objektu s jeho implicitnφmi hodnotami vlastnostφ, aplikace dßle nastavuje vlastnosti zm∞n∞nΘ p°i nßvrhu a kdy╛ je komponenta zobrazena vidφme ji tak, jak jsme ji navrhli. Konstruktor ale v╛dy urΦuje implicitnφ hodnoty vlastnostφ. Pro zm∞nu implicitnφ hodnoty vlastnosti, p°edefinujeme konstruktor komponenty k nastavenφ urΦenΘ hodnoty. Kdy╛ p°edefinujeme konstruktor, pak nov² konstruktor musφ v╛dy volat zd∞d∞n² konstruktor a to d°φve ne╛ provedeme cokoliv jinΘho.
    V na╣em p°φklad∞, na╣e novß komponenta musφ p°edefinovat konstruktor zd∞d∞n² od TMemo k nastavenφ vlastnosti WordWrap na false a vlastnosti Color na clYellow. P°idßme tedy deklaraci p°edefinovanΘho konstruktoru do deklarace t°φdy a zapφ╣eme nov² konstruktor do CPP souboru:
    class PACKAGE TWrapMemo : public TMemo
    {
    public:
      virtual __fastcall TWrapMemo(TComponent* Owner);
    };

    __fastcall TWrapMemo::TWrapMemo(TComponent* Owner)
     : TMemo(Owner)
    {
      Color = clYellow;
      WordWrap = false;
    }
    Poznßmka: Pokud pou╛ijeme Pr∙vodce komponentou k vytvo°enφ komponenty, pak v╣e co pot°ebujeme provΘst je p°idßnφ Φerven∞ oznaΦen²ch p°φkaz∙ do konstruktoru.
    Nynφ m∙╛eme instalovat novou komponentu na Paletu komponent a p°idat ji na formulß°. Vlastnost WordWrap je nynφ implicitn∞ false a vlastnost Color clYellow.
    Jestli╛e zm∞nφme (nebo vytvo°φme) novou implicitnφ hodnotu vlastnosti, musφme takΘ urΦit, ╛e hodnota je implicitnφ. Jestli╛e to neprovedeme, Builder nem∙╛e uklßdat a obnovovat hodnotu vlastnosti. Kdy╛ C++ Builder uklßdß popis formulß°e do souboru formulß°e, uklßdß pouze hodnoty vlastnostφ, kterΘ se li╣φ od sv²ch implicitnφch hodnot. Mß to dv∞ v²hody: zmen╣uje to soubor formulß°e a urychluje zavßd∞nφ formulß°e. Jestli╛e vytvo°φme vlastnost nebo zm∞nφme implicitnφ hodnotu vlastnosti je vhodnΘ aktualizovat deklaraci vlastnosti na novou implicitnφ hodnotu. Ke zm∞n∞ implicitnφ hodnoty vlastnosti, op∞tovn∞ deklarujeme vlastnost a p°ipojφme klauzuli default s novou implicitnφ hodnotou. Nenφ nutno op∞tovn∞ deklarovat prvky vlastnosti, pouze jmΘno a implicitnφ hodnotu. V na╣em p°φklad∞ provedeme:
    class PACKAGE TWrapMemo : public TMemo
    {
    public:
      virtual __fastcall TWrapMemo(TComponent* Owner);
    __published:
      __property Color = {default=clYellow};
      __property WordWrap = {default=false};
    };
    Specifikace implicitnφ hodnoty vlastnosti nemß vliv na celkovou prßci komponenty. Musφme stßle explicitn∞ nastavovat implicitnφ hodnotu v konstruktoru komponenty. Rozdφl je ve vnit°nφ prßci aplikace: Builder nezapisuje WordWrap do souboru formulß°e, jestli╛e je false, nebo╗ p°edpoklßdß, ╛e konstruktor nastavφ tuto hodnotu automaticky. TotΘ╛ platφ i o vlastnosti Color.

  3. Vytvo°te komponentu FontCombo (kombinovanΘ okno volby pφsma). Tuto komponentu odvo∩te od komponenty ComboBox tak, ╛e zm∞nφte implicitnφ hodnotu vlastnosti Style na csDropDownList a do vlastnosti Items p°i°adφte Screen->Fonts. Vyzkou╣ejte pou╛itφ tΘto komponenty v n∞jakΘ aplikaci (bude signalizovßna chyba).
  4. Namφsto p°i°azenφ seznamu pφsem v konstruktoru komponenty FontCombo je nutno jej p°i°adit v metod∞ Loaded, kterou p°edefinujeme (nejprve volßme metodu p°edka a potom provedeme p°i°azenφ). Vyzkou╣ejte provΘst tuto zm∞nu. Nynφ ji╛ tuto komponentu m∙╛eme pou╛φvat bez problΘm∙.
  5. V dal╣φm zadßnφ se pokusφme modifikovat komponentu ListBox a to tak, aby v zobrazenΘm textu mohly b²t pou╛ity znaky tabulßtor∙ (ke stylu okna je nutno p°idat p°φznak LBS_USETABSTOPS). Komponentu nazveme TabList a p°edefinujeme v nφ metodu CreateParams, kterou Builder pou╛φvß ke zm∞n∞ n∞kter²ch standardnφch hodnot pou╛φvan²ch p°i tvorb∞ komponenty. Tato metoda bude vypadat takto:

  6. void __fastcall TTabBox::CreateParams(Controls::TCreateParams &Params)
    {
      TListBox::CreateParams(Params);
      Params.Style |= LBS_USETABSTOPS;
    }
    Komponentu vyzkou╣ejte.
3. Vytvß°enφ vlastnostφ