Vážení zákazníci, dovolujeme si Vás upozornit, že na tuto ukázku knihy se vztahují autorská práva, tzv. copyright. To znamená, že ukázka má sloužit výhradnì pro osobní potøebu potenciálního kupujícího (aby ètenáø vidìl, jakým zpùsobem je titul zpracován a mohl se také podle tohoto, jako jednoho z parametrù, rozhodnout, zda titul koupí èi ne). Z toho vyplývá, že není dovoleno tuto ukázku jakýmkoliv zpùsobem dále šíøit, veøejnì èi neveøejnì napø. umisováním na datová média, na jiné internetové stránky (ani prostøednictvím odkazù) apod. redakce nakladatelství BEN technická literatura redakce@ben.cz
8 Použití souborù INI a RES 81 Tøebaže je tato kapitola pomìrnì krátká, obsahuje popis èasto používaných technik Soubory INI Pøípona (INI) tìchto souborù výstižnì urèuje jejich funkci Tyto soubory se používají k inicializaci aplikace plikace si pøi svém spuštìní z INI souboru naète napøíklad rozmìry svého formuláøe, cestu k souborùm nebo jiné informace Na konci bìhu aplikace zase tyto informace ukládá zpìt do INI souboru, aby je pøi opìtovném spuštìní mohla použít INI soubor sestává ze sekcí (sections) (poznáme je podle toho, že jejich názvy jsou psány mezi [ ]), sekce obsahují položky (keys) (poznáme je podle toho, že jejich názvy jsou následovány =) a hodnoty položek (values) (poznáme je podle toho, že jejich názvùm pøedchází =) Viz obr 81 Obr 81 Význam jednotlivých èástí INI souboru Práce s INI soubory v C++ Builderu je velmi snadná C++ Builder totiž definuje tøídu TIniFile, jejíž metody øeší vše potøebné za nás Jediné co je tøeba, je seznámit se s touto tøídou 811 Tøída TIniFile TIniFile je definována v knihovnì: vcl\inifileshpp Datové položky nsistring FileName (R/O) název INI souboru, na který se odvoláváme instancí TIniFile 238 David Matoušek: C++ Builder
Metody fastcall TIniFile(const nsistring FileName); konstruktor, FileName je jméno INI souboru, bool fastcall ReadBool(nsiString Section, nsistring Ident, bool Default); naète ze sekce Section hodnotu položky Ident, pokud se položka nevyskytuje, vezme hodnotu Default, long fastcall ReadInteger(nsiString Section, nsistring Ident, long Default); to samé pro int, nsistring fastcall ReadString(nsiString Section, nsistring Ident, nsistring Default); to samé pro nsistring, void fastcall WriteBool(nsiString Section, nsistring Ident, bool Value); zapíše do sekce Section položku Ident s hodnotou Value, void fastcall WriteInteger(nsiString Section, nsistring Ident, long Value); to samé pro int, void fastcall WriteString(nsiString Section, nsistring Ident, nsistring Value); to samé pro nsistring, void fastcall DeleteKey(nsiString Section, nsistring Ident); vymaže ze sekce Section položku Ident, void fastcall EraseSection(nsiString Section); vymaže sekci Section, void fastcall ReadSections(TStrings* Strings); naète názvy všech sekcí do seznamu Strings, void fastcall ReadSection(nsiString Section, TStrings* Strings); naète názvy všech položek sekce Section do seznamu Strings, void fastcall ReadSectionValues(nsiString Section, TStrings* Strings); naète položky sekce Section vèetnì jejich hodnot do Strings 812 Pøíklad Spuste C++ Builder, do formuláøe umístìte komponenty dle nákresu na obr 82 (komponenty Label není nutné pojmenovat) Pomocí objekt inspektoru (karta Events) vygenerujte funkce: FormCreate, FormClose (události OnCreate a OnClose formuláøe) a ListBoxSectionsClick (událost OnClick komponenty ListBoxSections) Upravte obsahy zdrojových souborù podle níže uvedených výpisù UNIT1H: #include <vcl\inifileshpp> class TForm1 : public TForm published: // IDE-managed Components David Matoušek: C++ Builder 239
Obr 82 Návrhový formuláø void fastcall ListBoxSectionsClick(TObject *Sender); private: // User declarations TIniFile *IniFile; public: // User declarations fastcall TForm1(TComponent* Owner); fastcall ~TForm1(); ; extern TForm1 *Form1; #endif UNIT1CPP: fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) IniFile=new TIniFile("INIFILEINI") 1 ; fastcall TForm1::~TForm1() delete(inifile); void fastcall TForm1::FormCreate 2 (TObject *Sender) 1 Otevøi soubor INIFILEINI z adresáøe WINDOWS (INI soubory se standardnì umís ují do adresáøe WINDOWS) 2 Událost vytvoøení formuláøe 240 David Matoušek: C++ Builder
//nastavení hodnot podle obsahu INI souboru: Left=IniFile->ReadInteger("DESKTOP","Left",Left); Top=IniFile->ReadInteger("DESKTOP","Top",Top); Height=IniFile->ReadInteger("DESKTOP","Height",Height); Width=IniFile->ReadInteger("DESKTOP","Width",Width); Edit->Text=IniFile->ReadString("TEXT","Text",Edit->Text); IniFile->ReadSections 1 ListBoxSections->Items); void fastcall TForm1::FormClose 2 (TObject *Sender, TClosection &ction) IniFile->WriteInteger("DESKTOP","Left",Left); IniFile->WriteInteger("DESKTOP","Top",Top); IniFile->WriteInteger("DESKTOP","Width",Width); IniFile->WriteInteger("DESKTOP","Height",Height); IniFile->WriteString("TEXT","Text",Edit->Text); void fastcall TForm1::ListBoxSectionsClick 3 (TObject *Sender) ListBoxSection->Clear() 4 ; IniFile->ReadSectionValues 5 ( ListBoxSections->Items ->Strings[ListBoxSections->ItemIndex], ListBoxSection->Items); Obr 83 Formuláø jsem umístil pøesnì do levého horního rohu obrazovky a do editaèního pole jsme napsal text 1 Naètení názvù sekcí do ListBoxSections 2 Událost konce aplikace, ulož zmìny do INI souboru 3 Událost výbìru položky z ListBoxSections 4 Nejdøíve smaž staré položky 5 Nahraj názvy položek a jejich hodnoty do ListBoxSection David Matoušek: C++ Builder 241
Pøeložte, zkuste mìnit polohu formuláøe a text v Edit Uložte, po novém spuštìní si aplikace zachová pøedchozí nastavení Dále si ovìøte, že v adresáøi WINDOWS vznikl soubor INIFILEINI (prohlédnìte si jej textovým editorem) Kontrolní výpis obsah souboru INIFILEINI: [DESKTOP] Left=0 Top=0 Width=281 Height=222 [TEXT] Text=hoj, Windows!!! 82 Soubory RES Úlohu RES souborù jsme struènì popsali již v kapitole 4 Na obr 46 je naznaèeno, že resource jsou posledním souborem, ze kterého se spojuje cílový kód aplikace C++ Builderu Co vlastnì RES soubor obsahuje? Dá se to napsat jednou vìtou: RES soubor obsahuje zdroje Zdrojem se v našem pøípadì rozumí bitová mapa, kurzor nebo ikona Proè se ale RES soubory používají, vždy všechno výše uvedené lze do programu dostat i pomocí standarních souborù (bmp, cur, ico)? no, ale je zde podstatný rozdíl! Standardní soubory lze použít za bìhu aplikace (takže musí být rozhodnì na disku spolu s cílovým kódem aplikace), RES soubory se pøipojí do cílového kódu souboru a pro bìh aplikace je již nepotøebujeme 821 Vytvoøení resource RES soubory budeme vytváøet pomocí Image Editoru, jeho spuštìní je snadné: Vyberte položku menu Tools Image Editor, spustí se Image Editor, zde vyberte položku menu File New Resource Obr 84 Volba nového elementu pro vložení do resource 242 David Matoušek: C++ Builder
Zásady práce v Image Editoru si rychle osvojíme, protože jsou prakticky stejné, jako v každém jiném grafickém editoru Nejdøíve klikneme pravým tlaèítkem myši na Contents, objeví se popup menu v nìmž mùžeme provést výbìr elementu, který chceme vytvoøit Viz obr 84 Vytvoøte tedy po jednom elementu bitové mapy, kurzoru a ikony Všimnìte si, že Image Editor pøehlednì øadí elementy do stromu, podle jejich typu Když kliknete pravým tlaèítkem, je popup menu bohatší, význam jeho nových položek je snad dostateènì jasný: Edit (umožní editovat element), Rename (zmìní jméno elementu), Delete (vymaže element) Zkuste pomocí Rename zmìnit jména na Bitmapa, Kurzor a Ikona 1 Obr 85 Strom pøed a po zmìnì jmen elementù Zkusme nejdøíve pracovat s bitovou mapou, zde je situace nejjednodušší Zvolte tedy z menu Edit, nyní mùžete kreslit bìžným zpùsobem (bitmapu lze pomocí schránky pøetáhnout i z jiné aplikace) Povšimnutí si zaslouží pouze položka menu Bitmap Image Properties Touto položkou menu lze zmìnit rozmìry bitové mapy a její barevné rozlišení Tento dialog se zobrazuje rovnìž pøi vytváøení bitové mapy Obr 86 Dialogové okno pro zmìnu vlastností bitové mapy 1 Velká a malá písmena nehrají roli David Matoušek: C++ Builder 243
Rovnìž i kreslení ikony je bìžnou záležitostí le pozor, protože ikona zùstává na pracovní ploše obrazovky, je umožnìno volit transparentní a inverzní barvu V praxi to znamená, že ikona nemùsí být vždy vidìt, protože pozadí mùže mít nevhodnou barvu Pokud máme pochybnosti, je velice jednoduché ikonu otestovat pomocí dialogu, který se zobrazí po výbìru položky menu Icon Test Zde lze volit barvu pozadí, ovládání je ryze intuitivní Nejsložitìjší se jeví kreslení kurzoru Je možno volit èernou, bílou, transparentní nebo inverzní barvu, viz obr 87 Pro snadnou zkoušku lze vyvolat položku menu Cursor Test, vytvoøí se dialog, který umožní provést test Dùležitá je také definice koncového bodu 1, která se provede pomocí položky menu Cursor Set Hot Spot Zkuste tedy nakreslit tyto tøi elementy a uložit celý RES soubor Obr 87 Volba barev kurzoru 822 Použití resource v aplikaci Vidíme, že samotné vytvoøení RES souboru je hraèkou, teï ale zbývá odpovìdìt na otázku, jak ve zdrojovém kódu sdìlíme, že chceme daný element z RES souboru použít Tento problém lze vtipnì rozdìlit na dva dílèí: 1) musíme pøekladaèi sdìlit název RES souboru, který chceme použít, 2) ve vhodném okamžiku musíme daný element nahrát za pomoci k tomu urèených funkcí První problém se øeší pomocí direktivy #pragma: #pragma resource "název_res_souboru" Do úvozovek se tedy napíše název RES souboru, který chceme použít (samozøejmnì, že pokud není v aktuálním adresáøi, musí se zapsat plná cesta) Druhý problém mùžeme vyøešit pomocí dalších funkcí Windows PI Funkce jsou tøi a jejich názvy se zdají být dostateènì jasné: HBITMP LoadBitmap(HINSTNCE hinstance, LPSTR lpbitmapname); HICON LoadIcon(HINSTNCE hinstance, LPSTR lpiconname); HCURSOR LoadCursor(HINSTNCE hinstance, LPSTR lpcursorname); 1 Tento bod je rozhodující pøi aktivaci myší Obvykle se logicky umísuje do vrcholu obrazce, který pøedstavuje kurzor 244 David Matoušek: C++ Builder
Každá z funkcí vyžaduje dva parametry: hinstance je handle na instanci aplikace, obvykle se na místo tohoto parametru zapisuje externí promìnná C++ Builderu s oznaèením HInstance, takto je definována: extern HINSTNCE HInstance; LPSTR je jméno elementu tak, jak jsme jej zapsali v Image Editoru 1 Funkce vrací handle na daný objekt, pokud element daného jména existuje, jinak vrací NULL 823 Pøíklad Spuste C++ Builder, pomocí Image Editoru nakreslete elementy popsané v kapitole 821 a uložte je do souboru RESOURCERES (do stejného adresáøe jako zdrojové soubory aplikace) Potom pomocí objekt inspektoru (karta Events) vygenerujte funkce FormCreate, FormPaint, FormResize (události OnCreate, OnPaint, OnResize formuláøe) O více se nemusíte starat, pouze upravte zdrojové soubory podle níže uvedených výpisù UNIT1H: class TForm1 : public TForm published: // IDE-managed Components void fastcall FormCreate(TObject *Sender); void fastcall FormPaint(TObject *Sender); void fastcall FormResize(TObject *Sender); private: // User declarations Graphics::TBitmap *Bitmap; public: // User declarations fastcall TForm1(TComponent* Owner); fastcall ~TForm1(); ; extern TForm1 *Form1; #endif UNIT1CPP: #include <vcl\vclh> #pragma hdrstop #include "Unit1h" #pragma resource "*dfm" #pragma resource "resourceres" TForm1 *Form1; 1 Nerozlišují se velká a malá písmena David Matoušek: C++ Builder 245