Vra╗me se k na╣emu prvnφmu programu, kter² jsme v vytvo°ili (formulß°
s tlaΦφtkem m∞nφcφm barvu formulß°e na zelenou). Zdrojov² text tohoto programu
je (hlaviΦkov² a CPP soubor):
#ifndef Unit1H #define Unit1H #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> class TForm1 : public TForm { __published: // IDE-managed
Components TButton *Button1; void __fastcall Button1Click(TObject
*Sender); private:
// User declarations public:
// User declarations __fastcall TForm1(TComponent* Owner); }; extern PACKAGE TForm1 *Form1; #endif #include <vcl.h> #pragma hdrstop #include "Unit1.h" #pragna package(smart_init) #pragma resource "*.dfm" TForm1 *Form1; __fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner) { } void __fastcall TForm1::Button1Click(TObject
*Sender) { Form1->Color = clGreen; Caption = "ZelenΘ okno"; } V uvedenΘ jednotce je pou╛ita t°φda a objekt. V na╣φ jednotce deklarujeme
novou t°φdu TForm1, kterß je odvozena od t°φdy TForm. TForm1
je datov² typ a pro prßci v aplikaci pot°ebujeme prom∞nnou tohoto typu.
Deklarujeme tedy instanci Form1 typu ukazatel na TForm1.
Objekt Form1 reprezentuje samotn² formulß° (p°esn∞ji °eΦeno jednß
se o ukazatel na formulß°). M∙╛eme deklarovat vφce ne╛ jeden objekt n∞jakΘ
t°φdy. Nap°. m∙╛eme mφt vφce pod°φzen²ch oken v aplikacφ vφcedokumentovΘho
rozhranφ.
Na╣e aplikace obsahuje tlaΦφtko. T°φda TForm1 mß polo╛ku Button1,
tj. p°idanΘ tlaΦφtko. TButton je t°φda a tedy Button1 je
objekt. Poka╛dΘ, kdy╛ vlo╛φme novou komponentu na formulß°, je vlo╛ena
do deklarace typu formulß°e novß polo╛ka se jmΘnem komponenty. V╣echny
obsluhy udßlostφ jsou metody t°φdy formulß°e. Kdy╛ vytvo°φme novou obsluhu
udßlosti, pak jejφ metoda je takΘ deklarovßna v typu formulß°e. TForm1
obsahuje metodu Button1Click. Aktußlnφ k≤d tΘto metody je uveden
v souboru CPP. ProhlΘdn∞te si jednotku n∞kterΘ jinΘ aplikace a zjist∞te,
kterΘ polo╛ky a metody jsou pou╛ity. Modifikßtor __fastcall urΦuje
zp∙sob p°edßvßnφ parametr∙ u metod.
Vytvß°enφ t°φdy v C++ Builderu zaΦφnßme odvozenφm t°φdy od existujφcφ t°φdy.
Kdy╛ p°idßme do projektu nov² formulß°, pak C++ Builder jej automaticky
odvozuje od TForm (je to definovßno prvnφm °ßdkem deklarace typu
t°φdy, v na╣em p°φpad∞ class
TForm1 : public TForm). V okam╛iku p°idßnφ formulß°e do projektu
je novß t°φda identickß s typem TForm. Po p°idßnφ komponenty na
formulß° nebo po zßpisu obsluhy udßlosti ji╛ identickß nenφ. Nov² formulß°
je stßle pln∞ funkΦnφ formulß° (m∙╛eme m∞nit jeho velikost a umφst∞nφ a
m∙╛eme jej takΘ uzav°φt). Novß t°φda formulß°e toti╛ zd∞dila v╣echny datovΘ
polo╛ky, vlastnosti, metody a udßlosti od typu TForm. T°φda od kterΘ
odvozujeme svoji t°φdu (od kterΘ d∞dφme data a k≤d) se naz²vß p°edek odvozenΘ
t°φdy. Odvozenß t°φda je potomek svΘho p°edka. Prap°edek v╣ech t°φd je
t°φda TObject.
Rozsah platnosti urΦuje pou╛itelnost a p°φstupnost datov²ch polo╛ek, vlastnostφ
a metod t°φdy; v╣echny jsou v rozsahu platnosti t°φdy a jsou pou╛itelnΘ
t°φdou a jejφmi potomky. Kdy╛ zapisujeme k≤d do obsluhy udßlosti t°φdy,
kter² se odkazuje na vlastnost, metodu nebo polo╛ku t°φdy samotnΘ, pak
nemusφme uvßd∞t v odkazu jmΘno objektu. Nap°. p°φkaz v obsluze udßlosti
pro Form1 Form1->Color
= clGreen; lze napsat jako Color
= clGreen;. Rozsah platnosti t°φdy je roz╣φ°en na v╣echny
potomky t°φdy. M∙╛eme takΘ pou╛φt jmΘno metody ze t°φdy p°edka k deklaraci
metody ve t°φd∞ potomka. Jednß se o p°edefinovßnφ metody (metoda potom
ve t°φd∞ potomka bude provßd∞t n∞co jinΘho). Deklarace t°φdy obsahuje takΘ
klφΦovß slova private: a public: oznaΦujφcφ mφsta pro datovΘ
polo╛ky a metody, kterΘ chceme do k≤du zapisovat p°φmo. Ve°ejnou Φßst deklarace
(Φßst za klφΦov²m slovem public) pou╛φvßme k deklarovßnφ datov²ch
polo╛ek a metod, ke kter²m chceme p°istupovat z jin²ch jednotek. K deklaracφm
v soukromΘ Φßsti (private) je omezen p°φstup pouze na tuto t°φdu.
Nynφ se pokusφme vytvo°it vlastnφ t°φdu (jinou ne╛ t°φdu formulß°e) a to
t°φdu umo╛≥ujφcφ pracovat s datumem. P°edpoklßdejme nßsledujφcφ deklaraci:
class TDatum : public
TObject {
int Den, Mesic,
Rok;
public:
TDatum(){};
void NastavHodnotu(int
D, int M, int R);
bool Prestupny();
};
Na╣e t°φda se sklßdß ze t°φ polo╛ek: Den, Mesic a Rok,
bezparametrickΘho konstruktoru (na╣i t°φdu odvozujeme od t°φdy, ve kterΘ
je definovßn bezparametrick² konstruktor a v odvozenΘ t°φd∞ jej musφme
tedy definovat takΘ) a dvou metod: NastavHodnotu a Prestupny.
Funkce NastavHodnotu m∙╛e vypadat nap°. takto:
void TDatum::NastavHodnotu(int
D, int M, int R){
Den = D;
Mesic = M;
Rok = R;
}
Nynφ ji╛ m∙╛eme deklarovat instanci t°φdy TDatum a s touto instancφ
pracovat.
TDatum *Datum;
Touto deklaracφ jsme nevytvo°ili objekt, ale pouze mφsto pro ulo╛enφ
odkazu na objekt (ukazatel). Instance objektu vytvß°φme operßtorem new.
Nßsleduje p°φklad prßce s na╣φ instancφ:
Datum = new TDatum;
Datum->NastavHodnotu(27,
5, 1942);
?
Na╣φ t°φdu se pokusφme pou╛φt v n∞jakΘ aplikaci. Vytvo°φme formulß°
se dv∞mi tlaΦφtky (p°i°adφme jim texty 1996 a 1997), kter²mi
budeme urΦovat rok a budeme zji╣╗ovat, zda se jednß o p°estupn² rok. Vytvo°enφ
objektu Datum budeme provßd∞t v obsluze udßlosti OnCreate
formulß°e (vytvß°enφ formulß°e - tφm zajistφme, ╛e objekt je vytvo°en p°ed
jeho pou╛itφm). Na zßv∞r (v obsluze udßlosti OnDestroy formulß°e)
objekt op∞t zru╣φme. Nßsleduje v²pis obou programov²ch soubor∙ na╣eho formulß°e
(hlaviΦkovΘho souboru a souboru CPP):
#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
class TDatum {
int Den, Mesic,
Rok;
public:
TDatum(){};
void NastavHodnotu(int
D, int M, int R);
bool Prestupny();
};
class TForm1 : public
TForm
{
__published:
// IDE-managed Components
TButton *Button1;
TButton *Button2;
void __fastcall
FormCreate(TObject *Sender);
void __fastcall
Button1Click(TObject *Sender);
void __fastcall
Button2Click(TObject *Sender);
private:
// User declarations
public:
// User declarations
__fastcall
TForm1(TComponent* Owner);
};
TDatum *Datum;
extern PACKAGE TForm1
*Form1;
#endif
#include <vcl\vcl.h>
#pragma hdrstop
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource
"*.dfm"
TForm1 *Form1;
TDatim *Datum;
__fastcall TForm1::TForm1(TComponent*
Owner)
: TForm(Owner)
{
}
void TDatum::NastavHodnotu(int
D, int M, int R){
Den = D;
Mesic = M;
Rok = R;
}
bool TDatum::Prestupny(){
if (Rok %
4 != 0) return false;
else if (Rok
% 100 != 0) return true;
else if (Rok % 400 != 0) return false;
else return true;
}
void __fastcall TForm1::FormCreate(TObject
*Sender)
{
Datum = new
TDatum;
}
void __fastcall TForm1::FormDestroy(TObject
*Sender)
{
delete Datum;
}
void __fastcall TForm1::Button1Click(TObject
*Sender)
{
Datum->NastavHodnotu(1,
1, 1996);
if (Datum->Prestupny())
Caption = "P°estupn²";
else Caption
= "Nep°estupn²";
}
void __fastcall TForm1::Button2Click(TObject
*Sender)
{
Datum->NastavHodnotu(1,
1, 1997);
if (Datum->Prestupny())
Caption = "P°estupn²";
else Caption
= "Nep°estupn²";
}
Prostudujte si tento v²pis a zjist∞te, co na╣e aplikace provßdφ. Vyzkou╣ejte.
Pokuste se nynφ vynechat p°φkaz v obsluze udßlosti OnCreate formulß°e
(objekt Datum nebudeme vytvß°et). Aplikaci znovu p°elo╛φme a teprve
p°i stisku n∞kterΘho tlaΦφtka je signalizovßna chyba, kterß indikuje p°φstup
k neplatnΘmu ukazateli. Vyzkou╣ejte.
V na╣i t°φd∞ pou╛φvßme bezparametrick² konstruktor. Bylo by ale v²hodnΘ,
aby nß╣ konstruktor zßrove≥ provedl inicializaci datov²ch polo╛ek t°φdy
a to podobn∞ jako metoda NastavHodnotu. Vytvo°φme tento konstruktor
a zm∞nφme takΘ obsluhu udßlosti OnCreate formulß°e. Bude nynφ tvo°ena
p°φkazem:
Datum = new TDatum(1,
1, 1900);
Vyzkou╣ejte.
Definici na╣φ t°φdy takΘ m∙╛eme umφstit do samostatnΘ jednotky a p°idßme
novΘ metody. ZaΦneme s v²vojem novΘ aplikace, formulß° zatφm nechßme prßzdn²
a zvolφme File | New Unit a dostaneme tento k≤d:
#include <vcl.h>
#pragma hdrstop
#include "Unit2.h"
#pragma package(smart_init)
Jednotku p°ejmenujeme na Datumy a zapφ╣eme do nφ koneΦnou verzi
definice t°φdy TDatum. Dostaneme tedy tyto dva soubory (H a CPP):
#ifndef DatumyH
#define DatumyH
class TDatum {
public:
TDatum(int
D, int M, int R);
void NastavHodnotu(int
D, int M, int R);
bool Prestupny();
void Zvetsi();
void Zmensi();
void Pricti(int
PocetDni);
void Odecti(int
PocetDni);
AnsiString
ZiskejText();
protected:
int Den, Mesic,
Rok;
int DniVMesici();
};
#endif
#include <vcl.h>
#pragma hdrstop
#include "Datumy.h"
#pragma package(smart_init)
TDatum::TDatum(int
D, int M, int R){
Den = D;
Mesic = M;
Rok = R;
}
void TDatum::NastavHodnotu(int
D, int M, int R){
Den = D;
Mesic = M;
Rok = R;
}
bool TDatum::Prestupny(){
if (Rok %
4 != 0) return false;
else
if (Rok % 100 != 0) return true;
else
if (Rok % 400 != 0) return false;
else return true;
}
int TDatum::DniVMesici(){
switch (Mesic)
{
case 1: case 3: case 5: case 7: case 8: case
10:
case 12: return 31;
case 4: case 6: case 9:
case 11: return 30;
case 2: if (Prestupny()) return 29;
else return 28;
};
}
void TDatum::Zvetsi(){
if (Den <
DniVMesici()) Den++;
else if (Mesic
< 12) { Mesic++; Den = 1; }
else { Rok++; Mesic = 1; Den = 1; }
}
void TDatum::Zmensi(){
if (Den >
1) Den--;
else if (Mesic
> 1) { Mesic--; Den = DniVMesici(); }
else { Rok--; Mesic = 12; Den = DniVMesici(); }
}
void TDatum::Pricti(int
PocetDni) {
for (int N
= 1; N <= PocetDni; N++) Zvetsi();
}
void TDatum::Odecti(int
PocetDni) {
for (int N
= 1; N <= PocetDni; N++) Zmensi();
}
AnsiString TDatum::ZiskejText()
{
char pom[30];
sprintf(pom,
"%d.%d.%d", Den, Mesic, Rok);
return AnsiString(pom);
}
Abychom tuto jednotku mohli vyzkou╣et vlo╛φme na ji╛ vytvo°en² formulß°
komponentu Label (zv∞t╣φme velikost pφsma) a Φty°i tlaΦφtka (vybavφme
je texty Dal╣φ, P°edchozφ, Za 10 a P°ed 10).
Objekt t°φdy TDatum vlo╛φme jako soukromou polo╛ku do t°φdy formulß°e.
Vytvo°φme obsluhy n∞kolika udßlostφ a dostaneme:
#ifndef Unit1H
#define Unit1H
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
class TForm1 : public
TForm
{
__published:
// IDE-managed Components
TLabel *Label1;
TButton *Button1;
TButton *Button2;
TButton *Button3;
TButton *Button4;
void __fastcall
FormCreate(TObject *Sender);
void __fastcall
Button1Click(TObject *Sender);
void __fastcall
Button2Click(TObject *Sender);
void __fastcall
Button3Click(TObject *Sender);
void __fastcall
Button4Click(TObject *Sender);
private:
// User declarations
TDatum
*Datum;
public:
// User declarations
__fastcall
TForm1(TComponent* Owner);
};
extern PACKAGE TForm1
*Form1;
#endif
#include <vcl.h>
#pragma hdrstop
#include "Datumy.h"
#include "Unit1.h"
#pragma package(smart_init)
#pragma resource
"*.dfm"
TForm1 *Form1;
__fastcall TForm1::TForm1(TComponent*
Owner)
: TForm(Owner)
{
}
void __fastcall TForm1::FormCreate(TObject
*Sender)
{
Datum = new
TDatum(14,
2, 1995);
Label1->Caption
= Datum->ZiskejText();
}
void __fastcall TForm1::Button1Click(TObject
*Sender)
{
Datum->Zvetsi();
Label1->Caption
= Datum->ZiskejText();
}
void __fastcall TForm1::Button2Click(TObject
*Sender)
{
Datum->Zmensi();
Label1->Caption
= Datum->ZiskejText();
}
void __fastcall TForm1::Button3Click(TObject
*Sender)
{
Datum->Pricti(10);
Label1->Caption
= Datum->ZiskejText();
}
void __fastcall TForm1::Button4Click(TObject
*Sender)
{
Datum->Odecti(10);
Label1->Caption
= Datum->ZiskejText();
}
void __fastcall TForm1::FormDestroy(TObject
*Sender)
{
delete Datum;
}
Prostudujte si text tΘto aplikace a pokuste se pochopit jak pracuje.
Aplikaci vyzkou╣ejte.
Jako jednoduch² p°φklad d∞diΦnosti m∙╛eme pozm∞nit p°edchozφ aplikaci odvozenφm
novΘ t°φdy a modifikovßnφm jednΘ z jeho funkcφ. M∞sφc v datumu budeme vypisovat
slovn∞, a zm∞nφme tedy metodu ZiskejText. Vytvo°φme dal╣φ t°φdu
(zapφ╣eme ji do jednotky Datumy):
class TNoveDatum
: public TDatum {
public:
TNoveDatum(int
D, int M, int R): TDatum(D, M, R){};
AnsiString
ZiskejText();
};
Novß funkce ZiskejText pou╛φvß k v²pisu data konstantnφ pole
s nßzvy m∞sφc∙:
char JmenaMesicu[12][10]
=
{"leden",
"·nor", "b°ezen", "duben", "kv∞ten", "Φerven",
"Φervenec",
"srpen", "zß°φ", "°φjen", "listopad", "prosinec"};
AnsiString TNoveDatum::ZiskejText()
{
char pom[30];
sprintf(pom,
"%d. %s %d", Den, JmenaMesicu[Mesic-1], Rok);
return AnsiString(pom);
}
V na╣φ aplikaci musφme je╣t∞ zm∞nit TDatum na TNoveDatum
(v deklaraci formulß°e a v obsluze OnCreate) a aplikaci m∙╛eme vyzkou╣et.
VCL je dob°e navr╛en² pracovnφ rßmec. Je zde v maximßlnφ
mo╛nΘ mφ°e pou╛ita d∞diΦnost. Jßdrem VCL je t°φda reprezentujφcφ komponentu.
Na nßsledujφcφm obrßzku je uvedena hierarchie t°φd VCL. Nenφ to ·plnΘ schΘma
hierarchie, ale pouze nepatrnß Φßst. Na vrcholu nalezneme TObject.
TObject je prap°edek v╣ech t°φd VCL. Pod TObject vidφme TPersistent.
Tato t°φda dßvß komponentßm mo╛nost ulo╛it se do souboru a do pam∞ti a
dal╣φ detaily nepot°ebujeme znßt.
TComponent slou╛φ jako zßkladnφ t°φda pro komponenty.
Tato t°φda poskytuje v╣echnu funkΦnost, kterou spoleΦn² zßklad komponent
vy╛aduje. Nevizußlnφ komponenty jsou odvozeny p°φmo od TComponent.
Vizußlnφ komponenty jsou odvozeny od t°φdy TControl, kterß je odvozena
od TComtonent. TControl p°idßvß dal╣φ funkΦnost, kterou vy╛adujφ
vizußlnφ komponenty. JednotlivΘ komponenty jsou pak odvozeny od TGraphicControl
nebo TWinControl.
T°φdy Form a Application reprezentujφ objekty
formulß°∙ a aplikace ve VCL. Tyto t°φdy jsou odvozeny od TComponent
a jsou tedy takΘ komponentami.
T°φda TApplication zaobaluje zßkladnφ operace
WindowsovskΘho programu. TApplication udr╛uje ikonu aplikace, poskytuje
kontext nßpov∞dy a provßdφ zßkladnφ zpracovßnφ zprßv. Ka╛dß aplikace C++
Builderu mß ukazatel na objekt TApplication nazvan² Application.
N∞kterΘ vlastnosti tohoto objektu m∙╛eme nastavovat na strßnce Application
dialogovΘho okna Project Options (zobrazφ se volbou Project |
Options). T°φda TForm zaobaluje ve VCL formulß°e. Formulß°e
jsou pou╛ity jako r∙znß okna aplikace.