8. Ud∞lßnφ komponenty dostupnΘ p°i nßvrhu

Registrovanou komponentu instalujeme na Paletu komponent a potom ji m∙╛eme vybφrat, umis╗ovat ji na formulß° a manipulovat s nφ p°i nßvrhu. Ud∞lßnφ na╣φ komponenty dostupnΘ b∞hem nßvrhu vy╛aduje n∞kolik krok∙:

Ne v╣echny tyto kroky vy╛aduje ka╛dß komponenta. Nap°. jestli╛e nedefinujeme ╛ßdnou novou vlastnost nebo udßlost, pak nenφ nutnΘ poskytnout pro nφ nßpov∞du. V╛dy je pouze zapot°ebφ provΘst registraci a p°eklad.
Kdy╛ ji╛ komponenty mßme registrovanΘ a p°elo╛enΘ do balφΦk∙, pak je m∙╛eme distribuovat ostatnφm v²vojß°∙m a instalovat v IDE.

Registrace komponenty

Registrace pracuje na zßklad∞ jednotky a tedy, pokud vytvß°φme n∞kolik komponent v jednΘ jednotce, pak je registrujeme v╣echny najednou. Kdy╛ ji╛ mßme komponenty v jednotce registrovßny, m∙╛eme p°elo╛it jednotku do nßvrhovΘho balφΦku, kter² m∙╛eme instalovat v IDE.
Pro registraci komponenty, p°idßme funkci Register do CPP souboru jednotky. V tΘto funkci registrujeme komponenty a urΦφme, kde na Palet∞ komponent budou instalovßny.
Kroky pro ruΦnφ registraci komponenty jsou:

Deklarovßnφ funkce Register

Funkce Register musφ existovat ve jmennΘm prostoru. Jmenn² prostor je jmΘno souboru komponent, kde s v²jimkou prvnφho pφsmena jsou v╣echna pφsmena malß.
Nßsledujφcφ kostra k≤du ukazuje jak funkce Register je implementovßna ve jmennΘm prostoru. Jmenn² prostor je nazvßn Novakomp, zatφmco soubor se jmenuje NovaKomp.CPP.
namespace Novakomp
{
  void __fastcall PACKAGE Register()
  {
  }
}
Poznßmka: Pokud vytvß°φme na╣φ komponentu volbou Component | New Component z hlavnφ nabφdky IDE, pak k≤d registrujφcφ na╣φ komponentu je p°idßn automaticky.
Uvnit° funkce Register volßme RegisterComponents pro v╣echny komponenty, kterΘ chceme p°idat na Paletu komponent. Makro PACKAGE je roz╣φ°eno na p°φkazy, kterΘ umo╛≥ujφ importovßnφ a exportovßnφ t°φd.

Zßpis funkce Register

Uvnit° funkce Register pro jednotku komponent, musφme registrovat v╣echny komponenty, kterΘ chceme p°idat na Paletu komponent. Pokud jednotka obsahuje vφce komponent, pak je registrujeme v╣echny najednou.
K registraci komponent volßme funkci RegisterComponents a to jednou pro ka╛dou strßnku Palety komponent, na kterou chceme p°idßvat komponenty. Funkce RegisterComponents provßdφ dv∞ d∙le╛itΘ v∞ci: specifikuje jmΘna komponent a specifikuje strßnku palety na kterou komponenty instalujeme.
Uvnit° funkce Register deklarujeme otev°enΘ pole typu TComponentClass, kterΘ obsahuje informace o registrovan²ch komponentßch. Pou╛φvßme tuto syntaxi:
TComponentClass classes[1] = {__classid(TNovaKomponenta)};
V tomto p°φpad∞ pole t°φd obsahuje prßv∞ jednu komponentu, ale do jednoho pole m∙╛eme vlo╛it v╣echny komponenty, kterΘ chceme registrovat. Nap°. nßsledujφcφ k≤d do pole umis╗uje dv∞ komponenty:
TComponentClass classes[2] =
    {__classid(TNovaKomponenta), __classid(TJinaKomponenta)};
Jin²m zp∙sobem p°idßvßnφ komponent do pole je p°i°azovßnφ komponent do pole v samostatn²ch p°φkazech. Nap°. nßsledujφcφ p°φkazy p°idßvajφ do pole stejnΘ dv∞ komponenty jako v p°edchozφm p°φklad∞:
TComponentClass classes[2];
classes[0] = __classid(TNovaKomponenta);
classes[1] = __classid(TJinaKomponenta);
JmΘno strßnky palety je typu AnsiString. Jestli╛e strßnka palety zadanΘho jmΘna zatφm neexistuje, pak C++ Builder vytvß°φ novou strßnku s tφmto jmΘnem. C++ Builder hledß jmΘna standardnφch strßnek ve zdroji seznamu °et∞zc∙, co╛ umo╛≥uje, aby internacionalizovanß verze C++ Builderu mohla mφt jmΘna strßnek ve svΘm p°irozenΘm jazyku. Pokud chceme instalovat komponentu na n∞kterou ze standardnφch strßnek, pak musφme zφskat °et∞zec pro jmΘno strßnky volßnφm funkce LoadStr a p°edßme konstantu reprezentujφcφ zdroj °et∞zce pro tuto strßnku, nap°. srSystem pro strßnku System.
Uvnit° funkce Register volßme RegisterComponents k registraci komponent v poli t°φd. RegisterComponents je funkce p°ebφrajφcφ t°i parametry: jmΘno strßnky Palety komponent, pole t°φd komponent a index poslednφho prvku v poli. Nßsledujφcφ funkce Register obsa╛enß v souboru NOVAKOMP.CPP, registruje komponentu nazvanou TMojeKomponenta a umis╗uje ji na strßnku Palety komponent nazvanou "R∙znΘ".
namespace Novakomp
{
  void __fastcall PACKAGE Register()
  {
      TComponentClass classes[1] = {__classid(TMojeKomponenta)};
      RegisterComponents("R∙znΘ", classes, 0);
  }
}
Pov╣imn∞te si, ╛e t°etφ parametr ve volßnφ RegisterComponents je 0, co╛ je index poslednφho prvku v poli t°φd (velikost pole minus 1).
M∙╛eme takΘ registrovat n∞kolik komponent na stejnΘ strßnce najednou nebo registrovat komponenty na r∙zn²ch strßnkßch.
V nßsledujφcφm p°φklad∞ jsou deklarovanΘ dv∞ pole: classes1 a classes2. V prvnφm volßnφ RegisterComponents, classes1 mß dva prvky a t°etφ parametr je index druhΘho prvku, co╛ je 1. V druhΘm volßnφ RegisterComponents, classes2 mß jeden prvek a t°etφ parametr je 0.
namespace Mojekomp
{
  void __fastcall PACKAGE Register()
  {
    // deklarace pole pro dv∞ komponenty
    TComponentClass classes1[2] = {__classid(TPrvni), __classid(TDruha)};
    // p°idßnφ novΘ palety se dv∞mi komponentami
    RegisterComponents("R∙znΘ", classes1, 1);
    // deklarace druhΘho pole
    TComponentClass classes2[1];
    // p°i°azenφ komponenty prvnφmu prvku v poli
    classes2[0]  = __classid(TTreti);
    // p°idßnφ komponenty na strßnku Samples
    RegisterComponents("Samples", classes2, 0);
  }
}

