Metody komponent se neli╣φ od ostatnφch metod objektu.
Jsou to funkce zabudovanΘ ve struktu°e t°φdy komponenty. I kdy╛ nejsou
╛ßdnß omezenφ na to, co m∙╛eme d∞lat s metodami komponenty, C++ Builder
pou╛φvß n∞kterΘ standardy. Tento nßvod se zab²vß:
Obecn∞, komponenty nemφvajφ mnoho metod a m∞li bychom minimalizovat
poΦet metod, kterΘ aplikace m∙╛e volat. Slu╛by kterΘ by mohly b²t implementovanΘ
jako metody je Φasto lep╣φ realizovat pomocφ udßlostφ. Udßlosti poskytujφ
rozhranφ, kterΘ odpovφdß prost°edφ C++ Builderu a je p°φstupnΘ p°i nßvrhu.
Zabrßn∞nφ zßvislostem
V╛dy, kdy╛ zapisujeme komponentu minimalizujeme podmφnky
vklßdanΘ na u╛ivatele komponenty. Do nejvy╣╣φ mφry by m∞l b²t u╛ivatel
komponenty schopn² d∞lat cokoli s komponentou a kdykoli to chce. Jsou situace,
kdy toto nelze splnit, ale na╣im cφlem je nejvφce se k tomu p°iblφ╛it.
P°esto╛e je nemo╛nΘ vypsat v╣echny druhy zßvislostφ, kter²m se chceme vyhnout,
nßsledujφcφ seznam uvßdφ to Φemu se mßme vyh²bat: Metodßm, kterΘ u╛ivatel
musφ volat, aby mohl pou╛φvat komponentu, metodßm, kterΘ musφ b²t pou╛ity
v urΦitΘm po°adφ a metodßm, kterΘ zp∙sobφ, ╛e urΦitΘ udßlosti nebo metody
mohou b²t chybnΘ.
Nap°. kdy╛ vyvolßnφ metody zp∙sobφ, ╛e na╣e komponenta
p°ejde do stavu, kdy volßnφ jinΘ metody m∙╛e b²t chybnΘ, pak napφ╣eme tuto
jinou metodu tak, aby kdy╛ ji u╛ivatel zavolß a komponenta je ve ╣patnΘm
stavu, pak metoda opravφ tento stav p°ed provedenφm vlastnφho k≤du. Minimßln∞
bychom m∞li zajistit generovßnφ v²jimky v p°φpadech, kdy u╛ivatel pou╛ije
nedovolenou metodu. Jin²mi slovy, jestli╛e vytvo°φme situaci, kde Φßsti
na╣eho k≤du jsou vzßjemn∞ zßvislΘ, musφme zajistit, aby pou╛φvßnφ k≤du
chybn²m zp∙sobem nezp∙sobilo u╛ivateli problΘmy. Varovßnφ je lep╣φ ne╛
havßrie systΘmu, kdy╛ se u╛ivatel nep°izp∙sobφ na╣im vzßjemn²m zßvislostem.
Pojmenovßvßnφ metod
C++ Builder neklade ╛ßdnß omezenφ na jmΘna metod a jejich
parametr∙. NicmΘn∞ je n∞kolik konvencφ, kterΘ usnad≥ujφ pou╛φvßnφ metod
pro u╛ivatele na╣φch komponent. Je vhodnΘ dodr╛ovat tato doporuΦenφ: Volφme
popisnß jmΘna. JmΘno jako PasteFromClipboard je mnohem vφce informativnφ
ne╛ jednoduchΘ
Paste nebo PFC. Ve jmΘnech sv²ch metod pou╛φvßme
slovesa. Nap°. ReadFileNames je mnohem srozumiteln∞j╣φ ne╛ DoFiles.
JmΘna metod by m∞la vyjad°ovat, co vracejφ. P°esto╛e metodu vracejφcφ vodorovnou
sou°adnici n∞Φeho m∙╛eme nazvat X, je mnohem v²hodn∞j╣φ pou╛φt jmΘno
GetHorizontalPosition.
Ujist∞te se, ╛e metody skuteΦn∞ musφ b²t metodami. Dobrß pom∙cka je, ╛e
jmΘno metody obsahuje sloveso. Jestli╛e vytvo°φme n∞kolik metod, jejich
jmΘno neobsahuje sloveso, zamyslete se nad tφm, zda by tyto metody nemohly
b²t vlastnostmi.
Chrßn∞nφ metod
V╣echny Φßsti t°φd, vΦetn∞ datov²ch slo╛ek, metod a vlastnostφ
mohou mφt r∙znΘ ·rovn∞ p°φstupu. Volba vhodnΘ ·rovn∞ p°φstupu pro metody
je jednoduchß. Metody kterΘ zapisujeme ve sv²ch komponentßch jsou ve°ejnΘ
nebo chrßn∞nΘ. Nenφ ╛ßdn² d∙vod pro vytvß°enφ soukrom²ch nebo zve°ej≥ovan²ch
metod.
V╣echny metody, kterΘ u╛ivatelΘ na╣ich komponent mohou
volat, musφ b²t ve°ejnΘ. Musφme mφt na pam∞ti, ╛e mnoho metod je volßno
v obsluhßch udßlostφ, a tak metody by se m∞li vyhnout pl²tvßnφm systΘmov²mi
zdroji nebo uvedenφm Windows do stavu, kdy nem∙╛e reagovat. Konstruktory
a destruktory musφ b²t v╛dy ve°ejnΘ.
Metody, kterΘ jsou implementaΦnφmi metodami pro komponentu,
musφ b²t chrßn∞nΘ. To zabrßnφ u╛ivateli v jejich volßnφ v nesprßvn² Φas.
Jestli╛e mßme metody, kterΘ u╛ivatelsk² k≤d nesmφ volat, ale objekty potomk∙
volat mohou, pak metody deklarujeme jako chrßn∞nΘ. Nap°. p°edpoklßdejme,
╛e mßme metodu kterß spolΘhß na nastavenφ jist²ch dat p°edem. Jestli╛e
tuto metodu ud∞lßme ve°ejnou, umo╛nφme tφm u╛ivateli, aby ji volat i p°ed
nastavenφm pot°ebn²ch dat. Pokud ale bude chrßn∞nß, zajistφme tφm, ╛e u╛ivatel
ji nem∙╛e volat p°φmo. M∙╛eme pak vytvo°it jinou ve°ejnou metodu, kterß
zajistφ nastavenφ dat p°ed volßnφm chrßn∞nΘ metody.
Metod, kterΘ musφ b²t v╛dy virtußlnφ a chrßn∞nΘ, jsou
implementaΦnφ metody vlastnostφ. Zaji╣╗ujφ, ╛e jedin² p°φstup k informacφm
vlastnostφ je prost°ednictvφm samotnΘ vlastnosti.
D∞lßnφ virtußlnφch metod
Virtußlnφ metody v komponentßch C++ Builderu se neli╣φ od
virtußlnφch metod v jin²ch t°φdßch. Metodu ud∞lßme virtußlnφ, kdy╛ chceme
aby r∙znΘ typy byly schopny provΘst r∙zn² k≤d v reakci na stejnΘ funkΦnφ
volßnφ. Jestli╛e vytvß°φme komponentu urΦenou pouze k p°φmΘmu pou╛itφ koncov²m
u╛ivatelem, ud∞lßme pravd∞podobn∞ v╣echny jejφ metody nevirtußlnφ. Na druhΘ
stran∞, jestli╛e vytvß°φme komponentu vφce abstraktnφ povahy, kterou jinφ
tv∙rci komponent mohou pou╛φt jako poΦßteΦnφ bod pro svΘ vlastnφ komponenty,
zvß╛φme vytvo°enφ virtußlnφch metod. Komponenty odvozenΘ od na╣φ komponenty
pak mohou p°edefinovat zd∞d∞nΘ virtußlnφ metody.
Deklarovßnφ metod
Deklarovßnφ metod v komponentßch se neli╣φ od deklarovßnφ
metod v jin²ch t°φdßch. P°i deklaraci novΘ metody v komponent∞ provedeme
dv∞ v∞ci: p°idßme jejφ deklaraci k deklaraci t°φdy komponenty a implementujeme
metodu v souboru CPP jednotky komponenty.
Nßsledujφcφ k≤d ukazuje komponentu, kterß definuje dv∞
novΘ metody: jednu chrßn∞nou metodu a jednu ve°ejnou virtußlnφ metodu.
class PACKAGE TPrikladKomponenty : public
TControl
{
protected:
void __fastcall Zvetsi();
public:
virtual int __fastcall VypoctiOblast();
};
V CPP souboru je implementace metod:
void __fastcall TPrikladKomponenty::Zvetsi()
{
Height = Height + 5;
Width = Width + 5;
}
int __fastcall TPrikladKomponenty::VypoctiOblast()
{
return Width * Height;
}
-
╚asto pou╛φvanΘ komponenty dialogov²ch oken m∙╛eme takΘ p°idat na Paletu
komponent. Na╣e komponenta dialogovΘho okna bude pracovat stejn∞ jako komponenty,
kterΘ reprezentujφ standardnφ dialogovß okna Windows. Vytvo°enφ komponenty
dialogovΘho okna vy╛aduje Φty°i kroky: definovßnφ rozhranφ komponenty,
vytvo°enφ a registraci komponenty, vytvo°enφ rozhranφ komponenty a testovßnφ
komponenty. Cφlem je vytvo°it jednoduchou komponentu, kterou u╛ivatel m∙╛e
p°idat k projektu a nastavit jejφ vlastnosti b∞hem nßvrhu. ?Obalovacφ
komponenta C++ Builderu p°i°azenß k dialogovΘmu oknu je vytvo°φ a provede
p°i b∞hu aplikace a p°edß data definovanß u╛ivatelem. Komponenta dialogovΘho
okna je tedy zase op∞tovn∞ pou╛itelnß a p°izp∙sobitelnßφ?
Ukß╛eme si jak vytvo°it obalovou komponentu okolo obecnΘho formulß°e
About
obsa╛enΘho v Zßsobnφk∙ objekt∙ C++ Builderu. Nejprve zkopφrujeme soubory
ABOUT.H,
ABOUT.CPP
a ABOUT.DFM do na╣eho pracovnφho adresß°e. ABOUT.CPP
vlo╛φme
do n∞jakΘ aplikace a provedeme p°eklad. Tφm vytvo°φme soubor
ABOUT.OBJ,
kter² budeme pot°ebovat p°i vytvß°enφ komponenty.
-
D°φve ne╛ m∙╛eme vytvo°it komponentu pro na╣e dialogovΘ okno, musφme urΦit
jak chceme, aby ji v²vojß° pou╛φval. Vytvo°φme rozhranφ mezi na╣im dialogov²m
oknem a aplikacφ, kterß jej pou╛φvß.
Nap°. podφvejme se na vlastnosti komponent standardnφch dialogov²ch
oken. Umo╛≥ujφ v²vojß°i nastavovat poΦßteΦnφ stav dialogovΘho okna, jako
je titulek a poΦßteΦnφ nastavenφ ovladaΦ∙, a po uzav°enφ dialogovΘho okna
p°evzφt zp∞t po╛adovanΘ informace. Nenφ to p°φmß interakce s jednotliv²mi
ovladaΦi v dialogovΘm okn∞, ale s vlastnostmi v obalovΘ komponent∞.
Rozhranφ tedy musφ obsahovat po╛adovanΘ informace, kterΘ formulß° dialogovΘho
okna m∙╛e zobrazit a vracet aplikaci. M∙╛eme si p°edstavit vlastnosti obalovΘ
komponenty jako data p°enß╣enß z a do dialogovΘho okna.
V p°φpad∞ okna
About, nepot°ebujeme vracet ╛ßdnΘ informace a
tedy vlastnosti obalovΘ komponenty obsahujφ pouze informace po╛adovanΘ
k zobrazenφ v okn∞. Jsou to Φty°i polo╛ky dialogovΘho okna About,
kterΘ aplikace m∙╛e ovlivnit a poskytneme tedy Φty°i vlastnosti typu °et∞zec.
Obvykl²m zp∙sobem vytvo°φme komponentu. Zadßme tato specifika: programovou
jednotku komponenty nazveme AboutDlg, od TComponent odvodφme
nov² typ komponenty TAboutBoxDlg a registrujeme vytvß°enou komponentu
na strßnce Samples Palety komponent. Po provedenφ t∞chto akcφ dostaneme:
#ifndef AboutDlgH
#define AboutDlgH
#include <vcl\sysutils.hpp>
#include <vcl\controls.hpp>
#include <vcl\classes.hpp>
#include <vcl\forms.hpp>
class PACKAGE TAboutBoxDlg : public TComponent
{
private:
protected:
public:
__fastcall TAboutBoxDlg(TComponent*
Owner);
__published:
};
#endif
CPP soubor vypadß takto:
#include <vcl\vcl.h>
#pragma hdrstop
#include "AboutDlg.h"
#pragma package(smart_init);
static inline TAboutBoxDlg *ValidCtrCheck()
{
return new TAboutBoxDlg(NULL);
}
__fastcall TAboutBoxDlg::TAboutBoxDlg(TComponent*
Owner)
: TComponent(Owner)
{
}
namespace Aboutdlg
{
void __fastcall PACKAGE Register()
{
TComponentClass classes[1] = {__classid(TAboutBoxDlg)};
RegisterComponents("Samples", classes,
0);
}
}
Novß komponenta mß nynφ pouze mo╛nosti zabudovanΘ do TComponent.
Je to nejjednodu╣╣φ nevizußlnφ komponenta.
-
Kdy╛ ji╛ mßme vytvo°enou komponentu a definovanΘ rozhranφ mezi komponentou
a dialogov²m oknem, m∙╛eme implementovat jejφ rozhranφ. To provedeme ve
t°ech krocφch: vlo╛φme jednotku formulß°e, p°idßme vlastnosti rozhranφ
a p°idßme metodu Execute.
Pro na╣φ obalovou komponentu k inicializaci a zobrazenφ obalenΘho dialogovΘho
okna musφme p°idat soubory formulß°e k projektu. Vlo╛φme tedy ABOUT.H
a sestavenφ s ABOUT.OBJ do hlaviΦkovΘho souboru komponenty:
#include "About.h"
#pragma link "About.obj"
HlaviΦkov² soubor formulß°e v╛dy deklaruje instanci t°φdy formulß°e.
V p°φpad∞ okna About, je t°φda formulß°e TAboutBox a soubor
ABOUT.H
obsahuje nßsledujφcφ deklaraci:
extern TAboutBox *AboutBox;
Vlastnosti v obalovΘ komponent∞ jsou jednodu╣╣φ ne╛ vlastnosti v normßlnφ
komponent∞. Umo╛≥ujφ pouze p°edßvßnφ dat mezi obalovou komponentou a dialogov²m
oknem. Vlo╛enφm dat do vlastnostφ formulß°e, povolφme v²vojß°i nastavit
data b∞hem nßvrhu pro obal k jejich p°edßnφ do dialogovΘho okna p°i b∞hu
aplikace.
Deklarace vlastnostφ rozhranφ vy╛aduje dv∞ dal╣φ deklarace v typu komponenty:
soukromou polo╛ku, kterou obal pou╛ije k ulo╛enφ hodnoty vlastnosti a samotnou
zve°ej≥ovanou deklaraci vlastnosti, kterß specifikuje jmΘno vlastnosti
a °φkß kterß polo╛ka je pou╛ita pro ulo╛enφ. Vlastnosti rozhranφ nevy╛adujφ
p°φstupovΘ metody. Pou╛φvajφ p°φm² p°φstup ke sv²m dat∙m. Podle konvencφ
mß objektovß polo╛ka pro ulo╛enφ hodnoty vlastnosti stejnΘ jmΘno jako vlastnost,
ale na zaΦßtku je p°idßno pφsmeno F. Datovß polo╛ka a vlastnost
musφ b²t stejnΘho typu.
Nap°. k deklaraci vlastnosti rozhranφ celoΦφselnΘho typu nazvanΘ Rok,
pou╛ijeme:
class PACKAGE TMujObal : public TComponent
{
private:
int FRok;
__published:
__property int Rok = {read=FRok, write=FRok};
}
Pro dialogovΘ okno About pot°ebujeme Φty°i vlastnosti typu String,
po jednΘ pro jmΘno produktu, informaci o verzi, autorsk²ch prßvech a komentß°.
Soubor ABOUTDLG.H nynφ vypadß takto:
class PACKAGE TAboutBoxDlg : public TComponent
{
private:
String FProductName, FVersion, FCopyright,
FComments;
__published:
__property String ProductName={read=FProductName,
write=FProductName};
__property String Version = {read=FVersion,
write=FVersion};
__property String Copyright = {read=FCopyright,
write=FCopyright};
__property String Comments = {read=FComments,
write=FComments};
};
Kdy╛ nynφ instalujeme komponentu na paletu a umφstφme ji na formulß°,
m∙╛eme nastavovat vlastnosti a tyto hodnoty jsou automaticky p°edßvßny
s formulß°em. Tyto hodnoty budou pou╛ity p°i provßd∞nφ dialogovΘho okna.
Poslednφ Φßstφ rozhranφ komponenty je otev°enφ dialogovΘho okna a vrßcenφ
v²sledku p°i jeho uzav°enφ. Komponenty obecn²ch dialogov²ch oken pou╛φvajφ
logickou funkci nazvanou Execute, kterß vracφ true, jestli╛e
u╛ivatel stiskl OK nebo false, kdy╛ u╛ivatel okno zru╣il.
Deklarace pro metodu Execute je v╛dy tato:
class PACKAGE TMujObal : public TComponent
{
public:
bool __fastcall Execute();
}
Minimßlnφ implementace pro Execute vy╛aduje vytvo°enφ formulß°e
dialogovΘho okna, jeho zobrazenφ jako modßlnφho dialogovΘho okna a vrßcenφ
true
nebo false (v zßvislosti na nßvratovΘ hodnot∞ ShowModal).
Nßsleduje minimßlnφ metoda Execute pro formulß° dialogovΘho
okna typu TMojeDialOkno:
bool __fastcall TMujObal::Execute()
{
bool Result;
DialOkno = new TMojeDialOkno(Application);
try
{
Result = (DialOkno->ShowModal()
== IDOK)
}
catch(...)
{
Result = false;
}
DialOkno->Free();
}
V praxi, b²vß vφce k≤du uvnit° bloku try..catch. P°ed volßnφm
ShowModal,
obal nastavφ n∞jakΘ vlastnosti dialogovΘho okna na zßklad∞ vlastnostφ rozhranφ
obalovΘ komponenty. Po nßvratu z ShowModal, obal pravd∞podobn∞ nastavφ
n∞kterΘ svΘ vlastnosti rozhranφ na zßklad∞ provedenφ dialogovΘho okna.
V p°φpad∞ okna About, pou╛ije obalovß komponenta Φty°i vlastnosti
rozhranφ k nastavenφ obsahu formulß°e dialogovΘho okna
About. Jeliko╛
okno About nevracφ ╛ßdnΘ informace, nenφ nutno provßd∞t nic po volßnφ
ShowModal.
Na╣e metoda Execute bude tedy vypadat takto:
bool __fastcall TAboutBoxDlg::Execute()
{
bool Result;
AboutBox = new TAboutBox(Application);
try
{
if (ProductName == "")
ProductName = Application->Title;
AboutBox->ProductName->Caption
= ProductName;
AboutBox->Version->Caption
= Version;
AboutBox->Copyright->Caption
= Copyright;
AboutBox->Comments->Caption
= Comments;
AboutBox->Caption = "About
"+ ProductName;
Result = (AboutBox->ShowModal()
== IDOK);
}
catch(...)
{
Result = false;
}
AboutBox->Free();
return Result == IDOK;
}
K hlaviΦkovΘmu souboru ABOUTDLG.H p°idßme deklaraci metody Execute
do ve°ejnΘ Φßsti t°φdy TAboutDlg.
class PACKAGE TAboutDlg : public TComponent
{
public:
virtual bool __fastcall Execute();
};
-
Kdy╛ instalujeme komponentu dialogovΘho okna, m∙╛eme ji pou╛φvat stejn∞
jako obecnß dialogovß okna, umφst∞nφm na formulß° a jejich provedenφm.
Rychl² zp∙sob k otestovßnφ okna About je p°idat na formulß° tlaΦφtko
a provΘst dialogovΘ okna p°i stisknutφ tohoto tlaΦφtka. Testovßnφ na╣φ
komponenty lze provΘst v t∞chto krocφch: vytvo°φme nov² projekt, umφstφme
komponentu okna About a komponentu tlaΦφtka na formulß°, dvojit∞
klikneme na tlaΦφtko (vytvo°φme prßzdnou obsluhu udßlosti stisku tlaΦφtka),
do obsluhy udßlosti stisku tlaΦφtka zapφ╣eme nßsledujφcφ °ßdek k≤du:
AboutBoxDlg1->Execute();
a spustφme aplikaci. M∙╛eme takΘ vyzkou╣et nastavit r∙znΘ vlastnosti
komponenty.