7. Prßce s datov²mi zdroji

D°φve ne╛ se zaΦneme zab²vat datov²mi zdroji, podφvßme se obecn∞ na jedno a dvouvrstvovΘ databßzovΘ aplikace. Jedno a dvou vrstvovΘ aplikace obsahujφ logiku, kterß manipuluje s databßzov²mi informacemi, ve stejnΘ aplikaci jako je u╛ivatelskΘ rozhranφ. Nebo╗ logika manipulace dat nenφ izolovßna ve specißlnφ vrstv∞, jsou tyto typy aplikacφ vyhovujφcφ pouze pokud dal╣φ aplikace nesdφlejφ stejnΘ databßzovΘ informace. Kdy╛ dal╣φ aplikace sdφlejφ databßzovΘ informace, pak tyto typy aplikacφ jsou vyhovujφcφ pouze pro jednoduchΘ databßze. M∙╛eme takΘ zaΦφt jedno nebo dvouvrstvov²mi aplikacemi, i kdy╛ mßme v ·myslu pro na╣i aplikaci pou╛φt model vφcevrstvovΘ aplikace. Umo╛nφ nßm vytvo°it u╛ivatelskΘ rozhranφ a logiku manipulace dat pozd∞ji p°esuneme na aplikaΦnφ server. Je tedy vhodnΘ izolovat logiku manipulace dat tak, aby ji bylo mo╛no snadno p°esunout.

Aplikace zalo╛enΘ na BDE

Proto╛e komponenty datovΘho p°φstupu (a BDE) provßd∞jφ Φtenφ, zßpis a prochßzenφ dat stejn∞ v jedno i dvouvrstvov²ch aplikacφch, nebudeme tyto typy aplikacφ zde nadßle rozli╣ovat. Kdy╛ vyvφjφme aplikaci zalo╛enou na BDE, pak do na╣φ aplikace musφme vlo╛it BDE. I kdy╛ to zv∞t╣uje velikost a komplikuje ╣φ°enφ aplikace, BDE m∙╛e b²t sdφleno s ostatnφmi aplikacemi zalo╛en²mi na BDE a nabφzφ mnoho v²hod. Aplikace zalo╛enΘ na BDE umo╛≥ujφ pou╛φvat volßnφ API knihovny BDE. I kdy╛ nechceme pou╛φvat API BDE, pak zßpisem aplikacφ zalo╛en²ch na BDE, zφskßme podporu, kterß jinak nenφ dostupnß. Jednß se o (tyto body budou popsßny ve 12. kapitole):
Architektura zalo╛enß na BDE
Jedno a dvouvrstvovΘ aplikace zalo╛enΘ na BDE obsahujφ: VzßjemnΘ vztahy mezi t∞mito prvky jsou uvedeny na nßsledujφcφm obrßzku:

Dal╣φ informace jsou uvedeny v t∞chto bodech:
Seznßmenφ s databßzemi a datov²mi mno╛inami
Databßze obsahujφ informace ulo╛enΘ v tabulkßch. Mohou takΘ obsahovat tabulky informacφ o tom, co je obsa╛eno v databßzi, objekty jako jsou indexy, kterΘ jsou pou╛φvßny tabulkami a objekty SQL jako jsou ulo╛enΘ procedury.
Strßnka Data Access Palety komponent obsahuje r∙znΘ komponenty datov²ch mno╛in, kterΘ reprezentujφ tabulky obsa╛enΘ v databßzi nebo logickΘ tabulky vytvo°enΘ z dat ulo╛en²ch v t∞chto databßzov²ch tabulkßch. Komponentu datovΘ mno╛iny musφme vlo╛it do svΘ aplikace, abychom mohli pracovat s databßzov²mi informacemi.
Ka╛dß komponenta na strßnce Data Access podporujφcφ BDE mß vlastnost DatabaseName, kterß specifikuje databßzi obsahujφcφ tabulku nebo tabulky, kterΘ dr╛φ informace v tΘto datovΘ mno╛in∞. Kdy╛ nastavujeme na╣φ aplikaci, pak musφme pou╛φt tuto vlastnost ke specifikaci databßze d°φve ne╛ m∙╛eme spojit datovou mno╛inu se specifick²mi informacemi obsa╛en²mi v tΘto databßzi. Jakou hodnotu specifikujeme zßvisφ na tom zda:
Pou╛φvßnφ sezenφ
Sezenφ izolujφ operace datovΘho p°φstupu jako je p°ipojenφ k databßzi a sprßva skupin databßzφ. V╣echno pou╛itφ BDE probφhß v kontextu sezenφ. Sezenφ m∙╛eme pou╛φt ke specifikaci konfiguraΦnφch informacφ aplikovan²ch na v╣echny databßze v sezenφ. To umo╛≥uje zm∞nit chovßnφ specifikovanΘ administrßtorem BDE. Sezenφ m∙╛eme pou╛φt k: Pokud na╣e aplikace m∙╛e p°istupovat ke stejnΘ databßzi soub∞╛n∞, pak musφme pou╛φt vφce sezenφ k izolaci t∞chto pou╛φvßnφ databßze. Aplikace riskuje soub∞╛n² p°φstup, kdy╛ spou╣tφ soub∞╛nΘ dotazy nebo kdy╛ pou╛φvß vφce vlßken. Pokud nepot°ebujeme pou╛φvat vφce sezenφ, pak je mo╛no pou╛φvat implicitnφ sezenφ.
P°ipojovßnφ k databßzi
BDE obsahuje ovladaΦe pro p°ipojenφ k r∙zn²m databßzφm. Verze Standard C++ Builderu obsahuje pouze ovladaΦe pro lokßlnφ databßze: Paradox, dBASE, FoxPro a Access. U verze Profesional, zφskßme takΘ adaptΘr ODBC, kter² umo╛≥uje pou╛φvat ovladaΦe ODBC. Tφm zφskßme p°φstup k databßzφm vyu╛φvajφcφm ODBC. Ostatnφ verze takΘ obsahujφ ovladaΦe pro vzdßlenΘ databßzovΘ servery. OvladaΦe instalovanΘ s SQL Links pou╛ijeme ke komunikaci se vzdßlen²mi databßzov²mi servery jako je Interbase, Oracle, Sybase, Informix, Microsoft SQL server a DB2.
Poznßmka: Jedin²m rozdφlem mezi jednovrstvov²mi a dvouvrstvov²mi aplikacemi zalo╛en²mi na BDE je to, zda pou╛φvajφ lokßlnφ nebo vzdßlenΘ databßzovΘ servery.