P°idßnφ bitovΘ mapy zobrazenΘ na palet∞

Ka╛dß komponenta vy╛aduje bitovou mapu reprezentujφcφ komponentu na Palet∞ komponent. Jestli╛e nespecifikujeme svou vlastnφ bitovou mapu, pak C++ Builder pou╛ije implicitnφ. Jeliko╛ bitovΘ mapy palety jsou pot°ebnΘ pouze b∞hem nßvrhu, nejsou p°elo╛eny v jednotce komponenty. Jsou v souboru zdroj∙ Windows se stejn²m jmΘnem jako mß jednotka, ale s p°φponou DCR (Design-time Component Resource). Tento soubor zdroj∙ m∙╛eme vytvo°it pomocφ Editoru obrßzk∙ v C++ Builderu. Ka╛dß bitovß mapa je Φtverec o stran∞ 24 bod∙.
Pro ka╛dou jednotku, kterou chceme instalovat, pot°ebujeme soubor DCR a v ka╛dΘm souboru DCR pot°ebujeme bitovou mapu pro ka╛dou registrovanou komponentu. Obraz bitovΘ mapy mß stejnΘ jmΘno jako komponenta. Soubor DCR musφ b²t ve stejnΘm adresß°i jako jednotka komponenty, C++ Builder zde tento soubor hledß, kdy╛ instaluje komponenty na paletu.
Nap°. jestli╛e vytvo°φme komponentu nazvanou TMujOvladac v jednotce nazvanΘ ToolBox, musφme vytvo°it soubor zdroj∙ nazvan² TOOLBOX.DCR, kter² obsahuje bitovou mapu nazvanou TMUJOVLADAC. Ve jmΘnech zdroj∙ nezßle╛φ na velikostφ pφsmen, ale podle konvence je obvykle zapisujeme velk²mi pφsmeny.

Poskytnutφ nßpov∞dy pro na╣i komponentu

Kdy╛ vybereme komponentu na formulß°i, p°φpadn∞ vlastnost nebo udßlost v Inspektoru objekt∙, pak m∙╛eme stisknutφm F1 zφskat informaci o tomto prvku. U╛ivatelΘ na╣ich komponent mohou zφskat informace o na╣φ komponent∞, jestli╛e vytvo°φme p°φslu╣nΘ soubory nßpov∞dy.
M∙╛eme poskytnout mal² soubor nßpov∞dy s informacemi o na╣ich komponentßch a u╛ivatelΘ mohou nalΘzt na╣i dokumentaci bez nutnosti n∞jakΘho specißlnφho kroku. Na╣e nßpov∞da se stane Φßstφ nßpov∞dnΘho systΘmu C++ Builderu.
Pro poskytnutφ kontextovΘ nßpov∞dy pro na╣i komponentu provedeme nßsledujφcφ kroky: Vytvo°φme polo╛ky nßpov∞dy, ud∞lßme polo╛ky kontextov∞ senzitivnφ a p°idßme nßpov∞du k nßpov∞d∞ C++ Builderu.
K vytvo°enφ souboru nßpov∞dy m∙╛eme pou╛φt libovoln² nßstroj. C++ Builder obsahuje Microsoft Help Workshop, kter² m∙╛eme pou╛φt k vytvo°enφ na╣eho nßpov∞dnΘho souboru.
Aby nß╣ soubor nßpov∞dy byl integrovateln² do nßpov∞dy knihovny komponent, je nutno dodr╛ovat nßsledujφcφ konvence:
  1. Ka╛dß komponenta musφ mφt prvek nßpov∞dy. Prvek nßpov∞dy komponenty obsahuje struΦn² popis komponenty. Prvek nßpov∞dy komponenty musφ obsahovat vazby na sekundßrnφ okna, kterΘ popisujφ pozici komponenty v objektovΘ hierarchii a kterΘ obsahujφ seznamy v╣ech vlastnostφ, udßlostφ a metod dostupn²ch pro u╛ivatele komponenty. V²vojß° aplikace zp°φstup≥uje tento prvek nßpov∞dy v²b∞rem komponenty na formulß°i a stiskem klßvesy F1. Prvek nßpov∞dy musφ mφt poznßmku pod Φarou # s unikßtnφ hodnotou pro prvek. Poznßmka pod Φarou # jednoznaΦn∞ identifikuje ka╛d² prvek v nßpov∞dnΘm systΘmu.

  2. Prvek nßpov∞dy komponenty musφ mφt poznßmku pod Φarou "K" pro vyhledßvßnφ klφΦov²ch slov, kterß obsahuje jmΘno t°φdy komponenty. Nap°. poznßmka pod Φarou klφΦovΘho slova pro komponentu TMemo je "TMemo". Prvek nßpov∞dy komponenty musφ mφt takΘ poznßmku pod Φarou "$", kterß poskytuje titulek prvku. Titulek se zobrazuje v dialogovΘm okn∞ Topics Found, dialogovΘm okn∞ Bookmark a okn∞ History.
  3. Ka╛dß komponenta musφ mφt sekundßrnφ navigaΦnφ prvky nßpov∞dy. Jednß se o:
  4. Vazby na objekty t°φd, vlastnostφ, metod nebo udßlostφ v nßpov∞dnΘm systΘmu C++ Builderu mohou b²t provedeny pomocφ Alink. Kdy╛ se odkazujeme na objekt t°φdy, pak Alink pou╛φvß jmΘno objektu t°φdy, nßsledovanΘ podtr╛enφm a °et∞zcem "object". Nap°. k vazb∞ na objekt TCustomPanel pou╛ijeme:
    !AL(TCustomPanel_object,1)
    U vazeb na vlastnost, metodu nebo udßlost, p°edchßzφ jmΘno vlastnosti, metody nebo udßlosti jmΘno t°φdy, kterß ji implementuje a podtr╛enφ. Nap°. k vazb∞ na vlastnost Text, kterß je implementovanß TControl pou╛ijeme:
    !AL(TControl_Text,1)
    Abychom vid∞li p°φklad sekundßrnφch navigaΦnφch prvk∙, zobrazφme prvek nßpov∞dy n∞jakΘ komponenty a klikneme na vazbu popsanou ?hierarchy?, ?properties?, ?methods? nebo ?events?.
  5. Ka╛dß vlastnost, udßlost a metoda, kterß je deklarovßna v komponent∞ musφ mφt nßpov∞dn² prvek. Prvek nßpov∞dy vlastnosti, udßlosti nebo metody zobrazuje deklaraci prvku a popisuje jeho pou╛φvßnφ. V²vojß° aplikace vidφ tyto prvky po jejich v²b∞ru v Inspektoru objekt∙ a stisku F1 nebo umφst∞nφm textovΘho kurzoru v Editoru k≤du na jmΘno prvku a stiskem F1.

  6. Prvek nßpov∞dy pro vlastnost, udßlost nebo metodu musφ obsahovat poznßmku pod Φarou "K" se jmΘnem vlastnosti, metody nebo udßlosti a toto jmΘno v kombinaci se jmΘnem komponenty. Tedy vlastnost TextTControl mß nßsledujφcφ "K" poznßmku pod Φarou:
    Text,TControl;TControl,Text;Text,
    Prvek nßpov∞dy vlastnosti, metody a udßlosti musφ mφt takΘ poznßmku pod Φarou "$", kterß urΦuje titulek prvku, nap°. ?TControl::Text?.
    V╣echny tyto prvky nßpov∞dy musφ mφt unikßtnφ ID prvku, zadanΘ jako poznßmka pod Φarou #.
