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╗:
-
U╛ivatel m∙╛e nastavovat vlastnosti b∞hem nßvrhu. To
je velmi d∙le╛itΘ, nebo╗ na rozdφl od metod, kterΘ jsou dostupnΘ pouze
p°i b∞hu aplikace, vlastnosti slou╛φ k p°izp∙sobenφ komponenty p°ed spu╣t∞nφm
aplikace. Vlastnosti mohou b²t zobrazeny v Inspektoru objekt∙, co╛ zjednodu╣uje
programovßnφ (mφsto pou╛itφ mnoha parametr∙ u konstruktoru t°φdy, C++ Builder
p°eΦte hodnoty z Inspektora objekt∙). Inspektor objekt∙ takΘ zji╣╗uje p°φpustnost
pou╛it²ch hodnot.
-
Na rozdφl od slo╛ek t°φd, vlastnosti mohou skr²t implementaΦnφ
detaily p°ed u╛ivateli. Nap°. data mohou b²t ulo╛ena v zak≤dovanΘm
tvaru, ale kdy╛ nastavujeme nebo Φteme hodnotu vlastnosti pot°ebujeme je
nezak≤dovanΘ. P°esto╛e hodnota vlastnosti m∙╛e b²t Φφslo, komponenta m∙╛e
hledat hodnotu v databßzi nebo k zφskßnφ hodnoty provßd∞t slo╛itΘ v²poΦty.
Vlastnosti poskytujφ k p°φkazu p°i°azenφ vedlej╣φ efekt. Kdy╛ provedeme
p°i°azenφ, je volßna metoda, kterß m∙╛e d∞lat cokoliv.
-
Implementace metody pro vlastnost m∙╛e b²t virtußlnφ,
co╛ znamenß, ╛e m∙╛e provßd∞t r∙znΘ v∞ci v r∙zn²ch komponentßch.
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:
-
Data vlastnosti jsou uklßdßny ve slo╛kßch t°φdy.
-
Slo╛ku t°φdy pro ulo╛enφ vlastnosti deklarujeme jako soukromou.
To zajistφ, ╛e komponenta, kterß deklaruje vlastnost, mß k nφ p°φstup,
ale u╛ivatelΘ komponenty a potomci komponenty ne. Potomci komponenty mohou
pou╛φvat samotnou zd∞d∞nou vlastnost, ale nemajφ p°φstup k vnit°nφmu ulo╛enφ
dat komponenty.
-
Identifikßtor pro slo╛ku vlastnosti t°φdy zaΦφnß pφsmenem
F
nßsledovanΘ jmΘnem vlastnosti. Nap°. data pro vlastnost Width jsou
ulo╛ena v polo╛ce objektu nazvanΘ FWidth.
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φ.
-
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.
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.
-
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).
-
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∙.
-
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:
void __fastcall TTabBox::CreateParams(Controls::TCreateParams
&Params)
{
TListBox::CreateParams(Params);
Params.Style |= LBS_USETABSTOPS;
}
Komponentu vyzkou╣ejte.