3. P°idßnφ grafiky k ovladaΦ∙m
  1. Okno seznamu a kombinovan² ovladaΦ majφ styly nazvanΘ Owner draw, co╛ znamenß, ╛e mφsto standardnφ metody zobrazovßnφ textu prvk∙ v ovladaΦi je pou╛ito vlastnφ zobrazovßnφ prvk∙. ╚astΘ pou╛itφ ovladaΦe s vlastnφm (u╛ivatelsk²m) zobrazovßnφm, je v p°φpad∞ pou╛itφ grafiky mφsto textu nebo spoleΦn∞ s textem. V╣echny ovladaΦe s vlastnφm zobrazovßnφm obsahujφ seznam prvk∙. Implicitn∞ tyto seznamy jsou seznamy °et∞zc∙, kterΘ se zobrazujφ jako text. Ke ka╛dΘmu prvku v seznamu m∙╛eme p°i°adit objekt, Φφm╛ si usnadnφme urΦovßnφ, kter² objekt kreslit. Obecn∞ p°i pou╛φvßnφ ovladaΦ∙ s vlastnφm zobrazovßnφm provedeme tyto kroky: nastavφme styl vlastnφho zobrazovßnφ, p°idßme k seznamu °et∞zc∙ grafickΘ objekty a zobrazφme prvky vlastnφm zobrazenφm.

  2. Komponenty ListBox a ComboBox majφ vlastnost Style. Tato vlastnost urΦuje, zda ovladaΦ pou╛φvß implicitnφ nebo vlastnφ zobrazovßnφ. Komponenty m°φ╛ek majφ vlastnost DefaultDrawing k povolenφ nebo zakßzßnφ implicitnφho zobrazovßnφ. Komponenty ListBox a ComboBox majφ styly vlastnφho zobrazovßnφ nazvanΘ fixed a variable, pro m°φ╛ky je v╛dy pou╛φvßn styl fixed (i kdy╛ jednotlivΘ °ßdky a sloupce mohou mφt r∙znΘ rozm∞ry, je nutno urΦit velikost ka╛dΘ bu≥ky p°ed zobrazenφm). V²znam t∞chto styl∙ je popsßn v nßsledujφcφ tabulce:
     
    Styl vlastnφho zobrazovßnφ V²znam
    Fixed V╣echny prvky majφ stejnou v²╣ku urΦenou vlastnostφ ItemHeight.
    Variable V²╣ky jednotliv²ch prvk∙ se mohou li╣it a jsou urΦeny za b∞hu aplikace.

    Ka╛d² seznam °et∞zc∙ mß mo╛nost, mimo svΘho seznamu °et∞zc∙, obsahovat i seznam objekt∙. Nap°. aplikace sprßvce soubor∙ m∙╛e obsahovat spoleΦn∞ s pφsmeny jednotek i bitovΘ mapy indikujφcφ typ jednotek. K tomu je zapot°ebφ p°idat k aplikaci po╛adovanΘ obrßzky a odkazy na n∞ vlo╛it do seznamu °et∞zc∙.
    OvladaΦ obrßzku je komponenta obsahujφcφ obrßzek (nap°. bitovou mapu). OvladaΦ obrßzku m∙╛eme pou╛φt k zobrazenφ obrßzku na formulß°i. M∙╛eme jej takΘ pou╛φt k dr╛enφ skryt²ch obrßzk∙, kterΘ pou╛φvßme v na╣φ aplikaci. Nap°. m∙╛eme ulo╛it bitovΘ mapy pro ovladaΦe vlastnφho zobrazovßnφ ve skryt²ch ovladaΦφch obrßzk∙. To provedeme takto: P°idßme komponenty Image na formulß°, nastavφme jejich vlastnosti Name, nastavφme jejich vlastnosti Visible na false a nastavφme jejich vlastnosti Picture na po╛adovanou bitovou mapu pomocφ Editoru obrßzk∙ z Inspektora objekt∙.
    Kdy╛ ji╛ mßme obrßzky v aplikaci, m∙╛eme je p°i°adit k °et∞zc∙m v seznamu °et∞zc∙ (m∙╛eme p°idßvat objekty spoleΦn∞ s °et∞zci nebo je p°i°adit k ji╛ existujφcφm °et∞zc∙m). Pokud jsou pot°ebnß data dostupnß, pak je vhodnΘ p°idßvat objekty a °et∞zce najednou. Nßsledujφcφ p°φklad ukazuje jak m∙╛eme p°idßvat obrßzky k seznamu °et∞zc∙. Je to Φßst aplikace, ve kterΘ spoleΦn∞ s pφsmenem pro ka╛dou existujφcφ jednotku, p°idßme bitovou mapu indikujφcφ typ jednotky (tato obsluha bude pou╛ita pozd∞ji p°i v²voji sprßvce soubor∙).
    void __fastcall TFMForm::FormCreate(TObject *Sender)
    {
      int AddedIndex;
      char DriveName[4] = "A:\";
      for (char Drive = 'A'; Drive <= 'Z'; Drive++)
      {
        DriveName[0] = Drive;
        switch (GetDriveType(DriveName))
        {
          case DRIVE_REMOVABLE:       // p°idßnφ prvku seznamu
            DriveName[1] = '\0';      // bere pouze pφsmeno jednotky
            AddedIndex = DriveList->Items->AddObject(DriveName,
               Floppy->Picture->Graphic);
            DriveName[1] = ':'        // p°evßdφ zp∞t na tvar A:\
            break;
          case DRIVE_FIXED:          // p°idßnφ prvku seznamu
            DriveName[1] = '\0';
            AddedIndex = DriveList->Items->AddObject(DriveName,
               Fixed->Picture->Graphic);
            DriveName[1] = ':'
            break;
          case DRIVE_REMOTE:        // p°idßnφ prvku seznamu
            DriveName[1] = '\0';
            AddedIndex = DriveList->Items->AddObject(DriveName,
               Network->Picture->Graphic);
            DriveName[1] = ':'
            break;
        }
        if ((int)(Drive - 'A') == getdisk()) // aktußlnφ jednotka?
          DriveList->ItemIndex = AddedIndex; // pak vybere prvek seznamu
      }
    }
    Kdy╛ nastavφme styl vlastnφho zobrazovßnφ, pak ji╛ Windows nezobrazuje ovladaΦ na obrazovku. Pro ka╛d² viditeln² prvek v ovladaΦi zaΦne generovat udßlosti. Na╣e aplikace tyto udßlosti musφ vyu╛φt pro zobrazenφ prvk∙.
    D°φve ne╛ aplikace m∙╛e zaΦφt se zobrazovßnφm prvku u stylu Variable, Windows generuje udßlost OnMeasureItem. Tato udßlost °φkß aplikaci, kde prvek bude na ovladaΦi zobrazen. Windows urΦuje velikost prvku (velikost pot°ebnou k zobrazenφ textu prvku souΦasn²m pφsmem). Na╣e aplikace m∙╛e udßlost zpracovat a zm∞nit volbu Windows. Nap°. chceme-li text prvku nahradit obrßzkem, pak zadßme velikost obrßzku. Ke zm∞n∞ velikosti prvku vytvo°φme obsluhu udßlosti OnMeasureItem (komponenty m°φ╛ky tuto udßlost nemajφ). Tato obsluha udßlosti mß dva d∙le╛itΘ parametry: index prvku a velikost prvku. Velikost je p°edßvßna odkazem a aplikace ji m∙╛e zmen╣it nebo zv∞t╣it. Pozice nßsledujφcφho prvku zßvisφ na velikosti p°edchozφch prvk∙. Nap°. kdy╛ v okn∞ seznamu, aplikace nastavφ v²╣ku prvnφho prvku na 5 bod∙, pak druh² prvek zaΦne ╣est²m bodem od hornφho okraje ovladaΦe, atd. V komponentßch ComboBox a ListBox m∙╛e aplikace ovliv≥ovat pouze v²╣ku prvku. ⌐φ°ka prvku je v╛dy ╣φ°ka ovladaΦe. U m°φ╛ek nelze m∞nit velikost bun∞k. Velikost ka╛dΘho °ßdku a sloupce musφme nastavit p°ed zobrazenφm pomocφ vlastnostφ ColWidths a RowHeights.
    Nßsledujφcφ k≤d p°ipojen² k obsluze udßlosti OnMeasureItem okna seznamu urΦuje v²╣ku ka╛dΘho prvku seznamu podle svΘ p°ipojenΘ bitovΘ mapy:
    void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,
                    int Index, int &Height)   // v²╣ka je p°edßna odkazem
    {
      int BitmapHeight=((TBitmap*)ListBox1->Items->Objects[Index])->Height
                       + 2;
      // ud∞lßme dostateΦnΘ mφsto pro bitovou mapu (+ 2)
      if (BitmapHeight > Height)
        Height = BitmapHeight;
    }
    V p°edchozφm k≤du musφme provΘst p°etypovßnφ vlastnosti Objects seznamu °et∞zc∙. Tato vlastnost je typu TObject a m∙╛e obsahovat odkaz na libovoln² typ objektu. Pokud zφskßvßme objekt z pole, musφme provΘst p°etypovßnφ na aktußlnφ typ prvku.
    Kdy╛ aplikace po╛aduje zobrazenφ nebo p°ekreslenφ ovladaΦe, pak Windows generuje udßlost OnDrawItem (OnDrawCell) pro ka╛d² viditeln² prvek v ovladaΦi. Tato udßlost obsahuje parametry urΦujφcφ index zobrazovanΘho prvku, obdΘlnφk, ve kterΘm prvek bude zobrazen a obvykle n∞jakΘ informace o stavu prvku (nap°. zda prvek mß zaost°enφ). Aplikace zpracuje ka╛dou udßlost zobrazenφm p°φslu╣nΘho prvku v danΘm obdΘlnφku. Nap°. nßsledujφcφ k≤d ukazuje jak zobrazit prvky v okn∞ seznamu, kter² mß ke ka╛dΘmu °et∞zci p°i°azenou bitovou mapu:
    void __fastcall TForm1::ListBox1DrawItem(TWinControl *Control,
        int Index, TRect &Rect, TOwnerDrawState State)
      TBitmap *Bitmap = (TBitmap *)ListBox1->Items->Objects[Index];
      ListBox1->Canvas->Draw(Rect.Left, Rect.Top + 2, Bitmap);
      ListBox1->Canvas->TextOut(Rect.Left + Bitmap->Width + 2, Rect.Top + 2,
        ListBox1->Items->Strings[Index]);
    }

  3. Dßle si ukß╛eme aplikaci zobrazujφcφ seznam pφsem dostupn²ch v systΘmu (jmΘno pφsma bude v seznamu zobrazeno pomocφ tohoto pφsma; pou╛ijeme seznam s u╛ivatelsk²m - vlastnφm zobrazovßnφm prvk∙). ZaΦneme novou aplikaci. Na formulß° umφstφme k hornφmu okraji komponentu Label s textem Pφsma systΘmu:, v∞t╣inu plochy formulß°e bude zabφrat komponenta ListBox a ve spodnφ Φßsti formulß°e bude dal╣φ komponenta Label (se jmΘnem vybranΘho pφsma). U komponenty ListBox nastavφme vlastnost Style na lbOwnerDrawVariable a vytvo°φme obsluhy zobrazujφcφ seznam. Obsluha udßlosti OnMeasureItem (udßlost zji╣╗ujφcφ v²╣ku prvku) bude vypadat takto:

  4. void __fastcall TForm1::ListBox1MeasureItem(TWinControl *Control,
          int Index, int &Height)
    {
      ListBox1->Canvas->Font->Name = ListBox1->Items->Strings[Index];
      ListBox1->Canvas->Font->Size = 0;
      Height = ListBox1->Canvas->TextHeight("Wg") +2;
    }
    Obsluha OnDrawItem (zobrazenφ prvku seznamu) vypadß takto:
    void __fastcall TForm1::DrawItem(TWinControl *Control,
          int Index, TRect &Rect, TOwnerDrawState State)
    {
      ListBox1->Canvas->FillRect(Rect);
      ListBox1->Canvas->Font->Name =ListBox1->Items->Strings[Index];
      ListBox1->Canvas->Font->Size = 0;
      ListBox1->Canvas->TextOut(Rect.Left+1, Rect.Top+1,
                                ListBox1->Items->Strings[Index]);
    }
    Obsluha kliknutφ na prvku seznamu pouze zobrazφ jmΘno vybranΘho prvku ve spodnφ komponent∞ Label:
    Label2->Caption = ListBox1->Items->Strings[ListBox1->ItemIndex];
    Zb²vß je╣t∞ vytvo°it obsluhu OnCreate formulß°e. Je tvo°ena p°φkazem:
    ListBox1->Items = Screen->Fonts;
    Tφm je aplikace hotova. M∙╛eme ji vyzkou╣et. 
  5. V tΘto kapitole se je╣t∞ seznßmφme s pou╛φvßnφm dal╣φ ze zßkladnφch komponent a to s komponentou ScrollBar. P°φmΘ pou╛itφ tΘto komponenty je vzßcnΘ. Typick²m p°φkladem je umo╛n∞nφ toho, aby si u╛ivatel mohl vybrat celoΦφselnou hodnotu z urΦitΘho rozsahu. ZaΦneme s v²vojem novΘ aplikace. Na formulß° umφstφme t°i komponenty ScrollBar a vlevo od ka╛dΘ z nich komponentuLabel. Ka╛d² posuvnφk se vztahuje k jednΘ ze t°φ zßkladnφch barev a budeme s nimi urΦovat slo╛ky barvy formulß°e. Posuvnφky majφ mnoho zvlß╣tnφch vlastnostφ. Min a Max pou╛φvßme k urΦenφ rozsahu mo╛n²ch hodnot, Position obsahuje souΦasnou pozici, vlastnosti LargeChange a SmallChange urΦujφ kroky, o kterΘ se zm∞nφ hodnota posuvnφku. V na╣em p°φklad∞ budou v╣echny posuvnφky mφt mo╛nΘ hodnoty od 0 do 255, poΦßteΦnφ hodnotu 192 a kroky budou 25 a 1. Obsluha udßlosti OnScroll posuvnφku zm∞nφ hodnotu Caption sousednφ komponenty Label a barvu formulß°e. Nap°. pro prvnφ posuvnφk bude tvo°ena p°φkazy:

  6. Label1->Caption = "╚ervenß: " + IntToStr(ScrollPos);
    Color=RGB(ScrollBar1->Position,ScrollBar2->Position,ScrollBar3->Position);
    Dal╣φ posuvnφky budou pro slo╛ky zelenß a modrß. Jejich obsluhy budou podobnΘ. Vytvo°te je sami. Funkce RGB vezme t°i hodnoty slo╛ek a vytvo°φ hodnotu s k≤dem v²slednΘ barvy. Pov╣imn∞te si, ╛e obsluha udßlosti OnScroll mß t°i parametry: Sender, ScrollCode (druh udßlosti) a ScrollPos (poslednφ pozici posuvnφku). Druh udßlosti m∙╛e b²t pou╛it pro velice p°esnΘ rozli╣enφ akcφ u╛ivatele. Jeho hodnota indikuje, zda u╛ivatel posouvß ukazatel (scTrack, scPosition a scEndScroll), zda kliknul na ╣ipky nebo na li╣tu v jednom ze dvou mo╛n²ch sm∞r∙ (scLineUp, scLineDown, scPageUp a scPageDown) a zda se pokusil o posun mimo rozsah (scTop a scBottom).
  7. Vytvo°te aplikaci, kde na formulß° umφstφte posuvnφk a komponentu Label s n∞jak²m textem. Pomocφ posuvnφku m∞≥te velikost pφsma komponenty Label (od 8 do 72).
  8. Ta╛enφ m∙╛e usnadnit u╛ivateli manipulaci s objekty na formulß°i. U╛ivatel m∙╛e tßhnout celΘ komponenty nebo tßhnout prvky z komponenty typu ListBox do jin²ch komponent.

  9. Ka╛d² ovladaΦ mß vlastnost DragMode, kterß urΦuje jak komponenta reaguje na zahßjenφ ta╛enφ. Pokud DragMode je dmAutomatic, pak ta╛enφ zaΦφnß automaticky kdy╛ u╛ivatel stiskne tlaΦφtko my╣i s kurzorem my╣i nad ovladaΦem. Proto╛e dmAutomatic m∙╛e kolidovat s dal╣φmi aktivitami my╣i, obvykle nastavujeme DragMode na dmManual (implicitnφ) a ta╛enφ zahßjφme zpracovßnφm udßlosti stisknutφ tlaΦφtka my╣i. K zahßjenφ ruΦnφho °φzenφ ta╛enφ volßme metodu BeginDrag komponenty.
    BeginDrag p°ebφrß parametr typu bool nazvan² Immediate. Pokud parametr mß hodnotu true, pak ta╛enφ zaΦφnß bezprost°edn∞, stejn∞ jako kdy╛ DragMode je nastaveno na dmAutomatic. P°i hodnot∞ false, ta╛enφ zaΦφnß a╛ p°i nepatrnΘm pohybu my╣φ (tφm lze rozli╣it zaΦßtek ta╛enφ od kliknutφ). Do obsluhy stisknutφ tlaΦφtka my╣i m∙╛eme takΘ umφstit n∞jakou podmφnku, nap°. testovat kterΘ tlaΦφtko my╣i bylo stisknuto.
    Nßsledujφcφ k≤d nap°. zpracovßvß udßlost stisknutφ my╣i nad oknem seznamu soubor∙ a ta╛enφ zahßjφme pouze p°i stisku levΘho tlaΦφtka my╣i:
    void __fastcall TFMForm::FileListBox1MouseDown(TObject *Sender,
                    TMouseButton Button, TShiftState Shift, int X, int Y)
    {
      if (Button == mbLeft) // pouze p°i stisknutΘm levΘm tlaΦφtku
      {
        TFileListBox *pLB = (TFileListBox *)Sender;
        if (pLB->ItemAtPos(Point(X,Y), true) >= 0) // je zde prvek?
          pLB->BeginDrag(false);                   // pokud ano, tßhneme
      }
    }
    D°φve ne╛ m∙╛eme prvek tßhnout, musφme urΦit, kam m∙╛eme prvek p°etßhnout. Kdy╛ u╛ivatel tßhne cokoliv nad ovladaΦem, pak ovladaΦ zφskß udßlost OnDragOver a musφme indikovat, zda ovladaΦ m∙╛e ta╛en² prvek akceptovat. C++ Builder m∞nφ kurzor my╣i v zßvislosti na tom, zda ta╛en² prvek je akceptovateln². K akceptovßnφ prvku ta╛enΘho nad ovladaΦem vytvo°φme obsluhu udßlostφ OnDragOver ovladaΦe. Obsluha mß parametr Accept, kter² nastavφme na true, pokud prvek je akceptovßn. Nastavenφm Accept na true specifikujeme, ╛e pokud v tomto mφst∞ u╛ivatel uvolnφ tlaΦφtko my╣i, pak aplikace m∙╛e generovat udßlost OnDragDrop pro stejn² ovladaΦ. Pokud Accept je false, pak aplikace nem∙╛e ukonΦit ta╛enφ prvku nad tφmto ovladaΦem. To znamenß, ╛e ovladaΦ nikdy nebude generovat udßlost OnDragDrop pro tento ovladaΦ a nemusφ tedy v∞d∞t, jak ji obslou╛it.
    Udßlost OnDragOver mß n∞kolik parametr∙, vΦetn∞ zdroje ta╛enφ a sou°adnic ukazatele my╣i. Obsluha udßlosti tyto parametry m∙╛e pou╛φt k urΦenφ, zda ta╛enφ akceptovat. ╚asto ovladaΦ akceptuje ta╛enφ prvku na zßklad∞ typu zdroje ta╛enφ, ale m∙╛e takΘ akceptovat prvky pouze specifick²ch instancφ.
    V nßsledujφcφm p°φklad∞ adresß°ov² strom akceptuje ta╛enΘ prvky pouze pokud pochßzejφ z okna seznamu soubor∙:
    void __fastcall TForm1::TreeView1DragOver(TObject *Sender,
      TObject *Source, int X, int Y, TDragState State, bool &Accept)
    {
      if (Source->InheritsFrom(__classid(TFileListBox)))
        Accept = true;
    }
    NestaΦφ pouze indikovat akceptovßnφ ta╛enφ, ale musφme takΘ definovat zpracovßnφ p°eta╛enΘho prvku. Pro zpracovßnφ p°eta╛enΘho prvku p°ipojφme k ovladaΦi akceptujφcφmu ta╛en² prvek obsluhu udßlosti OnDragDrop. Podobn∞ jako udßlost OnDragOver i udßlost OnDragDrop indikuje zdroj ta╛enφ a sou°adnice uvoln∞nφ kurzoru my╣i na akceptujφcφm ovladaΦi. Tyto informace umo╛≥ujφ obsluze zφskat pot°ebnΘ informace od zdroje ta╛enφ a urΦit, jak ta╛enφ zpracovat. Nap°. adresß°ov² strom akceptujφcφ prvek ta╛enφ z okna seznamu soubor∙ m∙╛e p°esunout soubor z jeho souΦasnΘho mφsta do urΦenΘho adresß°e:
    void __fastcall TForm1::TreeView1DragDrop(TObject *Sender,
      TObject *Source, int X, int Y)
    {
      if (Source->InheritsFrom(__classid(TFileListBox)))
      {
        TTreeNode *pNode = TreeView1->GetNodeAt(X,Y); // pNode je cφl ta╛enφ
        AnsiString NewFile = pNode->Text + AnsiString("\") +
          ExtractFileName(FileList->FileName); // jmΘno cφle ta╛enφ
        MoveFileEx(FileList->FileName.c_str(), NewFile.c_str(),
          MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED);
      }
    }
    Kdy╛ operace ta╛enφ konΦφ (u╛ivatel p°etßhne prvek nebo uvolnφ tlaΦφtko my╣i nad ovladaΦem neakceptujφcφm ta╛enφ), pak je zaslßna udßlost OnEndDrag zp∞t ovladaΦi odkud zaΦalo ta╛enφ. Tato udßlost mß d∙le╛it² parametr nazvan² Target, kter² indikuje ovladaΦ akceptujφcφ ta╛enφ. Mß-li tento parametr hodnotu NULL, pak ta╛enφ neakceptoval ╛ßdn² ovladaΦ. Parametry udßlosti OnEndDrag takΘ obsahujφ sou°adnice na p°ijφmajφcφm ovladaΦi, kde ta╛enφ skonΦilo.
    V nßsledujφcφm p°φkladu, okno seznamu soubor∙ zpracovßvß udßlost ukonΦenφ ta╛enφ p°ekreslenφm svΘho seznamu soubor∙, nebo╗ p°eta╛enφm souboru se obsah seznamu zm∞nil:
    void __fastcall TFMForm::FileList1EndDrag(TObject *Sender,
                    TObject *Target,   int X, int Y)
    {
      if (Target)
        FileList1->Update();
    }
  10. M∙╛eme pou╛φt TDragObject k p°izp∙sobenφ chovßnφ na╣eho objektu ta╛enφ. Implicitn∞, udßlosti OnDragOver a OnDragDrop indikujφ zdroj ta╛enΘho prvku a sou°adnice kurzoru my╣i nad akceptujφcφm ovladaΦem. M∙╛eme zφskat dal╣φ stavovΘ informace odvozenφm objektu ta╛enφ od TDragObject a p°edefinovßnφm jeho virtußlnφch metod. Pomocφ TDragObject, zdroj ta╛enφ je samotn² objekt a ne objekt ovladaΦe jako u objektu TDragControl.

  11. Vytvo°φme u╛ivatelsk² objekt ta╛enφ v udßlosti OnStartDrag. Pou╛ijeme ve°ejnou funkci IsDragObject v udßlosti OnDragOver kdy╛ akceptujeme ta╛enφ.
    TDragObject umo╛≥uje flexibiln∞j╣φ zpracovßnφ ta╛enφ. Normßln∞ parametr Source udßlostφ OnDragOver a OnDragDrop je ovladaΦ, kde operace ta╛enφ zaΦala. Pokud vφce ovladaΦ∙ r∙zn²ch typ∙ m∙╛e b²t zdrojem ta╛enφ stejnΘho typu dat, pak zdroj musφ mφt podporu pro ka╛d² typ ovladaΦe. Ta╛en² objekt umo╛≥uje cφli znßt pouze jak zpracovat ta╛en² objekt jako zdroj, nebo╗ ka╛d² ovladaΦ zdroje m∙╛e vytvo°it vhodn² typ ta╛enΘho objektu ve svΘ udßlosti OnStartDrag. Udßlosti OnDragOver a OnDragDrop mohou °φci zda zdroj je ta╛en² objekt a zabrßniti ovladaΦi ve volßnφ IsDragObject.
  12. M∙╛eme takΘ zm∞nit tvar ukazatele my╣i v pr∙b∞hu operace ta╛enφ. Provedeme to nastavenφm vlastnosti DragCursor komponenty. M∙╛eme takΘ vytvo°it sv∙j zdroj kurzoru.
  13. Ka╛d² Windowsovsk² program pou╛φvß zdroje. Zdroje jsou prvky programu, kterΘ nejsou spustiteln²m k≤dem. Zdroje nap°. zahrnujφ bitovΘ mapy, kurzory, dialogovß okna, ikony, nabφdky apod. Zdroje jsou obecn∞ obsa╛eny v souborech skriptu zdroj∙ (textov² soubor s p°φponou RC), kterΘ jsou p°eklßdßny p°ekladaΦem zdroj∙ a potom b∞hem fßze sestavovßnφ jsou p°ipojeny k aplikaΦnφmu EXE souboru.

  14. Zdroje jsou obvykle spojeny s provediteln²m souborem. N∞kterΘ zdroje, jako jsou bitovΘ mapy, tabulky °et∞zc∙ a zvukovΘ soubory mohou b²t ulo╛eny v externφch souborech (BMP, TXT a WAV) nebo mohou b²t p°ipojeny k aplikaΦnφmu EXE souboru. Umφst∞nφ zdroj∙ do EXE souboru mß dv∞ v²hody: Nev²hodou je zv∞t╣enφ EXE souboru. Tento soubor nenφ v∞t╣φ ne╛ spojenφ k≤du a externφch zdrojov²ch soubor∙, ale je zapot°ebφ del╣φ Φas k zavedenφ programu.
    Je zapot°ebφ se rozhodnout, zda zdroje budeme dr╛et v externφch souborech nebo zda je p°ipojφme k EXE souboru. M∙╛eme pou╛φt oba zp∙soby a dokonce jejich kombinaci v rßmci jednoho programu. TradiΦnφ Windowsovsk² program obsahuje alespo≥ jedno dialogovΘ okno a ikonu. Aplikace C++ Builderu se nepatrn∞ li╣φ. Dialogovß okna v C++ Builderu nejsou zdroji (popis formulß°e je ulo╛en jako zdroj, ale nejednß se o zdroj dialogovΘho okna). Aplikace C++ Builderu mß tradiΦnφ zdroj ikony. Kdy╛ vytvß°φme aplikaci, pak C++ Builder p°ebφrß soubor zdroje ikony. Podobn∞, kdy╛ volφme bitovou mapu pro tlaΦφtko nebo komponentu Image, pak C++ Builder vklßdß soubor bitovΘ mapy jako Φßst zdroje formulß°e. Formulß° a v╣echny jeho zdroje jsou spojeny s programov²m souborem p°i p°ekladu a sestavovßnφ programu. Toto probφhß automaticky.
    Jsou ale situace, kdy pot°ebujeme implementovat zdroje mimo normßlnφ zpracovßnφ C++ Builderu, Nap°. animaci chceme provßd∞t st°φdßnφm °ady bitov²ch map, kterΘ budou zavßd∞ny jako °ada zdroj∙ (zv²╣enφ rychlosti provßd∞nφ). Je tedy vhodnΘ znßt, jak C++ Builder p°ipojuje zdroje k programovΘmu souboru.
    Zdroje musφme takΘ vytvo°it. Pokud pou╛φvßme dobr² editor zdroj∙, pak to nenφ slo╛itΘ. Pro vytvo°enφ bitov²ch map, ikon a kurzor∙ lze pou╛φt Editor obrßzk∙ C++ Builderu. Tφmto editorem ale nenφ mo╛no vytvß°et jinΘ zdroje. Pokud mßme p°ekladaΦ Borland C++, pak k editaci zdroj∙ m∙╛eme pou╛φt Resource Workshop z tohoto produktu. Po vytvo°enφ zdroj∙ mßme soubor RC, kter² m∙╛eme p°idat k projektu C++ Builderu p°φmo nebo jej p°elo╛it do tvaru RES pomocφ p°ekladaΦe zdroj∙ (BRCC32.EXE) a k projektu p°idat soubor p°elo╛en²ch zdroj∙.
    Soubory RES nebo RC p°idßvßme k projektu pomocφ sprßvce projektu. Sprßvce projektu zobrazφme volbou View | Project Manager. Zde stiskneme tlaΦφtko Add File To Project na palet∞ nßstroj∙ sprßvce a v dialogovΘm okn∞ otev°enφ souboru vybereme p°idßvan² soubor zdroj∙ (se Sprßvcem projekt∙ se podrobn∞ji seznßmφme pozd∞ji).
  15. Pou╛itφ zdroj∙ si ukß╛eme na jednoduchΘ aplikaci. Tentokrßt pou╛ijeme ji╛ hotovou aplikaci Jumping Jack. Tento program ukazuje jednoduchou animaci se zvukov²m efektem. Hlavnφ formulß° obsahuje dv∞ tlaΦφtka, komponentu Image a komponentu Label. V tΘto aplikaci si ukß╛eme jak zavßd∞t bitovou mapu ulo╛enou jako zdroj, jak zavßd∞t a zobrazovat zdroje °et∞zc∙ a jak p°ehrßvat zvukovΘ soubory ulo╛enΘ jako zdroje. Aplikaci si stßhn∞te a vyzkou╣ejte.

  16. Podφvejte se na ΦervenΘ °ßdky v nßsledujφcφm v²pisu hlaviΦkovΘho souboru aplikace.
    #ifndef JJMainH
    #define JJMainH
    #include <vcl\Classes.hpp>
    #include <vcl\Controls.hpp>
    #include <vcl\StdCtrls.hpp>
    #include <vcl\Forms.hpp>
    #include <vcl\ExtCtrls.hpp>
    class TMainForm : public TForm
    {
    __published:    // IDE-managed Components
        TButton *Start;
        TButton *Stop;
        TImage *Image;
        TLabel *Label;
        void __fastcall FormCreate(TObject *Sender);

        void __fastcall StartClick(TObject *Sender);
        void __fastcall StopClick(TObject *Sender);
    private:        // User declarations
        bool done;
        void DrawImage(String& name);
    public:         // User declarations
        virtual __fastcall TMainForm(TComponent* Owner);
    };
    extern PACKAGE TMainForm *MainForm;
    #endif
    Na prvnφm z nich deklarujeme datovou slo╛ku typu bool, kterß je pou╛ita k urΦenφ zda animaci zastavit. Na druhΘm °ßdku je deklarace metody pou╛itΘ k zobrazovßnφ bitovΘ mapy v komponent∞ Image.
    Ve v²pisu zdrojovΘho k≤du jednotky, si pov╣imn∞te dvou funkcφ API, kterΘ jsou pou╛ity k zavßd∞nφ zdroj∙ °et∞zc∙ a zvukov²ch soubor∙. Na ΦervenΘm °ßdku, funkce LoadString zavßdφ zdroj °et∞zce do textovΘ vyrovnßvacφ pam∞ti na zßklad∞ ΦφselnΘ identifikace °et∞zce. ╪et∞zec je potom p°i°azen vlastnosti Caption komponenty Label. Na modrΘm °ßdku, funkce PlaySound je pou╛ita k p°ehrßnφ zdroje zvukovΘho souboru. P°φznak SND_ASYNC urΦuje, ╛e zvuk bude p°ehrßvßn asynchronn∞, tj. animace bude probφhat souΦasn∞ s p°ehrßvßnφm. P°φznak SND_RESOURCE °φkß Windows, ╛e zvuk je obsa╛en ve zdroji a ne v souboru na disku. Ob∞ tyto funkce p°ebφrajφ globßlnφ prom∞nnou HInstance, kterß °φkß Windows, kde hledat zdroje ve spustitelnΘm souboru. Pokud poΦφtaΦ nenφ vybaven zvukovou kartou, pak zvuk neusly╣φme.
    #include <vcl\vcl.h>
    // zapot°ebφ pro funkci PlaySound()
    #include <vcl\mmsystem.hpp>
    #pragma hdrstop
    #include "JJMain.h"
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    // definice pro zdroje °et∞zc∙
    #define IDS_UP    101
    #define IDS_DOWN  102
    HINSTANCE hInst;
    TMainForm *MainForm;
    //--------------------------------------------------------------
    __fastcall TMainForm::TMainForm(TComponent* Owner)
      : TForm(Owner), done(false)
    {
    }
    void __fastcall TMainForm::FormCreate(TObject *Sender)
    {
      hInst = (HINSTANCE)HInstance;
      // Zavedenφ a zobrazenφ prvnφ bitovΘ mapy
      Image->Picture->Bitmap->
        LoadFromResourceName((int)hInst, "ID_BITMAP1");
    }
    void __fastcall TMainForm::StartClick(TObject *Sender)
    {
      String s = "ID_BITMAP";
      char buff[10];
      done = false;
      while (!done) {
        for (int i=1;i<6;i++) {
          String resName = s + String(i);
          DrawImage(resName);
        }
        LoadString(hInst, IDS_UP, buff, sizeof(buff));
        Label->Caption = buff;
        Label->Refresh();
        PlaySound("ID_WAVEUP", hInst, SND_ASYNC | SND_RESOURCE);
        Sleep(200);
        for (int i=5;i>0;i--) {
          String resName = s + String(i);
          DrawImage(resName);
        }
        PlaySound("ID_WAVEDOWN", hInst, SND_ASYNC | SND_RESOURCE);
        LoadString(hInst, IDS_DOWN, buff, sizeof(buff));
        Label->Caption = buff;
        Label->Refresh();
        Sleep(200);
      }
    }
    void __fastcall TMainForm::StopClick(TObject *Sender)
    {
      done = true;
    }
    void TMainForm::DrawImage(String& name)
    {
      Image->Picture->Bitmap->LoadFromResourceName((int)hInst, name);
      Application->ProcessMessages();
      Sleep(20);
    }
    Nßsleduje v²pis zaΦßtku souboru skriptu zdroj∙.
    #define IDS_UP   101
    #define IDS_DOWN 102
    STRINGTABLE
    {
     IDS_UP, "Up"
     IDS_DOWN, "Down"
    }
    ID_WAVEUP   WAVE "up.wav"
    ID_WAVEDOWN WAVE "down.wav"
    ID_BITMAP1 BITMAP LOADONCALL MOVEABLE DISCARDABLE IMPURE
    {
     '42 4D 76 02 00 00 00 00 00 00 76 00 00 00 28 00'
     '00 00 20 00 00 00 20 00 00 00 01 00 04 00 00 00'
    ...
    ╚erven∞ oznaΦenΘ °ßdky definujφ zdroj tabulky °et∞zc∙. Tabulku °et∞zc∙ snadno vytvo°φme v libovolnΘm textovΘm editoru. «lutΘ °ßdky jsou zdroje WAVE (pro oba soubory WAV, kterΘ byly p°edem zaznamenßny a umφst∞ny do adresß°e projektu). Kdy╛ p°ekladaΦ zdroj∙ uvidφ deklaraci WAVE, p°eΦte urΦen² soubor a p°elo╛φ jej do binßrnφho souboru zdroj∙. BitovΘ mapy jsou vytvo°eny v tradiΦnφm editoru zdroj∙. Popis zdroj∙ pro bitovΘ mapy m∙╛e b²t velmi dlouh². Zbytek na╣eho souboru jsou zdroje bitov²ch map.

3. P°idßnφ grafiky k ovladaΦ∙m