Ka╛d² prvek nßpov∞dy komponenty, vlastnosti, metody a udßlosti musφ mφt poznßmku pod Φarou "A". Tato poznßmka je pou╛ita k zobrazenφ prvku, kdy╛ u╛ivatel vybere komponentu a stiskne F1 nebo kdy╛ vlastnost nebo udßlost je vybrßna v Inspektoru objekt∙ a u╛ivatel stiskne F1. Poznßmka pod Φarou "A" musφ spl≥ovat tyto konvence.
Pokud prvek nßpov∞dy je pro t°φdu komponenty, pak poznßmka pod Φarou obsahuje dv∞ polo╛ky odd∞lenΘ st°ednφkem p°i pou╛itφ tΘto syntaxe:
ComponentClass_Object;ComponentClass
kde ComponentClass je jmΘno t°φdy komponenty.
Pokud prvek nßpov∞dy je pro vlastnost nebo udßlost, pak poznßmka pod Φarou "A" obsahuje t°i polo╛ky odd∞lenΘ st°ednφky p°i pou╛itφ tΘto syntaxe:
ComponentClass_Element;Element_Type;Element
kde ComponentClass je jmΘno t°φdy komponenty, Element je jmΘno vlastnosti, metody nebo udßlosti a Type je Property, Method nebo Event.
Nap°. pro vlastnost nazvanou BackgroundColor komponenty nazvanΘ TMyGrid tato poznßmka pod Φarou je:
TMyGrid_BackgroundColor;BackgroundColor_Property;BackgroundColor
Pro p°idßnφ na╣eho nßpov∞dnΘho souboru k nßpov∞dnΘmu souboru C++ Builderu pou╛ijeme utilitu OpenHelp, kterou zp°φstupnφme volbou Help | Customize.

P°idßnφ editor∙ vlastnostφ

Inspektor objekt∙ poskytuje mo╛nost editace pro v╣echny typy vlastnostφ. NicmΘn∞ m∙╛eme poskytnout alternativnφ editor pro konkrΘtnφ vlastnost zßpisem a registracφ editoru vlastnosti. M∙╛eme registrovat editor vlastnosti, kter² lze pou╛φt pouze na vlastnosti ve vytvß°enΘ komponent∞, ale m∙╛eme takΘ vytvo°it editor, kter² lze pou╛φt na v╣echny vlastnosti jistΘho typu.
V nejjednodu╣╣φ ·rovni editor vlastnosti m∙╛e operovat jednφm nebo ob∞ma z t∞chto zp∙sob∙: zobrazovat a zp°φstupnit k editovßnφ u╛ivateli souΦasnou hodnotu jako textov² °et∞zec a zobrazit dialogovΘ okno provßd∞jφcφ n∞kterΘ typy editace. V zßvislosti na editovanΘ vlastnosti je u╛iteΦnΘ poskytnout jeden nebo oba zp∙soby.
Zßpis editoru vlastnosti vy╛aduje p∞t krok∙:
  1. Odvozenφ t°φdy editoru vlastnosti
  2. Editace vlastnosti jako text
  3. Editace vlastnosti jako celek
  4. Specifikaci atribut∙ editoru
  5. Registrace editoru vlastnosti.

Odvozenφ t°φdy editoru vlastnosti

Soubor DSGNINTF.HPP definuje n∞kolik typ∙ editor∙ vlastnosti, v╣echny jsou odvozeny od TPropetryEditor. Kdy╛ vytvß°φme editor vlastnosti, m∙╛eme t°φdu editoru vlastnosti odvodit p°φmo od TPropertyEditor nebo nep°φmo od jednoho z typ∙ editor∙ vlastnosti popsan²ch v dal╣φ tabulce (odvozujeme nov² objekt od jednoho z existujφcφho typu editoru vlastnosti). Soubor DSGNINTF.HPP takΘ definuje n∞kterΘ velmi specializovanΘ editory vlastnostφ pou╛φvanΘ pro unikßtnφ vlastnosti jako je nap°. jmΘno komponenty.
 
Typ Edituje vlastnosti
TOrdinalProperty Zßklad pro v╣echny editory vlastnostφ ordinßlnφch typ∙ (celoΦφselnΘ, znakovΘ a v²ΦtovΘ vlastnosti).
TIntegerProperty V╣echny celoΦφselnΘ typy vΦetn∞ p°eddefinovan²ch a u╛ivatelem definovan²ch interval∙.
TCharPropetry Typ Char a intervaly Char, jako ?A?..?Z?.
TEnumProperty Libovoln² v²Φtov² typ.
TFloatProperty LibovolnΘ reßlnΘ Φφslo.
TStringPropetry ╪et∞zce.
TSetElementProperty Individußlnφ prvek v mno╛in∞, zobrazovan² jako logickß hodnota.
TSetPropetry V╣echny mno╛iny. Mno╛iny nejsou p°φmo editovatelnΘ, ale m∙╛eme ji roz╣φ°it na seznam prvk∙ mno╛iny.
TClassPropetry Objekty. Zobrazφ jmΘno typu objektu a umo╛≥uje expandovat vlastnosti objektu.
TMethodProperty UkazatelΘ metod.
TComponentProperty Komponenty na formulß°i. U╛ivatel nem∙╛e editovat vlastnosti komponent, ale m∙╛e ukazovat na specifickΘ komponenty kompatibilnφho typu.
TColorPropetry Komponenta barev. Roletov² seznam obsahuje konstanty barev. DvojitΘ kliknutφ otevφrß dialogovΘ okno v²b∞ru barvy.
TFontNamePropetry JmΘna pφsma. Roletov² seznam obsahuje v╣echna aktußln∞ instalovanß pφsma.
TFontProperty Pφsma. Umo╛≥uje roz╣φ°it na individußlnφ vlastnosti pφsma stejn∞ jako p°φstup k dialogovΘmu oknu pφsma.

