Minulý díl našeho seriálu odbočil od problematiky resources, kterou jsme se zaobírali v předešlých dvou částech, a zaměřil se na několik zajímavých matematických, finančních a statistických funkcí. Dnes se ovšem – jak jsem slíbil – ke zdrojům opět vrátíme a předvedeme si práci s nimi prakticky. A to samozřejmě hlavně v souvislosti s vývojovým prostředím Delphi.
Jak jsme si již uvedli v předchozích textech týkajících se zdrojů, obecně se zdroje vyskytují v binární podobě uvnitř souborů s příponami *.res. V Delphi lze o zdrojích hovořit ještě v jedné souvislosti: popis každého formuláře (třeba i s případnými ikonami apod.) je uložen v souboru s příponou *.dfm, který tedy také můžeme chápat jako určitý specifický typ zdrojů. Soubory *.dfm jsou od Delphi verze 5 ukládány v textové podobě, ale i tak mohou nést binární informaci o ikoně.
Vysvětlili jsme si také, jakým způsobem je realizován vztah program – zdroje. Řekli jsme si, že soubor se zdrojovým kódem a soubor se zdroji jsou na sobě relativně nezávislé, a že chceme-li připojit zdroje k programu, provedeme to v Delphi pomocí direktivy překladače $R. Výsledkem je přilinkování zdrojů k programovému souboru: vznikne tak jeden výsledný soubor *.exe, který obsahuje jak program a data, tak i zdroje. Potřebujeme-li změnit zdroje (a nahradit tak třeba ikonu programu nějakou jinou), můžeme v zásadě bez problémů použít nový soubor se zdroji <.res), ale nezbytnou podmínkou je opětovná kompilace programu.
K práci s některými druhy zdrojů (bitmapy, ikony a kurzory) v prostředí Delphi je určen pomocný nástroj Image Editor. Vrhněme se tedy do práce: nejprve si ukážeme, jak pomocí Image Editoru vytvořit soubor se zdroji a jak jej použít v aplikaci vytvořené v Delphi.
Začneme prací s ikonami. Spustíme tedy nástroj Image Editor. Můžeme to provést hned několika způsoby:
Poté, co je Image Editor spuštěn, je nutné vytvořit nový soubor se zdroji: File – New – Resource File. Otevře se nový soubor (Untitled1.res), do něhož nyní vložíme několik ikon. Opakovaně tedy volte Resource – New – Icon. V dialogu, v němž je nutné zadat atributy ikony, zvolte Small Icon (16x16 pixelů) a ponechte standardní nastavení 16 barev, viz obrázek:
Potvrďte a nová ikona (zatím samozřejmě prázdná) je vložena do souboru Untitled1.res. Tímto způsobem vložte do souboru několik ikon, řekněme alespoň tři nebo čtyři (viz následující obrázek):
Nyní raději ikony přejmenujeme, protože názvy Icon1 až Icon4 vskutku nejsou příliš vypovídající. Protože mé výtvarné výtvory opravdu nejsou příliš reprezentativní, nepokusím se v následujícím příkladu kreslit nějaké složité grafické efekty a omezím se na geometrické útvary. Tomu tedy přizpůsobím názvy ikon. Připomenu, že přejmenování ikony je velmi jednoduché a provede se klepnutím na příslušný název pravým tlačítkem myši a zvolením položky „Rename“ z kontextové nabídky. Výsledek tedy může vypadat třeba takto:
Nyní zbývá poslední „maličkost“ – jednotlivé ikony nakreslit. Formálně jde o proces, který se odstartuje velmi jednoduše: stačí poklepat na název ikony a otevře se okno s jednoduchým grafickým editorkem (viz následující obrázek). V něm pak předáme slovo své umělecké můze a nakreslíme ikony tak, jak si přejeme, aby nakonec v aplikaci vypadaly.
Tak. Dejme tomu, že se nám úspěšně podařilo ikony nakreslit. Podotknu, že pokud nejste v malování zrovna dvakrát zruční, můžete použít třeba schránku systému Windows a s její pomocí zkopírovat do editoru třeba obsah jiné ikony nebo obrázku, který najdete někde na Internetu, nebo který získáte nějakou jinou cestou.
Jsou-li ikony nakresleny, stačí soubor Untitled1.res uložit (z nabídky Image Editoru File – Save). My jej při té příležitosti také přejmenujeme, třeba na NaseIkony.res. Po potvrzení můžete Image Editor opustit – jeho úloha v tomto okamžiku skončila.
Podíváte-li se nyní do vytvořeného souboru NaseIkony.res, příliš z jeho obsahu nezmoudříte, viz krátká ukázka:
˙˙ ˙˙
( ˙˙ ˙˙
( Ŕ
€ € €€ € € € €€ ŔŔŔ €€€ ˙ ˙ ˙˙ ˙
˙ ˙ ˙˙ ˙˙˙
ŞŞŞ ŞŞŞŞ ŞŞŞŞŞŞ
ŞŞŞŞŞŞ
ŞŞŞŞŞŞŞ ŞŞŞŞŞŞŞ ŞŞŞŞŞŞŞ ŞŞŞŞŞŞŞ
ŞŞŞŞŞŞ ŞŞŞŞŞ ŞŞŞŞ
˙˙ ˙˙
˙˙ ü đ Ŕ € €
Ŕ
Na této ukázce tedy jasně vidíme, že výsledek je už hotovým souborem se zdroji (který je v binární formě, jak jsme si uvedli v předchozím, teoretickém pojednání o zdrojích). Jinak řečeno – tnto soubor již můžeme bez jakýchkoliv dalších úprav použít přímo v aplikaci. Zdůrazňuji to proto, že si později ukážeme ještě jednu možnost vytvoření zdrojů, a při ní se k použitelnému (binárnímu) souboru budeme muset teprve dopracovat.
Nyní již můžeme spustit Delphi a vytvořit nový projekt. Naším cílem bude jednoduchá aplikace, která bude obsahovat seznam, z něhož bude moci uživatel zvolit požadovanou ikonu. Tato ikona se posléze zobrazí na formuláři.
Na formulář tedy vložte komponentu ListBox a Button. Ošetříme nejprve událost OnCreate formuláře. V obsluze této události pouze přidáme položky do seznamu (a nastavíme titulek formuláře a titulek tlačítka):
procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Items.Add(`Ctverec`);
ListBox1.Items.Add(`Trojuhelnik`);
ListBox1.Items.Add(`Kruznice`);
ListBox1.Items.Add(`Kruh`);
Caption := `Ukazka prace se
zdroji`;
Button1.Caption := `Zmen ikonu`;
end;
Klíčová činnost bude obsažena v obsluze události OnClick tlačítka Button1. V obsluze této události musíme načíst zvolenou ikonu ze zdrojů. K tomu použijeme funkci Windows API LoadIcon:
HICON LoadIcon(
HINSTANCE hInstance, // handle of
application instance
LPCTSTR lpIconName // icon-name string or
icon resource identifier
);
Funkce LoadIcon slouží k načtení ikony ze spustitelného souboru <.EXE). Jejím prvním parametrem je handle aplikace, jejíž spustitelný modul obsahuje ikonu, kterou chceme načíst. V našem případě se jedná přímo o naši aktuální (spuštěnou) aplikaci. Jak ji však identifikovat? Jak zjistíme potřebnou hodnotu handle?
Odpověď hledejme v jednotce SysUtils. Ta totiž obsahuje definici proměnné hInstance, která obsahuje právě potřebný handle. Přesněji řečeno – hInstance obsahuje hodnotu handle aktivní instance aplikace.
Druhým parametrem funkce LoadIcon říkáme, kterou ikonu chceme načíst. Identifikujeme ji jejím názvem, tak, jak jsme jej uvedli při vytváření souboru res v Image Editoru.
Návratovou hodnotou funkce LoadIcon je handle načtené ikony. Tento handle pak přiradíme do vlastnosti Icon.Handle, kterou máme k dispozici v Delphi. Výsledek, tedy fungující použití funkce LoadIcon, bude tedy vypadat takto:
procedure TForm1.Button1Click(Sender: TObject);
begin
case
ListBox1.ItemIndex of
0 : Icon.Handle := LoadIcon(hInstance,
`CTVEREC`);
1 : Icon.Handle := LoadIcon(hInstance,
`TROJUHELNIK`);
2 : Icon.Handle := LoadIcon(hInstance,
`KRUZNICE`);
3 : Icon.Handle := LoadIcon(hInstance,
`KRUH`);
else ShowMessage(`Oznacte prosim pozadovanou ikonu v
seznamu.`);
end;
end;
Zdálo by se, že jsme hotovi. Zkuste aplikaci přeložit a spustit (F9): funguje?
Jako už tradičně, v okamžiku, kdy položím řečnickou otázku „Funguje?“, aplikace nefunguje. Sice jsme bez potíží provedli překlad, nicméně i když budeme za běhu zuřivě vybírat názvy ze seznamu a klepat na tlačítko, ikona formuláře se nezmění. Proč?
Pozorní čtenáři problém jistě odhalili: musíme učinit ještě jeden, velmi důležitý krok, bez něhož aplikace nemůže fungovat. Musíme totiž soubor se zdroji přilinkovat k našemu spustitelnému souboru. Ještě než to učiníme, prohlédneme si velikost spustitelného souboru. Přestože ikony zabírají (vzhledem ke své malé velikosti a pouze 16 použitým barvám) hodně málo bajtů na disku, drobný rozdíl postřehneme.
Nevím, jak u vás (záleží to na řadě věcí, například na verzi Delphi), ale v mém případě zabírá spustitelný soubor aplikace 324608 bajtů. Připomínám, že se nyní jedná o nefunkční verzi bez ikon. Nyní připojíme k aplikaci soubor s ikonami, který jsme společně vytvořili v první části dnešního článku. Pokud jste četli i předchozí články o zdrojích, určitě si vzpomenete, že k přilinkování zdrojů slouží direktiva $R, kterou připíšeme do úvodu zdrojového souboru, hned za řádku, která přilinkovává soubor se zdroji formuláře (DFM):
...
var
Form1: TForm1;
implementation
{$R
*.DFM}
{$R NaseIkony.res}
...
Důležité ovšem je, abyste soubor NaseIkony.res nahráli do téhož adresáře, ve kterém je nyní projekt v Delphi. Pokud necháte soubor NaseIkony.res jinde, překladač jej nenajde a ohlásí při překladu chybu.
Pokud nyní aplikaci přeložíme a spustíme, zaregistrujeme dvě odlišnosti:
Aplikace funguje hezky, nicméně vzniká asi otázka, proč jsme to všechny dělali, neboli jaké jsou výhody tohoto řešení. Hlavní výhoda spočívá asi v tom, co se stane při požadavku na změnu ikon. Přesněji řečeno: co musíme udělat, budeme-li chtít nahradit současnou množinu čtyř ikon jinými? (další verze aplikace, lepší provedení ikon apod.)
Postup bude poměrně jednoduchý, navíc při něm poznáme výhody i nevýhody koncepce zdrojů. Nejprve spustíme Image Editor a vytvoříme nový soubor se zdroji, třeba NaseNoveIkony.res. Do něho přidáme čtyři ikony, pojmenujeme je stejně jako v předchozím případě (CTVEREC, TROJUHELNIK, KRUZNICE a KRUH). Nakreslíme vové, lepší ikony.
Soubor NaseNoveIkony.res, který jsme takto vytvořili, ovšem nestačí kamsi zkopírovat a očekávat, že aplikace si jej „načte“. Musíme provést rekompilaci projektu: otevřeme projekt v Delphi, napíšeme do direktivy $R nový název souboru (případně ponecháme stávající, pokud bychom název souboru se zdroji nezměnili) a aplikaci znovu zkompilujeme. Její integrální částí se tak stanou nové ikony – ale soubor s nimi (NaseNoveIkony.res) můžeme zase klidně smazat. Tímto způsobem tedy probíhá aktualizace aplikace – není nutné nijak zasahovat do zdrojového kódu (snad jen s výjimkou zadání názvu souboru *.res), ale opětovnému překladu se nevyhneme.
Novou verzi aplikace (s novou ikonou) vidíte na následujícím obrázku:
Jako tradičně, i dnes si uvedeme kompletní zdrojový kód. V dnešním případě všakmusím zdůraznit, že abyste jej mohli bez problémů použít (a přeložit), je nutné vytvořit i soubor se zdroji NaseIkony.res, který bude při překladu přilinkován do výsledného spustitelného souboru EXE.
unit Unit1;
interface
uses
Windows, Messages,
SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
StdCtrls;
type
TForm1 = class(TForm)
ListBox1:
TListBox;
Button1: TButton;
procedure
FormCreate(Sender: TObject);
procedure Button1Click(Sender:
TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R
*.DFM}
{$R NaseIkony.res}
procedure TForm1.FormCreate(Sender:
TObject);
begin
ListBox1.Items.Add(`Ctverec`);
ListBox1.Items.Add(`Trojuhelnik`);
ListBox1.Items.Add(`Kruznice`);
ListBox1.Items.Add(`Kruh`);
Caption := `Ukazka prace se
zdroji`;
Button1.Caption := `Zmen ikonu`;
end;
procedure
TForm1.Button1Click(Sender: TObject);
begin
case ListBox1.ItemIndex
of
0 : Icon.Handle := LoadIcon(hInstance, `CTVEREC`);
1 : Icon.Handle := LoadIcon(hInstance, `TROJUHELNIK`);
2
: Icon.Handle := LoadIcon(hInstance, `KRUZNICE`);
3 :
Icon.Handle := LoadIcon(hInstance, `KRUH`);
else
ShowMessage(`Oznacte prosim pozadovanou ikonu v seznamu.`);
end;
end;
end.
V dnešním článku jsme si vysvětlili, jak prakticky vytvořit soubor se zdroji, jak jej použít při psaní aplikace v Delphi a jak následně tento souboru aktualizovat. Práce s ikonami přitom patří k jednodušším aspektům tvorby zdrojů v Delphi. V dalším článku se proto budeme věnovat i jiným typům zdrojů, než jsou jen ikony.
Vaše ohlasy, které mi pravidelně zasíláte na emailovou adresu vkadlec@post.cz, a za které vám velmi děkuji, svědčí o tom, že problematika zdrojů vás zaujala a že ji považujete za dobře využitelnou při své praktické, každodenní práci. Věřím, že i dnešní článek přispěl k vaší lepší orientaci v této tématice a že pro vás bude užitečný.