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