Nßsleduje deklarace t°φdy jednoduchΘho editoru vlastnosti nazvanΘho TMujEditorVlastnosti:
class PACKAGE TMujEditorVlastnosti : public TPropertyEditor
{
   typedef TPropertyEditor inherited;
public:
   virtual bool __fastcall AllEqual(void);
   virtual System::AnsiString __fastcall GetValue(void);
   virtual void __fastcall SetValue(const System::AnsiString Value);
   __fastcall virtual ~TMujEditorVlastnosti(void) { }
   __fastcall TMujEditorVlastnosti(void) : Dsgnintf::TPropertyEditor() { }
};

Editovßnφ vlastnosti jako text

V╣echny vlastnosti musφ poskytovat °et∞zcovou reprezentaci sv²ch hodnot pro zobrazenφ v Inspektoru objekt∙. Mnoho vlastnostφ takΘ zp°φstup≥uje u╛ivateli typ v novΘ hodnot∞ pro vlastnost. T°φda editoru vlastnostφ poskytuje virtußlnφ metody, kterΘ m∙╛eme p°epsat pro p°evod mezi textovou reprezentacφ a aktußlnφ hodnotou. Tyto metody jsou nazvanΘ GetValue a SetValue. Nß╣ editor vlastnosti takΘ d∞dφ mno╛inu metod pou╛φvan²ch pro p°i°azenφ a Φtenφ jin²ch typ∙ hodnot (viz nßsledujφcφ tabulka):
 
Typ vlastnosti  Metoda "Get"  Metoda "Set"
reßln² GetFloatValue SetFloatValue
zßv∞r (udßlost) GetMethodValue SetMethodValue
ordinßlnφ typ GetOrdValue SetOrdValue
°et∞zec GetStrValue SetStrValue

Kdy╛ p°edefinujeme metodu GetValue, m∙╛eme stßle volat jednu z metod "Get" a kdy╛ p°edefinujeme metodu SetValue, m∙╛eme stßle volat jednu z metod "Set".
Metoda GetValue editoru vlastnosti vracφ °et∞zec, kter² reprezentuje souΦasnou hodnotu vlastnosti. Inspektor objekt∙ pou╛φvß tento °et∞zec ve sloupci hodnot pro vlastnost. Implicitn∞ GetValue vracφ "unknown".
K poskytnutφ °et∞zcovΘ reprezentace pro na╣i vlastnost, p°edefinujeme metodu GetValue editoru vlastnosti. Jestli╛e vlastnost nemß °et∞zcovou hodnotu, na╣e GetValue musφ p°evΘst hodnotu na jejφ °et∞zcovou reprezentaci.
Metoda SetValue editoru vlastnosti p°ebφrß °et∞zec zapsan² u╛ivatelem v Inspektoru objekt∙, p°evßdφ jej na p°φslu╣n² typ a nastavuje hodnotu vlastnosti. Jestli╛e °et∞zec nemß reprezentaci p°φslu╣nΘ hodnoty pro vlastnost, SetValue generuje v²jimku a nevhodnou hodnotu nepou╛ije. Pro p°eΦtenφ °et∞zcovΘ hodnoty z vlastnosti, p°edefinujeme metodu SetValue editoru vlastnosti. SetValue musφ p°evßd∞t °et∞zec a ov∞°ovat hodnotu p°ed volßnφm jednΘ z metod "Set".

Editovßnφ vlastnosti jako celek

Voliteln∞ m∙╛eme poskytnout dialogovΘ okno, ve kterΘm m∙╛e u╛ivatel viditeln∞ editovat vlastnost. Toto je u╛iteΦnΘ pro editory vlastnosti jejich╛ vlastnosti jsou t°φdy. P°φkladem je vlastnost Font, pro kterou u╛ivatel m∙╛e otev°φt dialogovΘ okno k volb∞ v╣ech atribut∙ pφsma. K poskytnutφ dialogovΘho okna celkovΘho editoru vlastnosti, p°edefinujeme metodu Edit t°φdy editoru vlastnosti.
Metoda Edit pou╛φvß stejnΘ metody "Get" a "Set" jako jsou pou╛ity v metodßch GetValue a SetValue (metoda Edit volß ob∞ tyto metody). Jeliko╛ editor je specifickΘho typu, obvykle nenφ pot°eba p°evßd∞t hodnotu vlastnosti na °et∞zec. Kdy╛ u╛ivatel klikne na tlaΦφtko '...' vedle vlastnosti nebo dvojit∞ klikne ve sloupci hodnot, Inspektor objekt∙ volß metodu Edit editoru vlastnosti. V implementaci metody Edit provedeme tyto kroky: Vytvo°φme nß╣ editor, p°eΦteme souΦasnΘ hodnoty a p°i°adφme je metodou "Get", kdy╛ u╛ivatel zm∞nφ n∞kterou hodnotu, p°i°adφme tuto hodnotu pomocφ metody "Set" a zru╣φme editor.

Specifikovßnφ atribut∙ editoru

Editor vlastnosti musφ poskytovat informace, kterΘ Inspektor objekt∙ m∙╛e pou╛φt k urΦenφ zobrazenΘho nßstroje. Nap°. Inspektor objekt∙ musφ znßt, zda vlastnost mß podvlastnosti nebo zda m∙╛e zobrazit seznam mo╛n²ch hodnot. Pro specifikaci atribut∙ editoru, p°edefinujeme metodu GetAttributes t°φdy editoru. GetAttributes je metoda vracejφcφ mno╛inu hodnot typu TPropertyAttributes, kterß m∙╛e obsahovat n∞kterΘ nebo v╣echny nßsledujφcφ hodnoty:
 
P°φznak V²znam, je-li vlo╛en Ovliv≥uje metodu
paValueList Editor m∙╛e zobrazit seznam v²Φtov²ch hodnot.  GetValues
paSubProperties Vlastnost mß podvlastnosti, kterΘ m∙╛e zobrazit.  GetProperties
paDialog Editor m∙╛e pro editaci zobrazit dialogovΘ okno.  Edit
paMultiSelect U╛ivatel m∙╛e vybrat vφce ne╛ jeden prvek. 
paAutoUpdate Aktualizuje komponentu po ka╛dΘ zm∞n∞, namφsto Φekßnφ na schvßlenφ hodnoty.  SetValue
paSortList Inspektor objekt∙ se°adφ seznam hodnot. 
paReadOnly U╛ivatel nem∙╛e modifikovat hodnotu vlastnosti. 
paRevertable Povoluje volbu Revert to Inherited v mφstnφ nabφdce Inspektora objekt∙ (nßvrat k p°edchozφ nebo implicitnφ hodnot∞). 

