Lekce 12 - RES soubory a INI soubory
S tímto dílem už je hotov tucet návodů. A to není málo! Celkem 120 bodů návodu! Ale teď už skončeme tlachání a pusťme se do programování: Tentokrát je hlavním cílem naučit vás pracovat s externím souborem *.RES. Ten se nejlépe upravuje v Image Editoru. Proč zrovna tam? Do RES souboru se dají uložit BitMaPy, ICOny a CURsory (ikony a kurzory).
Jak na to: NEJPRVE v menu Image Editoru zvolte File / New... / Resource File (.res) Poté se vám otevře okno se začínajícím souborovým stromem, uvnitř něhož je jen položka Contents. Kliknete-li na ni pravým tlačítkem nebo do horního menu na položku Resource, můžete zatím zvolit New a po jeho zvolení buď Bitmap, Icon, nebo Cursor. ZAČNĚME třeba Bitmapou! Zvolíte-li položku Bitmap, otevře se vám klasické okno, kde zvolíte rozměry (max. 768x768) a počet barev (2, 16, nebo 256). Po potvrzení se vytvoří větev Bitmap a v ní Bitmap1. Při každém dalším zvolení položky Bitmap v menu se přidá do větve Bitmap další BitmapX. Nyní můžeme vytvořené bitmapy editovat (dvojitým kliknutím se otevře okno na editaci - neukládá se, pouze se zavře, uloží se až soubor RES), přejmenovávat (opět jako ve Windows, akorát přes menu musíte nejprve levým myšítkem zvolit položku k přejmenování a potom teprve zvolit v menu Rename) a samozřejmě mazat (POZOR! Stejně jako u Přejmenování to lze dělat přes menu, ale opět musíte nejprve levým tlačítkem vybrat položku na vymazání!). POKRAČUJME editováním ikony. Kliknete tedy na New / Icon, po vyplnění okna s nastavením se vytvoří větev Icon a v ní stejně jako u Bitmap Bitmap1, Bitmap2... tak tady Icon1, Icon2... Stejně jako u samostatného souboru ikony, můžete i zde udělat soubor ikonu se čtyřmi ikonami (černobílá malá, černobílá velká, 16ti barevná malá, 16ti barevná malá). Vše platí stejně jako u Bitmap (přejmenování, mazání, editování).
SKONČÍME tedy tvorbou kurzorů. Zvolíte si New / Cursor, vytvoří se větev Cursor a v ní se stejným řádem, jako bitmapy a ikony, soubory kurzorů. Žádné ovládání se nemění (editace je stejná, mazání, editování...). V hlavním menu však přibude položka Cursor s položkami Set Hot Spot... (zvolíte číselné umístění místa, které bude provádět akce (u křížku je to střed, u šipky špička atd.)) a Test... (otestujete si vámi vytvořený kurzor).
KONEČNÝ soubor uložíme k programu pod jakýmkoli jménem.
Teď musíme náš program informovat, že jsme mu vyrobili zdrojový soubor (resource file). A to tak, že najdeme část programu
implementation {$R *.dfm}
A pod tento text ještě před procedury (hned za zelený text ve složené závorce{...}) napište: {$R FileName.res} Kde místo FileName bude název vašeho souboru. Po vytvoření exe souboru už nebude potřeba (ale pro Delphi ano - takže ho nemažte!!!!! - pouze u samotného EXE není potřeba - prostě ho nepoužívá, protože ho obsahuje v sobě převedený). A teď se pustíme do používání obrázků a ikon: Soubory TIcon a TBitmap mají položku Handle. A do ní dosadíte adresu obrázku ve zdroji příkazem:
Obrazek.Handle := LoadBitmap(HInstance, 'NázevObrázku'); Icon.Handle := LoadIcon(HInstance, 'NázevIkony');
První příkaz zařídí, že soubor Obrazek : TBitmap; bude vypadat jako bimapa v RES souboru, která se jmenuje NázevObrázku (Názvy bitmap(Obrazek a NázevObrázku) si samozřejmě můžete změnit). Druhý nám říká, že ikona okna (může to být však jakákoli proměnná typu TIcon) bude mít vzhled ikon ze zdrojového souboru, která se jmenuje NázevIkony (nebo jak si jí pojmenujete). Začněme příklad, abyste lépe pochopili:
{$R *.dfm} {$R Zdroj.res} procedure TOkno.Button1Click(Sender: TObject); var Obrazek : TBitmap; begin Obrazek := TBitmap.Create; Obrazek.Handle := LoadBitmap(HInstance, 'Obraz'); Canvas.Draw(0,0,Obrazek); end; procedure TOkno.Button2Click(Sender: TObject); begin Icon.Handle := LoadIcon(HInstance, 'Ikonka'); end;
První procedura se spustí po kliknutí na tlačítko Button1, nadefinuje a vytvoří proměnnou Obrazek typu TBitmap, načte do ní obrázek ze Zdroj.res pojmenovaný Obraz a vykreslí se na plochu okna. Druhá procedura se spustí po kliknutí na Button2 a pouze načte do ikony okna ikonu jménem Ikonka ze Zdroj.res.
Kurzorům se věnujme samostatně: S těmi to není tak jednoduché. Každý kurzor má své číslo. Vy si pro svůj také nějaké musíte zvolit. Zde jsou konstanty, které už mají nějaký tvar (dají se přepsat, ale je to zbytečné): crDefault=0 (nepřepsatelný), crNone=-1, crArrow=-2, crCross=-3, crIBeam=-4, crSizeNESW=-6. crSizeNS=-7, crSizeNWSE=-8, crSizeWE=-9, crUpArrow=-10, crHourGlass=-11, crDrag=-12, crNoDrop=-13, crHSplit=-14, crVSplit=-15, crMultiDrag=-16, crSQLWait= -17, crNo=-18 (nepřepsatelný), crAppStart=-19, crHelp=-20, crHandPoint= -21, crSizeAll=-22
My si tedy budeme raději volit kladné konstanty (ale nemusíme je pojmenovávat). Pokud za nějaké číslo není dosazen obrázek, nastaví se automaticky crDefault (neboli 0). Pokud chceme určit, že Okno bude mít kurzor crDrag, můžeme klidně napsat:
Okno.Cursor := -12;
Je to to samé jako:
Okno.Cursor := crDrag;
Prostě crDrag je konstanta (to je jakoby proměnná, ale nedá se měnit (je konstantní)), stejně jako vše ostatní. Jak si vytvoříte vlastní konstantu si můžete přečíst v bodě 4. Nyní vás obeznámím, jak změnit kurzor třeba v Okně. Bez vytvoření konstanty. Pokud si jí vytvoříte, budete jí psát místo čísla 15 (to je číslo, které jsem zvolil pro kurzor-lze jej ovšem změnit na jiné).
Okno.Cursor := 15; {nebo třeba Okno.Cursor := MojeKonstanta;} Screen.Cursors[15] := LoadCursor(HInstance, 'NazevKurzoru'); {Opět může místo 15 být třeba MojeKonstanta}
První řádek je snad jasný (za kurzor pro Okno dosadíme kurzor 15 (nebo např. MojeKonstanta)). Okno. tam bylo zbytečné, ale je to názornější (Okno.Cursor stačilo napsat jenom jako Cursor). Na druhém řádku se do nastavení počítače (jen po dobu spuštění programu) na pozici 15 dosadí obrázek kurzoru ze zdroje pojmenovaný NazevKurzoru. Příklad si uvedeme po probrání tvorby konstanty...
Kde definovat konstantu?! Máte dvě možnosti (u proměnných jsou 3 -
znáte zatím 2). Obě jsou stejné, jako u proměnných (jednu z nich
neznáte). U proměnných zadáváte před jejich seznam var (=variable a tj.
proměnná). Před konstanty stejným způsobem const (=constant, tj.
konstanta). A nyní způsoby:
1. !!NELZE POUŽÍT U KONSTANT!! do private, nebo public
Např.
public
{ Public declarations }
Cislo : Integer;
end;
2. !!Pr. a Kon. nelze použít výše, než jsou nadefinovány!! mezi procedury (pod implemantation)
Např.
... end; var Textik : string; Number : real; const Pet=5; Pozdrav='Ahoj'; procedure TOkno.Button2Click(Sender: TObject); ...
3. !!Pr. a Kon. lze použít pouze pro jednu proměnnou!!
mezi procedure a její begin
Příklady:
1.:
procedure TOkno.Button1Click(Sender: TObject); var Obrazek : TBitmap; const StoDvacet=120; DvaACtvrt=2.25; begin ...
Co můžete tedy dosazovat a jak?: Konstanty definujete pomocí klasického rovnítka a dosadíte real, Integer, string, nebo klidně i Boolean... Z toho plyne jedna zajímavost: Nebaví vás psát True a False? Nadefinujte si dvě konstanty třeba A(true) a N(false):
const
N=False;
A=True;
Pak už jen pište: Okno.Enabled := N; (A máte po legraci. . Ano, okno se znepřístupní, to
však znamená, že konstanty fungují. Ale také, že musíte použít
tlačítko Delphi v menu v položce Run pojmenované Program reset (Ctrl + F2) -
to se hodí zapamatovat)
Nyní slíbená ukázka, jak dosadit kurzor pomocí konstanty:
procedure TOkno.FormCreate(Sender: TObject); const MujKurzor=13; begin Cursor := MujKurzor; Screen.Cursors[MujKurzor] := LoadCursor(HInstance, 'Sipka'); end;
Není to zas tak těžké. Číslo kurzoru jsem si určil třináct (pro
vztek pověrčivých ... nebo
je to snad šťastné číslo?). Třináctku jsem pojmenoval MujKurzor. Nyní
jsem zadal, že kurzor Okna bude MujKurzor (13). Zde už jsem Okno. vynechal!
Dále už jsem jen 13.kurzoru v systému přiřadil vzhled kurzoru Sipka z RES
souboru přiloženému k DPR, DFM a PAS souborům.
!!!POZOR!!!
Ikony, které umístíte do RES souborů (nemusí být jen jeden) se budou
uživateli automaticky nabízet jako ikony k zástupci! O to bude váš program
LEPŠÍ! Teda aspoň já jsem rád, když se mi nelíbí hlavní ikona programu
a můžu ji změnit za podobnou, ale hezčí. Např. WinAmp! ten má taky na
výběr kvanta ikon!
INI soubory
To by bylo! Nyní vás seznámím s tajemstvím INI souborů. Do těch si pro tentokrát neuloží programátor obrázky, ale uživatel nastavení (přesněji: program uloží proměnné určující nastavení). Základem je přidat do uses na začátku programu pod interface položku
IniFiles: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IniFiles;
Dále už s INI soubory můžeme programovat. Jsou opravdu výhodné a mrzí
mne, že jsem se o nich dozvěděl celkem pozdě ... nejdřív si musíte INI soubor
nadefinovat (na jednom z výše uvedených tří míst - nejlépe na oněch dvou
vám již déle známých):
IniSoubor: TIniFile; // IniSoubor může být jakýkoli název
A poté ho také musíme vytvořit (před použitím (zápis, čtení)):
IniSoubor := TIniFile.Create('NázevSouboru.ini'); // Vůbec // nemusí mít koncovku ini, ale je to tak standardní
Pokud ini soubor otevřete v textovém editoru (lze to, a dokonce ho tam můžete upravit!), má takovýto tvar:
[Název jedné sekce] Název položky (Booleanová)=1 Název další položky=Ano [Název další sekce] Název Integerové položky=12 Název další položky=12
První řádek nám určuje, že začíná jedna sekce INI souboru.
"Název položky (Booleanová)" se může stejně jako "Název jedné sekce"
jmenovat jakkoli. stejně tak i vše ostaní. Třetí řádek oznamuje další
sekci. Do ní můžete umístit něco se stejným jménem (např.:"Název
další položky"). Na druhém řádku je Boolean (1=True, 0=Fasle). Třetí je
string a pátý a šestý je Integer. A to zdaleka není vše, co lze do Ini
souboru zapsat. Nemusíte se bát, do souboru nebudete zapisovat tak, jak jste
to četli!
A jak tedy? Příkazů je dost, ale všechny mají tento tvar:
PromennaTypuTIniFile.WriteNeco('Název sekce', 'Název proměnné', ZapisovanaPromenna);
OK, zní to divně! Nebojte, vysvětlím to! PromennaTypuTIniFile je například námi již vytvořený IniSoubor. ZapisovanaPromenna je proměnná, která souvisí s WriteNeco:
příkaz místo WriteNeco | typ ZapisovanaPromenna | co provede |
WriteInteger | Integer | zapíše celé číslo |
WriteString | String | zapíše text |
WriteBool | Boolean | zapíše 1 nebo 0 |
WriteDate | TDateTime | zapíše datum |
WriteDateTime | TDateTime | zapíše datum a čas |
WriteFloat | Real | zapíše real |
WriteTime | TDateTime | zapíše čas |
Nakonec soubor zavřete příkazem Destroy;
Příklad:
procedure TOkno.FormClose(Sender: TObject; var Action: TCloseAction); var Inik : TIniFile; begin Inik := TIniFile.Create('Kravina.ini'); Inik.WriteBool('Hlavní sekce', 'Zaškrtnuto', CheckBox1.Checked); Inik.WriteString('Hlavní sekce','Text','Ano'); Inik.Destroy; end;
Nyní máme uložen v adresáři Windows (nebo WINNT) soubor Kravina.ini, který obsahuje jednu sekci jménem Hlavní sekce a v ní položku Zaškrtnuto (Boolean) a Text (string). Pokud zadáte místo Kravina.ini celou adresu (C:\\Kravina.ini), uloží se ini soubor do vámi vybraného adresáře.
A jak číst v programu? Ovšem, že ini soubor není pro uživatele, aby si četl nastvení, ale pro program aby po spuštění nastavil třeba vzhled tak, aby uživateli vyhovoval. Příkazů je stejný počet, jako u zápisu (to je myslím logické) a mají podobný tvar:
PromennaCtenehoTypu := TypuTIniFile.ReadNeco('Název sekce', 'Název proměnné', NahradniPromenna);
Je to trochu jiné! Psaní je procedura a čtení funkce. Co je
PromennaTypuTIniFile už víte, PromennaCtenehoTypu je proměnná, do které
se zapíše to, co se přečte a NahradniProměnná je proměnná (nebo hodnota
proměnné), která se dosadí za PromennaCtenehoTypu, pokud se programu z
jakéhokoli důvodu nepodařilo přečíst určenou věc.
ReadNeco má tyto náhražky:
příkaz místo ReadNeco | typ čtené a náhradní proměnné |
ReadInteger | Integer |
ReadString | String |
ReadBool | Boolean |
ReadDate | TDateTime |
ReadDateTime | TDateTime |
ReadFloat | Real |
ReadTime | TDateTime |
Čte to samé, jako zapisovaly podobné příkazy výše. Opět byste měli
INI soubor uzavřít, aby nezabíral místo v paměti. Ale pokud je lokální,
jako v našem případě a použijete Destroy; na konci, je to zbytečné (ale
názorné ).
Příklad:
procedure TOkno.FormCreate(Sender: TObject); var Inik : TIniFile; begin Inik := TIniFile.Create('Kravina.ini'); CheckBox1.Checked := Inik.ReadBool('Hlavní sekce', 'Zaškrtnuto', True); Inik.Destroy; end;
INI soubor se může jmenovat jinak (takže místo Inik třeba INISouborek), než když jsme do něj v jiné proceduře zapisovali (nebo i četli)... Nenačetli jsme sice výše zadaný Text, ale nemusíme použít vše... Pokud si uživatel spustí program poprvé (nebo po smazání Kravina.ini), bude CheckBox1 zaškrtnuto. Potom už bude takové, jaké ho nechal uživatel, když program zavíral.
Case
Na závěr vám ukážu jedno vylepšení:
case Cislo of 1: begin Jedna; end; 2: begin Dva; end; end;
Je to vlastně zjednodušené vypisování if. Je to to samé jako:
if Cislo = 1 then begin Jedna; end else if Cislo = 2 then begin Dva; end;
Při více možnostech pro proměnnou (tentokrát je to Cislo : Integer;) se hodí použít CASE! Stejně tak lze Case použít i pro jiné typy proměnných a není vždy potřeba begin a end (třeba v našem jednořádkovém případě, kde se spustí procedura Jedna, nebo Dva):
case Cislo of 1: Jedna; 2: Dva; end;
A nyní jeden skvělý zdrojový kód: nejprve nadefinujte:
IniFile : TIniFile; Status : Integer;
A potom už můžete (nejprve) zapisovat stav okna po uzavření. Pokud máte volně posuvné a tvarovatelné okno, určitě se vám to bude hodit!
IniFile := TInifile.Create('NázevNeboAdresaSouboru.ini'); Status := 0; case WindowState of wsNormal: begin IniFile.WriteInteger('Hlavní okno', 'Top', Top); IniFile.WriteInteger('Hlavní okno', 'Left', Left); IniFile.WriteInteger('Hlavní okno', 'Width', Width); IniFile.WriteInteger('Hlavní okno', 'Height', Height); Status := 1; end; wsMinimized: Status := 2; wsMaximized: Status := 3; end; if not Active then Status := 2; IniFile.WriteInteger('Hlavní okno', 'Status', Status); ... IniFile.Destroy;
První řádek vytvořil IniFile. Dále jsme dosadili za Status nulu a použili case ve spojitosti s WindowState našeho okna. Pokud je WindowState wsNormal, zjistí se pozice okna na obrazovce, jeho rozměry a Status se změní na 1 (to znamená, že okno bylo v normálním stavu). Pokud je WindowState wsMinimized, je Status 2 a když wsMaximized, tak 3. Dále zjišťujeme, jestli je okno aktivní (to většinou při zavírání bývá, jenom když je minimalizované, tak nemusí...) a pokud není (to značí not - if not Active then je to samé, jako if Active = False then), je Status 2. Nyní už jen zapíšeme Status do IniFile. Tři tečky značí místo, kam můžete psát své zápisky do ini souboru a po nich následuje zavírání IniFile. Doufám, že vše chápete...
... protože je čas na příklad? Nee! Tentokrát necháme příklad
příkladem. Vždyť sám zdrojový kód je příkladem. My jsme si přece
ukázali, jak zapsat pozici okna, ale ještě jsme jí nenačetli. Že to
dovedete? To byste se divili! Je tam totiž jedna záludnost :
Jdeme na to! Nejprve opět nadefinujte:
IniFile : TIniFile; Status : Integer;
A potom pište (samozřejmě do procedury FormCreate!):
IniFile := TInifile.Create('NázevNeboAdresaSouboru.ini'); Status := IniFile.ReadInteger('Hlavní okno', 'Status', 0); if Status <> 0 then begin Top := IniFile.ReadInteger('Hlavní okno', 'Top', Top); Left := IniFile.ReadInteger('Hlavní okno', 'Left ', Left ); Width:= IniFile.ReadInteger('Hlavní okno', 'Width', Width); Height := IniFile.ReadInteger('Hlavní okno', 'Height ', Height ); case Status of 2: PostMessage(Handle, wm_SysCommand, sc_Minimize, 0); {ona záludnost} 3: WindowState := wsMaximized; end; ... end;
Upřímně řečeno, myslím, že byste to zvládli, ale prý WindowState :=
wsMinimized; nefunguje. U mne na PC to funguje , ale kdoví, jak u někoho
jiného. Při programování je ale třeba myslet na každého! A tak program s
tímto zdrojovým kódem pošle zprávu Windows, aby minimalizovala okno...
Ostatní je podobné, jako při zápisu, takže to blíže popisovat nebudu.
Nyní mám oddych (a můžu programovat) a vy se pusťte do využívání svých
nových znalostí (teda aspoň doufám, že nových...
)...

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 414x (210.38 kB)
Aplikace je včetně zdrojových kódů v jazyce Delphi