Pou╛φvßnφ datov²ch zdroj∙

Komponenta TDataSource je nevizußlnφ databßzovß komponenta, kterß pracuje jako propojenφ mezi datovou mno╛inou a datov²mi komponentami na formulß°i. Ka╛dß datovß mno╛ina musφ mφt odpovφdajφcφ komponentu datovΘho zdroje. Komponenta datovΘho zdroje spojuje vizußlnφ datovΘ ovladaΦe na formulß°i s datovou mno╛inou. Vizußlnφ databßzovΘ ovladaΦe zφskßvajφ data z a zasφlajφ data do komponenty datovΘho zdroje. Komponenta datovΘho zdroje p°enß╣φ data z datovΘ mno╛iny k vizußlnφm ovladaΦ∙m a z vizußlnφch ovladaΦ∙ zp∞t do datovΘ mno╛iny. Ka╛d² datov² ovladaΦ musφ b²t p°i°azen ke komponent∞ datovΘho zdroje, aby mohl zobrazovat a manipulovat s daty.
Poznßmka: M∙╛eme takΘ pou╛φt komponentu datovΘho zdroje ke spojenφ datov²ch mno╛in do vzßjemnΘm vztahu master - detail.
Komponenty datovΘho zdroje umis╗ujeme do datovΘho modulu nebo na formulß° a to stejn∞ jako umis╗ujeme jinΘ komponenty databßzovΘho p°φstupu. Musφme pou╛φt alespo≥ jednu komponentu datovΘho zdroje pro ka╛dou komponentu datovΘ mno╛iny v datovΘm modulu nebo na formulß°i.
S datov²mi zdroji se seznßmφme v t∞chto bodech:

Pou╛φvßnφ vlastnostφ TDataSource

TDataSource mß pouze n∞kolik zve°ej≥ovan²ch vlastnostφ. Nßsledujφ informace o pou╛φvßnφ t∞chto vlastnostφ. Jsou popsßny v t∞chto bodech:
Nastavovßnφ vlastnosti DataSet
Vlastnost DataSet urΦuje datovou mno╛inu, ze kterΘ komponenta datovΘho zdroje zφskßvß svß data. B∞hem nßvrhu m∙╛eme vybrat datovou mno╛inu v rozbalovacφm seznamu v Inspektoru objekt∙. Za b∞hu aplikace m∙╛eme p°epφnat datovΘ mno╛iny pro komponentu datovΘho zdroje podle pot°eby. Nap°. nßsledujφcφ k≤d p°epφnß datovΘ mno╛iny pro komponentu datovΘho zdroje CustSource mezi Customers a Orders:
if (CustSource->DataSet == Customers)
  CustSource->DataSet = Orders;
else
  CustSource->DataSet = Customers;
