5. Vytvß°enφ metod

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;
}

  1. ╚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ßφ?

  2. 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.
  3. 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ß.

  4. 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.
  5. 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.

  6. 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();
    };
  7. 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:

  8. AboutBoxDlg1->Execute();
    a spustφme aplikaci. M∙╛eme takΘ vyzkou╣et nastavit r∙znΘ vlastnosti komponenty.
5. Vytvß°enφ metod