Vlastnost Color mß n∞kolik mo╛nostφ, jak ji u╛ivatel zadß v Inspektoru objekt∙: zßpisem, v²b∞rem ze seznamu a editorem. Metoda GetAttributes TColorProperty, tedy obsahuje n∞kolik atribut∙ ve svΘ nßvratovΘ hodnot∞:
virtual __fastcall TPropertyAttributes TColorProperty::GetAttributes()
{
  return TPropertyAttributes()<<paMultiSelect<<paDialog<<paValueList;
}

Registrace editoru vlastnosti

Vytvo°en² editor vlastnosti se musφ v C++ Builderu registrovat. Registracφ editoru vlastnosti p°i°adφme typ vlastnosti k editoru vlastnosti. M∙╛eme registrovat editor se v╣emi vlastnostmi danΘho typu nebo s jistou vlastnostφ jistΘho typu komponenty. K registraci editoru vlastnosti volßme funkci RegisterPropetryEditor.
Tato funkce mß Φty°i parametry: Prvnφm je ukazatel na informace o typu pro editovanou vlastnost. To je v╛dy volßnφ funkce __typeinfo, nap°. __typeinfo(TMojeKomponenta). Druh²m je typ komponenty, na kter² je tento editor aplikovßn. Jestli╛e tento parametr je NULL, editor je pou╛iteln² na v╣echny vlastnosti danΘho typu. T°etφm parametrem je jmΘno vlastnosti. Tento parametr mß v²znam pouze, jestli╛e p°edchozφ parametr specifikuje konkrΘtnφ typ komponenty. V tomto p°φpad∞, m∙╛eme specifikovat jmΘno konkrΘtnφ vlastnosti v typu komponenty, se kterou tento editor pracuje. Poslednφm parametrem je typ editoru vlastnosti pou╛it² pro editovßnφ specifikovanΘ vlastnosti.
Nßsleduje ukßzka funkce, kterß registruje editory pro n∞kterΘ standardnφ komponenty na Palet∞ komponent:
namespace Newcomp
{
  void __fastcall PACKAGE Register()
  {
    RegisterPropertyEditor(__typeinfo(TComponent), 0L, "",
                           __classid(TComponentProperty));
    RegisterPropertyEditor(__typeinfo(TComponentName), TComponent,
                           "Name", __classid(TComponentNameProperty));
    RegisterPropertyEditor(__typeinfo(TMenuItem), TMenu, "",
                           __classid(TMenuItemProperty));
  }
}
T°i p°φkazy v tΘto funkci ukazujφ r∙znΘ pou╛itφ RegisterPropertyEditor: Prvnφ p°φkaz je nejtypiΦt∞j╣φ. Registruje editor vlastnosti TComponentProperty pro v╣echny vlastnosti typu TComponent (nebo potomk∙ TComponent, kterΘ nemajφ registrovßn vlastnφ editor). Obecn∞, kdy╛ registrujeme editor vlastnosti, vytvo°φme editor pro jist² typ a chceme jej pou╛φt pro v╣echny vlastnosti tohoto typu, pak jako druh² parametr pou╛ijeme NULL a jako t°etφ parametr prßzdn² °et∞zec. Druh² p°φkaz je nejspecifiΦt∞j╣φm typem registrace. Registruje editor pro jistou vlastnost v jistΘm typu komponenty. V tomto p°φpad∞ je to editor pro vlastnost Name (typ TComponentName) v╣ech komponent. T°etφ p°φklad je specifiΦt∞j╣φ ne╛ prvnφ, ale nenφ limitovßn jako druh². Registruje editor pro v╣echny vlastnosti typu TMenuItem v komponentßch typu TMenu.

P°idßvßnφ editoru komponenty

Editory komponent urΦujφ co nastane, kdy╛ dvojit∞ klikneme na komponentu na NßvrhovΘm formulß°i a p°idßvß p°φkazy do mφstnφ nabφdky, kterß je zobrazena p°i kliknutφ prav²m tlaΦφtkem my╣i na komponent∞. Umo╛≥uje takΘ kopφrovat na╣i komponentu do schrßnky Windows v p°izp∙sobenΘm formßtu.
Pokud na╣φ komponent∞ nedßme editor komponenty, pak C++ Builder pou╛ije implicitnφ editor komponenty. Implicitnφ editor komponenty je implementovßn t°φdou TDefaultEditor. TDefaultEditor nep°idßvß ╛ßdnΘ novΘ prvky v mφstnφ nabφdce. Kdy╛ na komponent∞ dvojit∞ klikneme, pak TDefaultEditor hledß vlastnosti komponenty a generuje (nebo p°echßzφ na) prvnφ obsluhu udßlosti.
K vytvo°enφ editoru komponenty pro na╣φ komponentu, musφme odvodit novou t°φdu od TComponentEditor a potom provΘst jednu nebo vφce v∞cφ z: Z p°edchozφho seznamu je po╛adovßna pouze registrace Editoru komponenty.

P°idßvßnφ prvku k mφstnφ nabφdce

Kdy╛ u╛ivatel klikne na komponent∞ prav²m tlaΦφtkem my╣i, pak jsou volßny metody GetVerbCount a GetVerb Editoru komponenty k vytvo°enφ mφstnφ nabφdky. Tyto metody m∙╛eme p°epsat pro p°idßnφ p°φkazu k mφstnφ nabφdce.
Metodu GetVerbCount p°epφ╣eme, aby vracela poΦet p°φkaz∙ p°idan²ch do mφstnφ nabφdky. Metodu GetVerb p°epφ╣eme, aby vracela °et∞zce, kterΘ chceme p°idat pro ka╛d² z t∞chto p°φkaz∙. Znak & v °et∞zci, zp∙sobφ, ╛e nßsledujφcφ znak bude podtr╛en a bude pracovat jako zkracovacφ klßvesa pro tento prvek nabφdky. Na konec p°φkaz∙, kterΘ zobrazujφ dialogovΘ okno zapφ╣eme .... GetVerb mß jeden parametr, kter² specifikuje index p°φkazu.
Nßsledujφcφ k≤d p°episuje metody GetVerbCount a GetVerb pro p°idßnφ dvou p°φkaz∙ k mφstnφ nabφdce:
int __fastcall TMujEditor::GetVerbCount(void)
{
  return 2;
}
System::AnsiString __fastcall TMujEditor::GetVerb(int Index)
{
  switch (Index)
  {
    case 0: return "&DoThis ... "; break;
    case 1: return "Do&That"; break;
  }
}
Poznßmka: Ujistφme se, ╛e metoda GetVerb vracφ hodnotu pro ka╛d² mo╛n² index specifikovan² GetVerbCount.
Kdy╛ p°φkaz poskytnut² GetVerb je vybrßn v NßvrhovΘm formulß°i, pak je volßna metoda ExecuteVerb. Pro ka╛d² p°φkaz poskytnut² v metod∞ GetVerb, implementujeme akci v metod∞ ExecuteVerb. M∙╛eme p°istupovat ke komponent∞, kterß bude editovßna pomocφ vlastnosti Component editoru.
Nßsledujφcφ metoda ExecuteVerb implementuje p°φkazy pro p°edchozφ metodu GetVerb:
void __fastcall TMujEditor::ExecuteVerb(int Index)
{
  switch (Index)
  {
    case 0:
      TMujDialog *MySpecialDialog = new TMujDialog();
      MySpecialDialog->Execute();
      // pou╛φvßme vlastnost Component pro p°φstup k instanci TMojeComponenta
      ((TMojeComponenta *)Component)->ThisProperty = MySpecialDialog->ReturnValue;
      delete MySpecialDialog;
      break;
    case 1:
      That();  // volßnφ metody "That"
      break;
  }
}