M∙╛eme takΘ nastavit vlastnost DataSet na datovou mno╛inu z jinΘho formulß°e k synchronizaci datov²ch ovladaΦ∙ na dvou formulß°φch. Nap°.
void __fastcall TForm2::FormCreate(TObject *Sender)
{
  DataSource1->DataSet = Form1->Table1;
}
Nastavovßnφ vlastnosti Name
Name umo╛≥uje specifikovat smysluplnΘ jmΘno pro komponentu datovΘho zdroje, kterΘ se musφ li╣it od v╣ech jmen ostatnφch datov²ch zdroj∙ v na╣φ aplikaci. JmΘno komponenty datovΘho zdroje je zobrazovßno pod ikonou komponenty v datovΘm modulu. Je vhodnΘ aby toto jmΘno indikovalo p°i°azenou datovou mno╛inu. Nap°. p°edpoklßdejme, ╛e mßme datovou mno╛inu nazvanou Customers a ╛e je spojena s komponentou datovΘho zdroje nastavenφm vlastnosti komponenty datovΘho zdroje DataSet na Customers. Vlastnost Name u komponenty datovΘho zdroje pak nastavφme nap°. na CustomersSource.
Nastavovßnφ vlastnosti Enabled
Vlastnost Enabled urΦuje zda komponenta datovΘho zdroje je p°ipojena ke svΘ datovΘ mno╛in∞. Kdy╛ Enabled je true, pak datov² zdroj je p°ipojen k datovΘ mno╛in∞. Datov² zdroj m∙╛eme doΦasn∞ odpojit od svΘho datovΘho spoje nastavenφm Enabled na false. Kdy╛ Enabled je false, pak v╣echny datovΘ ovladaΦe p°ipojenΘ ke komponent∞ datovΘho zdroje jsou prßzdnΘ a neaktivnφ, dokud Enabled op∞t nenastavφme na true. Je ale doporuΦovßno °φdit p°φstup k datovΘ mno╛in∞ prost°ednictvφm metod DisableControls a EnableControls datovΘ mno╛iny, nebo╗ ovliv≥ujφ v╣echny p°ipojenΘ datovΘ zdroje.
Nastavovßnφ vlastnosti AutoEdit
Vlastnost AutoEdit datovΘho zdroje urΦuje, zda datovß mno╛ina p°ipojenß k datovΘmu zdroji automaticky p°echßzφ do stavu dsEdit, kdy╛ u╛ivatel zaΦne zapisovat do datovΘho ovladaΦe spojenΘho s datovou mno╛inou. Pokud AutoEdit je true (implicitn∞), pak datovß mno╛ina automaticky p°ejde do stavu dsEdit, kdy╛ u╛ivatel zapisuje do p°ipojenΘho datovΘho ovladaΦe. Jinak, datovß mno╛ina p°echßzφ do stavu dsEdit pouze kdy╛ aplikace explicitn∞ volß metodu Edit.

Pou╛φvßnφ udßlostφ datovΘho zdroje

