Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

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! PromennaTypuTI­niFile 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 PromennaTypuTI­niFile 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 PromennaCtene­hoTypu, 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... :-) )...

Delphi

 

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 410x (210.38 kB)
Aplikace je včetně zdrojových kódů v jazyce Delphi

 

Předchozí článek
Matematické funkce a funkce, práce s Shell, animovaná ryba
Všechny články v sekci
Delphi
Přeskočit článek
(nedoporučujeme)
Přehled proměnných, StringGrid a Pagecontrol
Článek pro vás napsal Kukensius
Avatar
Uživatelské hodnocení:
1 hlasů
Jméno: Lukáš Kučera alias Kukensius<br/> Narození: říjen 1987 (ve znamení vah)<br/> Bydliště: Jihlava, Česká Republika<br/> Studium: 1. ročník magisterského studia<br/> Škola: Vysoké učení technické v Brně<br/> Fakulta: Fakulta elektrotechniky ...
Aktivity