13. T°φdy v C++ Builderu III
  1. DokonΦete vytvß°enφ va╣φ kalkulaΦky.


  2. Prap°edkem v╣ech t°φd VCL je t°φda TObject. Podφvejme se na jejφ definici.

  3. class DELPHICLASS TObject {
    public:
      __fastcall  TObject();
      __fastcall Free();
      TClass  __fastcall ClassType();
      void    __fastcall CleanupInstance();
      void *  __fastcall FieldAddress(const ShortString &Name);
      static TObject * __fastcall InitInstance(TClass cls, void *instance);
      static ShortString __fastcall ClassName(TClass cls);
      static bool __fastcall ClassNameIs(TClass cls, const AnsiString string);
      static TClass __fastcall ClassParent(TClass cls);
      static void * __fastcall ClassInfo(TClass cls);
      static long __fastcall InstanceSize(TClass cls);
      static bool __fastcall InheritsFrom(TClass cls, TClass aClass);
      static void * __fastcall MethodAddress(TClass cls, const ShortString &Name);
      static ShortString __fastcall MethodName(TClass cls, void *Address);
      bool __fastcall GetInterface(const TGUID &IID, /* out */ void *Obj);
      static PInterfaceEntry __fastcall GetInterfaceEntry(const TGUID IID);
      static PInterfaceTable * __fastcall GetInterfaceTable(void);
      ShortString __fastcall ClassName() {return ClassName(ClassType()); }
      bool __fastcall ClassNameIs(const AnsiString string)
        { return ClassNameIs(ClassType(), string); }
      TClass __fastcall ClassParent() { return ClassParent(ClassType()); }
      void * __fastcall ClassInfo() { return ClassInfo(ClassType()); }
      long __fastcall InstanceSize() { return InstanceSize(ClassType()); }
      bool __fastcall InheritsFrom(TClass aClass)
        { return InheritsFrom(ClassType(), aClass); }
      void * __fastcall MethodAddress(const ShortString &Name)
        { return MethodAddress(ClassType(), Name); }
      ShortString __fastcall MethodName(void *Address)
        { return MethodName(ClassType(), Address); }
      virtual HResult __fastcall SafeCallException(TObject *ExceptObject,
                                                   void *ExceptAddr);
      virtual void __fastcall AfterConstruction();
      virtual void __fastcall BeforeDestruction();
      virtual void __fastcall Dispatch(void *Message);
      virtual void __fastcall DefaultHandler(void* Message);
    private:
      virtual TObject* __fastcall NewInstance(TClass cls);
    public:
      virtual void __fastcall FreeInstance();
      virtual __fastcall ~TObject();
    };
    V tomto v²pisu je deklarovßna t°φda TObject, kterß obsahuje n∞kolik metod, kterΘ m∙╛eme aplikovat na jak²koli objekt VCL, vΦetn∞ nßmi definovan²ch objekt∙ odvozen²ch od TObject. V∞t╣ina metod t°φdy TObject je Φasto pou╛φvßna systΘmem. N∞kterΘ metody t°φdy TObject mohou hrßt d∙le╛itou roli p°i psanφ obecn²ch aplikacφ. Nap°. metoda ClassName vracφ °et∞zec se jmΘnem t°φdy. Tuto metodu je mo╛nΘ aplikovat jak na objekt (instanci), tak i na t°φdu (datov² typ), proto╛e se jednß o statickou metodu. N∞kdy m∙╛e b²t takΘ u╛iteΦnΘ zφskat odkaz na vlastnφ t°φdu nebo jejφho p°edch∙dce. To zaji╣╗ujφ metody ClassType a ClassParent. Jakmile znßme odkaz na t°φdu, m∙╛eme jej pou╛φt stejn²m zp∙sobem, jako by se jednalo o objekt: nap°. pro volßnφ metody ClassName. Dal╣φ u╛iteΦnß metoda je InstanceSize, kterß vracφ velikost objektu. Pou╛itφ n∞kter²ch metod tΘto t°φdy si ukß╛eme v nßsledujφcφ aplikaci. Metodu ClassNameIs jsme ji╛ pou╛ili v p°edchozφ kapitole p°i ta╛enφ typu pφsma. Na formulß° umφstφme okno seznamu (ListBox) a tlaΦφtko. Obsluha stisknutφ tlaΦφtka bude tvo°ena nßsledujφcφmi p°φkazy (pov╣imn∞te si takΘ poslednφho p°φkazu, kter² zabrßnφ dal╣φmu stisknutφ tlaΦφtka):
    void __fastcall TForm1::Button1Click(TObject *Sender)
    {
      ListBox1->Items->Add("JmΘno t°φdy: " + Button1->ClassName());
      ListBox1->Items->Add("JmΘno t°φdy p°edka: " +
        Button1->ClassParent()->ClassName());
      ListBox1->Items->Add("Velikost instance: " +
        IntToStr(Button1->InstanceSize()));
      ListBox1->Items->Add(" ");
      ListBox1->Items->Add("JmΘno t°φdy: " + ClassName());
      ListBox1->Items->Add("JmΘno t°φdy p°edka: " +
        ClassParent()->ClassName());
      ListBox1->Items->Add("Velikost instance: " + IntToStr(InstanceSize()));
      Button1->Enabled = false;
    }
    Vyzkou╣ejte Φinnost aplikace a pokuste se pochopit jak pracuje (a co d∞lß).
  4. Hlavnφ nabφdka C++ Builderu obsahuje v╣echny volby pot°ebnΘ k prßci s C++ Builderem. Tato nabφdka se pou╛φvß obvykl²m zp∙sobem. NejΦast∞ji pou╛φvanΘ volby je mo╛no takΘ zadßvat na Palet∞ nßstroj∙. Paleta nßstroj∙ je popsßna na nßsledujφcφm obrßzku.


  5. Paleta nßstroj∙ je pln∞ p°izp∙sobitelnß. Mezi Paletou nßstroj∙ a Paletou komponent je svislß Φßra, kterou je mo╛no p°etahovat my╣φ vlevo nebo vpravo a m∞nit tak ╣φ°ku t∞chto palet. P°izp∙sobovßnφ Palety nßstroj∙ je snadnΘ. Na paletu m∙╛eme p°idßvat tlaΦφtka, odstra≥ovat tlaΦφtka a m∞nit uspo°ßdßnφ tlaΦφtek. Pro konfiguraci Palety nßstroj∙ musφme pou╛φt mφstnφ nabφdku. Ukß╛eme my╣φ na Paletu nßstroj∙ a k zobrazenφ mφstnφ nabφdky klikneme prav²m tlaΦφtkem my╣i. Volby mφstnφ nabφdky jsou popsßny v nßsledujφcφ tabulce.
     
    Prvek nabφdky Popis
    Show Hints UrΦuje zda je zobrazovßna bublinkovß nßpov∞da pro tlaΦφtka palety.
    Hide Skr²vß Paletu nßstroj∙.
    Help Vyvovßvß nßpov∞du C++ Builderu pro Paletu nßstroj∙.
    Properties Zobrazφ dialogovΘ okno Editoru palety nßstroj∙, kterΘ umo╛≥uje Paletu nßstroj∙ p°izp∙sobit podle na╣ich po╛adavk∙.
    Pokud Paletu nßstroj∙ skryjeme, pak jejφ op∞tovnΘ zobrazenφ lze provΘst volbou View | Toolbar.
    Pro p°izp∙sobovßnφ Palety nßstroj∙ musφme v mφstnφ nabφdce palety zvolit Properties. Tφm zobrazφme dialogovΘ okno Editoru palety nßstroj∙. Toto dialogovΘ okno obsahuje v╣echna mo╛nß tlaΦφtka palety. Pro p°idßnφ tlaΦφtka na paletu staΦφ tlaΦφtko pouze p°etßhnout my╣φ z okna Editoru na paletu. K odstran∞nφ tlaΦφtka z palety, staΦφ tlaΦφtko p°etßhnou mimo paletu. Uspo°ßdßnφ tlaΦφtek na palet∞ lze provΘst jejich p°eta╛enφm na novΘ pozice. TlaΦφtko Reset v okn∞ Editoru slou╛φ pro nßvrat k implicitnφmu nastavenφ tlaΦφtek.
  6. Paleta komponent C++ Builderu je pou╛φvßna k v²b∞ru komponenty, kterou budeme umis╗ovat na formulß°. Paleta komponent je vφcestrßnkovΘ okno. Zßlo╛ky strßnek umo╛≥ujφ p°echßzet mezi strßnkami. Umφst∞nφ komponenty na formulß° je dvoukrokov² proces. Nejprve pomocφ Palety komponent vybereme komponentu, kterou chceme umφstit na formulß° a potom kliknutφm na formulß°i umφstφme komponentu na formulß°. Lev² hornφ roh komponenty je umφst∞n na mφst∞ kliknutφ.

  7. N∞kdy se dostaneme do situace, ╛e pot°ebujeme na formulß° umφstit vφce stejn²ch komponent. K provedenφ tΘto akce stiskneme a p°i v²b∞ru komponenty na Palet∞ komponent dr╛φme stisknutou klßvesu Shift. Po v²b∞ru komponenty klßvesu uvolnφme. VybranΘ tlaΦφtko komponenty je nynφ na palet∞ zobrazeno s modr²m rßmeΦkem. Nynφ p°i ka╛dΘm kliknutφ na formulß°i umφstφme na formulß° v╛dy tuto vybranou komponentu. Komponenta z∙stßvß stßle vybrßna. K zru╣enφ jejφho v²b∞ru stikneme na Palet∞ komponent v²b∞rovΘ tlaΦφtko (tlaΦφtko se ╣ipkou na levΘ stran∞ palety).
    Komponenty na formulß° lze vklßdat je╣t∞ jin²m zp∙sobem. Jednodu╣e dvojit∞ klikneme na tlaΦφtko komponenty na palet∞ nßstroj∙ a komponenta je umφt∞na doprost°ed formulß°e. Komponentu potom m∙╛eme b∞╛n²m zp∙sobem p°etßhnout na po╛adovanΘ mφsto.
    Paleta komponent mß stejnou mφstnφ nabφdku jako Paleta nßstroj∙. Pou╛φvßme ji stejn²m zp∙sobem k provßd∞nφ obdobn²ch ·loh.
    Na Palet∞ komponent nemusφ b²t zobrazeny v╣echny existujφcφ zßlo╛ky strßnek (nevejdou se tam) a zobrazenß strßnka nemusφ zobrazovat v╣echny komponenty, kterΘ jsou na nφ umφst∞ny. V t∞chto p°φpadech lze pou╛φt posuvnφky podle nßsledujφcφho obrßzku.
  8. Nedφlnou souΦßstφ IDE C++ Builderu je Inspektor objekt∙. Inspektor objekt∙ umo╛≥uje nastavovat vlastnosti komponent b∞hem nßvrhu. Inspektor objekt∙ mß t°i hlavnφ oblasti:
  9. Selektor komponenty je rozbalovacφ seznam v hornφ Φßsti Inspektora objekt∙. Selektor komponenty umo╛≥uje v²b∞r komponenty. Obvykle komponentu vybφrßme kliknutφm my╣i na komponent∞ na formulß°i. N∞kdy to ale nenφ mo╛nΘ (komponenta m∙╛e b²t p°ekryta jinou komponentou).
    Selektor komponenty zobrazuje t°φdu komponenty a t°φdu od kterΘ je komponenta odvozena. Nap°. komponenta Memo nazvanß Memo je uvedena v Selektoru objekt∙ takto:
    Memo: TMemo
    JmΘno t°φdy se nezobrazuje v rozbalovacφm seznamu komponent, ale pouze v hornφ Φßsti Selektoru komponent. V²b∞r komponenty provedeme v²b∞rem v Selektoru komponenty. V Selektoru komponenty jsou uvedeny pouze komponenty z aktußlnφho formulß°e a samotn² formulß°. Ostatnφ formulß°e a jejich komponenty zde nejsou uvßd∞ny.
    Strßnka vlastnostφ Inspektora objekt∙ zobrazuje v╣echny vlastnosti dostupnΘ b∞hem nßvrhu pro prßv∞ vybranou komponentu. Strßnka vlastnostφ mß dva sloupce. Vlevo je sloupec se jmΘny vlastnostφ a vpravo sloupec hodnot. Pokud na formulß°i je vybrßno vφce komponent, pak Inspektor objekt∙ uvßdφ v╣echny vlastnosti, kterΘ majφ vybranΘ komponenty spoleΦnΘ. Toto m∙╛eme vyu╛φt p°i modifikaci n∞kolika komponent najednou. Nap°. ke zm∞n∞ ╣φ°ky n∞kolika komponent na stejnou hodnotu vybereme v╣echny tyto komponenty a v Inspektoru objekt∙ zm∞nφme hodnotu vlastnosti Width. Vlastnost Width je tφm modifikovßna u v╣ech vybran²ch komponent.
    V mnoha p°φpadech je p°i zadßvßnφ testovßna p°φpustnost hodnoty vlastnosti. Nap°. hodnota vlastnosti Width nem∙╛e b²t zßpornß. Zadßme-li zde zßpornou hodnotu, pak ji C++ Builder zm∞nφ na nejmen╣φ mo╛nou hodnotu (obvykle na 0). Zadßme-li zde hodnotu, kterß nenφ cel²m Φφslem, pak je vypsßna chybovß zprßva.
    Strßnka udßlostφ uvßdφ v╣echny udßlosti, kterΘ komponenta m∙╛e zpracovßvat. K vytvo°enφ obsluhy udßlosti, dvojit∞ klikneme ve sloupci hodnot u udßlosti, kterou chceme obslou╛it. V tomto p°φpad∞ jmΘno obsluhy udßlosti je generovßno C++ Builderem. Jestli╛e obsluze udßlosti chceme jmΘno p°i°adit sami, pak jej zapφ╣eme do sloupce hodnot a stiskneme Enter.
    C++ Builder odstra≥uje v╣echny prßzdnΘ obsluhy udßlostφ p°i p°ekladu nebo uklßdßnφ jednotky do souboru. To vyu╛φvßme v p°φpad∞, kdy pot°ebujeme n∞kterou vytvo°enou obsluhu udßlost zru╣it. Pouze vyprßzdnφme jejφ obsah a p°i p°φ╣tφm p°ekladu je takovßto obsluha odstran∞na. Nenφ vhodnΘ p°i ru╣enφ obsluhy postupovat tak, ╛e v Editoru k≤du vyma╛eme celou obsluhu (vΦetn∞ hlaviΦky). Pokud zru╣enφ provedeme tφmto zp∙sobem, pak p°i p°ekladu je signalizovßna chyba (C++ Builder nevφ, ╛e obsluha byla zru╣ena).
  10. C++ Builder je urΦen k vytvß°enφ aplikacφ zalo╛en²ch na VCL. M∙╛eme jej ale pou╛φt k vytvo°enφ jinΘho typu aplikace? C++ Builder je standardnφ p°ekladaΦ C++ a lze jφm tedy p°eklßdat libovoln² typ 32 bitovΘho programu C++. B∞╛n∞ je mo╛no pou╛φt C++ Builder k vytvß°enφ DLL (dynamicky sestavovanß knihovna). P°i seznamovßnφ s C++ jsme si mnohokrßt ukßzali, ╛e v C++ Builderu lze vytvß°et konzolovΘ aplikace. M∙╛eme takΘ p°eklßdat programy zapsanΘ v MFC nebo OWL. V tomto p°φpad∞ pou╛ijeme samostatn² p°ekladaΦ.

  11. Nynφ si ukß╛eme jak vytvo°it program, kter² pou╛φvß pouze funkce API. Jednß se o program, kter² vytvo°φ okno a do okna vypφ╣e n∞jak² text. ZaΦn∞me vytvß°et novou aplikaci, postupujeme, jako p°i vytvß°enφ konzolovΘ aplikace a v pr∙vodci vytvß°enφm konzolovΘ aplikace nastavφme voliΦ Windows (GUI). Vygenerovan² obsah zdrojovΘho souboru sma╛eme a nahradφme jej nßsledujφcφm k≤dem.
    #define STRICT
    #include <windows.h>
    #pragma hdrstop
    #pragma argsused
    LRESULT FAR PASCAL _export WndProc(HWND, UINT, WPARAM, LPARAM);
    int PASCAL WinMain(HINSTANCE hInstance,
      HINSTANCE hPrevInstance, LPSTR lpszCmd, int nCmdShow)
    {
      static char AppName[] = "HelloWorld";
      HWND        hwnd;
      MSG         msg;
      WNDCLASS    wndclass;
      if (!hPrevInstance)
      {
        wndclass.style         = CS_HREDRAW | CS_VREDRAW;
        wndclass.lpfnWndProc   = (WNDPROC)WndProc;
        wndclass.cbClsExtra    = 0;
        wndclass.cbWndExtra    = 0;
        wndclass.hInstance     = hInstance;
        wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
        wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
        wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
        wndclass.lpszMenuName  = 0;
        wndclass.lpszClassName = AppName;
        RegisterClass(&wndclass);
      }
      hwnd = CreateWindow(AppName,
        "Hello World",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);
      ShowWindow(hwnd, SW_NORMAL);
      while (GetMessage(&msg, NULL, 0, 0))
      {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
      }
      return msg.wParam;
    }
    LRESULT FAR PASCAL _export
    WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
      switch(message)
      {
        case WM_PAINT :
        {
          char text[] = "Ahoj!";
          PAINTSTRUCT ps;
          BeginPaint(hwnd, &ps);
          TextOut(ps.hdc, 20, 20, text, 5);
          EndPaint(hwnd, &ps);
          break;
        }
        case WM_DESTROY : {
          PostQuitMessage(0);
          return 0;
        }
        default:
          return DefWindowProc(hwnd, message, wParam, lParam);
      }
      return 0;
    }
    Program p°elo╛φme a spustφme. Vidφme, ╛e v C++ Builderu je mo╛no vytvo°it program API Windows. Toto je pouze ukßzka mo╛nostφ C++ Builderu. TakovΘto programy nebudeme vytvß°et.
13. T°φdy v C++ Builderu III