Umíme to s Delphi, 41. díl – pracujeme s celou aplikací

V jednotlivých kapitolách seriálu jsme velmi často pracovali s tou či onou komponentou, s tou či onou vlastností, s tou či onou událostí. Dosud jsme ale trochu opomíjeli prvek z nejdůležitějších – celou aplikaci, tedy aplikaci jako celek. V dnešní kapitole se pokusíme tento rest napravit: podíváme se, jakým způsobem je možné pracovat s aplikací jako s celkem.
Aplikace jsou důležité...

S trochou nadsázky bychom mohli tuto kapitolu nazvat také třeba „nejdůležitějším prvkem aplikace je ona samotná“. Z předchozích dílů seriálu jistě umíte pracovat s mnoha komponentami, dokážete ošetřit nejednu událost a sofistikovaně zareagovat na nejrůznější stavy, které se při provozu aplikace vyskytnou. Všechny činnosti, kterými jsme se ovšem dosud zabývali, směřují vždy ke konkrétní komponentě. Co si ale počít v případě, že potřebujeme ošetřit událost „uživatel minimalizoval hlavní okno aplikace“? Jak reagovat na situaci, ve které se uživatel z naší aplikace přepnul do jiné? Je například možné změnit barvu boxíků zobrazujících plovoucí nápovědu? Následující obrázek demonstruje, že ano a v dalším textu se také dozvíte, jakým způsobem:)

...ale nejen ony

Ještě předtím se ale podíváme na několik dalších tříd, které jsou v Delphi obsaženy. Takových (hotových) tříd je v Delphi nespočet, protože víme, že Delphi je na objektově orientované architektuře postaveno. Některé z těchto tříd můžete přímo používat ve svých aplikacích, u některých to přímo možné není. V každém případě však nezaškodí lehký přehled těchto tříd, neboť většina z nich je (z nějakého důvodu) poměrně důležitá.

Po vytvoření (založení) nové aplikace vytvoří Delphi nový formulář a vygeneruje příslušný programový kód. Z „hlediska objektů“ je vytvořena nová třída TForm1 vzniklá děděním z třídy TForm a zároveň je vytvořen objekt třídy TForm1 (proměnná Form1). Protože TForm1 je potomek třídy TForm, dědí všechny jeho vlastnosti a chování, přesněji řečeno atributy a metody.

Aniž si to nutně musíme uvědomit, formulář typu TForm1 zpravidla dále specializujeme. To se děje např. přidáváním dalších komponent. Jakmile se do toho pustíme, přestává být samozřejmě tento potomek identický se svým rodičem (s třídou TForm). Přidání komponenty na formulář znamená přidání atributu do třídy TForm1, ošetření libovolné události některé komponenty znamená přidání metody do třídy TForm1. Kromě toho je samozřejmě možné přidávat do této třídy další atributy a metody „ručně“, tj. napsáním příslušného kódu do deklarace třídy ve zdrojovém souboru v Code Editoru.

Hierarchie tříd a knihovna vizuálních komponent

Hierarchií tříd i knihovnou vizuálních komponent jsme se již v tomto seriálu zabývali, proto je dnes jen pro úplnost stručně shrneme.

Systémová knihovna Delphi se nazývá Knihovna vizuálních komponent (Visual Component Library, VCL). Srdcem Delphi je hierarchie tříd této knihovny. Každá třída v systému je potomkem datového typu TObject (vznikla děděním od tohoto typu), takže celá hierarchie má jediný kořen (zjednodušenou hierarchii VCL ukazuje následující obrázek). Tím je umožněno používat TObject jako náhradu za jakýkoliv objektový typ v systému. Při používání komponent vlastně vytváříme objekty (tj. konkrétní výskyty) koncových tříd hierarchie - listů ze stromu hierarchie.

Například metody reagující na událost obvykle obsahují parametr Sender typu TObject. Z výše uvedeného důvodu tedy můžete jako odesílatele uvést prvek libovolné třídy VCL, jelikož je určitě odvozen od třídy TObject. TObject je třídou, jejíž metody zapouzdřují základní chování, jako např. vytvoření, zrušení a manipulace se zprávami.

V následujících podkapitolách si trochu podrobněji popíšeme právě třídu TObject, ale i další použitelné třídy z VCL. Pokud v nejbližší době nehodláte v Delphi provádět nic „nestandardního, bez informací uvedených v následujících dvou podkapitolkách se možná obejdete (a můžete přeskočit až ke kapitolce TApplication). V každém případě však jejich přečtení rozšíří váš všeobecný přehled o tom, jak Delphi funguje a z čeho se skládá.

Třída TObject

TObject je třída, která zapouzdřuje základní chování běžné pro všechny objekty VCL. Je dobré o ní vědět několik málo informací, nicméně při vývoji aplikací ji nikdy nevyužíváme přímo. Přestože TObject technicky není abstraktní třídou, obyčejně se objekty této třídy přímo nevytváří.