Datov² zdroj mß t°i udßlosti:
Pou╛φvßnφ udßlosti OnDataChange
Udßlost OnDataChange nastßvß, kdy╛ kurzor je p°esunut na jin² zßznam. Kdy╛ aplikace volß Next, Prior, Insert nebo n∞kterou jinou metodu, kterß m∞nφ pozici kurzoru, pak je generovßna udßlost OnDataChange. Tato udßlost je u╛iteΦnß, kdy╛ aplikace manußln∞ synchronizuje komponenty.
Pou╛φvßnφ udßlosti OnUpdateData
Udßlost OnUpdateData nastane, kdy╛ data v souΦasnΘm zßznamu majφ b²t aktualizovßna. Nap°. udßlost OnUpdateData nastane, kdy╛ je volßna metoda Post, ale d°φve ne╛ jsou data skuteΦn∞ zapsßna do databßze. Tato udßlost je u╛iteΦnß, kdy╛ aplikace pou╛φvß standardnφ (nedatabßzovΘ) ovladaΦe a pot°ebuje je synchronizovat s datovou mno╛inou.
Pou╛φvßnφ udßlosti OnStateChange
Udßlost OnStateChange nastßvß, kdy╛ stav datovΘ mno╛iny datovΘho zdroje se zm∞nφ. Stav datovΘ mno╛iny je zaznamenßn ve vlastnosti State datovΘ mno╛iny. OnStateChange je u╛iteΦnß pro provßd∞nφ akcφ souvisejφcφch se zm∞nou stavu datovΘho zdroje.
Nap°. v pr∙b∞hu normßlnφho databßzovΘho sezenφ se stav datovΘ mno╛iny m∞nφ Φasto. K zachycenφ t∞chto zm∞n, m∙╛eme zapsat obsluhu udßlosti OnStateChange, kterß zobrazφ aktußlnφ stav datovΘ mno╛iny v komponent∞ Label na formulß°i. Nßsledujφcφ k≤d ukazuje jak to provΘst:
void __fastcall TForm1::DataSource1StateChange(TObject *Sender)
{
  AnsiString S;
  switch (CustTable->State)
  {
    case dsInactive: S = "Inactive"; break;
    case dsBrowse: S = "Browse"; break;
    case dsEdit: S = "Edit"; break;
    case dsInsert: S = "Insert"; break;
    case dsSetKey: S = "SetKey"; break;
  }
  CustTableStateLabel->Caption = S;
}
Podobn∞ OnStateChange m∙╛e b²t pou╛ito k povolenφ nebo zakßzßnφ tlaΦφtek nebo prvk∙ nabφdek na zßklad∞ souΦasnΘho stavu.
void __fastcall TForm1::DataSource1StateChange(TObject *Sender)
{
  CustTableEditBtn->Enabled = (CustTable->State == dsBrowse);
  CustTableCancelBtn->Enabled = (CustTable->State == dsInsert ||
                                 CustTable->State == dsEdit ||
                                 CustTable->State == dsSetKey);
  ...
}

  1. Nynφ zahßjφme v²voj databßzovΘ aplikace pro fiktivnφ firmu Global Dive Supply. Jeliko╛ nß╣ projekt se bude sklßdat z n∞kolika formulß°∙ vytvo°φme si nejprve prßzdn² standardnφ formulß° pro tuto firmu (bude tvo°it zßklad v╣ech formulß°∙ aplikace). Takto vytvo°en² formulß° m∙╛eme vlo╛it do zßsobnφku objekt∙.

  2. Uzav°eme v╣echny soubory (volbou File | Close All) a zvolφme File | New Form. Tφm vytvo°φme nov² prßzdn² formulß°, kter² nenφ zapojen do ╛ßdnΘho projektu. Vlastnost Name u tohoto formulß°e zm∞nφme na Base a hodnotu vlastnosti Caption vyprßzdnφme. Titulnφ °ßdek formulß°e nynφ obsahuje prßzdn² °ßdek.
    Na formulß° zaΦneme p°idßvat komponenty. K hornφmu okraji formulß°e vlo╛φme Panel (pro jmΘno na╣φ firmy) a dal╣φ panel vlo╛φme ke spodnφmu okraji formulß°e (pro °φdφcφ tlaΦφtka). V²╣ka obou panel∙ bude asi 40 bod∙. U hornφho panelu zru╣φme hodnotu vlastnosti Caption a vlastnost Align nastavφme na alTop. Do hornφho panelu umφstφme komponentu Label a nastavφme jejφ vlastnosti: vlastnost Align na alLeft, Caption na Global Dive Supply a vlastnost Font na pφsmo Arial, tuΦnou kurzφvu, velikost 16 a barvu Purple.
    U spodnφho panelu zru╣φme hodnotu vlastnosti Caption, vlastnost Align zm∞nφme na alBottom a vlastnosti BevelInner a BevelOuter nastavφme na bvNone. Na spodnφ panel vpravo p°idßme tlaΦφtko pro uzavφrßnφ formulß°e. Zm∞nφme jeho Caption na Exit a vytvo°φme jeho obsluhu stisknutφ, kterß bude tvo°ena p°φkazem
    Close();
    Tφm je vytvo°en zßklad pro formulß° na╣φ fiktivnφ firmy a mohli bychom jej umφstit do Zßsobnφku objekt∙. Zde na uΦebn∞ se nßm to ale nepoda°φ (mßme zakßzßn zßpis). Formulß° tedy ulo╛φme n∞kolikrßt pod r∙zn²m jmΘnem (do adresß°e, kter² jsme si vytvo°ili pro tuto aplikaci). JmΘno BaseMod pou╛ijeme pro formulß° pou╛it² jako ╣ablonu, jmΘno HomeMod pro °φdφcφ formulß° aplikace a jmΘno CustMod pro formulß° zßkaznφk∙.
  3. K vytvo°enφ novΘho prßzdnΘho projektu zvolφme File | New Application. Jeliko╛ v╣echny svΘ formulß°e budeme odvozovat od na╣eho formulß°e (╣ablony), musφme odstranit implicitnφ formulß° vytvo°en² C++ Builderem pro nov² projekt. Pomocφ sprßvce projektu zru╣φme Form1. Jsme dotßzßni, zda soubor ulo╛it; odpovφme No.

  4. Prvnφ formulß°, kter² v na╣em projektu vytvo°φme, bude °φdφcφ formulß° aplikace. Ve Sprßvci projektu p°ejdeme na Projektov² uzel, v jeho mφstnφ nabφdce zvolφme Add a k projektu p°idßme nß╣ ji╛ ulo╛en² formulß° HomeMod. U tohoto formulß°e zm∞nφme vlastnost Name na Home a vlastnost Caption na Global Dive Supply Central Control.
    Na lev² okraj spodnφho panelu p°idßme tlaΦφtko, zm∞nφme jeho vlastnost Caption na Customers a vytvo°φme obsluhu jeho stisku, kterß bude tvo°ena p°φkazem:
    Cust->Show();
    Cust bude jmΘno formulß°e, kter² bude pou╛it k zobrazenφ informacφ o zßkaznφcφch. Kdy╛ u╛ivatel stiskne toto tlaΦφtko ve spu╣t∞nΘ aplikaci, pak p°edchozφ k≤d zp∙sobφ zobrazenφ uvedenΘho formulß°e. Vedle tlaΦφtka Customers vlo╛φme dal╣φ tlaΦφtko a zm∞nφme jeho vlastnost Caption na Terms. Pro toto tlaΦφtko zapφ╣eme takΘ obsluhu jeho stisku:
    Term->Show();
    Term bude jmΘno formulß°e, kter² pou╛ijeme k zobrazenφ informacφ o placenφ objednßvek. Kdy╛ u╛ivatel stiskne toto tlaΦφtko, pak tento k≤d zp∙sobφ zobrazenφ uvedenΘho formulß°e. TlaΦφtko Exit nechßme beze zm∞ny a formulß° ulo╛φme.
  5. Datov² modul je typ formulß°e, kter² obsahuje p°ipojenφ na externφ databßzi a pracuje jako jednoduch² centrßlnφ zdroj pro v╣echny ostatnφ formulß°e aplikace. Zvolφme File | New, p°ejdeme na strßnku Data Modules, nastavφme voliΦ Inherit, vybereme objekt Customer Data a stiskneme tlaΦφtko OK. U vytvo°enΘho datovΘho modulu zm∞nφme vlastnost Name na Data, u tabulek Customers a Orders zm∞nφme vlastnost Active na true a modul ulo╛φme pod jmΘnem DataMod. K DatovΘmu modulu se za chvφli vrßtφme.
  6. Nynφ p°idßme formulß° CustMod, kter² se zobrazφ po stisku tlaΦφtka Customers. Ve Sprßvci projektu v mφstnφ nabφdce projektovΘho uzlu zvolφme Add a vybereme tento d°φve ulo╛en² formulß°. Vlastnost Name zm∞nφme na Cust a Caption na Customer Contacts. My╣φ p°esuneme tento formulß° nepatrn∞ dol∙ a vpravo (aby byl vid∞t hornφ okraj formulß°e Home). K formulß°i p°ipojφme nß╣ Datov² modul. Vybereme nov² formulß°, zvolφme File | Include Unit Hdr, vybereme DataMod a stiskneme OK. Nynφ formulß° CustMod mß p°φstup ke v╣em informacφm obsa╛en²m v DatovΘm modulu.

  7. Na formulß° na jeho hornφ panel blφzko jeho pravΘho okraje vlo╛φme komponentu Edit. Zm∞nφme jejφ vlastnost Name na FilterText, zru╣φme hodnotu vlastnosti Text a nastavφme Width na 80. Vlevo od tΘto komponenty vlo╛φme znaΦku. Zm∞nφme jejφ Name na FilterToggle, Caption na Filter? a Alignment na taLeftJustify.
    Na formulß° dßle p°idßme komponentu TDBGrid. Zm∞nφme jejφ vlastnost Align na alClient. Jeliko╛ nß╣ formulß° pou╛φvß datov² modul DataMod, m∙╛eme nastavit vlastnost DataSource komponenty TDBGrid na Data->CustomerSource. Dßle je nutno urΦit, kterΘ ·daje budeme zobrazovat. Klikneme prav²m tlaΦφtkem na TDBGrid a z jeho mφstnφ nabφdky zvolφme Columns Editor. V zobrazenΘm dialogovΘm okn∞ stiskneme tlaΦφtko Add All Fields a zru╣φme v╣echny sloupce mimo: Company, State, Phone, FAX a Contact. Polo╛ku Contact p°esuneme p°ed Phone a okno uzav°eme. Nynφ m∙╛eme pomocφ my╣i nastavit ╣φ°ku jednotliv²ch sloupc∙ (p°eta╛enφm rozd∞lovacφch Φar v hlaviΦce tabulky).
    Zapφ╣eme takΘ obsluhy udßlostφ. Obsluha OnChange editaΦnφho ovladaΦe je tvo°ena p°φkazy:
    FilterToggle->Checked = true;
    Data->Customers->Filtered = true;
    a obsluha udßlosti kliknutφ na znaΦce je tvo°ena p°φkazem:
    Data->Customers->Filtered = FilterToggle->Checked;
    Zobrazφme nß╣ Datov² modul DataMod, vybereme tabulku Customers a vytvo°φme jejφ obsluhu udßlosti OnFilterRecord. Bude tvo°ena p°φkazem:
    Accept = (CustomersState->Value == Cust->FilterText->Text);
    Tφm je formulß° CustMod hotov a m∙╛eme jej ulo╛it. Datov² modul se ale nynφ odkazuje na znaΦku formulß°e CustMod. Musφme tedy k DatovΘmu modulu p°idat hlaviΦkov² soubor CustMod (p°i vybranΘm DatovΘm modulu, zvolφme File | Include Unit Hdr, vybereme CustMod a stiskneme OK).
  8. Na╣e aplikace pot°ebuje je╣t∞ jeden formulß°. Mφsto vytvo°enφ novΘho formulß°e, kter² zd∞dφ vlastnosti od BaseMod, nß╣ nov² formulß° m∙╛eme odvodit i od n∞kterΘho formulß°e ve stejnΘm projektu. Zvolφme File | New, p°ejdeme na strßnku Project1 (pokud jsme projekt nep°ejmenovali) a nastavφme voliΦ Inherit. Nynφ vidφme v Zßsobnφku objekt∙ v╣echny formulß°e pou╛itΘ v na╣em projektu. Vybereme Cust, stiskneme OK a op∞t my╣φ posuneme nov² formulß° nepatrn∞ dol∙ a doprava. U tohoto novΘho formulß°e zm∞nφme Name na Term a Caption na Display Orders By Terms. K formulß°i op∞t p°idßme hlaviΦkov² soubor na╣eho DatovΘho modulu. Formulß° ulo╛φme pod jmΘnem TermMod.

  9. V╣echny komponenty, a╛ na TDBGrid m∙╛eme nechat beze zm∞ny. Vybereme TDBGrid a nastavφme vlastnost DataSource na Data->OrderSource. Z mφstnφ nabφdky TDBGrid zvolφme Columns Editor. Z polo╛ek tabulky nechßme zobrazovat pouze: OrderNo, CustNo, CustCompany, SaleDate, Terms a PaymentMetod. Po°adφ prvnφch t°φ zm∞nφme takto: CustNo, CustCompany a OrderNo. U polo╛ek OrderNo a CustNo zmen╣φme ╣φ°ku sloupce.
    Musφme je╣t∞ zm∞nit k≤d obsluh udßlostφ OnClick editaΦnφ komponenty a znaΦky formulß°e (zd∞d∞n² k≤d je nutno zru╣it) a p°idat obsluhu udßlosti OnFilterRecord pro tabulku Orders. Pro editaΦnφ komponentu pou╛ijeme k≤d:
    FilterToggle->Checked = true;
    Data->Orders->Filtered = true;
    ZnaΦka bude mφt k≤d:
    Data->Orders->Filtered = FilterToggle->Checked;
    V DatovΘm modulu vybereme tabulku Orders a zapφ╣eme jejφ obsluhu udßlosti OnFilterRecord. Bude ji tvo°it p°φkaz:
    Accept = (OrdersTerms->Value == Term->FilterText->Text);
    Tφm je v²voj na╣φ aplikace hotov. Do °φdφcφho formulß°e je nutno je╣t∞ vlo╛it hlaviΦkovΘ soubory obou dal╣φch formulß°∙ a ulo╛it v╣echny soubory. Aplikaci m∙╛eme vyzkou╣et.

  10. Podφvßme se je╣t∞ na jednu podobnou aplikaci. ⌐ablona formulß°e, kterou v tΘto aplikaci budeme pou╛φvat,  je zobrazena na nßsledujφcφm obrßzku.

  11. ZaΦn∞te v²voj novΘ aplikace a vytvo°φme nßsledujφcφ formulß°. V hornφ Φßsti je panel a na n∞m je pou╛ita komponenta TImage (okolo obrßzku je umφst∞na komponenta TBevel) a vedle dv∞ a dv∞ komponenty TLabel (nad sebou). BφlΘ okraje pφsmen jsou tvo°eny tφm, ╛e bφl² text je p°ekryt stejn²m Φern²m textem, kter² je o jeden bod posunut nahoru. Vlastnost Name formulß°e zm∞nφme na GDSStdForm a ulo╛φme jej do souboru GDSStd.cpp.
  12. Ve v²voji aplikace budeme pokraΦovat tφm, ╛e na nov² formulß°, odvozen² od p°edchozφho, p°idßme komponenty datovΘho p°φstupu a n∞kolik dal╣φch ovladaΦ∙ (viz nßsledujφcφ obrßzek). Zvolφme File | New, p°ejdeme na strßnku Project1, nastavφme voliΦ Inherit, vybereme GDSStdForm a stiskneme OK.


  13. K formulß°i p°idßme nßsledujφcφ soukromΘ polo╛ky (dv∞ datovΘ slo╛ky pro ulo╛enφ parametru filtrovacφho kritΘria ve tvaru reßlnΘho Φφsla nebo datumu a dv∞ metody) :
    double FLastAmount;
    TDateTime FLastDate;
    double __fastcall CalcAmountDue(void);
    void __fastcall ConvertFilterCriteria(void);
    Implementace metod je:
    double __fastcall TStdDataForm::CalcAmountDue(void)
    {
      return OrdersItemsTotal->Value * (1.0 + OrdersTaxRate->Value
        / 100) + OrdersFreight->Value - OrdersAmountPaid->Value;
    }
    /* P°evßdφ text filtrovacφho kritΘria na datum nebo reßlnΘ Φφslo. Tato
       hodnota bude pou╛ita v obsluze OnFilterRecord mφsto p°φmΘho pou╛itφ
       filtrovacφho kritΘria a °et∞zec tedy nenφ nutno p°evßd∞t v╛dy p°i
       vzniku tΘto udßlosti. */
    void __fastcall TStdDataForm::ConvertFilterCriteria(void)
    {
      if (FilterCriteria->Text != "")
      {
        switch (FilterOnRadioGroup->ItemIndex)
        {
          case 0:
            FLastDate = StrToDate(FilterCriteria->Text);
            break;
          case 1:
            FLastAmount = StrToFloat(FilterCriteria->Text);
            break;
        }
      }
      if (Orders->Filtered) Orders->Refresh();
    }
    Jedna z komponent TTable mß nastaveny vlastnosti: Name na Orders, DatabaseName na BCDEMOS, TableName na Orders.db a Active na true. Druhß komponenta TTable mß vlastnost Name nastavenu na Cust, vlastnost DatabaseName na BCDEMOS, TableName na Customers.db a Active na true. U komponenty datovΘho zdroje je Name nastaveno na OrdersSource a vlastnost DataSet na Orders.
    Prvnφ komponenta TTable (Orders) bude pou╛φvat poΦitatelnΘ polo╛ky. V mφstnφ nabφdce tΘto komponenty zvolφme Fields editor. Tφm zobrazφme Editor polo╛ek. Seznam Editoru polo╛ek je zatφm prßzdn². V mφstnφ nabφdce Editoru zvolφme Add Fields a v zobrazenΘm okn∞ jsou uvedeny v╣echny polo╛ky datovΘ mno╛iny Orders. V╣echny vybereme a stiskneme OK. Tφm jsme do seznamu Editoru polo╛ek p°idali v╣echny polo╛ky tabulky. Vytvo°φme je╣t∞ jednu vyhledßvacφ a dv∞ poΦitatelnΘ polo╛ky. V mφstnφ nabφdce Editoru polo╛ek zvolφme New Field a v zobrazenΘm dialogovΘm okn∞ zapφ╣eme do Φßsti Name jmΘno CustName, v kombinovanΘm ovladaΦi Type vybereme String, do Size zadßme 20 a nastavφme voliΦ Lookup. Dßle Dataset nastavφme na Cust, Key Fields na CustNo, Lookup Keys na CustNo, ResultField na Company a stiskneme OK. Tφm je definovßna vyhledßvacφ polo╛ka.
    Podobn∞ vytvo°φme poΦitatelnΘ polo╛ky. V mφstnφ nabφdce Editoru polo╛ek zvolφme New Field a v zobrazenΘm dialogovΘm okn∞ do Φßsti Name zapφ╣eme hodnotu TaxAmount, v kombinovanΘm ovladaΦi Type vybereme Currency, nastavφme voliΦ Calculated  a stiskneme OK. Pro p°idßnφ druhΘ polo╛ky zvolφme op∞t New Field, do Φßsti Name zadßme AmountDue, Type a Calculated nastavφme stejn∞ jako u p°edchozφ polo╛ky a stiskneme OK. Tφm mßme poΦitatelnΘ polo╛ky definovßny. P∙vodnφ i p°idanΘ polo╛ky jsou nynφ popsßny polo╛kov²mi komponentami. Jeliko╛ pozd∞ji v m°φ╛ce budeme chtφt zobrazovat pouze polo╛ky OrderNo, CustNo, vyhledßvacφ a ob∞ poΦitatelnΘ polo╛ky, je nutno, aby pouze u t∞chto p∞ti polo╛kov²ch komponent byla nastavena vlastnost Visible na true (ostatnφ polo╛kovΘ komponenty ji musφ mφt nastavenu na false).
    Je nutno je╣t∞ definovat obsluhu udßlosti OnCalcFields prvnφ komponenty TTable. Obsluhu tvo°φ p°φkazy:
    OrdersTaxAmount->Value=OrdersItemsTotal->Value*(OrdersTaxRate->Value/100);
    OrdersAmountDue->Value=CalcAmountDue();
    U tΘto komponenty je nutno je╣t∞ vytvo°it obsluhu udßlosti OnFilterRecord. Tato obsluha se bude ale m∞nit. Budou se zde st°φdat nßsledujφcφ dv∞ obsluhy (p∙vodn∞ je udßlosti p°i°azena prvnφ z nich):
    void __fastcall TStdDataForm::OrdersFilterOnAmount(TDataSet * DataSet,
      bool & Accept)
    {
      Accept = (CalcAmountDue() >= FLastAmount);
    }
    void __fastcall TStdDataForm::OrdersFilterOnDate(TDataSet * DataSet,
      bool & Accept)
    {
      Accept = (OrdersSaleDate->Value >= FLastDate);
    }
    Dal╣φ ovladaΦe, kterΘ byly p°idßny, jsou umφst∞ny na komponent∞ panelu. P°idßme tedy komponentu panelu a nastavφme u n∞j vlastnost Name na StdCtrlPanel, vlastnost Align nastavφme na alTop a vlastnost Height na 72.
    Podle p°edchozφho obrßzku vlo╛te na panel dal╣φ komponenty. Vlevo je umφst∞na komponenta TRadioGroup, uprost°ed TGroupBox (obsahuje komponenty TLabel a TEdit) a vpravo TCheckBox a dv∞ tlaΦφtka. Na komponenty se budeme odkazovat v k≤du a zm∞nφme jejich vlastnosti Name takto: u TRadioGroup na FilterOnRadioGroup, u TLabel na FilterOnLabel, u TEdit na FilterCriteria, u znaΦky na FilterCheckBox, u levΘho tlaΦφtka na NextBtn a u pravΘho tlaΦφtka na PriorBtn.
    Pro formulß° musφme vytvo°it obsluhu udßlosti OnCreate. Je tvo°ena p°φkazy:
    FLastDate = EncodeDate(1995, 1, 1);
    FLastAmount = 1000;
    FilterOnRadioGroup->ItemIndex = 0;
    N∞kterΘ komponenty majφ takΘ p°i°azeny obsluhy udßlostφ. Obsluha kliknutφ na skupin∞ voliΦ∙ je tvo°ena p°φkazy:
    FilterOnLabel->Caption =
      FilterOnRadioGroup->Items->Strings[FilterOnRadioGroup->ItemIndex];
    switch (FilterOnRadioGroup->ItemIndex)
    {
      case 0:
        Orders->OnFilterRecord = OrdersFilterOnDate;
        FilterCriteria->Text = AnsiString(FLastDate);
        break;
      case 1:
        Orders->OnFilterRecord = OrdersFilterOnAmount;
        FilterCriteria->Text = AnsiString(FLastAmount);
        break;
    }
    ActiveControl = FilterCriteria;
    if (Orders->Filtered)
      Orders->Refresh();
    Obsluhu OnExit editaΦnφho ovladaΦe tvo°φ p°φkaz:
    ConvertFilterCriteria();
    a obsluhu OnKeyPress p°φkazy:
    if (Key == 0x13)
    {
      ConvertFilterCriteria();
      Key = 0x00;
    }
    Obsluha kliknutφ na znaΦce je tvo°ena:
    ConvertFilterCriteria();
    Orders->Filtered = FilterCheckBox->Checked;
    NextBtn->Enabled = ! FilterCheckBox->Checked;
    PriorBtn->Enabled = ! FilterCheckBox->Checked;
    Zb²vajφ je╣t∞ obsluhy stisku obou tlaΦφtek. Obsluha prvnφho je tvo°ena p°φkazy:
    ConvertFilterCriteria();
    Orders->FindNext();
    a obsluha druhΘho:
    ConvertFilterCriteria();
    Orders->FindPrior();
    Tφm je formulß° hotov. Bude op∞t tvo°it ╣ablonu od kterΘ budeme odvozovat formulß°e skuteΦn∞ pou╛φvanΘ aplikacφ. Vlastnost Name formulß°e zm∞nφme na StdDataForm a formulß° ulo╛φme do souboru GdsData.
  14. Nynφ se ji╛ budeme zab²vat hlavnφm formulß°em aplikace. Odvodφme jej od prßv∞ vytvo°enΘho formulß°e (StdDataForm). Zvolφme File | New, p°ejdeme na strßnku Project1, nastavφme voliΦ Inherit, vybereme StdDataForm a stiskneme OK.

  15. Vlastnost Name vytvo°enΘho formulß°e zm∞nφme na GridViewForm, na zb²vajφcφ plochu formulß°e p°idßme komponentu TDBGrid a nastavφme u nφ: Align na alClient, DataSource na OrdersSource a vytvo°φme pro nφ obsluhu dvojitΘho kliknutφ tvo°enou p°φkazem:
    RecViewForm->Show();
    Tφm je hlavnφ formulß° aplikace hotov. Zvolφme Project | Options a zru╣φme vytvß°enφ na╣ich p∙vodnφch dvou formulß°∙ (╣ablon) a z poslednφho formulß°e vytvo°φme hlavnφ formulß° aplikace. Ulo╛φme jej pod jmΘnem GridForm.
  16. Dal╣φm formulß°em, kter² na╣e aplikace bude je╣t∞ po╛adovat, je formulß° zobrazen² na nßsledujφcφm obrßzku.


  17. Tento formulß° je op∞t odvozen od na╣i druhΘ ╣ablony. Zb²vajφcφ plochu formulß°e zaplnφme panelem a na n∞j umφstφme komponenty podle p°edchozφho obrßzku. Tento formulß° ji╛ neobsahuje ╛ßdn² k≤d a je zobrazovßn dvojit²m kliknutφm na m°φ╛ce v p°edchozφm formulß°i (v tomto formulß°i jsou podrobnΘ informace o vybranΘm zßkaznφkovi). Vlastnost Name formulß°e zm∞nφme na RecViewForm a formulß° ulo╛φme do souboru RecForm. Podle p°edchozφho obrßzku se pokuste dokonΦit v²voj aplikace sami.
7. Prßce s datov²mi zdroji