Zm∞na chovßnφ dvojitΘho kliknutφ

Kdy╛ na komponentu dvojit∞ klikneme, pak je volßna metoda Edit Editoru komponenty. Implicitn∞ metoda Edit provßdφ prvnφ p°φkaz p°idan² do mφstnφ nabφdky. I kdy╛ provßd∞nφ prvnφho p°φkazu je obvykle vhodnß my╣lenka, n∞kdy toto implicitnφ chovßnφ m∙╛eme pot°ebovat zm∞nit. Nap°. m∙╛eme po╛adovat alternativnφ chovßnφ pokud do mφstnφ nabφdky nep°idßme ╛ßdn² p°φkaz nebo m∙╛eme po╛adovat zobrazenφ dialogovΘho okna, kterΘ spojuje n∞kolik p°φkaz∙, kdy╛ na komponent∞ dvojit∞ klikneme.
P°epsßnφm metody Edit specifikujeme novΘ chovßnφ pro dvojitΘ kliknutφ na komponent∞. Nap°. nßsledujφcφ metoda Edit zp∙sobφ zobrazenφ dialogovΘho okna pφsma p°i dvojitΘm kliknutφ na komponent∞:
void __fastcall TMujEditor::Edit(void)
{
  TFontDialog *pFontDlg = new TFontDialog(NULL);
  pFontDlg->Execute();
  // vlastnost Component pou╛φvßme pro p°φstup k instanci TMojeComponenta
  ((TMokeKomponenta *)Component)->Font = pFontDlg->Font;
  delete pFontDlg;
}
Pokud chceme p°ejφt do Editoru k≤du na obsluhu udßlosti p°i dvojitΘm kliknutφ na komponent∞, pak pou╛ijeme jako t°φdu p°edka TDefaultEditor namφsto TComponentEditor. Potom mφsto p°epsßnφ metody Edit p°epφ╣eme chrßn∞nou metodu TDefaultEditor::EditProperty. EditProperty prochßzφ obsluhami udßlostφ komponenty a pou╛ije prvnφ nalezenou. Toto hledßnφ m∙╛eme zm∞nit. Nap°.
void __fastcall TMujEditor::EditProperty(TPropertyEditor* PropertyEditor, bool &Continue,
                                         bool &FreeEditor)
{
  if (PropertyEditor->ClassNameis("TMethodProperty") &&
      CompareText(PropertyEditor->GetName, "OnSpecialEvent") == 0)
  {
    TDefaultEditor::EditProperty(PropertyEditor, Continue, FreeEditor);
  }
}

P°φdßvßnφ formßtu schrßnky

Implicitn∞, kdy╛ u╛ivatel zvolφ Copy p°i vybranΘ komponent∞, pak komponenta je kopφrovßna do schrßnky v internφm formßtu C++ Builderu. Potom ji m∙╛eme vlo╛it na jin² formulß° nebo datov² modul. Na╣i komponentu m∙╛eme kopφrovat v dal╣φch formßtech do schrßnky p°epsßnφm metody Copy.
Nap°. nßsledujφcφ metoda Copy umo╛≥uje komponent∞ TImage kopφrovat sv∙j obrßzek do schrßnky. Tento obrßzek je ignorovßn IDE C++ Builderu, ale m∙╛e b²t vklßdßn do jin²ch aplikacφ.
void __fastcall TMujEditor::Copy(void)
{
  WORD AFormat;
  int AData;
  HPALETTE APalette;
  ((TImage*)Component)->Picture->SaveToClipboardFormat(AFormat,AData, APalette);
  TClipboard *pClip = Clipboard(); // nevyprazd≥uje schrßnku
  pClip->SetAsHandle(AFormat, AData);
}

Registrace editoru komponenty

Kdy╛ ji╛ mßme definovßn editor komponenty, m∙╛eme jej registrovat pro prßci s jistou t°φdou komponenty. Registrovan² editor komponenty je vytvo°en pro ka╛dou komponentu, kdy╛ je vybrßna na nßvrhovΘm formulß°i.
K vytvo°enφ asociace mezi Editorem komponenty a t°φdou komponenty volßme RegisterComponentEditor. Tato funkce p°ebφrß jmΘno t°φdy komponenty, kterß pou╛φvß editor a jmΘno t°φdy Editoru komponenty, kterou mßme definovanou. Nap°. nßsledujφcφ p°φkaz registruje t°φdu Editoru komponenty nazvanou TMujEditor pro prßci se v╣emi komponentami typu TMojeKomponenta:
RegisterComponentEditor(__classid( TMojeKomponenta), __classid(TMujEditor));
Volßnφ RegisterComponentEditor umφstφme do jmennΘho prostoru kde registrujeme na╣i komponentu.
Pokud novß komponenta nazvanß TMojeKomponenta a jejφ editor TMujEditor jsou implementovßny v NovaKomp.cpp, pak nßsledujφcφ k≤d (v NovaKomp.cpp) registruje komponentu a spojuje ji s Editorem komponenty:
namespace Novakomp
{
  void __fastcall PACKAGE Register()
  {
      TComponentClass classes[1] = {__classid(TMojeKComponenta)};
      RegisterComponents("R∙znΘ", classes, 0);
      RegisterComponentEditor(classes[0], __classid(TMujEditor));
  }
}

P°eklad komponent do balφΦk∙