Pokud při vytváření nové (své vlastní, uživatelské) třídy neudáte předka, ze kterého byste rádi svou novou třídu oddědili, Delphi automaticky použije jako předka právě třídu TObject. Velká část „schopností“ a výkonu programovacího nástroje Delphi je přítomna právě díky metodám třídy TObject. Poměrně velké množství těchto metod je použito interně prostředím Delphi a uživatelům není povoleno je přímo volat. Některé další metody jsou potlačeny (předefinovány) v následnických třídách třídy TObject - a také v komponentách.

Třída TObject kromě jiného zajišťuje:

  • schopnost vytvářet, spravovat a rušit objekty (instance) alokováním, inicializací a uvolňováním paměti potřebné pro daný objekt,
  • schopnost objektu informovat o svém jménu a své třídě a dále schopnost objektu prozradit své published vlastnosti,
  • podporu manipulace se zprávami,
  • a další.

Třída TComponent

Třída TComponent je potomkem třídy TPersistent, která je přímým potomkem TObject. Všechny komponenty VCL (tedy ty, které se běžně umisťují na formulář) pocházejí z TComponent. Ani tuto třídu ovšem obvykle při programování nezbytně nepotřebujeme – přesněji řečeno, využívá se pouze jako základní třída při vytváření nevizuálních komponent, které budou schopny objevit se na paletě komponent a být k dispozici při práci s Form Designerem. Při případnému vytváření vizuálních (tedy viditelných uživateli za běhu aplikace) komponent se jako základní (bázová) třída používá TControl nebo jeho následníci. Pokud má navíc vytvářená komponenta býti „okenní“, používá se ještě spíše třída TWinControl.

Třída TComponent zajišťuje například:

  • schopnost objevit se na paletě komponent,
  • schopnost vlastnit a udržovat další komponenty,
  • rozšířenou možnost práce se soubory a proudy dat (streamy),
  • schopnost býti konvertován do ovládacího prvku ActiveX nebo jiného COM objektu,
  • a další.

Třída TApplication

Konečně se dostáváme k tomu, co již inzeroval název dnešního dílu seriálu. Třída TApplication zapouzdřuje váš projekt jako aplikaci pod Windows (tedy jako celek). Metody a vlastnosti TApplication zabezpečují základní chování aplikace pod Windows – vytváření, spouštění, udržování a rušení (ukončení) aplikace. TApplication velmi zjednodušuje rozhraní mezi vývojářem (tj. vámi) a prostředím Windows:
  • zpracování zpráv,
  • kontextová on-line nápověda,
  • řízení výjimek,
  • manipulace se základními částmi aplikace definovanými Windows, např. hlavním oknem, okenní třídou, atd.,
  • a další.
Každá aplikace vytvořená v Delphi automaticky (nemusíte se o to tedy žádným způsobem starat) definuje proměnnou Application třídy TApplication. S touto proměnnou souvisí tři řádky hlavního programu každé aplikace (spatřit je můžete například volbou Project – View Source z hlavního menu Delphi 5 či View – Project Source z hlavního menu Delphi 3):

program Project2;

uses
  Forms,
  Unit1 in `Unit1.pas` {Form1};

{$R *.RES}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.Run;
end.

První řádka ve výkonném bloku zajistí pro aplikace potřebné inicializace, druhá vytvoří její hlavní okno a třetí aplikaci spustí.

TApplication má samozřejmě své vlastnosti, události a metody. Vzápětí si některé z nich uvedeme. Vzhledem k tomu, že TApplication se neobjevuje v Object Inspectoru, dají se vlastnosti měnit jen programově a některé navíc v hlavním menu pomocí volby Project – Options…, např. soubor s nápovědou pro aplikaci, apod.

Ještě než si shrneme důležité vlastnosti, události a metody třídy TApplication, ukážeme si, jak s těmito vlastnostmi, událostmi a metodami pracovat. Již bylo řečeno, že je nutné činit tak za běhu programu. Konkrétní způsob je velmi jednoduchý – právě díky tomu, že proměnná Application, která je automaticky definována v každé aplikaci, má globální platnost. Ve zdrojovém textu tedy můžete kdekoliv, v libovolné funkci napsat příkaz tohoto typu:

  Application.název_funkce_či_atributu;

Příklad: chcete-li ukončit aplikaci, napište kdekoliv (jako jste to psali v rámci příkladů v tomto seriálu již nesčíslněkrát) Application.Terminate; Zde tedy vidíte, co se za tímto často používaným příkazem skrývá: jde o volání metody Terminate objektu Application třídy TApplication. Také si vzpomeňte, že žádný objekt Application třídy TApplication nebyl nikdy ručně definován – vše zařídilo samo Delphi.

Následující tabulka přináší přehled nejdůležitějších vlastností třídy TApplication:

