12. Prßce s grafikou II
  1. Kreslenφ za b∞hu aplikace si ukß₧eme jeÜt∞ na jednΘ jednoduchΘ aplikaci. ZaΦneme s v²vojem novΘ aplikace. U formulß°e nastavφme vlastnost Color na clBlack. Na formulß° dßle p°idßme komponentu Timer, kde Interval nastavφme na 500. P°ed deklaraci t°φdy formulß°e do hlaviΦkovΘho souboru formulß°e umφstφme tyto deklarace:

  2. const int  MaxPoints = 15;  // PoΦet kreslen²ch bod∙
    struct TRPoint {
      float X, Y;
    };
    a do soukromΘ Φßsti deklarace t°φdy formulß°e p°idßme:
    TRPoint     Points[MaxPoints];
    float       Rotation;     // v radißnech
    int         PointCount;
    void __fastcall RotatePoints();
    Metoda RotatePoints bude tvo°ena p°φkazy:
    void __fastcall TForm1::RotatePoints()
    {
     // VÜechny ·hly jsou v radißnech
     const float M_2PI = 2 * M_PI;
     float StepAngle = M_2PI / PointCount;
     Rotation += M_PI / 32;
     if (Rotation > StepAngle) Rotation -= StepAngle;
     int i;
     float j;
     for (i = 0, j = Rotation; i < PointCount; i++, j += StepAngle) {
      Points[i].X = cos(j);
      Points[i].Y = sin(j);
     }
    }
    K formulß°i vytvo°φme obsluhu udßlosti OnCreate s p°φkazy:
    Canvas->Pen->Color = clTeal;
    Rotation = 0;
    PointCount = MaxPoints;
    RotatePoints();
    Dßle vytvo°φme obsluhu OnPaint formulß°e. Zde budou p°φkazy:
    int centerX = ClientWidth / 2;
    int centerY = ClientHeight / 2;
    int radius = min(centerY, centerX);
    Canvas->Ellipse(0, 0, radius*2, radius*2);
    int i,j;
    for (i = 0; i < PointCount; i++) {
     for (j = i + 1; j < PointCount; j++) {
      Canvas->MoveTo(radius + floor(Points[i].X * radius),
       radius + floor(Points[i].Y * radius));
      Canvas->LineTo(radius + floor(Points[j].X * radius),
       radius + floor(Points[j].Y * radius));
     }
    }
    Obsluhu OnResize formulß°e tvo°φ p°φkaz:
    Invalidate();
    Zb²vß jeÜt∞ vytvo°it obsluhu OnTimer ΦasovaΦe. Zde budou p°φkazy:
    RotatePoints();
    Invalidate();
    Tφm je naÜe aplikace hotova. VyzkouÜejte co d∞lß a sna₧te se pochopit v²znam jednotliv²ch metod.
  3. Dßle se seznßmφme s pou₧φvßnφm komponenty HeaderControl. ZaΦneme s v²vojem novΘ aplikace. Na hornφ okraj formulß°e umφstφme komponentu HeaderControl a nastavφme u nφ vlastnost Sections na t°i sekce s texty ╚ervenß, Zelenß a Modrß (Üφ°ku jednotliv²ch sekcφ nastavφme na 125, minimßlnφ Üφ°ku na 50, maximßlnφ Üφ°ku na 250 a zarovnßvßnφ na centrovßnφ). Na formulß° dßle vlo₧φme vedle sebe t°i komponenty Shape tak, aby zaplnily Üφ°ku jednotliv²ch sloupc∙ hlaviΦky, vlastnost Shape u nich nastavφme na stEllipse a barvu v²pln∞ zm∞nφme podle textu v hlaviΦce. Dßle vytvo°φme obsluhu udßlosti OnSectionTrack ovladaΦe HeaderControl, kterß bude tvo°ena p°φkazy:

  4. Section->Width = Width;
    Shape1->Width = HeaderControl->Sections->Items[0]->Width;
    Shape2->Width = HeaderControl->Sections->Items[1]->Width;
    Shape2->Left = HeaderControl->Sections->Items[1]->Left;
    Shape3->Width = HeaderControl->Sections->Items[2]->Width;
    Shape3->Left = HeaderControl->Sections->Items[2]->Left;
    Tφm je aplikace hotova, m∙₧eme ji vyzkouÜet. MyÜφ lze p°etahovat d∞lφcφ Φßry v hlaviΦce a tφm m∞nit Üφ°ku zobrazenΘ elipsy ve sloupci jeho₧ Üφ°ku m∞nφme.
  5. V tΘto kapitole se budeme jeÜt∞ zab²vat vytvß°enφm hodin. Na formulß° umφstφme komponenty Timer a Panel (panel zv∞tÜφme na celou plochu formulß°e a takΘ zv∞tÜφme pφsmo jeho titulku). Vytvo°φme jeÜt∞ obsluhu udßlosti OnTimer ΦasovaΦe. Bude tvo°ena p°φkazem:

  6. Panel1->Caption = TimeToStr(Time());
    Funkce Time vracφ objekt typu TDateTime, kter² obsahuje aktußlnφ Φas a funkce TimeToStr jej p°evede na °et∞zec. Tφm jsou nejjednoduÜÜφ (digitßlnφ) hodiny hotovy. Tvar v²pisu je urΦen nastavenφm nßrodnostnφch zvyklostφ ve Windows.
  7. V dalÜφ aplikaci se pokusφme vytvo°it analogovΘ hodiny. Formulß°, kter² pot°ebujeme pro ruΦiΦkovΘ hodiny je jeÜt∞ jednoduÜÜφ. Obsahuje pouze ΦasovaΦ. V∞tÜina k≤du je v obsluze udßlosti OnPaint. Proto₧e pot°ebujeme vykreslovat t°i r∙znΘ hodinovΘ ruΦiΦky, p°idßme do formulß°e ve°ejnou metodu, kterou budeme kreslit jednotlivΘ ruΦiΦky. Bude to funkce:

  8. void __fastcall TForm1::KresliRucicku(int XStred, int YStred,
                            int Polomer, int ZpPolomer, double Uhel)
    {
      Canvas->MoveTo(XStred-floor(ZpPolomer*cos(Uhel)),
                     YStred-floor(ZpPolomer*sin(Uhel)));
      Canvas->LineTo(XStred+floor(Polomer*cos(Uhel)),
                     YStred+floor(Polomer*sin(Uhel)));
    }
    Do deklarace formulß°e jeÜt∞ vlo₧φme nßsledujφcφ soukromΘ polo₧ky:
    unsigned short int Hodina, Minuta, Sekunda;
    int XStred, YStred, Polomer;
    Obsluha udßlosti OnPaint formulß°e je tvo°ena nßsledujφcφmi p°φkazy:
    double Uhel;
    int I, X, Y, Velikost;
    XStred = ClientWidth / 2;
    YStred = ClientHeight / 2;
    if (XStred > YStred) Polomer = YStred - 10;
    else Polomer = XStred - 10;
    Canvas->Pen->Color = clYellow;
    Canvas->Brush->Color = clYellow;
    Velikost = Polomer / 50 + 1;
    for (I = 0; I < 12; I++){
      Uhel = 2 * M_PI * (I + 9) / 12;
      X = XStred - floor(Polomer * cos(Uhel));
      Y = YStred - floor(Polomer * sin(Uhel));
      Canvas->Ellipse(X-Velikost, Y-Velikost, X+Velikost, Y+Velikost);
    }
    Canvas->Pen->Width = 2;
    Canvas->Pen->Color = clBlue;
    Uhel = 2 * M_PI * (Minuta+45) / 60;
    KresliRucicku(XStred, YStred, Polomer * 90 / 100, 0, Uhel);
    Uhel = 2 * M_PI * (Hodina + 9 + Minuta / 60) / 12;
    KresliRucicku(XStred, YStred, Polomer * 70 / 100, 0, Uhel);
    Canvas->Pen->Width = 1;
    Canvas->Pen->Color = clRed;
    Uhel = 2 * M_PI * (Sekunda + 45) / 60;
    KresliRucicku(XStred, YStred, Polomer, Polomer * 30 / 100, Uhel);
    Zb²vß jeÜt∞ vytvo°it n∞kolik obsluh udßlostφ. Obsluha OnTimer ΦasovaΦe je tvo°ena p°φkazy:
    unsigned short SetinySec;
    DecodeTime(Time(), Hodina, Minuta, Sekunda, SetinySec);
    Refresh();
    Obsluhu OnResize formulß°e tvo°φ p°φkaz: Refresh(); Jestli₧e vytvo°φme jeÜt∞ obsluhu udßlosti OnCreate formulß°e s nßsledujφcφm p°φkazem, pak hodiny budou ukazovat sprßvn² Φas ihned od zobrazenφ.
    Timer1Timer(this);
    Vytvo°te tyto hodiny.
  9. P°edchozφ program sice funguje, ale k dokonalosti mu jeÜt∞ n∞co chybφ. Obrßzek hodin je nestabilnφ; p°φliÜ blikß. Ve skuteΦnosti je toti₧ ka₧dou sekundu cel² obsah formulß°e vymazßn a znovu vykreslen. Pokuste se tento program vylepÜit tak, ₧e sma₧ete pouze starou sekundovou ruΦiΦku a potom ji nakreslete znova na novΘm mφst∞.
  10. Chceme-li ulo₧it informaci o stavu aplikace, abychom ji mohli p°i dalÜφm spuÜt∞nφ programu obnovit, m∙₧eme ji ulo₧it do souboru, a to v takovΘm formßtu, jak² uznßme za vhodn². NicmΘn∞ Windows zajiÜ¥ujφ explicitnφ podporu pro inicializaΦnφ soubory (s p°φponou INI). Ka₧dß aplikace m∙₧e mφt sv∙j vlastnφ INI soubor a zapisovat do n∞j °et∞zce, Φφsla nebo hodnoty typu bool. StejnΘ hodnoty je mo₧nΘ takΘ Φφst. Builder obsahuje t°φdu TIniFile, s jejφ₧ pomocφ m∙₧eme manipulovat s INI soubory. Vytvo°φme objekt tΘto t°φdy, p°i°adφme mu soubor a m∙₧eme z n∞j informace jak Φφst, tak je do n∞j zapisovat. Pro vytvo°enφ tohoto objektu je nutnΘ zavolat konstruktor, kterΘmu p°edßme jako parametr nßzev souboru.

  11. Existujφ dv∞ mo₧nosti umφst∞nφ INI souboru na disku. Jednak je mo₧nΘ ulo₧it jej do adresß°e aplikace a konstruktoru p°edat ·plnou cestu k n∞mu. Druh²m b∞₧n∞jÜφm °eÜenφm je ulo₧it inicializaΦnφ soubor do adresß°e Windows. V tomto p°φpad∞ zadßvßme pouze nßzev souboru.
    INI soubory jsou rozd∞leny na sekce oznaΦenΘ nßzvem uzav°en²m v hranat²ch zßvorkßch. Ka₧dß sekce obsahuje n∞kolik prvk∙ t°φ mo₧n²ch druh∙: °et∞zec, celΘ Φφslo nebo logickß hodnota. T°φda TIniFile obsahuje metody pro Φtenφ ka₧dΘho z t∞chto typ∙ a jsou zde tΘ₧ metody pro jejich zßpis. V metodßch urΦen²ch ke Φtenφ m∙₧eme specifikovat implicitnφ hodnotu, kterß bude pou₧ita v p°φpad∞, kdy odpovφdajφcφ zßznam v INI souboru neexistuje. Vyu₧itφ INI soubor∙ si ukß₧eme v nßsledujφcφ aplikaci. Formulß° aplikace je prßzdn² a jsou zde pouze obsluhy udßlostφ OnCreate a OnClose formulß°e. Do INI souboru budeme uklßdat umφst∞nφ a velikost naÜeho formulß°e a p°i dalÜφm spuÜt∞nφ toto umφst∞nφ a velikost pou₧ijeme. Do soukromΘ Φßsti deklarace formulß°e umφstφme (do hlaviΦkovΘho souboru formulß°e vlo₧φme #include <vcl/inifiles.hpp>):
    TIniFile *IniFile;
    Obsluha OnCreate je tvo°ena p°φkazy:
    int Stav;
    IniFile = new TIniFile("Project1.ini");
    Stav = IniFile->ReadInteger("Form1","Status", 0);
    if (Stav != 0) {
      Top = IniFile->ReadInteger("Form1","Top", 0);
      Left = IniFile->ReadInteger("Form1","Left", 0);
      Width = IniFile->ReadInteger("Form1","Width", 0);
      Height = IniFile->ReadInteger("Form1","Height", 0);
      switch (Stav) {
        case 2: WindowState = wsMinimized; break;
        case 3: WindowState = wsMaximized; break;
      }
    }
    a obsluhu OnClose tvo°φ:
    int Stav;
    if (Application->MessageBox("Ulo₧it aktußlnφ stav formulß°e?",
                   "Dotaz", MB_YESNO | MB_ICONQUESTION ) == IDYES) {
      switch (WindowState) {
          case wsNormal:
            IniFile->WriteInteger("Form1","Top", Top);
            IniFile->WriteInteger("Form1","Left", Left);
            IniFile->WriteInteger("Form1","Width", Width);
            IniFile->WriteInteger("Form1","Height", Height);
            Stav = 1;
            break;
          case wsMinimized: Stav = 2; break;
          case wsMaximized: Stav = 3; break;
      }
      if (!Active) Stav = 2;
      IniFile->WriteInteger("Form1","Status", Stav);
    }
    delete IniFile;
    Tφm je naÜe aplikace hotova a m∙₧eme ji vyzkouÜet. ProhlΘdn∞te si takΘ v n∞jakΘm textovΘm editoru vytvo°en² INI soubor. Pokuste se pochopit, jak tato aplikace pracuje.
  12. V demonstraΦnφch programech firmy Borland je uveden dalÜφ grafick² editor. Tento editor mß samostatnou paletu nßstroj∙. Aplikaci si stßhn∞te, p°elo₧te a vyzkouÜejte jak pracuje. Podφvejte se jak²m zp∙sobem je vy°eÜena prßce s paletou. ProhlΘdn∞te si takΘ, jak jsou vy°eÜeny ostatnφ obsluhy udßlostφ.
  13. DalÜφ aplikace nßs podrobn∞ji seznßmφ s pou₧φvßnφm posuvnφku. Aplikaci si op∞t stßhn∞te a vyzkouÜejte. Podφvejte se na obsluhu udßlosti OnScroll posuvnφku. M∙₧eme zde zjiÜ¥ovat, jakß Φinnost s posuvnφkem je provßd∞na.
12. Prßce s grafikou II