14. Formuláře I
  1. Nejjednodušší způsob zobrazení zprávy pro uživatele je použití okna zpráv, které zobrazíme funkcí ShowMessage. Ukážeme si to na následující aplikaci: Vytvoříme nový projekt a na formulář umístíme tlačítko. Do obsluhy události OnClick tlačítka zapíšeme následující kód:

  2. ShowMessage("C++ Builder vás zdraví");
    Aplikaci spustíme a po stisku tlačítka je zobrazeno okno zpráv se zadaným textem.
  3. Metoda MessageDlg zobrazuje okno zpráv uprostřed obrazovky. Toto okno zpráv zobrazuje text zprávy, titulek, ikonu a tlačítka. Metoda má čtyři parametry: První parametr určuje text zprávy, druhý typ okna (titulek a ikonu okna), třetí zobrazená tlačítka v okně a poslední kontext nápovědy (co bude zobrazeno při stisku tlačítka Help nebo klávesy F1).

  4. Druhý parametr je výčtového typu a možné hodnoty jsou: mtWarning (varování), mtError (chyba), mtInformation (informace), mtConfirmation (potvrzení) a mtCustom (uživatelský typ). Tyto hodnoty určují typ okna, tj. titulek a ikonu okna. Třetí parametr (použitá tlačítka) je množina typu TMsgDlgButtons s možnými hodnotami: mbYes, mbNo, mbOK, mbCancel, mbHelp, mbAbort, mbRetry, mbIgnore a mbAll. Jestliže nechceme používat kontext nápovědy, pak poslední parametr bude mít nulovou hodnotu.
    Použití si ukážeme na následujícím příkladu. Vytvoříme novou aplikaci s tlačítkem. Obsluha stisku tlačítka bude tvořena příkazem:
    MessageDlg("Jsi tam?", mtConfirmation,
               TMsgDlgButtons() << mbYes << mbNo, 0);
    Aplikace je hotova a můžeme ji vyzkoušet. Vyzkoušejte, jak se projeví změna druhého parametru na vzhledu okna zpráv. Pokuste se také změnit zobrazená tlačítka.
  5. Ve většině případů ale budeme chtít zjistit, kterým tlačítkem bylo okno uzavřeno (je možno zjistit z vrácené hodnoty). Možné vrácené hodnoty jsou: mrNone, mrAbort, mrYes, mrNo, mrOK, mrRetry, mrCancel, mrIgnore a mrAll. Ukážeme si to na příkladu. V předchozím zadámí změníme obsluhu stisku tlačítka takto:

  6. switch (MessageDlg("Chceš ukončit aplikaci?", mtConfirmation,
                       TMsgDlgButtons() << mbYes << mbNo, 0)){
      case mrYes:
        MessageDlg("Ukončení aplikace.", mtInformation,
                   TMsgDlgButtons() << mbOK, 0);
        Close();
        break;
      case mrNo:
        MessageDlg("Aplikace pokračuje v práci.", mtInformation,
                   TMsgDlgButtons() << mbOK, 0);
    }
    Vyzkoušejte.
  7. Existuje také metoda MessageDlgPos, která se od MessageDlg liší pouze tím, že má o dva parametry více. Tyto parametry (jsou poslední) určují souřadnice zobrazení okna zpráv.
  8. Na následující aplikaci si ukážeme, jak C++ Builder používá jednotky formulářů. Vytvoříme jednoduchou aplikaci, která zobrazí druhé okno, když stiskneme tlačítko. Začneme vytvářet novou aplikaci volbou File | New Aplication. U formuláře změníme vlastnost Name na HlavniFormular a vlastnost Caption na Testovací program s více formuláři. Uložíme projekt (jednotku nazveme Hlavni a projekt ViceForm). Na formulář nyní umístíme tlačítko. Změníme jeho Name na ZobrazForm2 a Caption na Zobraz druhý formulář.

  9. K vytvoření nového formuláře zvolíme File | New Form. Nový formulář je umístěn nad našim původním formulářem (má stejné rozměry). My ale budeme potřebovat menší formulář. Zmenšíme tedy jeho rozměry asi na polovinu a umístíme jej doprostřed hlavního formuláře. U nového formuláře změníme vlastnost Name na DruhyForm a vlastnost Caption na Druhý formulář. Zvolíme File | Save a uložíme druhý formulář pod jménem Druhy.
    Na druhý formulář umístíme doprostřed ještě komponentu Label. U této komponenty změníme vlastnost Caption na Toto je druhý formulář a tento text necháme zobrazovat větším a barevným písmem.
    Klikneme na hlavní formulář a dvojitě klikneme na tlačítko (budeme vytvářet jeho obsluhu). Obsluha tlačítka bude tvořena příkazem:
    DruhyForm->ShowModal();
    Když nyní spustíme program, pak překladač nám oznamuje, že nalezl nedefinovaný symbol DruhyForm. Toto je ale náš druhý formulář. Máme nyní dva zdrojové soubory, každý s hlavičkovým souborem. Problém je ten, že jednotka Hlavni nevidí deklaraci (hlavičkový soubor) jednotky Druhy. Když se podíváme na začátek jednotky Hlavni, pak vidíme tyto řádky:
    #include <vcl.h>
    #pragma hdrstop
    #include "Hlavni.h"
    //--------------------------------------------------------------
    Vidíme zde použití #include "Hlavni.h", ale nikde nevkládáme hlavičkový soubor Druhy.h. Je zapotřebí zvolit File | Include Unit Hdr, čímž zobrazíme dialogové okno Include Unit. V okně vidíme seznam dostupných jednotek. V tomto dialogovém okně se zobrazují pouze jednotky, které existují v projektu a nejsou ještě vloženy do aktuální jednotky. Již vložené jednotky zde nejsou uváděny. V našem případě je zde pouze jednotka Druhy. Vybereme ji a stiskneme OK. Když se podíváme na začátek jednotky Hlavni, pak zde vidíme:
    #include <vcl.h>
    #pragma hdrstop
    #include "Hlavni.h"
    #include "Druhy.h"
    //--------------------------------------------------------------
    Nyní je již vše v pořádku, aplikaci můžeme vyzkoušet. Projekt si uložte, budeme jej ještě potřebovat.
    Při práci s více formuláři je pouze zapotřebí pomocí volby File | Include Unit Hdr zajistit vložení hlavičkových souborů jednotek na které se odkazujeme do zdrojových jednotek formuláře, ze kterých se odkazujeme.
  10. Dále se budeme zabývat překladem a sestavováním projektů v C++ Builderu. Při každé volbě Run | Run C++ Builder překládá a sestavuje náš program. Nejsou ale překládány všechny jednotky projektu, ale pouze ty z nich, které byly změněny od posledního překladu. Toto zkracuje dobu trvání překladu. Informace o tom, které jednotky byly změněny jsou udržovány automaticky C++ Builderem. Ne vždy ale chceme program spouštět. Např. můžeme chtít program pouze přeložit, abychom věděli, zda v něm nejsou chyby. C++ Builder má v nabídce Project tři volby (Compile Unit, Make a Build), které lze použít pro překlad programu (jsou zde další volby pro překlad skupiny projektů, ale těmi se zatím nebudeme zabývat).

  11. Volba Project | Compile Unit způsobí překlad jednotky právě zobrazené v Editoru kódu a výpis všech chyb a varování. Je to nejrychlejší způsob testování našeho programu na chyby. Provádí se pouze překlad (bez sestavování). Volba Project | Make překládá všechny jednotky změněné od posledního překladu a také sestavuje celý projekt. První sestavení projektu trvá déle než další sestavení. To proto, že inkrementační sestavovací program vytváří všechny potřebné soubory, které jsou pak používány pro zkrácení dalších sestavování. Volba Project | Build trvá nejdéle. Jsou přeloženy všechny jednotky projektu. Po překladu všech jednotek je celý projekt sestaven. Tento příkaz je používán pouze výjimečně, např. po editaci vytvářecího souboru projektu. Je vhodné jej také použít při výskytu různých nedefinovaných chyb.
  12. Formuláře můžeme rozdělit do několika skupin. Formuláře jsou hlavními vytvářecími bloky aplikací C++ Builderu. Každá aplikace GUI má alespoň jeden formulář, který slouží jako hlavní okno. Hlavní okno může být prázdné, může být zaplněno ovladači nebo může mít na sobě zobrazenou bitovou mapu. Hlavní okno bývá většinou vybaveno nabídkou a může mít také stavový řádek a paletu nástrojů. Hlavní okna různých aplikací se mohou velmi lišit.
  13. Různá dialogová okna používaná v aplikacích C++ Builderu jsou také formuláře. Dialogová okna se obvykle od normálních oken v některých věcech liší:
  14. Dialogová okna v C++ Builderu se liší od dialogových oken v jiných programovacích prostředích. V jiných programovacích prostředích jsou dialogová okna vytvářena Editorem dialogových oken. V mnoha případech Editor dialogových oken je vizuální nástroj, který pracuje podobně jako Návrhový formulář C++ Builderu. Vytvořené dialogové okno je zde definováno skriptem souboru zdrojů.
    Dialogová okna v C++ Builderu jsou normální formuláře. K zabránění změny velikosti okna změníme vlastnost BorderStyle na bsDialog nebo bsSingle. Pokud použijeme bsDialog, pak dialogové okno bude mít na titulním řádku pouze uzavírací tlačítko. Všechny formuláře C++ Builderu mají podporu pro přechod na další ovladač při stisku klávesy Tab.
    Dialogová okna C++ Builderu mohou být modální nebo nemodální. Modální dialogové okno musí být uzavřeno dříve, než uživatel může pokračovat v používání aplikace (pokud je modální okno otevřeno, pak zbývající část aplikace je nefunkční). Při nemodálním dialogovém oknu, je možno pracovat v tomto okně a také ve zbývající části aplikace. To zda dialogové okno se bude chovat jako modální nebo nemodální je určeno tím, zda okno je zobrazeno metodou ShowModal (modální) nebo Show (nemodální).
  15. Nyní se vrátíme k našemu projektu ViceForm (zobrazování druhého formuláře). K tomuto projektu přidáme okno O aplikaci. Pokud tento projekt již nemáme otevřen, pak jej otevřeme volbou File | Open Project. K otevření lze také použít volbu File | Reopen (zobrazíme seznam nejposledněji používaných projektů a souborů, ze kterého si můžeme otevíraný projekt vybrat; seznam má dvě části, v horní části jsou projekty, ve spodní soubory). Nejprve na hlavní formulář přidáme tlačítko pro zobrazování vytvářeného dialogového okna. Změníme jeho vlastnosti Name na OAplTlacitko a vlastnost Caption na O aplikaci. Obsluha stisku tohoto tlačítka bude tvořena příkazem:

  16. OknoOApl->ShowModal();
    Dále budeme pokračovat vývojem našeho dialogového okna. Vytvoříme nový formulář (volba File | New Form) a jeho rozměry zmenšíme asi na polovinu. Vlastnost Name změníme na OknoOApl, vlastnost Caption na O aplikaci a vlastnost BorderStyle na bsDialog. Do okna přidáme komponenty Label podle následujícího obrázku.

    Znak pro označení autorských práv (c v kroužku) má kód 169 a je možno jej zadat pomocí klávesy Alt (Alt + 0169). Na formulář dále přidáme obrázek ikony. Na formulář vložíme komponentu Image a umístíme ji podle dalšího obrázku. Vlastnost AutoSize u ní změníme na true a dvojitě klikneme na hodnotu vlastnosti Picture. V zobrazeném okně editoru stiskneme tlačítko Load, přejdeme do adresáře Program Files\Common Files\Borland Shared\Images\Icons a vybereme zde nějakou ikonu.
    Do spodní části formuláře umístíme komponentu BitBtn a vodorovně ji vycentrujeme pomocí Palety zarovnávání. Vlastnost Kind u ní nastavíme na bkOK. Tím je vytváření tlačítka hotovo. Tlačítko obsahuje kód k uzavření okna.
    Okolo textů umístíme ještě rámeček. Ten je tvořen komponentou Bevel. Vybereme tuto komponentu a namísto kliknutí na formuláři, táhneme myší rámeček okolo textů na formuláři. Dále u komponenty Bevel změníme vlastnost Shape na bsFrame.

    Nyní již můžeme formulář dialogového okna uložit (volba File | Save) a dáme mu jméno OAplikaci. Ještě je zapotřebí do jednotky hlavního formuláře vložit hlavičkový soubor vytvořeného dialogového okna. Přejdeme do Editoru kódu (stiskem F12) a vybereme stránku Hlavni.cpp. Zvolíme File | Include Unit Hdr, vybereme jednotku OAplikaci a stiskneme OK. Nyní již program můžeme vyzkoušet.
    Třídy společných dialogových oken (TOpenDialog, TSaveDialog, apod) nejsou vytvořeny jako formuláře. Windows poskytuje tato dialogová okna jako množinu oken, kterou je možno používat ve všech Windowsovských aplikacích (jejich definice je uložena v souboru COMDLG32.DLL). Třídy dialogových oken VCL zaobalují tato okna a usnadňují jejich používání.
  17. Sekundární okno je formulář, který je zobrazován z hlavního okna. V C++ Builderu není rozdíl mezi sekundárním oknem a dialogovým oknem. V jiných programovacích prostředích musíme specifikovat, zda se jedná o sekundární nebo dialogové okno.
  18. Zatím jsme se zabývali pouze SDI (Single Document Interface) aplikacemi. SDI aplikace mají jedno hlavní okno a obvykle podle potřeby zobrazují dialogová okna, ale nezobrazují podřízená okna. Některé programy používají model MDI (Multiple Document Interface). MDI aplikace obsahují hlavní okno a podřízená okna. Příkladem MDI aplikace je textový editor Word (může zde být současně otevřeno více dokumentů). Podřízená okna je možno přemisťovat pouze uvnitř hlavního okna. MDI aplikace obvykle mají v nabídce volbu Window (Okno) s volbami, které umožňují podřízená okna rozmisťovat a určovat aktivní podřízené okno. Při minimalizaci podřízeného okna, je ikona okna obsažena v hlavním okně. MDI aplikacemi se budeme zabývat později.
  19. V dalším příkladu si ukážeme použití šablony dialogového okna. Vytvoříme nový prázdný projekt, zvolíme File | New, na stránce Dialogs zvolíme PasswordDialog a stiskneme OK. Tím jsme k našemu projektu přidali další formulář (formulář pro zadávání hesla). Zobrazte tento přidaný formulář (šablonu) a vyberte v ní editační komponentu. Podívejte se na vlastnost PasswordChar této komponenty. Hodnota vlastnosti je *. Když uživatel bude zapisovat do této komponenty nějaký text, bude namísto každého zapsaného znaku zobrazen znak hvězdičky. Tyto činnosti jsou již nadefinované v použité šabloně.

  20. Na náš původní formulář přidáme tlačítko a vygenerujeme obsluhu stisku tohoto tlačítka. Do obsluhy vložíme příkaz:
    PasswordDlg->ShowModal();
    Do jednotky hlavního formuláře je ještě nutno vložit hlavičkový soubor dialogového okna. Nyní již aplikaci můžeme spustit a vyzkoušet zadávání hesla. V tomto příkladě jsme si ukázali použití šablon, tj. již dříve vytvořených formulářů, ve kterých můžeme i něco dodělat.
  21. V době návrhu jsou dialogová okna normální formuláře. Při běhu aplikace mohou být modální nebo nemodální. Většina dialogových oken je modálních. Při nemodálním spuštění může uživatel používat libovolný formulář na obrazovce. Můžeme např. vytvořit nemodální formulář k zobrazování stavových informací. Pokud požadujeme, aby nemodální okno bylo stále zobrazeno nad ostatními okny, nastavíme jeho vlastnost FormStyle na hodnotu fsStayOnTop.

  22. Vytvoříme nový prázdný projekt, na formulář přidáme tlačítko a vytvoříme obsluhu stisku tohoto tlačítka s kódem:
    AboutBox->Show();
    K projektu přidáme dále ze zásobníku formulářů okno About (zvolíme File | New a na stránce Forms vybereme About Box) a volbou File | Include File Hdr přidáme k Unit1 hlavičkový soubor Unit2. Nyní již aplikaci můžeme spustit a vyzkoušet si chování nemodálního dialogového okna (okno About nelze uzavřít). Můžete také vyzkoušet změnu chování když vlastnost FormStyle okna About změníme na hodnotu fsStayOnTop.
  23. Pokud v naší aplikaci změníme obsluhu tlačítka na

  24. AboutBox->ShowModal();
    pak okno bude zobrazeno v modálním stavu. Vyzkoušejte chování modálního okna. Způsob zobrazení neovlivňuje vzhled okna.
  25. Třída TForm má mnoho vlastností. Některé z těchto vlastností jsou zastaralé a zřídka používané, jiné se používají často. Nyní se seznámíme s často používanými vlastnostmi. Vynecháme přitom vlastnosti, které nám jsou již známé (Color, Left, Top, Width a Height). Nejprve se budeme zabývat vlastnostmi použitelnými jak při návrhu, tak i při běhu aplikace.
  26. Některé vlastnosti jsou přístupné pouze za běhu prostřednictvím kódu. Nejdůležitější z nich jsou tyto vlastnosti:
  27. Formuláře jsou také komponenty. Formuláře mají mnoho metod společných s komponentami. Společné metody jsou např. Show, ShowModal a Invalidate. Jsou ale metody, které existují pouze pro formuláře. Následuje popis nejčastěji používaných metod formuláře:
  28. Formuláře mohou reagovat na různé události. Následuje popis nejčastěji používaných událostí:
  29. Při vytváření formuláře je generováno mnoho různých událostí. Je důležité vědět v jakém pořadí jsou tyto události generovány. Toto pořadí je: Při rušení formuláře jsou události generovány v tomto pořadí: Toto pořadí je v některých případech důležité. Není např. možno používat v předchozí obsluze události nějaký objekt, který bude vytvořen až v další události.
  30. První formulář, který vytvoříme se stává hlavním formulářem projektu a je prvním formulářem vytvořeným po spuštění aplikace. Můžeme ale požadovat jiný hlavní formulář. Ke změně hlavního formuláře projektu zvolíme Project | Options, přejdeme na stránku Forms a určíme nový hlavní formulář. Na stejné stránce tohoto dialogového okna můžeme také určit, které formuláře budou automaticky vytvářeny po spuštění aplikace a pořadí jejich vytváření (vytvářené formuláře jsou uvedeny v části Auto-Create Forms a jsou vytvářeny v uvedeném pořadí).
  31. Používání modálních a nemodálních formulářů si ukážeme v další aplikaci. Hlavní formulář bude obsahovat text (komponentu Label) ?Toto je hlavní formulář aplikace? a dvě tlačítka: ?Otevři modální formulář? a ?Otevři nemodální formulář?. Po přidání dvou nových formulářů do projektu volbou File | New Form (nazveme je Modalni a Nemodalni; vlastnost Name formuláře) můžeme napsat obsluhy stisku tlačítek. Pro Otevři modální formulář bude obsluha tvořena příkazy:

  32. TModalni *Modal = new TModalni(this);
    Modal->ShowModal();
    Modal->Free();
    Pro druhé tlačítko to jsou příkazy:
    TNemodalni *Nemodal = new TNemodalni(this);
    Nemodal->Show();
    Po zavření modálního formuláře se ukončí metoda ShowModal a formulář je uvolněn z paměti. Metoda Show je ukončena okamžitě a formulář z paměti uvolnit nelze, neboť je stále zobrazen. Nemodální formuláře jsou z paměti uvolněny až při uzavření hlavního formuláře. Není to sice nejlepší řešení, ale zatím jej použijeme. Oba naše další formuláře budou obsahovat tlačítko Zavřít a text ?Modální formulář resp. ?Nemodální formulář. Obsluha stisku tlačí?. Zavřít je tvořena pouze voláním metody Close. Modální formulář bude mít ještě tlačítko ?Otevři další modální formulář pro vytvoření dalšího (stejného) modálního formuláře (u nemodálních formulářů to není zapotřebí, neboť opakovaným stiskem tlačítka na hlavním formuláři lze vytvořit více stejných nemodálních formulářů). Obsluha stisku tohoto tlačítka je tvořena pří?
    TModalni *DalsiModal = new TModalni(this);
    DalsiModal->ShowModal();
    DalsiModal->Free();
    Hlavní formulář používá oba další formuláře a musíme tedy do Unit1 vložit hlavičkové soubory Unit2 a Unit3 (File | Include Unit Hdr). Objekty dialogových oken vytváříme sami (operátorem new) a můžeme tedy odstranit kód, který Builder automaticky generuje pro definování objektu formuláře. V obou programových jednotkách těchto formulářů tedy musíme odstranit deklaraci TModalni Modalni; resp. TNemodalni Nemodalni; a je nutno zrušit automatické vytváření těchto formulářů. V dialogovém okně Project Options na stránce Forms přesuneme jména těchto dvou formulářů z levého do pravého sloupce. Nyní již můžeme naši aplikaci vyzkoušet a vytvořit několik modálních a nemodálních formulářů a zjistit, jak s nimi lze pracovat. Není ale vhodné těchto oken vytvářet mnoho (z důvodu spotřeby systémových zdrojů), maximálně asi 10.
  33. V závislosti na uvažovaném použití dialogového okna, je nutno do okna umístit tlačítka (např. tlačítko OK a Cancel). Nastavení vlastností komponent tlačítek (vlastnosti Cancel a Default) umožňuje volat kód obsluhy události stisku tlačítka, když uživatel stiskne klávesu Esc nebo Enter. Např. když formulář obsahuje tlačítko s nastavenou vlastností Default na true, pak stisk klávesy Enter spustí kód obsluhy události OnClick pro toto tlačítko, pokud některé jiné tlačítko není zaostřeno. Existuje-li jiné zaostřené tlačítko, pak stisk klávesy Enter způsobí provedení obsluhy události OnClick zaostřeného tlačítka.

  34. Modální okno bude automaticky uzavřeno, když uživatel stiskne některé tlačítko s nenulovou hodnotou vlastností ModalResult. Různé hodnoty této vlastnosti také umožňují určit, kterým tlačítkem bylo okno uzavřeno. Např. máme-li tlačítko Cancel, nastavíme jeho vlastnost ModalResult na mrCancel a pokud náš formulář obsahuje dále tlačítko OK, nastavíme jeho ModalResult na mrOK. Obě tlačítka lze nyní použít k uzavření okna a hodnota vlastnosti ModalResult použitého tlačítka je návratová hodnota funkce ShowModal. Testováním hodnoty funkce ShowModal lze zjistit, kterým tlačítkem bylo okno uzavřeno.
    V mnoha případech můžeme vytvářet tlačítka pomocí komponenty BitBtn pouhým nastavením vlastnosti Kind (určíme tím text zobrazený na tlačítku a hodnotu vlastnosti ModalResult).
14. Formuláře I