Vlastnost Význam
Active Udává, je-li aplikace právě aktivní (což je v případě, že formulář aplikace má zaměření).
CurrentHelpFile Označuje aktuální soubor nápovědy.
ExeName Obsahuje název souboru, kterým byla aplikace spuštěna (včetně adresářové cesty). Zkuste si např. ShowMessage(Application.ExeName);
Handle Handle hlavního okna (formuláře) aplikace. Vysvětlení pojmu hledejte pod tabulkou.
HelpFile Obsahuje „default“ (přednastavený, implicitní) soubor nápovědy.
HintColor Udává barvu, kterou se bude zobrazovat plovoucí nápověda. Standardně je tato barva žlutá, zkuste si ji změnit – dodá to aplikaci velmi originální nádech:-)
HintHidePause Specifikuje dobu, po kterou se bude plovoucí nápověda zobrazovat. Pak obdélníček s touto nápovědou zmizí.
HintPause Udává časovou prodlevu, která nastane mezi umístěním kurzoru nad prvek a zobrazením plovoucí nápovědy.
HintShortCuts Říká, jestli součástí plovoucích nápověd bude zobrazení klávesové zkratky příslušného prvku.
HintShortPause Specifikuje dobu, která uplyne před zobrazením plovoucí nápovědy v případě, že jiná plovoucí nápověda je již zobrazena. Všimněte si, že doba před zobrazením plovoucí nápovědy je mnohem kratší, pokud je již nějaká (jiná) plovoucí nápověda zobrazena.
Icon Udává ikonu, která bude reprezentovat aplikaci na pruhu Windows.
MainForm Říká, který formulář je hlavním.
ShowHint Povoluje / zakazuje zobrazování plovoucí nápovědy (v celé aplikaci).
ShowMainForm Udává, má-li se zobrazit hlavní formulář aplikace při jejím spuštění.
Terminated Obsahuje true, pokud aplikace právě obdržela od Windows zprávu WM_QUIT, která znamená, že aplikace má být ukončena.
Title Obsahuje text, který bude reprezentovat aplikaci na pruhu Windows.

Poznámka: o pojmu handle jsme se již zmiňovali, nicméně pro jistotu zopakujme, že handle si můžete představit jako jednoznačný (číselný) identifikátor, tedy číselný údaj, který jednoznačně určuje, identifikuje daný objekt. Handle si můžete představit také jako ukazatel – v důsledku to není přesné, ale významově jde skoro o totéž: handle je ukazovátko na určitý objekt, je to jakási násada, jakési držadlo tohoto objektu. Ve Windows má snad každý objekt, každý dialog svůj handle. Delphi své vývojáře před používáním handle důsledně chrání a v drtivé většině funkcí se bez nich obejdete. Existuje však několik výjimek (zpravidla jde o zapouzdřené funkce Windows API), ve kterých se handle používají, stejně tak v případě, že chcete používat přímo některé funkce Windows API.

Tolik tedy k nejdůležitějším vlastnostem třídy TApplication. Je vidět, že mnohé z nich se týkají plovoucí nápovědy (hint), další pomohou lépe ovládat „návaznost aplikace“ na operační systém Windows: titulek zobrazující se na pruhu Windows, ikona, apod.

V následující tabulce si shrneme důležité události třídy TApplication:

Událost Význam, kdy vzniká
OnActivate V okamžiku, kdy se aplikace stane aktivní.
OnDeactivate V okamžiku, kdy se aplikace stane neaktivní.
OnException Objeví se, když se v aplikaci objeví neošetřená výjimka (pomocí této události tedy můžeme specifikovat implicitní chování při všech výjimkách, které se nám nechce explicitně ošetřovat).
OnHelp Když se v aplikaci objeví žádost o nápovědu.
OnHint Objeví se, když je ukazatel myši umístěn nad ovládací prvek, jež může zobrazit plovoucí nápovědu.
OnIdle Je generována, když se aplikace stane nečinnou. V obsluze této události je vhodné provést takové akce, které sice potřebujeme provést, ale nechceme jimi „zdržovat“ běžný provoz aplikace. Aplikace je v klidu např. ve chvíli, kdy čeká na uživatelský vstup, apod. Událost je generována pouze když aplikace přejde do klidového stavu, nikoliv stále během doby, kdy tento stav trvá.
OnMessage Generuje se, když aplikace obdrží zprávu od Windows.
OnMinimize Objeví se, když je aplikace minimalizována.
OnRestore Objeví se, když je aplikace obnovena do své původní velikosti.
OnShortCut Je generována při stisku klávesy, ještě před událostí OnKeyDown.
Na závěr

Shrnutí vlastností a událostí třídy TApplication máme tedy úspěšně za sebou. Byl bych velmi rád, kdybyste informace uvedené v dnešním díle seriálu nepovažovali za zbytečné a jejich přečtení za neproduktivní. Myslím, že vývojář v Delphi by měl mít povědomost i o třídách typu TComponent či TObject, přestože je ve své práci přímo nevyužívá. Také ve chvíli, kdy se začneme zabývat tvorbou vlastních komponent, bude jistě znalost těchto tříd velkou výhodou – důvodem je fakt, že tyto třídy se občas používají jako předek nově vytvářené komponenty (i když je pravdou, že častěji se používá třída „vyšší úrovně“ – tedy například již hotová komponenta, apod.). Ale to vše podrobně rozebereme v okamžiku, kdy se na tvorbu komponent vrhneme. Do příštího dílu nám zbývá dokončit popis třídy TApplication; podrobněji se zaměříme na metody této třídy, z nichž některé se velmi často používají.
Váš názor Další článek: Nová rubrika: kapesní počítače na Živě

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , , ,