10. Knihovna vizußlnφch komponent
  1. V roce 1995 Borland uvedl na trh nov² produkt nazvan² Delphi. Delphi umo╛≥uje rychl² v²voj aplikacφ pomocφ n∞Φeho, co se naz²vß komponenta. Komponenty jsou objekty, kterΘ mohou b²t vlo╛eny na formulß° a pracujeme s nimi pomocφ vlastnostφ, metod a udßlostφ. Je to vizußlnφ programovßnφ.

  2. Delphi je zalo╛eno na jazyku Object Pascal a je v n∞m pou╛ita VCL (Visual Component Library). VCL je pracovnφ rßmec aplikace pro programovßnφ ve Windows zapsan² v Object Pascalu. VCL nenφ kompatibilnφ s OWL nebo MFC. Je to pracovnφ rßmec, jeho╛ jßdro se velmi li╣φ. VCL je zalo╛eno na koncepci vlastnostφ, metod a udßlostφ.
    ProΦ se zde ale zab²vßme Delphi a jazykem Object Pascal? D∙vod je jednoduch². VCL kterΘ je jßdrem Delphi je takΘ jßdrem C++ Builderu. I kdy╛ komponenty VCL jsou zabaleny ve t°φdßch Object Pascalu je mo╛no je bez problΘm∙ pou╛φvat v C++ Builderu.
    Ve°ejnΘ rozhranφ komponent (Φßst komponent, kterou vidφ u╛ivatel) tvo°φ vlastnosti, metody a udßlosti. Vlastnosti jsou prvky komponent, kterΘ °φdφ prßci komponenty. Mnoho komponent mß spoleΦnΘ vlastnosti. V╣echny viditelnΘ komponenty nap°. majφ vlastnosti Top a Left. Tyto dv∞ vlastnosti urΦujφ pozici komponenty na formulß°i a to jak b∞hem nßvrhu, tak i za b∞hu aplikace. V╣echny komponenty majφ vlastnost Owner, kterou VCL pou╛φvß k ulo╛enφ ukazatele na nad°φzenou komponentu (nebo formulß°), tj. vlastnost urΦuje vlastnφka komponenty. Vlastnosti vybranΘ komponenty jsou zobrazovßny v Inspektoru objekt∙ a m∙╛eme zde takΘ m∞nit jejich hodnoty.
    Pokud nap°. zm∞nφme hodnotu vlastnosti Left samotnΘho formulß°e, pak formulß° se na obrazovce p°emφstφ podle zadanΘ hodnoty tΘto vlastnosti. To ukazuje d∙le╛it² aspekt vlastnostφ; je to vφce ne╛ jednoduchß datovß slo╛ka t°φdy. Ka╛dß vlastnost mß p°i°azenou datovou slo╛ku, ale samotnß vlastnost nenφ touto datovou slo╛kou. Zm∞na vlastnosti Φasto zp∙sobφ provedenφ n∞jakΘho k≤du, kterΘmu °φkßme p°φstupovß metoda.
    Vlastnosti mohou b²t urΦeny b∞hem nßvrhu (kdy╛ navrhujeme nß╣ formulß°) nebo za b∞hu aplikace (pomocφ k≤du b∞╛φcφho programu). V obou p°φpadech, pokud vlastnost mß p°φstupovou metodu, pak tato p°φstupovß metoda je volßna a provedena, kdy╛ vlastnost je modifikovßna. Zm∞nφme-li vlastnost Left formulß°e, pak p°φstupovß metoda zp∙sobφ p°esun formulß°e na obrazovce.
    C++ Builder nßm tedy umo╛nφ, abychom na obrazovce vid∞li v²sledek na╣φ zm∞ny. Ne v╣echny vlatnosti zobrazujφ provedenΘ zm∞ny na formulß°i b∞hem nßvrhu (n∞kdy to nenφ mo╛nΘ).
    Ke zm∞n∞ vlastnosti za b∞hu aplikace jednodu╣e vlastnosti p°i°adφme hodnotu. Kdy╛ provedeme p°i°azenφ, pak VCL volß p°φstupovou metodu pro tuto vlastnost. Ke zm∞n∞ vlastnosti Left za b∞hu pou╛ijeme nap°. p°φkaz
    Form1->Left = 200;
    V p°φpad∞ vlastnosti Left (a takΘ vlastnosti Top), VCL p°esouvß a p°ekresluje formulß° (je provedeno volßnφm funkcφ API Windows SetWindowPos a InvalidateRect). Pov╣imn∞te si, ╛e v p°edchozφm p°φkazu je pou╛it k nastavenφ vlastnosti operßtor nep°φmΘho selektoru (->). V╣echny komponenty VCL jsou alokovßny v hromad∞. Pro p°φstup k vlastnostem a metodßm komponent je v╛dy pou╛φvßn nep°φm² selektor. T°φdy, kterΘ vytvo°φme pro pou╛itφ v aplikaci C++ Builderu m∙╛eme alokovat v zßsobnφku nebo v hromad∞, ale v╣echny t°φdy VCL komponent a v╣echny t°φdy od nich odvozenΘ, musφ b²t alokovßny pouze v hromad∞.
    Vlastnosti majφ dva p°φstupovΘ specifikßtory, kterΘ jsou pou╛ity, kdy╛ vlastnost je Φtena nebo modifikovßna. Je to Φtecφ specifikßtor a zßpisov² specifikßtor. Je mo╛no °φci, ╛e p°φstupovΘ specifikßtory p°i°adφ Φtecφ a zßpisovΘ metody k vlastnosti. Kdy╛ vlastnost je Φtena nebo zapisovßna, pak metody p°i°azenΘ k vlastnosti jsou volßny automaticky. Kdy╛ provedeme p°i°azenφ (jako v p°edchozφm p°φkazu), pak je zp°φstupn∞n zßpisov² specifikßtor. To zp∙sobφ, ╛e VCL testuje, zda pro zßpisov² specifikßtor existuje p°φstupovß metoda. Pokud ano, pak je p°φstupovß metoda volßna. Pokud neexistuje, pak VCL p°i°adφ novou hodnotu datovΘ slo╛ce p°i°azenΘ k vlastnosti.
    Kdy╛ se odkazujeme na vlastnost (pou╛ijeme vlastnost na pravΘ stran∞ p°i°azovacφho p°φkazu), pak je zp°φstupn∞n Φtecφ specifikßtor:
    int x = Form1->Left;
    V tomto p°φpad∞ VCL volß Φtecφ specifikßtor pro p°eΦtenφ hodnoty vlastnosti Left. V∞t╣inou Φtecφ specifikßtor ned∞lß nic jinΘho ne╛ to, ╛e vracφ souΦasnou hodnotu vlastnosti.
  3. Vlastnosti vlastnostφ (promi≥te toto spojenφ) jsou urΦeny tv∙rcem komponenty. N∞kterΘ vlastnosti mohou b²t urΦeny pouze pro Φtenφ. Tyto vlastnosti m∙╛eme Φφst (zφskat jejich hodnotu), ale nelze jejich hodnotu modifikovat. Mohou b²t takΘ vlastnosti urΦenΘ pouze pro zßpis (nenφ mo╛no Φφst jejich hodnotu). N∞kterΘ vlastnosti mohou b²t specifikovßny pouze za b∞hu aplikace. Tyto vlastnosti nelze pou╛φvat p°i nßvrhu a nejsou tedy zobrazovßny v Inspektoru objekt∙. Vlastnosti obvykle majφ implicitnφ hodnoty (poΦßteΦnφ hodnotu zobrazenou v Inspektoru objekt∙).

  4. N∞kterΘ vlastnosti pou╛φvajφ jako p°ipojenou datovou slo╛ku pole. Je to nap°. vlastnost Lines komponenty Memo (pole textov²ch °et∞zc∙). Kdy╛ vybereme tuto vlastnost v Inspektoru objekt∙, pak na pravΘm okraji hodnoty vlastnosti vidφme malΘ tlaΦφtko se t°emi teΦkami. Toto tlaΦφtko nßm °φkß, ╛e vlastnost m∙╛e b²t editovßna pomocφ Editoru vlastnostφ. Nap°. pro pole °et∞zc∙ je zobrazeno dialogovΘ okno, ve kterΘm m∙╛eme editovat °et∞zce. V p°φpad∞ vlastnosti Font je p°i stisku tohoto tlaΦφtka zobrazeno dialogovΘ okno volby pφsma. Typ editoru vlastnosti zßvistφ na typu vlastnosti a editor zobrazφme stiskem tlaΦφtka se t°emi teΦkami nebo dvojit²m kliknutφm na hodnot∞ vlastnosti.
    Vlastnosti mohou b²t instance dal╣φch t°φd VCL. P°φkladem je vlastnost Font. Tato vlastnost obsahuje informace jako typ pφsma, barvu a velikost pφsma, atd. Pokud najdeme vlastnost Font v Inspektoru objekt∙, pak vidφme p°ed slovem Font znak plus. Tφm jsme informovßni o tom, ╛e vlastnost se sklßdß z podvlastnostφ. Dvojit²m kliknutφm na jmΘnu vlastnosti s podvlastnostmi jsou v Inspektoru objekt∙ tyto podvlastnosti zobrazeny a m∙╛eme s nimi pracovat samostatn∞.
    N∞kterΘ vlastnosti jsou mno╛iny. Mno╛ina je kolekce mo╛n²ch hodnot pro vlastnost. Vlastnost Style v objektu Font je p°φkladem mno╛iny. Pov╣imn∞te si, ╛e u vlastnosti Style v Inspektoru objekt∙ je uveden znak +. Pokud tuto vlastnost rozbalφme (dvojit∞ na nφ klikneme), pak se zobrazφ mo╛nΘ prvky mno╛iny. V na╣em p°φpad∞ se jednß o styly pφsma: bold, italic, underline a strikeout. Mno╛ina m∙╛e b²t prßzdnß nebo m∙╛e obsahovat jednu nebo vφce mo╛n²ch hodnot. Dal╣φm dvojit²m kliknutφm na stylu jej op∞t sbalφme.
    V²Φet je seznam mo╛n²ch voleb pro vlastnost. Kdy╛ je vybrßna vlastnost s v²Φtem, pak na pravΘ stran∞ jejφ hodnoty je zobrazeno tlaΦφtko rozbalovacφho seznamu (stiskem tlaΦφtka se seznam mo╛n²ch voleb rozbalφ a m∙╛eme z n∞j vybφrat). Dvojit²m kliknutφm na hodnot∞ takovΘto vlastnosti cyklicky prochßzφme seznamem voleb.
    Mno╛ina od v²Φtu se li╣φ tφm, ╛e u v²Φtu musφ b²t zvolena prßv∞ jedna z mo╛n²ch hodnot, zatφmco u mno╛iny jich m∙╛e b²t libovoln² poΦet.
  5. Metody v komponentßch VCL jsou funkce, kterΘ mohou b²t volßny k provedenφ jistΘ akce. Nap°. v╣echny vizußlnφ komponenty majφ metodu Show, kterß komponentu zobrazφ a metodu Hide, kterß komponentu skryje. Nap°.

  6. MojeOkno->Show();
    // a pozd∞ji
    MojeOkno->Hide();
    Tyto funkce jsou normßlnφ metody t°φdy komponenty. Metody VCL mohou b²t stejn∞ jako v C++ ve°ejnΘ, soukromΘ nebo chrßn∞nΘ.
    Stejn∞ jako funkce v C++, n∞kterΘ metody p°ebφrajφ parametry a vracejφ hodnoty. Zßvisφ to na tom, jak metoda byla tv∙rcem komponenty zapsßna. Nap°. metoda GetTextBuf zφskßvß text z komponenty TEdit. M∙╛e b²t pou╛ita takto:
    char buff[256];
    int pocetZnaku = Edit1->GetTextBuf(buff, sizeof(buff));
    Jak vidφme, tato metoda p°ebφrß dva parametry a vracφ celoΦφselnou hodnotu. Kdy╛ tuto metodu vyvolßme, pak obsah editaΦnφ komponenty je umφst∞n do buff a vrßcenß hodnota je poΦet znak∙ zφskan²ch z editaΦnφ komponenty.
  7. Windows je prost°edφ °φzenΘ udßlostmi. Udßlostmi °φzenΘ znamenß, ╛e program je °φzen udßlostmi, kterΘ se vyskytnou v prost°edφ Windows. Udßlosti zahrnujφ p°esun my╣i, kliknutφ my╣φ a stisk klßvesy na klßvesnici.

  8. Programßto°i p°echßzejφcφ z prost°edφ DOSu nebo sßlov²ch poΦφtaΦ∙ mohou mφt r∙znΘ problΘmy s koncepcφ udßlostmi °φzenΘho programovßnφ. Programy pracujφcφ pod Windows stßle zφskßvajφ od Windows udßlosti. Udßlosti ve Windows zahrnujφ aktivovßnφ nabφdky, stisknutφ tlaΦφtka, p°esun okna, po╛adavek na p°ekreslenφ okna, apod. Windows oznamuje udßlost programu zasφlßnφm zprßv. V souΦasnosti je asi 175 mo╛n²ch zprßv, kterΘ Windows m∙╛e zaslat aplikaci, ale jen n∞kterΘ z nich se vyskytujφ Φast∞ji.
    Ka╛dß komponenta je urΦena k reagovßnφ na jistΘ udßlosti. Obvykle to jsou udßlosti Windows, ale mohou b²t i z jinΘho zdroje. Nap°. komponenta tlaΦφtka je urΦena k reagovßnφ na kliknutφ my╣φ. DatabßzovΘ komponenty mohou reagovat na udßlosti, kterΘ nepochßzejφ od Windows.
    Kdy╛ komponenta reaguje na udßlost °φkßme, ╛e obsluhuje udßlost. Udßlosti jsou obslou╛eny pomocφ funkcφ nazvan²ch obsluhy udßlostφ. JmΘna obsluh udßlostφ pro komponentu jsou uvedeny na strßnce Events Inspektora objekt∙. JmΘno udßlosti popisuje udßlost, na kterou majφ reagovat. Nap°. udßlosti kliknutφ my╣φ se naz²vß OnClick.
  9. Po del╣φ dob∞ se op∞t vrßtφme k aplikacφm GUI. ZaΦneme v²voj novΘ aplikace. U formulß°e zm∞nφme vlastnost Name na VMU (vlastnosti, metody a udßlosti) a Caption na Testovacφ program VMU. Dßle p°idßme na formulß° komponentu Memo (zv∞t╣φme ji na v∞t╣inu plochy formulß°e; p°i spodnφm okraji nechßme mφsto pro tlaΦφtko). U tΘto komponenty zm∞nφme vlastnost Name na Memo a vlastnost Lines na text Testovacφ program pou╛φvajφcφ vlastnosti, metody a udßlosti. Do spodnφ Φßsti formulß°e vlo╛φme je╣t∞ tlaΦφtko. Zm∞nφme jeho vlastnost Name na Tlacitko, vlastnost Caption na Zobraz/Ukryj a vodorovn∞ jej na formulß°i vycentrujeme (pomocφ palety zarovnßvßnφ; zobrazφme volbou View | Alignment Palette a zvolφme Center horizontally; centrovan² objekt musφ b²t vybrßn).

  10. Dßle vytvo°φme obsluhu stisku tlaΦφtka. Je tvo°ena touto funkcφ:
    void __fastcall TVMU::TlacitkoClick(TObject *Sender)
    {
      static bool jeViditelny;
      jeViditelny = !jeViditelny;
      if (jeViditelny) Memo->Hide();
      else Memo->Show();
    }
    Vidφme, ╛e se jednß o metodu t°φdy TVMU (jmΘno na╣eho formulß°e). Modifikßtor __fastcall zde urΦuje zp∙sob p°edßvßnφ parametr∙ p°i volßnφ funkce. K≤d obsluhy nastavuje hodnotu statickΘ prom∞nnΘ jeViditelny. Statickß prom∞nnß je takovß prom∞nnß, kterß neztrßcφ svoji hodnotu mezi funkΦnφmi volßnφmi (je to n∞co jako globßlnφ prom∞nnß). StatickΘ prom∞nnΘ jsou inicializovßny nulou. V na╣em p°φpad∞ se jednß o prom∞nnou typu bool a je tedy inicializovßna hodnotou false. V╛dy p°i volßnφ tΘto funkce prom∞nnß jeViditelny obsahuje opaΦnou hodnotu ne╛ byla p°i p°edchozφm volßnφ. Program nynφ m∙╛eme vyzkou╣et.
  11. Kdy╛ se podφvßme na na╣i statickou prom∞nnou, pak zjistφme, ╛e pouze urΦuje, zda komponenta Memo je viditelnß. Stejnou informaci obsahuje takΘ vlastnost Visible komponenty Memo. Statickß prom∞nnß je tedy zbyteΦnß a obsluhu stisku tlaΦφtka lze zm∞nit takto:

  12. void __fastcall TVMU::TlacitkoClick(TObject *Sender)
    {
      if (Memo->Visible) Memo->Hide();
      else Memo->Show();
    }
    Po provedenφ tΘto zm∞ny se funkce programu nezm∞nφ.
  13. Na╣e obsluha udßlosti p°ebφrß ukazatel na TObject nazvan² Sender. Ka╛dß obsluha udßlosti mß alespo≥ tento parametr. N∞kterΘ obsluhy udßlostφ majφ vφce parametr∙. Podφvejme se nap°. na obsluhu stisku tlaΦφtka my╣i:

  14. void __fastcall TVMU::TlacitkoMouseDown(TObject *Sender,
         TMouseButton Button, TShiftState Shift, int X, int Y)
    {
    }
    Zde jsou parametry, kterΘ nßs informujφ o tom, kterΘ tlaΦφtko my╣i bylo stisknuto, kterΘ klßvesy byly stisknuty a sou°adnice mφsta stisknutφ. Jsou to tedy informace, kterΘ m∙╛eme pot°ebovat v obsluze udßlosti.
    Co to je ale Sender? Sender je ukazatel na komponentu, od kterΘ udßlost pochßzφ. V na╣em programu parametr Sender je nepodstatn², proto╛e ji╛ p°edem vφme, ╛e udßlost bude pochßzet od na╣eho tlaΦφtka Zobraz/Ukryj. Parametr Sender ale umo╛≥uje, aby vφce komponent pou╛φvalo jednu obsluhu udßlosti.
    Ukß╛eme si to na na╣em programu. TlaΦφtko ji╛ umφst∞nΘ na formulß°i p°ejmenujeme na Zobraz a p°idßme dal╣φ tlaΦφtko Ukryj. Budeme postupovat takto: Pokud vrchnφm oknem je Editor k≤du, pak stiskem tlaΦφtka F12 jej p°esuneme za nßvrhv² formulß°. Vybereme ji╛ existujφcφ tlaΦφtko a zm∞nφme u n∞j vlastnosti Name a Caption na Zobraz. Napravo od tohoto tlaΦφtka p°idßme novΘ tlaΦφtko a zm∞nφme jeho Name a Caption na Ukryj.
    Kdy╛ nynφ vybereme tlaΦφtko Zobraz a v Inspektoru objekt∙ p°ejdeme na strßnku Udßlostφ, pak uvidφme, ╛e obsluha udßlosti OnClick se nynφ jmenuje ZobrazClick (p°ejmenovali jsme tlaΦφtko). Vrßtφme se k p∙vodnφmu nßzvu, tj. zapφ╣eme zde TlacitkoClick. Vybereme dßle tlaΦφtko Ukryj, v Inspektoru objekt∙ nalezneme udßlost OnClick a v rozbalovacφm seznamu tΘto udßlosti vybereme TlacitkoClick (v seznamu je uvedena pouze tato obsluha udßlosti). Na hodnot∞ TlacitkoClick v Inspektoru objekt∙ dvojit∞ klikneme, Φφm╛ p°ejdeme do Editoru k≤du na tuto obsluhu. K≤d obsluhy modifikujeme takto:
    void __fastcall TVMU::TlacitkoClick(TObject *Sender)
    {
      if (Sender == Ukryj) Memo->Hide();
      else Memo->Show();
    }
    Program je hotov, m∙╛eme jej vyzkou╣et. Mßme zde jednu obsluhu udßlosti, kterß obsluhuje udßlost OnClick obou tlaΦφtek. Parametr Sender urΦuje, kterΘ tlaΦφtko bylo stisknuto. Mohli bychom sice mφt pro ka╛dΘ tlaΦφtko jinou obsluhu udßlosti, ale nenφ to nutnΘ.
    V tomto p°φkladu jsme si ukßzali, ╛e po vytvo°enφ obsluhy udßlosti pro jednu komponentu, m∙╛eme p°ipojit tuto obsluhu pro udßlost stejnΘho typu jinΘ komponenty. M∙╛eme tedy pou╛φt stejnou obsluhu pro vφce komponent.
  15. Nßsleduje n∞kolik rad pro pou╛φvßnφ udßlostφ: Na ka╛dou udßlost komponenty m∙╛eme reagovat podle pot°eby. Nenφ nutno reagovat na v╣echny udßlosti definovanΘ v komponent∞. Udßlosti jsou obslou╛eny funkcemi nazvan²mi obsluhy udßlostφ. Pro obsluhy udßlostφ C++ Builder generuje implicitnφ jmΘno, kterΘ m∙╛e b²t programßtorem zm∞n∞no. JmΘna obsluh udßlostφ m∞nφme pouze v Inspektoru objekt∙. Parametr Sender obsluhy udßlosti m∙╛e b²t pou╛it k zji╣t∞nφ, kterß komponenta udßlost generovala. Dvojit²m kliknutφm na jmΘnu obsluhy udßlosti v Inspektoru objekt∙ p°ejdeme do Editoru k≤du na tuto obsluhu. Ka╛dß obsluha udßlosti obsahuje parametry pot°ebnΘ k zpracovßnφ udßlosti.
  16. VCL je knihovna zapsanß v Object Pascalu. Je zapsßna v Object Pascalu, proto╛e byla p∙vodn∞ urΦena pro Delphi. Nynφ se pou╛φvß i v C++ Builderu. C++ Builder je p°ekladaΦ C++ a v Φem je vytvo°eno VCL nenφ podstatnΘ. Podφvejte se na nßsledujφcφ k≤d:

  17. int sirkaObrazovky = GetSystemMetrics(SM_CXSCREEN);
    int vyskaObrazovky = GetSystemMetrics(SM_CYSCREEN);
    int v = MainForm->Height;
    int s = MainForm->Width;
    MainForm->Top = (vyskaObrazovky / 2) - (v / 2);
    MainForm->Left = (sirkaObrazovky / 2) - (s / 2);
    TPoint souradniceKurzoru;
    GetCursorPos(&souradniceKurzoru);
    v -= 150;
    s -= 150;
    MainForm->Height = v;
    MainForm->Width = s;
    for (int i = 0; i < 150; i +=3) {
      MainForm->Height = v + i;
      MainForm->Width = s + i;
      SetCursorPos(MainForm->Left + MainForm->Width,
                   MainForm->Top + MainForm->Height);
    }
    SetCursorPos(souradniceKurzoru.x, souradniceKurzoru.y);
    M∙╛eme jej nap°. pou╛φvat jako obsluhu stisku tlaΦφtka. Polo╛me si otßzku co v tomto k≤du je Object Pascal a co C++. V╣e je C++. VCL i C++ mohou pracovat souΦasn∞, co╛ umo╛≥uje rychl² v²voj aplikacφ pomocφ C++. VCL dßvß rychl² v²voj pomocφ komponent a zbytek m∙╛e b²t zapsßn v C++. Je pot°eba pouze dodr╛ovat n∞kterß pravidla.
  18. Kdy╛ vlo╛φme komponentu na formulß° C++ Builder automaticky zapisuje k≤d, kter² dynamicky vytvß°φ komponentu (a nemusφme ani v∞d∞t jak). Musφme to ale znßt, kdy╛ chceme vytvo°it a pou╛φvat t°φdu VCL za b∞hu programu. Nap°. m∙╛eme pot°ebovat zobrazit dialogovΘ okno otev°enφ souboru a nemßme komponentu TOpenDialog vlo╛enou na formulß°. Nenφ to ╛ßdn² problΘm, m∙╛eme objekt vytvo°it sami. Provedeme to takto:

  19. TOpenDialog *dlg = new TOpenDialog(this);
    dlg->Title = "Otev°enφ novΘho souboru";
    dlg->Execute();
    Objekt musφ b²t vytvo°en pomocφ operßtoru new. V╣echny pokusy o lokßlnφ alokaci jsou odmφtnuty. V∞t╣inu komponent VCL m∙╛eme vytvß°et za b∞hu, stejn∞ jako v pr∙b∞hu nßvrhu. Je snadn∞j╣φ vytvß°et komponenty p°i nßvrhu, nebo╗ k nastavovßnφ vlastnostφ lze pou╛φt Inspektor objekt∙ (nenφ nutno je nastavovat prost°ednictvφm k≤du). Podφvejme se ale na nßsledujφcφ k≤d:
    TRect obdelnik;
    obdelnik.top = 0;
    obdelnik.left = 0;
    obdelnik.right = 100;
    obdelnik.bottom = 100;
    Zde nenφ dodr╛en po╛adavek na dynamickou alokaci. To je mo╛no proto, ╛e TRect nenφ t°φda, TRect je struktura, kterß zaobaluje strukturu RECT Windows. Jinak °eΦeno TRect VCL je jinΘ jmΘno pro strukturu RECT Windows. Stejn∞ to platφ i pro TPoint, TSize, TLogFont, TDrawItemStruct a dal╣φ struktury Windows, kterΘ jsou dostupnΘ pro pou╛itφ ve VCL.
  20. VCL neumo╛≥uje pou╛itφ implicitnφch parametr∙ funkcφ. Ukß╛eme si to na funkci MessageBox Windows API. Tato funkce p°ebφrß Φty°i parametry: madlo okna zobrazujφcφho okno zprßv, text zprßvy, titulek okna a parametr Flags urΦujφcφ tlaΦφtka a ikony zobrazenΘ v okn∞ zprßv. V MFC nebo OWL lze pou╛φt tuto funkci pouze se specifikacφ zobrazenΘho textu:

  21. MessageBox("Toto je zprßva");
    Toto je mo╛nΘ v OWL nebo MFC (lze zde vyu╛φt implicitnφ hodnoty parametr∙) ale ne ve VCL. Ve VCL je nutno pou╛φt:
    Application->MessageBox("Toto je zprßva", "Zprßva", MB_OK);
    Zde je nutno specifikovat v╣echny parametry. Pov╣imn∞te si, ╛e ve v╣ech t°ech p°φpadech (OWL, MFC i VCL) je pracovnφm rßmcem automaticky vytvo°en parametr madla okna.
  22. T°φdy VCL nepodporujφ vφcenßsobnou d∞diΦnost. Tzn. nelze vytvo°it novou komponentu odvozenφm od dvou existujφcφch komponent. Nenφ to velkΘ omezenφ, nebo╗ vφcenßsobnß d∞diΦnost je pou╛φvßna velmi z°φdka a nelze ji pou╛φvat pouze ve spojitosti s VCL. Ve t°φdßch, kterΘ nejsou obvozeny od VCL ji v C++ Builderu m∙╛eme i nadßle pou╛φvat bez omezenφ.
  23. Je nutno se takΘ seznßmit s t°φdami °et∞zc∙ znak∙ VCL. V konzolov²ch aplikacφch jsme pou╛φvali °et∞zce jako pole znak∙. Nynφ ji╛ vφme, ╛e jazyk C++ umo╛≥uje vytvo°it t°φdu k provßd∞nφ po╛adovan²ch ·loh. Je ale dobrß a ╣patnß zprßva. Dobrou zprßvou je, ╛e existuje t°φda usnad≥ujφcφ prßci s °et∞zci. ⌐patnß zprßva je, ╛e takov²chto t°φd je n∞kolik. Nejprve se podφvejme na C zp∙sob:

  24. char buff[30];
    strcpy(buff, "Ahoj!");
    if (!strcmp(buff, "Ahoj!"))
      strcat(buff, " Co je novΘho?");
    Toto p°i pou╛φvßnφ t°φd °et∞zc∙ je mo╛no zapsat takto:
    String S = "Ahoj!";            // p°φmΘ p°i°azenφ
    if (S == "Ahoj!")              // test na rovnost
      S = S + " Co je novΘho?";    // z°et∞zenφ °et∞zc∙
    Pokud porovnßme tyto dva k≤dy, pak m∙╛eme °φci, ╛e druh² je mnohem srozumiteln∞j╣φ. Vidφme, ╛e m∙╛eme provßd∞t p°i°azenφ °et∞zce pomocφ operßtoru =, rovnost testujeme operßtorem == a k p°idßnφ °et∞zce na konec jinΘho °et∞zce pou╛φvßme operßtor +.
    T°φdy °et∞zc∙ takΘ majφ metody. Tyto metody umo╛≥ujφ zjistit dΘlku °et∞zce, hledat v °et∞zci pod°et∞zce, zru╣it Φßst °et∞zce, p°evßd∞t °et∞zce na velkß pφsmena a mnoho dal╣φch.
    Jak je uvedeno v²╣e, mßme mo╛nost volit z vφce t°φd °et∞zc∙. Jednou z t∞chto t°φd °et∞zc∙, kterß je Φßstφ knihovny t°φd C++ je t°φda string. Druhou nalezneme v STL (knihovna standardnφch ╣ablon). Jednß se o t°φdu basic_string. Ob∞ jsou dobr²mi t°φdami °et∞zc∙, ale nejsou urΦeny pro prßci s VCL. VCL nabφzφ dal╣φ dv∞ t°φdy °et∞zc∙.
  25. T°φda SmallString emuluje datov² typ krßtkΘho °et∞zce Pascalu (Pascal mß dva datovΘ typy °et∞zc∙: krßtkΘ a dlouhΘ °et∞zce). T°φda SmallString je implementovßna jako ╣ablona. Tato t°φda je poskytnuta z d∙vodu kompatibility s Pascalem a nepou╛φvßme ji p°i zßpisu novΘho k≤du v C++ Builderu. P°i pou╛φvßnφ tΘto t°φdy pou╛φvßme syntaxi:

  26. SmallString<30> s;
    s = "Nazdar";
    Jedin²m d∙vodem pro pou╛φvßnφ tΘto t°φdy v aplikcφch C++ Builderu je to, ╛e ji vy╛adujφ n∞kterΘ komponenty.
  27. Zßkladnφm datov²m typem °et∞zc∙ ve VCL je Pascalovsk² dlouh² °et∞zec. Je to datov² typ v╣ech textov²ch vlastnostφ komponent. Nap°. vlastnosti Text, Name a Caption jsou v╣echno dlouhΘ °et∞zce Pascalu. VCL takΘ pou╛φvß tento typ v mnoha metodßch a obsluhßch udßlostφ komponent.

  28. V Pascalu je dlouh² °et∞zec datov²m typem jazyka a ne pole znak∙ jako v C nebo C++. V C++ neexistuje jeho zabudovan² ekvivalent. Proto╛e dlouhΘ °et∞zce jsou pou╛φvßny hlavn∞ ve VCL a proto╛e C++ Builder pou╛φvß PascalovskΘ VCL, je vytvo°ena t°φda, kterß odpovφdß tomuto typu Pascalu. Tato t°φda se jmenuje AnsiString a m∙╛e b²t pou╛ita v╛dy, kdy╛ je vy╛adovßn Pascalovsk² dlouh² °et∞zec.
    N∞kde v hlaviΦkovΘm souboru SYSDEFS.H nalezneme nßsledujφcφ °ßdek:
    typedef AnsiString String;
    To umo╛≥uje pou╛itφ jmΘna String (s velk²m S) p°i deklaraci instance t°φdy AnsiString namφsto pou╛itφ oficißlnφho jmΘna t°φdy AnsiString.
    String s = "Toto je test";
    Proto╛e String je doporuΦovanß p°ezdφvka pro t°φdu AnsiString, nenφ d∙vod k pou╛φvßnφ jmΘna AnsiString v na╣ich programech C++ Builderu (i kdy╛ jej samoz°ejm∞ m∙╛eme pou╛φvat).
    AnsiString je t°φda °et∞zc∙ s velk²mi mo╛nostmi. Konstruktory tΘto t°φdy umo╛≥ujφ vytvo°it objekt AnsiString z char, char *, int a double. Tyto konstruktory usnad≥ujφ p°i°azenφ °et∞zcovΘ konstanty AnsiString a p°evod celΘho nebo reßlnΘho Φφsla na °et∞zec. V╣echny nßsledujφcφ p°φklady pou╛φvajφ konstruktory AnsiString (n∞kterΘ explicitn∞ a jinΘ implicitn∞):
    String FloatString = 123.45;
    String JinyFloatString(0.999);
    String IntString = 49;
    String CharString = 'A';
    Label1->Caption = "Toto je test";
    double d = 3.14 * 20;
    Edit1->Text = d;
    V p°φpad∞ p°φmΘho p°i°azenφ, p°ekladaΦ C++ aplikuje p°φslu╣n² konstruktor. Pro prvnφ p°φkaz je tedy provedeno n∞co jako:
    String FloatString = String((double)123.45);
    Jin²m d∙vodem, ╛e p°edchozφ k≤d pracuje je to, ╛e t°φda AnsiString mß p°etφ╛en operßtor p°i°azenφ (=). Dal╣φ p°etφ╛enΘ operßtory, kterΘ zjednodu╣╣ujφ prßci jsou operßtor z°et∞zenφ (+) a operßtor rovnosti (==).
    T°φda AnsiString mß mnoho metod, kterΘ usnad≥ujφ manipulaci s °et∞zci. V nßsledujφcφ tabulce jsou uvedeny Φasto pou╛φvanΘ metody. Nenφ to ·pln² seznam metod (popis v╣ech metod nalezneme v nßpov∞d∞).
     
    Metoda Popis
    c_str Vracφ ukazatel (char *) na text °et∞zce.
    Delete Ru╣φ Φßst °et∞zce.
    Insert Vklßdß text do specifikovanΘho °et∞zce na specifikovanou pozici.
    Length Vracφ dΘlku °et∞zce (bez ukonΦujφcφho NULL).
    LowerCase P°evßdφ °et∞zec na malß pφsmena.
    Pos Vracφ pozici hledanΘho °et∞zce v °et∞zci.
    SubString Vracφ pod°et∞zec z °et∞zce, zaΦφnajφcφ na danΘ pozici a danΘ dΘlky.
    ToDouble P°evßdφ °et∞zec na Φφslo v pohyblivΘ °ßdovΘ Φßrce. Pokud °et∞zec nem∙╛e b²t p°eveden, je generovßna v²jimka.
    ToInt P°evßdφ °et∞zec na celΘ Φφslo. Pokud °et∞zec nem∙╛e b²t p°eveden, je generovßna v²jimka.
    ToIntDef P°evßdφ °et∞zec na celΘ Φφslo a urΦuje implicitnφ hodnotu pro p°φpad, kdy °et∞zec nem∙╛e b²t p°eveden.
    Trim Odstra≥uje ·vodnφ a koncovΘ mezery z °et∞zce.
    UpperCase P°evßdφ °et∞zec na velkß pφsmena.
    N∞kterΘ z t∞chto metod pot°ebujφ vysv∞tlenφ. Jednou z nich je metoda c_str. Tato podivn∞ nazvanß metoda je pot°ebnß, kdy╛ po╛adujeme zφskat ukazatel na znakovou oblast AnsiString (ukazatel na pole znak∙). To vy╛adujφ n∞kterΘ funkce API. Nap°. funkci API DrawText pou╛φvßme takto:
    RECT R(0, 0, 100, 20);
    // nejprve zp∙sob C
    char buff[] = "Toto je test";
    DrawText(Canvas->Handle, buff, -1, &R, DT_SINGLELINE);
    // nynφ zp∙sob VCL
    String s = "Toto je test";
    DrawText(Canvas->Handle, s.c_str(), -1, &R, DT_SINGLELINE);
    Druh² parametr funkce DrawText vy╛aduje ukazatel na °et∞zec zobrazovan²ch znak∙ a zφskßme jej metodou c_str.
    Dßle se zastavφme u metody ToInt. Tato metoda p°evßdφ textov² °et∞zec na celoΦφselnou hodnotu. Nap°. na formulß°i mßme editaΦnφ komponentu, kterou budeme pou╛φvat k zφskßnφ celoΦφselnΘ hodnoty od u╛ivatele. Proto╛e editaΦnφ komponenta dr╛φ pouze text, musφme jej p°evΘst na celΘ Φφslo. To provedeme takto:
    int hodnota = Edit1->Text.ToInt();
    Podobn∞ pracuje metoda ToDouble. Pokud p°evod nem∙╛e b²t proveden, pak ob∞ metody generujφ v²jimku. Nap°. kdy╛ u╛ivatel zadß S123, pak je generovßna v²jimka, proto╛e S nelze p°evΘst na celΘ Φφslo.
    N∞kterΘ metody nepracujφ na °et∞zci samotnΘm, ale vracejφ nov² °et∞zec. Je to nap°. metoda UpperCase. Pokud pou╛ijeme nßsledujφcφ k≤d, pak zjistφme, ╛e se nic nestane:
    String JmenoSouboru = "c:\\prac\\mojedata.dat";
    JmenoSouboru.UpperCase();
    SprßvnΘ pou╛itφ je:
    JmenoSouboru = JmenoSouboru.UpperCase();
    Je╣t∞ se zmφnφme o metod∞ Format, kterß umo╛≥uje vytvß°et °et∞zce z prom∞nn²ch a to stejn∞ jako to umo╛≥uje funkce sprintf. P°i na╣em seznamovßnφ s touto funkcφ jsme uvedli p°φkazy:
    char buff[20];
    int x = 10 * 20;
    sprintf(buff, "V²sledek je: %d", x);
    Stejn² v²sledek dosßhneme i p°i pou╛itφ metody Format:
    String S;
    int x = 10 * 20;
    S = Format("V²sledek je: %d", OPENARRAY(TVarRec, (x)));
    Je n∞kolik d∙vod∙, aby metoda byla zapsßna tφmto zp∙sobem, ale nebudeme se jimi nynφ zab²vat. M∙╛eme °φci, ╛e metodu Format nebudeme pou╛φvat a to proto, ╛e si nebudeme pamatovat jak ji pou╛φt. Jejφ pou╛itφ lze takΘ snadno obejφt. Nap°.
    int x = 10 * 20;
    char buff[20];
    sprintf(buff, "V²sledek je: %d", x);
    String S = buff;
    U t°φdy AnsiString se lze takΘ odkazovat na jednotlivΘ znaky °et∞zce. Pou╛φvßme k tomu operßtor indexace ([]). Nap°.
    String S = "Ahoj";
    Label1->Caption = S[2];
    Tento k≤d p°i°adφ vlastnosti Caption komponenty Label1 znak h (znaky °et∞zce jsou indexovßny od 1; tj. prvnφ znak °et∞zce mß index 1). To je vy╛adovßno pro kompatibilitu s Delphi. M∙╛e to b²t zdrojem n∞kter²ch chyb. Nap°. nßsledujφcφ k≤d programu je chybn².
    String S = "c:\\prac\\mujprogram.exe";
    int index = S.LastDelimiter("\\");
    S.Delete(0, index);
    Tento k≤d je chybn² nebo╗ 0 nenφ p°φpustn²m indexem. Sprßvn² zßpis poslednφho °ßdku je:
    S.Delete(1, index);
  29. Vytvo°φme nynφ aplikaci s formulß°em, na kter² vlo╛φme editaΦnφ ovladaΦ, dv∞ komponenty Label (jednu nad editaΦnφ ovladaΦ a druh² pod) a tlaΦφtko. EditaΦnφ ovladaΦ vyprßzdnφme, u hornφ komponenty Label zm∞nφme Caption na Zadej text:, u spodnφ komponenty Label vlastnost Caption vyprßzdnφme a u tlaΦφtka zm∞nφme text na Zm∞≥ na velkß pφsmena. Pro tlaΦφtko vytvo°te pot°ebnou obsluhu udßlosti OnClick (text z editaΦnφ komponenty p°evedeme na velkß pφsmena a zobrazφme jej ve spodnφ komponent∞ Label).
  30. Vytvo°te aplikaci, ve kterΘ budete zji╣╗ovat existenci zadanΘho pod°et∞zce v zadanΘm °et∞zci (m∙╛ete pou╛φt metodu Pos t°φdy AnsiString). ╪et∞zec a pod°et∞zec zadßvejte v editaΦnφch ovladaΦφch. Vypisujte, zda pod°et∞zec byl nebo nebyl nalezen.
  31. Vytvo°te aplikaci, kterß zadan² text v editaΦnφm ovladaΦi upravφ takto: Mezi jednotlivΘ znaky p∙vodnφho °et∞zce budou vlo╛eny znaky mezer. V²sledek zobrazte v komponent∞ Label.
  32. Jazyk Pascal mß datov² typ mno╛ina, kter² op∞t nenφ v C++. Mno╛iny jsou ve VCL Φasto pou╛φvanΘ a musφme znßt jak je pou╛φt. Mno╛ina je kolekce podobn²ch objekt∙. Nap°. vlastnost Style t°φdy TFont m∙╛e obsahovat nula nebo vφce nßsledujφcφch hodnot: fsBold, fsItalic, fsUnderline a fsStrikeout.

  33. Jak ji╛ bylo uvedeno v²╣e, v jazyku C++ nenφ zabudovanß podpora mno╛in. V C++ se pro podobnΘ ·Φely pou╛φvajφ bitovß pole, co╛ je vyhovujφcφ zp∙sob. My ale pot°ebujeme pou╛φvat zp∙sob z VCL a proto C++ Builder emuluje mno╛iny Pascalu. Je to provedeno ╣ablonou t°φdy nazvanou Set. Tato ╣ablona se velmi snadno pou╛φvß.
    Vra╗me se k vlastnosti Style. Tuto vlastnost n∞kdy pot°ebujeme nastavit i za b∞hu aplikace. Nap°. chceme p°idat atributy pro tuΦnΘ pφsmo a kurzφvu. M∙╛eme deklarovat prom∞nnou typu TFontStyles (typ mno╛iny mo╛n²ch styl∙ pφsma) a k tΘto mno╛in∞ p°idat styly fsBold a fsItalic. To provedeme takto:
    TFontStyles Styly;
    Styly << fsBold << fsItalic;
    Pov╣imn∞te si pou╛itφ operßtoru <<. Tento operßtor je ve t°φd∞ Set p°etφ╛en k umo╛n∞nφ p°idßvßnφ prvku do mno╛iny. V²╣e uveden² k≤d nezm∞nφ styl pφsma, pouze vytvo°φ mno╛inu a vlo╛φ do nφ dva prvky. Ke zm∞n∞ stylu pφsma, musφme p°i°adit nov∞ vytvo°enou mno╛inu vlastnosti Font->Style n∞jakΘ komponenty:
    Memo1->Font->Style = Styly;
    Pozd∞ji m∙╛eme po╛adovat, aby pφsmo z∙stalo tuΦnΘ, ale aby ji╛ nebyla pou╛ita kurzφva. V tomto p°φpad∞ m∙╛eme odstranit styl kurzφvy z mno╛iny. K odstran∞nφ prvku z mno╛iny pou╛φvßme operßtor >>:
    Styly >> fsItalic;
    Memo1->Font->Style = Styly;
    ╚asto pot°ebujeme zjistit, zda v mno╛in∞ se vyskytuje n∞jak² prvek. Nap°. chceme zjistit, zda styl pφsma je nastaven na tuΦnΘ pφsmo. K tomu lze pou╛φt metodu Contains:
    bool jeTucne = Memo1->Font->Style.Contains(fsBold);
    if (jeTucne) delejNeco();
    N∞kdy pot°ebujeme zaΦφnat prßzdnou mno╛inou. K vyprßzdn∞nφ mno╛iny pou╛φvßme metodu Clear. Nap°.
    Memo1->Font->Style.Clear();
    Memo1->Font->Style = Memo1->Font->Style << fsBold << fsItalic;
    Zde nejprve mno╛inu vyprßzdnφme a pak p°i°adφme dva styly. M∙╛eme ale takΘ vytvo°it doΦasnou mno╛inu (mno╛ina po vytvo°enφ je v╛dy prßzdnß) a ihned do nφ p°idat dva prvky. P°edchozφ k≤d je mo╛no takΘ zapsat takto:
    Memo1->Font->Style = TFontStyle() << fsBold << fsItalic;
    Nßsledujφcφ k≤d je ale chybn²:
    Memo1->Font->Style << fsBold << fsItalic;
    Zde nem∙╛e b²t volßna zßpisovß metoda vlastnosti Style. K provedenφ aktualizace vlastnosti Style je nutno pou╛φvat operßtor p°i°azenφ:
    Memo1->Font->Style = Memo1->Font->Style << fsBold << fsItalic;

