17. Nabídka I
  1. Naše seznamování s nabídkou budeme provádět na dokončení aplikace Zápisnik. Návrhář nabídky umožňuje rychlé vytvoření nabídky. Hlavní nabídka je tvořena komponentou MainMenu. Každý prvek nabídky je instance třídy MenuItem. Nemusíme se zabývat tím, jak tyto třídy pracují, neboť Návrhář nabídky vytváření nabídky usnadňuje.

  2. Nejprve musíme přidat na formulář komponentu MainMenu. Otevřeme projekt prototypu aplikace Zápisník (vytvořený v předchozích kapitolách). Na formulář vložíme (kamkoliv) komponentu MainMenu a změníme její vlastnost Name na Nabidka. Povšimněte si, že tato komponenta má velmi málo vlastností a žádnou událost. Všechna práce nabídky je soustředěna do jednotlivých prvků nabídky. Dvojitým kliknutím na vložené komponentě MainMenu zobrazíme Návrhář nabídky. Návrhář nabídky vypadá jako prázdný formulář bez rastru. Můžeme změnit jeho velikost. Návrhář nabídky vždy udržuje volné místo pro nově vytvářený prvek nabídky. Když poprvé Návrhář nabídky spustíme, pak je vybrán prázdný prvek. Změníme jeho vlastnost Name na NabSoubor a vlastnost Caption na &Soubor. Znak & je použit pro podtržení následujícího znaku textu prvku nabídky (urychlovací klávesa). V našem případě bude v nabídce zobrazeno Soubor.
    Nabídka Soubor je nyní zobrazena v Návrháři nabídky a také na hlavním formuláři (je překrytý návrhářem). Nabídka na formuláři je od palety nástrojů oddělena komponentou Bevel. V návrháři nabídky nyní vidíme dvě volná místa (jedno pod vloženým prvkem a druhé napravo od něj). Přejdeme na spodní volné místo (Inspektor objektů zobrazuje prázdnou komponentu MenuItem a čeká na zadání Name a Caption. Vlastnost Name změníme na SouborNovy a Caption na &Nový a stiskneme Enter. Pod vloženým prvkem nabídky v Návrháři nabídky je opět vytvořen prázdný prvek. Obdobným způsobem vytvoříme tyto další prvky nabídky: Otevřít, Uložit a Uložit jako. Na vhodná místa textů vložte i znaky &. Kdykoliv se můžeme vrátit zpět a opravit případné chyby. Je také vhodné dodržovat standardní konvence. Např. když volba prvku v nabídce zobrazuje dialogové okno, pak text prvku nabídky by měl končit třemi tečkami.
    Do nabídky nyní potřebujeme vložit separátor (vodorovnou čáru, která odděluje prvky nabídky). Separátor vložíme obdobně jako libovolný jiný prvek nabídky, pouze vlastnost Caption musí být jeden znak pomlčky. Pod separátor do nabídky Soubor vložíme ještě prvky Tisk a Nastavení tiskárny, další separátor a prvek nabídky Konec.
    Tímto způsobem bychom mohli pokračovat ve vytváření dalších nabídek. Ukážeme si ale jinou možnost a to vkládání nabídky ze šablony. Standardní šablony nabídky jsou všechny v angličtině a naše nabídka nebude jazykově konzistentní, ale je vhodné vědět jak používat šablonu nabídky. Přejdeme na prázdný prvek nabídky napravo od nabídky Soubor a v místní nabídce zvolíme Insert From Template. V zobrazeném dialogovém okně vidíme seznam dostupných šablon nabídky. Můžeme používat předdefinované šablony nebo vytvořit svoje vlastní. Vybereme zde nabídku Edit a stiskneme OK. Celá nabídka Edit je vložena do naší aplikace. Vidíme, že je to snadné. Obdobně ještě provedeme vložení nabídky Help.
    V přidaných nabídkách budeme potřebovat provést asi nějaké změny. Nabídka Edit obsahuje některé zbytečné prvky. Provedeme jejich zrušení. Jedním ze zbytečných prvků je prvek Repeat <comand>. Vybereme jej v Návrháři nabídky a stiskneme klávesu Delete. To je vše, prvek je zrušen. Obdobně zrušíme prvek Paste Special. Výběr prvků v nabídce lze také rozšiřovat (použití kláves Ctrl a Shift jako když provádíme výběr v jiných aplikacích). Ukážeme si praktické použití. Nabídka Edit stále obsahuje zbytečné prvky. Vybereme zde prvek Goto a při stisknuté klávese Shift klikneme na prvek nabídky Object. Tím vybereme všechny prvky od Goto až k Object. Stiskneme klávesu Delete a všechny vybrané prvky zrušíme najednou. Přejdeme na nabídku Help a zrušíme prostřední dva prvky (zůstane zde pouze Contents a About).
    Do již vytvořené nabídky je také možno vkládat nové prvky. Vybereme prvek před který nový prvek chceme vložit a stisknneme klávesu Insert. Tím vytvoříme místo pro nově vkládaný prvek. V nabídce Edit vybereme prvek Find a stiskneme klávesu Insert. U nově vytvořené prvku změníme vlastnost Name na EditSelectAll a Caption na Select &All. Přejdeme na volné místo ve spodní části nabídky Edit a přidáme zde separátor a nový prvek (Name změníme na EditWordWrap a Caption na &Word Wrap).
    Prvky nabídky lze také přesouvat. K tomuto je možno použít operací se schránkou nebo tažení. Přetáhneme nyní prvek Select All pod prvek Undo.
    Někdy můžeme požadovat modifikaci vlastnosti několika prvků nabídky najednou. V naší aplikaci zatím nebudeme implementovat některé funkce (tisk a nápovědu). Volby v nabídce, které se týkají těchto činností zakážeme. V nabídce Help vybereme prvek Contents a nastavíme vlastnost Enabled na false. V nabídce Soubor vybereme oba prvky týkající se tisku a opět nastavíme vlastnost Enabled na false. Tím oba prvky zakážeme. Totéž provedeme s prvky Find a Replace v nabídce Edit.
    V některých případech také požadujeme vytvoření podnabídky. Podnabídka je prvek nabídky, který při výběru zobrazí další volby nabídky. Podnabídku vytvoříme tak, že vybereme prvek nabídky, který má být podnabídkou a při stisknuté klávese Ctrl stiskneme klávesu šipky vpravo. Tím se vytvoří prázdné místo (napravo od vybraného prvku) a ve vytváření podnabídky postupujeme běžným způsobem. V naší aplikaci podnabídky nebudeme používat.
    V nabídce lze také definovat zkracovací klávesy. Zkracovací klávesa je určena vlastností ShortCut. V nabídce Edit vybereme prvek Select All a změníme u něj vlastnost ShortCut na Ctrl+A. Tím jsme tomuto prvku přidali zkracovací klávesu (je zobrazována v nabídce).
    Ve vytvořené nabídce provedeme ještě některé další změny. Prvek Word Wrap slouží k přepínání volby zalamování slov. Implicitně tato volba je zapnutá a bylo by to vhodné indikovat zobrazením odškrtnutí u této volby. To provedeme nastavenám vlastnosti Checked na true. Pokud se nám jména některých prvků nabídky nelíbí, pak je můžeme přejmenovat. Je vhodné je přejmenovat dříve, než k nabídce přiřadíme kód.
    Před zahájením vytváření kódu na formulář ještě umístíme komponenty OpenDialog a SaveDialog. Nyní se již můžeme zabývat vytvářením obsluh událostí jednotlivých voleb v nabídce. Dvojitým kliknutím na prvku nabídky v Návrháři nabídky vytvoříme kostru obsluhy volby tohoto prvku (obsluha události OnClick prvku nabídky). Začneme volbou Konec. Dvojitě na ní klikneme a v Editoru kódu se objeví obsluha SouborKonecClick. Do této obsluhy zapíšeme příkaz
    Close();
    Funkce Close uzavírá formulář. Pokud by se naše aplikace skládala z více formulářů a chtěli bychom ji uzavřít z libovolného místa, pak bychom museli použít příkaz
    Application->Terminate();
    (Close je možno k uzavření aplikace použít pouze na hlavním formuláři; na jiných formulářích je zavřen pouze formulář).
    Další jednoduchá obsluha je pro volbu Edit | Cut. Je tvořena příkazem
    Memo->CutToClipboard();
    Vytvoříme ji. Další jednoduché obsluhy vytvořte sami (Copy, Paste a Select All). Tyto obsluhy obsahují volání metod CopyToClipboard, PasteFromClipboard a SelectAll objektu Memo. Obsluha volby Nový bude tvořena příkazy:
    if (Memo->Modified) {
      switch (MessageDlg("Současný soubor byl změněn. Chcete jej uložit?",
        mtConfirmation, TMsgDlgButtons() << mbYes << mbNo << mbCancel, 0)) {
        case mrYes:
          SouborUlozClick(Sender);
          break;
        case mrCancel: return;
      }
    }
    if (Memo->Lines->Count > 0) Memo->Clear();
    SaveDialog1->FileName = "";
    Voláme zde obsluhu volby Uložit. Obsluha volby Otevřít je tvořena příkazy:
    if (Memo->Modified) {
      switch (MessageDlg("Současný soubor byl změněn. Chcete jej uložit?",
        mtConfirmation, TMsgDlgButtons() << mbYes << mbNo << mbCancel, 0)) {
        case mrYes:
          SouborUlozClick(Sender);
          break;
        case mrCancel: return;
      }
    }
    OpenDialog1->FileName = "";
    if (OpenDialog1->Execute())
    {
      if (Memo->Lines->Count > 0) Memo->Clear();
      Memo->Lines->LoadFromFile(OpenDialog1->FileName);
      SaveDialog1->FileName = OpenDialog1->FileName;
    }
    Obsluha volby Uložit je tato:
    if (SaveDialog1->FileName != "")
    {
      Memo->Lines->SaveToFile(SaveDialog1->FileName);
      Memo->Modified = false;
    }
    else SouborUlozJakoClick(Sender);
    a obsluha Uložit jako vypadá takto:
    SaveDialog1->Title = "Uložit jako";
    if (SaveDialog1->Execute())
    {
      Memo->Lines->SaveToFile(SaveDialog1->FileName);
      Memo->Modified = false;
    }
    Obsluha WordWrap bude tvořena příkazy (pokud se provádí zalamování slov, pak je zbytečný vodorovný posuvník):
    Memo->WordWrap = !Memo->WordWrap;
    EditWordWrap->Checked = Memo->WordWrap;
    if (Memo->WordWrap) Memo->ScrollBars = ssVertical;
    else Memo->ScrollBars = ssBoth;
    a poslední obsluha tj. Undo, příkazem (komponenta Memo nemá metodu Undo, je zapostředí zaslat zprávu Windows, aby tuto operaci provedl):
    SendMessage(Memo->Handle, WM_UNDO, 0, 0);
    Aplikce je hotova. Můžeme ji vyzkoušet. Ukázali jsme si, jak aplikaci vybavit nabídkou.
  3. Aplikaci můžeme také vybavit místní nabídkou. Místní nabídku k některé komponentě (každá komponenta může mít jinou místní nabídku) nebo samotnému formuláři přiřadíme vlastností PopupMenu komponenty. Nejprve ale místní nabídku musíme vytvořit.

  4. K naši předchozí aplikaci (přesněji její komponentě Memo) přidáme nyní místní nabídku s volbami Cut, Copy a Paste. Na formulář umístíme komponentu PopupMenu, změníme její vlastnost Name na MistniNabidka a dvojitě na ní klikneme. Spustíme tím Návrhář nabídky. Volby vkládané do místní nabídky se vyskytují v hlavní nabídce a můžeme je tedy překopírovat. V místní nabídce Návrháře formuláře zvolíme Select Menu a v zobrazeném dialogovém okně je uveden seznam nabídek dostupných z naší aplikace. Zvolíme zde Nabidka a stiskneme OK. Tím je v Návrháři nabídky zobrazena naše hlavní nabídka. V nabídce Edit vybereme prvky Cut, Copy a Paste a stiskem Ctrl+C je překopírujeme do schránky. V místní nabídce Návrháře nabídky opět zvolíme Select Menu a vybereme MistniNabidka (vrátíme se do vytvářené místní nabídky). Stiskem Ctrl+V obsah schránky vložíme do místní nabídky. Dále je nutno změnit vlastnosti Name vložených prvků nabídky. Změníme je na PopupCut, PopupCopy a PopupPaste. Posledním krokem je vytvoření obsluh událostí voleb místní nabídky. Obsluhy jsou ale stejné jako pro obdobné volby hlavní nabídky a můžeme tedy tyto již vytvořené obsluhy přiřadit i prvkům místní nabídky. U komponenty Memo je také nutno změnit vlastnost PopupMenu na MistniNabidka.
    Tlačítka na paletě nástrojů jsou zatím nefunkční. Je nutno jejím událostem OnClick přiřadit obsluhy. Je opět možno použít již vytvořené obluhy pro volby v hlavní nabídce. Tím jsme dokončili vývoj naší aplikace.
  5. Viděli jsme již, jak použít vytvořenou šablonu nabídky. Nyní se ještě zmíníme o tom jak takovouto šablonu vytvořit. Při vytváření šablony nabídky začneme vývojem nové aplikace a na formulář umístíme komponentu MainMenu. V Návrháři nabídky nyní vytvoříme požadovanou nabídku a volbou Save As Template z místní nabídky Návrháře nabídky ji uložíme (dáme ji smysluplné jméno). Pro zrušení šablony nabídky v místní nabídce Návrháře nabídky zvolíme Delete Templates, v zobrazeném okně vybereme rušenou šablonu a stiskneme OK.
  6. V další aplikaci se budeme zabývat změnami v nabídce. Při modifikaci prvku nabídky se obvykle používají tři vlastnosti. Vlastnost Checked používáme k přidání nebo odstranění značky odškrtnutí v prvku nabídky. Vlastnost Enabled je možno použít k znevýraznění prvku nabídky a uživatel jej potom nemůže zvolit. Dále můžeme měnit vlastnost Caption prvku nabídky, tzn. zobrazený text prvku nabídky. Použití těchto vlastností si ukážeme v této aplikaci. Na formulář umístíme dvě komponenty GroupBox (nad sebe) a vedle každé z nich umístíme tlačítko (s textem Ukryj). Do horního GroupBox umístíme dva editační ovladače (vložíme do nich nějaké implicitní texty) a změníme jeho Caption na Editační ovladače. Do spodního GroupBox umístíme dvě značky a změníme jeho Caption na Značky. Na formulář přidáme ještě nabídku a to podle následující tabulky (pokud při zadávání vlastností prvků nabídky zadáváme pouze Caption, pak vlastnost Name je odvozena ze zadaného Caption; vygenerovaná Name jsou ale poněkud nesrozumitelné - jsou vynechána písmena s diakritickými znaménky; tuto možnost použijeme v této aplikaci):
  7. &Soubor  &Tlačítka &Zobrazit  &Nápověda
    &Konec Zakaž &první &Editační ovladače &O aplikaci
    Zakaž &druhé   Znač&ky
    U prvku nabídky Zakaž první nastavíme vlastnost Enabled na false a u obou prvků v nabídce Zobrazit nastavíme Checked na true. Komponenty uvnitř GroupBox se v naši aplikaci nevyužívají, tlačítka budeme používat k zobrazení nebo skrytí jednotlivých GroupBox i s ovladači, které obsahují. Stejnou akci je možné provést příkazy v nabídce Zobrazit. Pokaždé, když zvolíme jeden z těchto příkazů nebo stiskneme jedno z těchto tlačítek, provedou se tři akce: změní se viditelnost příslušného GroupBox, změní se text na tlačítku z Ukryj na Zobraz (nebo naopak) a změní se stav odškrtnutí prvku nabídky. Obsluha stisku prvního tlačítka a volby Editační ovladače bude tedy tvořena příkazy (pro obě akce použijte stejnou obsluhu události; vidíme, že jména prvků nabídky jsou nesrozumitelná):
    GroupBox1->Visible = ! GroupBox1->Visible;
    Editanovladae1->Checked = ! Editanovladae1->Checked;
    if (GroupBox1->Visible) Button1->Caption = "Ukryj";
    else Button1->Caption = "Zobraz";
    Obdobně vytvořte i obsluhu události pro druhé tlačítko a volbu Značky. Dále se budeme zabývat volbami v nabídce Tlačítka. Základní myšlenkou je, aby tyto volby měnily text podle prováděné akce. Toho dosáhneme např. obsluhou:
    if (Button1->Enabled){
      Button1->Enabled = false;
      Zakaprvn1->Caption = "Povol &první";
    } else {
      Button1->Enabled = true;
      Zakaprvn1->Caption = "Zakaž &první";
    }
    Situace je ale složitější protože požadujeme, aby druhé tlačítko mohlo být povoleno, pouze pokud je povoleno první tlačítko. Mohou být tedy povoleny obě tlačítka, žádné tlačítko nebo první povoleno a druhé zakázáno. Když jsou obě tlačítka povolena, zakážeme volbu nabídky Zakaž první, čímž zabráníme uživateli v zakázání prvního tlačítka. Když jsou zakázána obě tlačítka, zakážeme volbu nabídky Zakaž druhé, čímž zabráníme v povolení pouze druhého tlačítka. Předchozí obsluhu tedy nahradíme obsluhou:
    if (Button1->Enabled){
      Button1->Enabled = false;
      Zakaprvn1->Caption = "Povol &první";
      Zakadruh1->Enabled = false;
    } else {
      Button1->Enabled = true;
      Zakaprvn1->Caption = "Zakaž &první";
      Zakadruh1->Enabled = true;
    }
    Obsluha volby Zakaž druhé je obdobná
    V této aplikaci se zabýváme změnou prvku nabídky. Mohli bychom také zneviditelnit prvek nabídky změnou hodnoty vlastnosti Visible na false. Je ale vhodné tuto operaci nepoužívat. Doplňte zbývající obsluhy a aplikaci vyzkoušejte. V této aplikaci vidíme, že vlastnosti Name jednotlivých prvků nabídek jsou poněkud ?nečitelné. Je vhodné je mě?.
  8. Vlastnost Visible je možno používat ke změně viditelnosti jednotlivých nabídek. Můžeme si vybrat mezi zakázanými nebo neviditelnými nabídkami. Druhý přístup je častější. Do nabídky předchozí aplikace doplníme další nabídku Nabídky s volbami: ?Odstraň soubor?, ?Odstraň nápovědu?, ?Zakaž tlačítka? a ?Zakaž zobrazit?. Obsluha první volby bude tvořena příkazy:

  9. Soubor1->Visible = ! Soubor1->Visible;
    Odstrasoubor1->Checked = ! Odstrasoubor1->Checked;
    Vytvořte zbývající obsluhy a aplikaci vyzkoušejte.
  10. V jedné aplikaci můžeme také střídat několik nabídek. Pokusíme se to vyzkoušet. Vytvoříme aplikaci, ve které na formulář vložíme dvě komponenty MainMenu (pro každou z těchto komponent navrhneme jinou nabídku). Právě používaná nabídka formuláře je určena vlastností Menu formuláře. Můžeme tedy v první nabídce mít prvek nabídky s obsluhou:

  11. Form1->Menu = MainMenu2;
    Volbou tohoto prvku zobrazíme druhou nabídku. Obdobně v druhé nabídce budeme mít volbu pro zobrazení první nabídky. Dokončete tuto aplikaci a vyzkoušejte.
  12. Před naším seznamováním s nabídkou jsme vytvořili aplikaci, kde jsme myší kreslili na formuláři čtverce a kruhy. Nyní k této aplikaci přidáme nabídku pro volbu barvy tvarů a jejich okrajů (tím se myslí barva štětce a pera) a pro výběr velikosti tvaru a jeho okraje. Naši aplikaci vybavíme touto nabídkou (urychlovací klávesy si doplňte sami; doplňujte je také v dalších aplikacích):
  13. Soubor  Barva Velikost Nápověda
    Nový Pero Zvětšit šířku pera  O aplikaci
    ----- Štětec  Zmenšit šířku pera
    Konec ------------------
    Zvětšit velikost tvaru
    Zmenšit velikost tvaru
    Formulář inicializuje a ukládá pouze současný poloměr kruhu (tato hodnota se také používá jako polovina strany čtverce), ostatní hodnoty jsou uloženy ve vlastnostech plátna (Canvas). Jako soukromou položku formuláře tedy přidáme:
    int Polomer;
    Pro změnu barev použijeme komponentu ColorDialog. Budeme se také snažit, aby rozměry nebyly záporné. Obsluha události OnCreate formuláře bude tvořena příkazem:
    Polomer = 5;
    Obsluhu události OnMouseDown změníme pouze tak, že namísto konstant 10 použijeme položku Polomer. Obsluha události OnMouseMove zůstane beze změny. Obsluha volby v nabídce Barva | Pero bude tvořena příkazy:
    ColorDialog1->Color = Canvas->Pen->Color;
    if (ColorDialog1->Execute()) Canvas->Pen->Color = ColorDialog1->Color;
    Obdobně vyřešíme i změnu barvy štětce (Brush). Obsluha volby Velikost | Zmenšit šířku pera bude:
    Canvas->Pen->Width = Canvas->Pen->Width - 2;
    if (Canvas->Pen->Width < 3) Zmenitkupera1->Enabled = false;
    a obsluha volby Velikost | Zvětšit šířku pera bude:
    Canvas->Pen->Width = Canvas->Pen->Width + 2;
    Zmenitkupera1->Enabled = true;
    Obdobně vyřešte volby změny velikosti tvaru (položky Polomer). Tuto hodnotu měňte s krokem 5. Volbou Nápověda | O aplikaci zobrazte okno zpráv funkcí ShowMessage (zobrazte zde název aplikace a svoje jméno). Obsluha volby Soubor | Konec bude tvořena příkazem:
    Close();
    Zbývající nevyřešená volba v nabídce (Soubor | Nový). Je tvořena příkazem:
    Refresh();
    Tato metoda překreslí celé okno a smaže jeho obsah. Tím ale ztratíme svoji kresbu. Aplikaci vyzkoušejte.
  14. Předchozí aplikace má stále ten nedostatek, že překrytím okna nebo zmenšením jeho velikosti ztrácíme jeho obsah. Nyní se tento problém pokusíme vyřešit. Nejprve se ale musíme seznámit s tím, co je ve Windows kreslení a malování. Kreslení (drawing) je to, co jsme zatím prováděli v naši aplikaci (aplikace neví jak vytvořený obrázek překreslit). Malování (painting) je to, co musíme dělat, aby aplikace překreslila za jakýchkoli podmínek nakreslený obrázek. Jestliže nabídneme metodu pro překreslení obsahu formuláře (obsluha události OnPaint), pak tato metoda je automaticky volána, když část formuláře byla skryta a potřebuje překreslit.

  15. Vyřešení našeho problému spočívá v ukládání informací o nakreslených tvarech a vytvoření obsluhy události OnPaint, ve které naše tvary zobrazíme. Pro ukládání informací o nakresleném tvaru si vytvoříme novou strukturu:
    struct TTvar {
      bool Kruznice;
      int X, Y, Velikost, PeroSire;
      TColor BarvaPera, BarvaStetce;
    };
    Deklaraci této struktury umístíme do hlavičkového souboru formuláře před deklaraci typu formuláře. Proměnné této struktury (popisující jednotlivé tvary) budeme ukládat do seznamu (standardní třída TList). Tento seznam nazvaný SeznamTvaru je soukromá položka formuláře a je inicializována v obsluze události OnCreate formuláře:
    Polomer = 5;
    SeznamTvaru = new TList;
    Tvar do seznamu budeme přidávat v obsluze události OnMouseDown a po přidání tvaru do seznamu vždy provedeme překreslení. Tato událost bude nyní obsahovat příkazy:
    TTvar *Tvar;
    if (Button == mbLeft) {
      Tvar = new TTvar;
      Tvar->Kruznice = ! Shift.Contains(ssShift);
      Tvar->X = X;
      Tvar->Y = Y;
      Tvar->Velikost = Polomer;
      Tvar->PeroSire = Canvas->Pen->Width;
      Tvar->BarvaPera = Canvas->Pen->Color;
      Tvar->BarvaStetce = Canvas->Brush->Color;
      SeznamTvaru->Add(Tvar);
      Repaint();
    }
    Aby probíhalo překreslování, je nutno vytvořit obsluhu události OnPaint:
    TTvar *Tvar;
    Tvar = new TTvar;
    for (int I=0; I < SeznamTvaru->Count; I++){
      Tvar = (TTvar *)SeznamTvaru->Items[I];
      Canvas->Pen->Color = Tvar->BarvaPera;
      Canvas->Pen->Width = Tvar->PeroSire;
      Canvas->Brush->Color = Tvar->BarvaStetce;
      if (Tvar->Kruznice) Canvas->Ellipse(Tvar->X-Tvar->Velikost,
                Tvar->Y-Tvar->Velikost,Tvar->X+Tvar->Velikost,
                Tvar->Y+Tvar->Velikost);
      else Canvas->Rectangle(Tvar->X-Tvar->Velikost,
                Tvar->Y-Tvar->Velikost,Tvar->X+Tvar->Velikost,
                Tvar->Y+Tvar->Velikost);
    }
    delete Tvar;
    V této obsluze jsou vykresleny všechny tvary uvedené v seznamu (počet prvků seznamu je určen Count a přistupujeme k nim indexováním vlastnosti Items). Musíme ještě změnit obsluhu volby nabídky Soubor | Nový a to takto:
    if (SeznamTvaru->Count > 0)
      if (MessageDlg("Chcete opravdu zrušit všechny tvary?",
          mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
        SeznamTvaru->Clear();
        Refresh();
      }
    Aplikaci vyzkoušejte. Přidejte ještě volbu nabídky pro změnu barvy formuláře.
  16. Komponenta Image je obvykle považována za zobrazovač obrázků. Vytvoříme nyní aplikaci pro zobrazování obrázků. Na formulář umístíme komponentu Image (bude zabírat celou plochu formuláře) a vytvoříme následující nabídku:
  17. Soubor Volby Nápověda
    Otevřít Zaplnit O aplikaci
    ----- Centrovat
    Konec
    Obsluhu voleb Konec a O aplikaci si vytvořte sami. Volba Otevřít bude tvořena kódem:
    if (OpenDialog1->Execute()){
      Image1->Picture->LoadFromFile(OpenDialog1->FileName);
      Caption = "Obrázek: " + OpenDialog1->FileName;
    }
    Na formulář musíme tedy vložit i komponentu OpenDialog, kde nastavíme vlastnosti Filter na Bitové mapy (*.bmp), Ikony (*.ico) a MetaSoubor (*.wmf) a Options na [ofHideReadOnly, ofPathMustExist, ofFileMustExist]. Zjistěte, co tyto volby znamenají. Volba nabídky Zaplnit bude tvořena příkazy:
    Image1->Stretch = ! Image1->Stretch;
    Zaplnit1->Checked = Image1->Stretch;
    a volba Centrovat příkazy:
    Image1->Center = ! Image1->Center;
    Centrovat1->Checked = ! Image1->Center;
    Nyní již aplikaci můžeme vyzkoušet. Zjistěte, co provádějí jednotlivé volby nabídky.
  18. Poslední dvě aplikace nyní spojíme dohromady. Můžeme načíst existující bitovou mapu, nakreslit přes ní několik tvarů a výsledek uložit do souboru. V této aplikaci použijeme předposlední verzi aplikace kreslení tvarů (informace o nakreslených tvarech nemusíme ukládat, neboť jsou vloženy přímo do bitové mapy). Všechny výstupní operace týkající se plátna formuláře musíme změnit na plátno komponenty Image (např. Image1->Canvas->Pen->Color). Aplikace bude mít nabídku:
  19. Soubor  Barva Velikost  Nápověda
    Nový Pero Zvětšit šířku pera O aplikaci
    Otevřít Štětec Zmenšit šířku pera
    Uložit jako ------------------
    ----- Zvětšit velikost tvaru
    Konec Zmenšit velikost tvaru
    Volba Barva | Pero bude tedy obsahovat příkazy:
    ColorDialog1->Color = Image1->Canvas->Pen->Color;
    if (ColorDialog1->Execute())
      Image1->Canvas->Pen->Color = ColorDialog1->Color;
    Volba Ulož jako bude tvořena příkazem:
    if (SaveDialog1->Execute())
      Image1->Picture->SaveToFile(SaveDialog1->FileName);
    U komponenty SaveDialog musíme nastavit tyto vlastnosti: DefaultExt na BMP, FileName na Tvary.bmp, Filter na Soubory bitové mapy (*.bmp) a Options na [ofOwerwritePromtp, ofHideReadOnly, ofPathMustExist, ofFileMustExist]. U komponenty OpenDialog nastavíme vlastnosti: DefaultExt na BMP, Filter na Soubory bitové mapy (*.bmp) (v této aplikaci je možno používat pouze soubory bitových map) a Options na [ofHideReadOnly, ofPathMustExist, ofFileMustExist, ofShareAware]. Musíme samozřejmě uložit původní barvu a po otevření bitové mapy ji obnovit. To vyřešíme v obsluze volby Otevřít takto:
    if (OpenDialog1->Execute()){
      TColor BPera = Image1->Canvas->Pen->Color;
      TColor BStetce = Image1->Canvas->Brush->Color;
      int SirePera = Image1->Canvas->Pen->Width;
      Image1->Picture->LoadFromFile(OpenDialog1->FileName);
      Caption = "Obrázek: " + OpenDialog1->FileName;
      Image1->Canvas->Pen->Color = BPera;
      Image1->Canvas->Brush->Color = BStetce;
      Image1->Canvas->Pen->Width = SirePera;
    }
    Za zmínku stojí ještě obsluha volby Nový. Zde je nutno plochu komponenty Image vybarvit bílou barvou. To provedeme takto:
    if (MessageDlg("Chcete opravdu zrušit všechny tvary?",
        mtConfirmation, TMsgDlgButtons() << mbYes << mbNo, 0) == mrYes){
      TRect Oblast=Rect(0,0,Image1->Picture->Width,Image1->Picture->Height);
      TColor Barva = Image1->Canvas->Brush->Color;
      Image1->Canvas->Brush->Color = clWhite;
      Image1->Canvas->FillRect(Oblast);
      Image1->Canvas->Brush->Color = Barva;
    }
    Ostatní obsluhy událostí nepotřebují žádné vysvětlení. Vytvořte je sami a aplikaci vyzkoušejte.
17. Nabídka I