Kdy╛ ji╛ komponenty jsou registrovanΘ, pak je musφme p°elo╛it jako balφΦky a to d°φve ne╛ je m∙╛eme instalovat v IDE. BalφΦek m∙╛e obsahovat jednu nebo n∞kolik komponent a takΘ u╛ivatelsk²ch editor∙ vlastnostφ.
K vytvo°enφ a p°ekladu balφΦku, umφstφme zdrojovΘ k≤dy jednotek na╣ich komponent do seznamu obsahu balφΦku. Pokud na╣e komponenty zßvisφ na dal╣φch balφΦcφch, vlo╛φme tyto balφΦky do seznamu po╛adavk∙. P°elo╛en² balφΦek s komponentami ji╛ m∙╛eme instalovat na Paletu komponent.
Obecn²m problΘmem p°i registraci a instalovßnφ u╛ivatelskΘ komponenty je to, ╛e komponenta se nezobrazuje v seznamu komponent po ·sp∞╣n∞ instalovanΘm balφΦku. Nßsleduje p°ehled obecn²ch p°φΦin nezobrazovßnφ komponenty v seznamu nebo na palet∞:
  1. Kdy╛ pracujeme s p°ipojenou databßzφ, je Φasto u╛iteΦnΘ mφt ovladaΦ spojen s n∞jakou polo╛kou databßze. Aplikace tedy m∙╛e zalo╛it propojenφ mezi ovladaΦem a n∞jakou Φßstφ databßze. C++ Builder obsahuje datovΘ ovladaΦe typ∙ editaΦnφch oken, seznam∙, kombinovan²ch oken a m°φ╛ek. M∙╛eme takΘ vytvo°it sv∙j vlastnφ datov² ovladaΦ. Je n∞kolik stup≥∙ zßvislosti dat datov²ch ovladaΦ∙. Nejjednodu╣╣φ je datovß zßvislost pouze pro Φtenφ, nebo prohlφ╛enφ dat, a umo╛n∞nφ reakce na aktußlnφ stav databßze. Slo╛it∞j╣φ je editovatelnß datovß zßvislost, kde u╛ivatel m∙╛e editovat hodnoty v databßzi manipulacφ s ovladaΦem.

  2. Nynφ se pokusφme vytvo°it ovladaΦ urΦen² pouze pro Φtenφ, kter² je spojen s jednou polo╛kou v databßzi. OvladaΦ bude pou╛φvat kalendß° vytvo°en² v p°edchozφ kapitole.
    Vytvo°enφ datovΘho ovladaΦe kalendß°e provedeme v nßsledujφcφch krocφch: vytvo°φme a registrujeme komponentu, ud∞lßme ovladaΦ urΦeny pouze pro Φtenφ, p°idßme datovΘ propojenφ a reakce na zm∞ny dat.
    Pou╛ijeme obecn² postup s t∞mito specifikami: jednotku komponenty nazveme DBCal, odvodφme nov² typ komponenty nazvan² TDBCalendar od TSampleCalendar a registrujeme TDBCalendar na strßnce Samples Palety komponent.
    V²sledek na╣φ prßce je (nejprve je uveden v²pis hlaviΦkovΘho souboru jednotky):
    #ifndef DBCalH
    #define DBCalH
    #include <vcl\sysutils.hpp>
    #include <vcl\controls.hpp>
    #include <vcl\classes.hpp>
    #include <vcl\forms.hpp>
    #include <vcl\grids.hpp>
    #include "CALSAMP.h"
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
    protected:
    public:
    __published:
    };
    #endif
    CPP soubor vypadß takto:
    #pragma link "Calsamp"  // vazba na TSampleCalendar
    #include <vcl\vcl.h>
    #pragma hdrstop
    #include "DBCal.h"
    #pragma package(smart_init);
    static inline TDBCalendar *ValidCtrCheck()
    {
     return new TDBCalendar(NULL);
    }
    namespace Dbcal
    {
      void __fastcall PACKAGE Register()
      {
        TComponentClass classes[1] = {__classid(TDBCalendar)};
        RegisterComponents("Samples", classes, 0);
      }
    }
  3. Jeliko╛ tento kalendß° bude urΦen pouze pro Φtenφ, je vhodnΘ znemo╛nit u╛ivateli provßd∞nφ zm∞n v ovladaΦi. Provedeme to ve dvou krocφch: p°idßme vlastnost ReadOnly a dovolφme pot°ebnΘ aktualizace. Kdy╛ tato vlastnost je nastavena na true, jsou v╣echny bu≥ky v ovladaΦi nevybφratelnΘ. P°idßme deklaraci vlastnosti a soukromou polo╛ku k ulo╛enφ hodnoty:

  4. class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
      bool FReadOnly;
    protected:
    public:
      __fastcall TDBCalendar(TComponent* Owner);
    __published:
      __property bool ReadOnly={read=FReadOnly,write=FReadOnly,default=true};
    };
    Zapφ╣eme definici konstruktoru:
    __fastcall TDBCalendar::TDBCalendar(TComponent* Owner)
     : TSampleCalendar(Owner)
    {
      FReadOnly = true;
    }
    a p°edefinujeme metodu SelectCell k zßkazu v²b∞ru, jestli╛e ovladaΦ je pouze pro Φtenφ.
    bool __fastcall TDBCalendar::SelectCell(long ACol, long ARow)
    {
      if (FReadOnly) return false;
      return TSampleCalendar::SelectCell(ACol, ARow);
    }
    Nesmφme zapomenout p°idat deklaraci SelectCell k deklaraci t°φdy TDBCalendar. Jestli╛e nynφ p°idßme kalendß° na formulß°, zjistφme, ╛e komponenta ignoruje kliknutφ a stisky kurzorov²ch klßves.
    Kalendß° pouze pro Φtenφ pou╛φvß metodu SelectCell pro v╣echny typy zm∞n, vΦetn∞ nastavovßnφ vlastnostφ Row a Col. Metoda UdpateCalendar nastavuje Row a Col poka╛dΘ, kdy╛ se zm∞nφ datum, ale jeliko╛ SelectCell nepovolφ zm∞ny, v²b∞r se nem∞nφ, i kdy╛ se zm∞nφ datum. K omezenφ tohoto absolutnφho zßkazu zm∞n, m∙╛eme p°idat internφ logickou polo╛ku ke kalendß°i a povolit zm∞ny, kdy╛ je tato polo╛ka nastavena na true:
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
    bool FUpdating;
    public:
      virtual void __fastcall UpdateCalendar();
    };

    bool __fastcall TDBCalendar::SelectCell(long ACol, long ARow)
    {
      if (!FUpdating && FReadOnly) return false;
      return TSampleCalendar::SelectCell(ACol, ARow);
    }
    void __fastcall TDBCalendar::UpdateCalendar()
    {
      FUpdating = true;
      try
      {
        TSampleCalendar::UpdateCalendar();
      }
      catch(...)
      {
        FUpdating = false;
        throw;
      }
      FUpdating = false;
    }
    Kalendß° stßle neumo╛≥uje u╛ivateli provßd∞t zm∞ny datumu, ale ji╛ sprßvn∞ reaguje na zm∞ny datumu provedenΘ zm∞nou vlastnostφ datumu. Dßle pot°ebujeme ke kalendß°i p°idat schopnost prohlφ╛et datumy.

  5. Propojenφ mezi ovladaΦem a databßzφ je obsluhovßno objektem nazvan²m datov² spoj. C++ Builder poskytuje n∞kolik typ∙ datov²ch spoj∙. Objekt datovΘho spoje, kter² propojuje ovladaΦ s jednou polo╛kou v databßzi je TFieldDataLink. Jsou takΘ datovΘ spoje pro celΘ tabulky. Objekt datovΘho ovladaΦe vlastnφ sv∙j objekt datovΘho spoje. Tj. ovladaΦ mß odpov∞dnost za vytvo°enφ i uvoln∞nφ datovΘho spoje. K vytvo°enφ datovΘho spoje jako vlastn∞nΘho objektu provedeme t°i kroky: deklarujeme objektovou polo╛ku, deklarujeme p°φstupovΘ vlastnosti a inicializujeme datov² spoj.

  6. Komponenta vy╛aduje polo╛ku pro ka╛d² sv∙j vlastn∞n² objekt. V na╣em p°φpad∞ kalendß° pot°ebuje polo╛ku typu TFieldDataLink pro sv∙j datov² spoj:
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
      TFieldDataLink *FDataLink;
    };
    D°φve ne╛ m∙╛eme p°elo╛it aplikaci, musφme vlo╛it hlaviΦkovΘ soubory DB.HPP a DBTables.HPP do hlaviΦkovΘho souboru na╣φ jednotky.
    Ka╛d² datov² ovladaΦ mß vlastnost DataSource, kterß specifikuje kter² objekt datovΘho zdroje v aplikaci poskytuje data ovladaΦi. Dßle ovladaΦ, kter² p°istupuje k samostatnΘ polo╛ce vy╛aduje vlastnost DataField ke specifikaci polo╛ky datovΘho zdroje. Tyto p°φstupovΘ vlastnosti neposkytujφ p°φstup k vlastn∞nΘmu objektu sami, ale odpovφdajφcφmi vlastnostmi ve vlastn∞nΘm objektu. Deklarujeme vlastnosti DataSource a DataField a jejich implementaΦnφ metody a zapφ╣eme metody jako ?p°edßvajφcφ? metody k odpovφdajφcφm vlastnostem objektu datovΘho spoje.
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
      AnsiString __fastcall GetDataField();
      TDataSource *__fastcall GetDataSource();
      void __fastcall SetDataField(const AnsiString Value);
      void __fastcall SetDataSource(TDataSource *Value);
    __published:
      __property AnsiString DataField = {read=GetDataField,
                                         write=SetDataField, nodefault};
      __property TDataSource *DataSource = {read=GetDataSource,
                                            write=SetDataSource, nodefault};
    };

    AnsiString __fastcall TDBCalendar::GetDataField()
    {
      return FDataLink->FieldName;
    }
    TDataSource *__fastcall TDBCalendar::GetDataSource()
    {
      return FDataLink->DataSource;
    }
    void __fastcall TDBCalendar::SetDataField(const AnsiString Value)
    {
      FDataLink->FieldName = Value;
    }
    void __fastcall TDBCalendar::SetDataSource(TDataSource *Value)
    {
      if(Value != NULL)
        Value->FreeNotification(this);
      FDataLink->DataSource = Value;
    }
    Nynφ, kdy╛ mßme vytvo°eno spojenφ mezi kalendß°em a jeho datov²m spojem, je jeden velmi d∙le╛it² krok. Musφme p°i vytvß°enφ ovladaΦe kalendß°e vytvo°it objekt datovΘho spoje a datov² spoj zru╣it p°ed zru╣enφm kalendß°e.
    Datov² ovladaΦ vy╛aduje p°φstup k svΘmu datovΘmu spoji prost°ednictvφm svΘ existence, a musφme tedy vytvo°it objekt datovΘho spoje v jeho vlastnφm konstruktoru a zru╣it objekt datovΘho spoje p°ed sv²m samotn²m zru╣enφm. P°epφ╣eme tedy konstruktor a destruktor kalendß°e k vytvß°enφ a ru╣enφ objektu datovΘho spoje.
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    public:
      __fastcall TDBCalendar(TComponent* Owner);
      __fastcall ~TDBCalendar();
    };

    __fastcall TDBCalendar::TDBCalendar(TComponent* Owner)
     : TSampleCalendar(Owner)
    {
      FReadOnly = true;
      FDataLink = new TFieldDataLink();
      FDataLink->Control = this;
    }
    __fastcall TDBCalendar::~TDBCalendar()
    {
      FDataLink->Control = NULL;
      FDataLink-OnUpdateData = NULL;
      delete FDataLink;
    }
    Nynφ mßme kompletnφ datov² spoj, ale nemßme mo╛nost °φdit, kterß data budou Φtena z p°ipojenΘ polo╛ky.

  7. Nß╣ ovladaΦ mß datov² spoj a vlastnosti specifikujφcφ datov² zdroj a datovou polo╛ku a musφme je╣t∞ vytvo°it reakce na zm∞ny v datech tΘto datovΘ polo╛ky, nebo╗ se m∙╛eme p°esunout na jin² zßznam. V╣echny objekty datov²ch spoj∙ majφ udßlosti nazvanΘ OnDataChange. Kdy╛ datov² zdroj indikuje zm∞nu ve sv²ch datech, objekt datovΘho spoje volß obsluhu udßlostφ p°ipojenou k tΘto udßlosti. K aktualizaci ovladaΦe v reakci na datovΘ zm∞ny, p°ipojφme obsluhu k udßlosti OnDataChange datovΘho spoje.

  8. V na╣em p°φpad∞, p°idßme metodu DataChange ke kalendß°i a urΦφme ji jako obsluhu pro OnDataChange datovΘho spoje v konstruktoru. V destruktoru musφme obsluhu odpojit a to p°ed zru╣enφm objektu.
    class PACKAGE TDBCalendar : public TSampleCalendar
    {
    private:
      void __fastcall DataChange(TObject *Sender);
    };

    __fastcall TDBCalendar::TDBCalendar(TComponent* Owner)
     : TSampleCalendar(Owner)
    {
      FReadOnly = true;
      FDataLink = new TFieldDataLink();
      FDataLink->Control = this;
      FDataLink->OnDataChange = DataChange;
    }
    __fastcall TDBCalendar::~TDBCalendar()
    {
      FDataLink->Control = NULL;
      FDataLink-OnUpdateData = NULL;
      FDataLink->OnDataChange = NULL;
      delete FDataLink;
    }
    void __fastcall TDBCalendar::DataChange(TObject *Sender)
    {
      if (FDataLink->Field == NULL) CalendarDate = 0;
      else CalendarDate = FDataLink->Field->AsDateTime;
    }
    Tφm je zobrazovacφ databßzov² ovladaΦ kalendß°e hotov.

  9. Pokuste se u prßv∞ vytvo°enΘ komponenty zadat bitovou mapu zobrazenou na palet∞ a vytvo°it nßpov∞du, kterou zapojφte do nßpov∞dnΘho systΘmu C++ Builderu.
8. Ud∞lßnφ komponenty dostupnΘ p°i nßvrhu