22. R∙znΘ aplikace II
  1. DalÜφ komponentou, kterou se budeme zab²vat je komponenta TChart (na Palet∞ komponent najdeme dalÜφ dv∞ verze tΘto komponenty TDBChart a TQRChart; tyto verze se pou₧φvajφ obdobn∞, ale zatφm je nebudeme pou₧φvat). Komponenta op∞t umo₧≥uje vytvß°et grafy. Po umφst∞nφ tΘto komponenty na formulß° m∙₧eme zahßjit vytvß°enφ grafu. V mφstnφ nabφdce komponenty TChart zvolφme Edit Chart. Je zobrazen Editor grafu. Nynφ ji₧ m∙₧eme editovat graf, definovat a zapl≥ovat jeho datovΘ sΘrie.

  2. Editor grafu vypadß takto:

    Strßnka Chart (z vn∞jÜφch strßnek) Editoru grafu obsahuje definujφcφ informace pro graf. Jsou r∙znΘ mo₧nosti definovßnφ obecn²ch a specifick²ch parametr∙ grafu. N∞kterΘ parametry nem∙₧eme zadßvat dokud nejsou definovanΘ sΘrie dat v grafu. Nap°. se pokuste modifikovat parametr Title a uvidφte, ₧e se ihned zm∞nφ v grafu. Ne ale vÜechny zm∞ny vidφme v grafu ihned.
    Nejprve se tedy budeme zab²vat p°idßvßnφm sΘriφ. Stiskneme tlaΦφtko Add na strßnce Series (na vn∞jÜφ strßnce Chart). Je zobrazena galerie typ∙ graf∙. Vybereme jeden pro p°idßnφ do naÜeho grafu (pozd∞ji jej budeme moci zm∞nit, pokud budeme po₧adovat jin² zp∙sob zobrazenφ dat) a stiskneme OK. Typ sΘrie je automaticky p°idßn k naÜemu grafu. V Editoru grafu vidφme p°idanou novou konfiguraci pro novou sΘrii.
    Po p°idßnφ sΘrie do grafu jsou takΘ p°idßny n∞kterΘ nßhodnΘ hodnoty, kterΘ jsou zobrazeny v grafu (jsou viditelnΘ pouze p°i nßvrhu). Pokud nynφ p°elo₧φme naÜi aplikaci, pak uvidφme prßzdn² graf.
    Je tedy zapot°ebφ p°idat data k sΘrii. Tato Φinnost se liÜφ pro TDBChart a nebudeme se jφ zatφm zab²vat. P°edpoklßdejme, ₧e na formulß°i mßme komponentu TChart s p°idanou sΘriφ. Nynφ se pokusφme zaplnit sΘrii programov∞. Budeme p°edpoklßdat, ₧e mßme sΘrii Pie (s implicitnφm jmΘnem Series1). Na formulß° umφstφme tlaΦφtko a vytvo°φme obsluhu jeho stisknutφ s k≤dem:
    Series1->Add(40, "Pencil", clRed);
    Series1->Add(60, "Paper", clBlue);
    Series1->Add(30, "Ribbon", clGreen);
    Popis metody Add a dalÜφch pot°ebn²ch metod a vlastnostφ je dostupn² v nßpov∞d∞. NaÜi aplikaci se pokusφme spustit a po stisknutφ tlaΦφtka uvidφme zobrazenφ grafu, k≤d tedy pracuje.
    B∞hem nßvrhu jsou vÜechny vlastnosti grafu a sΘriφ dostupnΘ v Inspektoru objekt∙ nebo v Editoru grafu. Editace sΘrii nejsnadn∞ji provedeme v Editoru grafu na strßnce Series. Pokuste se provΘst n∞kterΘ zm∞ny a uvidφte, ₧e se provedenΘ zm∞ny automaticky projevujφ v grafu. P°i nßvrhu nenφ dostupn² nßÜ k≤d a pou₧φvajφ se tedy nßhodnß data. Abychom zjistili, jak se naÜe zm∞ny projevφ za b∞hu, musφme aplikaci spustit.
    Mnoho v∞cφ m∙₧eme vy°eÜit vizußln∞ v Editoru nebo m∙₧eme n∞kterΘ parametry modifikovat v Inspektoru objekt∙. M∙₧eme je takΘ °eÜit k≤dem.
    Pokuste se modifikovat aplikaci ze 4. a 5. zadßnφ p°edchozφ kapitoly tak, aby se mφsto komponenty ChartFX pou₧φvala komponenta TChart. Vφce se touto komponentou nebudeme zab²vat.

  3. Pro zadßvßnφ datum∙ a Φas∙ lze pou₧φt komponentu TDateTimePicker. Vlastnost DateMode urΦuje re₧im zobrazenφ ovladaΦe a vlastnost Kind urΦuje zda ovladaΦ bude po₧φvßn pro datum nebo Φas. Umφst∞te tuto komponentu na formulß° a vyzkouÜejte si jejφ pou₧itφ.
  4. Komponenta TAnimate slou₧φ k p°ehrßvßnφ klip∙ AVI. Pracuje s nekomprimovan²mi soubory AVI nebo klipy komprimovanΘ k≤dovßnφm RLE. Tato komponenta nepodporuje zvuky u klip∙. Nßsledujφ n∞kterΘ vlastnosti tΘto komponenty:
  5. Pokuste se tuto komponentu pou₧φt v n∞kterΘ aplikaci.
  6. Komponenta TSplitter rozd∞luje klientskou oblast formulß°e na Φßsti, kterΘ mohou m∞nit velikost. Tuto komponentu p°idßvßme na formulß° mezi dva zarovnanΘ ovladaΦe. Spliter je umφst∞n mezi ovladaΦem kter² je zarovnßn s jednφm okrajem formulß°e a ovladaΦem, kter² zapl≥uje zbytek klientskΘ oblasti. Pou₧itφ si ukß₧eme v nßsledujφcφ aplikaci.

  7. ZaΦneme v²voj novΘ aplikace. Na formulß° umφstφme Panel, kter² zarovnßme se spodnφm okrajem formulß°e. Dßle na formulß° p°idßme komponentu TSplitter u kterΘ musφme takΘ nastavit vlastnost Align na alBottom. Na formulß° p°idßme komponentu TDirectoryListBox, u kterΘ vlastnost Align nastavφme na alLeft, dalÜφ komponentu TSplitter (vlastnost Align je zde ji₧ nastavena na alLeft). Zb²vajφcφ plochu formulß°e zaplnφme komponentou TFileListBox (Align nastavφme na alClient). Nynφ ji₧ aplikaci m∙₧eme vyzkouÜet. Spustφme ji a pokusφme se m∞nit velikosti jednotliv²ch oblastφ formulß°e.

  8. DalÜφ zajφmavou oblastφ C++ Builderu je podpora souborov²ch proud∙. Knihovna VCL obsahuje abstraktnφ t°φdu TStream a jejφ t°i potomky: TFileStream, THandleStream a TMemoryStream. Pro nahrßvßnφ dat ze souboru a uklßdßnφ do souboru m∙₧eme pou₧φt dva souborov∞ orientovanΘ proudy. THandleStream se pou₧φvß v p°φpad∞, kdy ji₧ mßme madlo souboru. TFileStream pou₧ijeme, kdy₧ mßme jen jmΘno souboru. T°etφ proudovou t°φdou je TMemoryStream, kterß pracuje s pam∞tφ a nikoli se skuteΦn²m souborem. Tato t°φda vÜak obsahuje specißlnφ metody pro kopφrovßnφ svΘho obsahu do nebo z jinΘho proudu, kter² m∙₧e b²t souborov²m proudem. Proudy mohou nahradit tradiΦnφ soubory. Jejich velkou v²hodou je nap°. to, ₧e m∙₧eme pracovat s pam∞¥ov²mi proudy, a potom je ulo₧it do souboru. Tφmto zp∙sobem lze zv²Üit rychlost programu intenzivn∞ pracujφcφho se soubory.

  9. ZvlßÜt∞ d∙le₧itou vlastnostφ proud∙ je jejich schopnost p°enßÜet komponenty. VÜechny t°φdy knihovny VCL jsou potomci TPersistent, specißlnφ t°φdy umo₧≥ujφcφ uklßdßnφ objekt∙ do proud∙ a obsahujφ metody pro uklßdßnφ a nahrßvßnφ vÜech vlastnostφ a ve°ejn²ch polo₧ek. Proto mohou vÜichni potomci t°φdy TComponent uklßdat sami sebe do proudu nebo mohou b²t nahrßnφm z proudu automaticky vytvo°eni. Program k tomu m∙₧e vyu₧φvat metod proudu WriteComponent a ReadComponent. Proudy v zßsad∞ nev∞dφ nic o Φtenφ nebo zßpisu komponent. Metody t°φd TStream jednoduÜe pou₧φvajφ dv∞ jinΘ t°φdy: TReader a TWriter, ob∞ potomky t°φdy TFiler. Objekty TReader a TWriter pou₧φvajφ proud, ke kterΘmu se vztahujφ a jsou schopnΘ mu p°id∞lit specißlnφ znaΦky pro provedenφ kontroly datovΘho formßtu. Objekt TWriter m∙₧e ulo₧it znaΦku komponenty, potom ulo₧it komponentu, vÜechny jejφ vlastnosti a vÜechny komponenty, kterΘ obsahuje. Obsahuje metodu WriteRootComponent, kterß ulo₧φ komponentu p°edanou jako parametr a takΘ vÜechny komponenty, kterΘ obsahuje. Podobn∞ t°φda TReader obsahuje metodu ReadRootComponent, kterß je schopnß vytvo°it novΘ objekty s vyu₧itφm informace o t°φdßch ulo₧en²ch v proudu. To je mo₧nΘ pod jednou podmφnkou: nßzev komponenty musφ b²t aplikacφ registrovßn (funkcφ RegisterClasses).
    Vra¥me se ale ke konkrΘtnφ aplikaci. ZaΦneme v²vojem novΘ aplikace. Formulß° tΘto aplikace je jednoduch². Na hornφ okraj formulß°e vlo₧φme komponentu Panel (zruÜφme jeho titulek) a na nφ vlo₧φme t°i voliΦe s texty Label, Edit a Button (prvnφ z nich nastavφme). P°i kliknutφ myÜφ na formulß°i, vytvo°φme komponentu urΦenou vybran²m voliΦem. P°ed deklaraci typu formulß°e vlo₧φme deklaraci v²ΦtovΘho typu
    enum Typ {Label, Edit, ButtonX};
    popisujφcφ vybran² voliΦ a do soukromΘ Φßsti deklarace formulß°e umφstφme:
    int Citac;
    Typ Odkaz;
    Vytvo°te obsluhy kliknutφ na voliΦφch tak, aby v polo₧ce Odkaz byla ulo₧ena informace o vybranΘm voliΦi. Dßle vytvo°φme obsluhu OnCreate formulß°e s t∞mito p°φkazy:
    Odkaz = Label;
    Citac = 0;
    Po vytvo°enφ obsluhy OnMouseDown formulß°e ji₧ m∙₧eme aplikaci vyzkouÜet. Tuto obsluhu tvo°φ p°φkazy:
    TControl *Objekt;
    AnsiString Nazev;
    switch (Odkaz) {
      case Label: Objekt = new TLabel(this); break;
      case Edit: Objekt = new TEdit(this); break;
      case ButtonX: Objekt = new TButton(this); break;
    }
    Objekt->Parent = this;
    Objekt->Left = X;
    Objekt->Top = Y;
    Citac++;
    Nazev = String(Objekt->ClassName()) + IntToStr(Citac);
    Nazev.Delete(1, 1);
    Objekt->Name = Nazev;
    Objekt->Visible = true;
    Klikßnφm myÜi na formulß°i vytvß°φme komponenty urΦenΘ vybran²m voliΦem. VyzkouÜejte.
  10. TΘto aplikaci dßle umo₧nφme uklßdßnφ vlo₧en²ch komponent do souboru a jejich op∞tovnΘmu nahrßnφ ze souboru. K aplikaci p°idßme nabφdku Soubor s volbami: ZruÜit, Otev°φt, Ulo₧it jako a Konec. P°idßme takΘ komponenty OpenDialog a SaveDialog (kde nastavφme vhodnΘ vlastnosti; u naÜich soubor∙ budeme pou₧φvat p°φponu CMP). Tyto komponenty musφme vlo₧it na ji₧ pou₧itou komponentu Panel. Obsluhu volby ZruÜit tvo°φ p°φkazy (zruÜφme vÜechny komponenty mimo komponent vlo₧en²ch na panel):

  11. for (int I = ControlCount-1; I >= 0; I--)
      if (String(Controls[I]->ClassName()) != "TPanel") Controls[I]->Free();
    Citac = 0;
    Komponenty uklßdanΘ do proudu musφme registrovat a tedy do obsluhy OnCreate formulß°e p°idßme p°φkazy:
    TComponentClass classes[3] =
                 {__classid(TEdit), __classid(TLabel), __classid(TButton)};
    RegisterClasses(classes, 2);
    Vytvo°φme jeÜt∞ obsluhu volby Ulo₧it jako. Tvo°φ ji p°φkazy:
    if (SaveDialog1->Execute()){
      TFileStream *S;
      S = new TFileStream(SaveDialog1->FileName, fmOpenWrite | fmCreate);
      for (int I = 0; I < ControlCount; I++)
        if (String(Controls[I]->ClassName()) != "TPanel")
          S->WriteComponent(Controls[I]);
      delete S;
    }
    Obsluhu volby Otev°φt tvo°φ:
    if (OpenDialog1->Execute()) {
      TFileStream *S;
      TComponent *Novy;
      Zruit1Click(this);
      S = new TFileStream(OpenDialog1->FileName, fmOpenRead);
      while (S->Position < S->Size){
        Novy = S->ReadComponent(NULL);
        InsertControl(dynamic_cast<TControl *> (Novy));
        Citac++;
      }
      delete S;
    }
    Zb²vajφcφ obsluhy vytvo°te sami. Aplikaci vyzkouÜejte.
  12. JeÜt∞ se seznßmφme s klφΦov²mi slovy C++ p°idan²mi do C++ Builderu pro podporu VCL.

  13. Operßtor __classid je pou₧φvßn p°ekladaΦem pro generovßnφ ukazatele na vtable (tabulka virtußlnφch metod) pro specifikovanou t°φdu. Tento operßtor byl takΘ pou₧it v p°edchozφm p°φklad∞. Syntaxe:
    __classid(classname)
    Nap°. __classid pou₧φvßme p°i registraci editoru vlastnosti, komponenty nebo t°φdy a s metodou InheritsFrom t°φdy TObject.
    KlφΦovΘ slovo __closure je pou₧φvßno k deklarovßnφ specißlnφho typu ukazatele na metodu. Na rozdφl od normßlnφho ukazatele na funkci, tento ukazatel obsahuje i ukazatel na objekt. Ve standardnφm C++ m∙₧eme p°i°adit instanci odvozenΘ t°φdy ukazateli na zßkladnφ t°φdu, ale nem∙₧eme p°i°adit metodu odvozenΘ t°φdy ukazateli na metodu zßkladnφ t°φdy. Ukazuje to nßsledujφcφ p°φklad:
    class base
    {
     public:
     void func(int x);
    };
    class derived: public base
    {
     public:
     void new_func(int i);
    };
    void (base::*bptr)(int);
    bptr = &derived::new_func; // nedovoleno
    JazykovΘ rozÜφ°enφ __closure umo₧≥uje toto v C++ Builderu provΘst. Closure p°i°azuje ukazatel na metodu k ukazateli na instanci t°φdy. Ukazatel na instanci t°φdy je pou₧it jako ukazatel this, kdy₧ volßme p°i°azenou metodu. Deklarace Closure je stejnß jako deklarace ukazatele na funkci, ale p°ed identifikßtorem funkce je uvedeno klφΦovΘ slovo __closure. Nap°.
    struct MyObject
    {
      double MemFunc(int);
    };
    double func1(MyObject *obj)
    {
      double ( __closure *myClosure )(int);
      // Inicializace Closure.
      myClosure = obj -> MemFunc;
      // Pou₧itφ Closure k volßnφ metody.
      return myClosure(1);
    }
    V C++ Builderu jsou Closure pou₧φvßny s udßlostmi.
    KlφΦovΘ slovo __property deklaruje v deklaraci t°φdy vlastnost. Vlastnosti mohou b²t deklarovßny pouze ve t°φdßch. Pro pole vlastnostφ, index pole m∙₧e b²t libovolnΘho typu. Syntaxe:
    <property declaration> ::=
      __property <type> <id> [ <prop dim list> ]="{" <prop attrib list> "}"
      <prop dim list> ::= "[" <type> [ <id> ] "]" [ <prop dim list> ]
      <prop attrib list> ::= <prop attrib> [ , <prop attrib list> ]
      <prop attrib> ::=     read = <data/function id>
      <prop attrib> ::=     write = <data/function id>
      <prop attrib> ::=     stored = <data/function id>
      <prop attrib> ::=     stored = <boolean constant>
      <prop attrib> ::=     default = <constant>
      <prop attrib> ::=     nodefault
      <prop attrib> ::=     index = <const int expression>
    Vlastnosti majφ n∞kolik slu₧eb, Φφm₧ se odliÜujφ od datov²ch slo₧ek. Vlastnosti mohou mφt: KlφΦovΘ slovo __published specifikuje, ₧e vlastnosti v tΘto sekci jsou zobrazeny v Inspektoru objekt∙. Sekci __published mohou mφt pouze t°φdy odvozenΘ od TObject. Pravidla viditelnosti pro zve°ej≥ovanΘ slo₧ky jsou stejnΘ jako pro ve°ejnΘ slo₧ky. Jedin² rozdφl mezi zve°ej≥ovan²mi a ve°ejn²mi slo₧kami je ten, ₧e u zve°ej≥ovan²ch slo₧ek jsou generovßny informace RTTI. To umo₧≥uje aplikacφm dynamickΘ dotazy na slo₧ky, metody a vlastnosti.
  14. N∞kolik parametr∙ klφΦovΘho slova __declspec poskytuje jazykovou podporu pro VCL. Nßsleduje popis t∞chto parametr∙.

  15. Parametr delphiclass je pou₧it pro deklarovßnφ t°φd odvozen²ch od TObject. Tyto t°φdy jsou vytvo°eny tak, aby byly kompatibilnφ s VCL.
    Parametr delphireturn je pou₧it pro deklarovßnφ t°φd, kterΘ vytvß°φme v C++ Builderu pro podporu zabudovan²ch datov²ch typ∙ a jazykov²ch konstrukcφ Object Pascalu, kterΘ nejsou p°irozenΘ v C++. To zahrnuje Currency, AnsiString, Variant, TDateTime a Set. Parametr delphireturn oznaΦuje t°φdy C++ pro VCL kompatibilnφ zpracovßnφ volßnφ funkcφ (parametry a nßvratovΘ hodnoty). Tento modifikßtor je zapot°ebφ, kdy₧ p°edßvßme strukturu funkci hodnotou mezi Object Pascalem a C++.
    Parametr dynamic je pou₧φvßn pro deklarovßnφ dynamick²ch funkcφ. DynamickΘ funkce se podobajφ virtußlnφm, ale jsou jinak ulo₧enΘ.
    Parametr hidebase chrßnφ sΘmantiku programu Object Pascalu p°i p°edßvßnφ virtußlnφch a p°ekryt²ch funkcφ C++ Builderu. V Object Pascalu, virtußlnφ funkce v zßkladnφ t°φd∞ mohou b²t zobrazeny v odvozenΘ t°φd∞ jako funkce se stejn²m jmΘnem, ale mohou b²t chßpßny jako kompletn∞ novΘ funkce bez explicitnφho vztahu k p°edchozφ funkci. P°ekladaΦ pou₧φvß makro HIDESBASE, k specifikaci, ₧e tyto typy deklaracφ funkcφ jsou kompletn∞ samostatnΘ. Nap°. jestli₧e zßkladnφ t°φda T1 deklaruje virtußlnφ bezparametrickou funkci func a odvozenß t°φda T2 deklaruje funkci se stejn²m jmΘnem a signaturou, pak DCC32 vytvß°φ hlaviΦkov² soubor s nßsledujφcφm prototypem:
    virtual void T1::func(void);
    HIDESBASE void T2::func(void);
    Bez HIDESBASE, sΘmantika C++ indikuje, ₧e virtußlnφ funkce T1::func bude p°epsßna T2::func.
    Parametr package indikuje, ₧e k≤d definice t°φdy bude p°elo₧en do balφΦku. Parametr pascalimplementation indikuje, ₧e k≤d definice t°φdy bude implementovßn v Object Pascalu.
22. R∙znΘ aplikace II