Kontrolnφ otßzky:

  1. Co to je pracovnφ rßmec?
  2. Je VCL pracovnφ rßmec C++?
  3. Je zapot°ebφ um∞t programovat v Pascalu a v C++ p°i programovßnφ v C++ Builderu?
  4. Jsou vlastnosti datov²mi slo╛kami t°φd?
  5. Musφme reagovat na v╣echny udßlosti definovanΘ komponentou?
  6. Jsou v╣echny komponenty viditelnΘ b∞hem nßvrhu?
  7. Mohou b²t objekty VCL alokovßny lokßln∞ (v zßsobnφku) nebo dynamicky?
  8. Jsou metody v komponentßch VCL ekvivalentnφ s funkcemi v C++?
  9. Jsou v╣echny t°φdy VCL odvozeny od TObject?
  10. Uve∩te n∞kterou nevizußlnφ komponentu?
  11. Sdφlejφ v╣echny komponenty n∞kterΘ spoleΦnΘ vlastnosti?
  12. Uve∩te alespo≥ dv∞ vlastnosti, kterΘ majφ v╣echny vizußlnφ komponenty.
  13. M∙╛e n∞kolik komponent sdφlet stejnou obsluhu udßlosti?
╪e╣enφ
10. Knihovna vizußlnφch komponent