19. MDI
  1. Ka╛dß aplikace m∙╛e b²t implementovßna jako vφcedokumentovΘ rozhranφ (MDI) nebo jednodokumentovΘ rozhranφ (SDI). V aplikaci MDI m∙╛e b²t otev°eno vφce dokument∙ nebo pod°φzen²ch oken v jednom nad°φzenΘm okn∞. V aplikaci SDI m∙╛e b²t pouze jedno okno dokumentu. ZaΦneme novou aplikacφ. Pro formulß° vytvo°φme nabφdku:
  2. Okno
    NovΘ
    a nastavφme tyto vlastnosti formulß°e: Caption na MDI rßm, FormStyle na fsMDIForm a WindowMenu na Okno1. K aplikaci p°idßme dal╣φ formulß°, kde nastavφme: Caption na Pod°φzenΘ okno, FormStyle na fsMDIChild a Position na poDefaut. Obsluha volby NovΘ bude tvo°ena p°φkazy (deklaraci instance formulß°e Form2 m∙╛eme v jednotce druhΘho formulß°e vynechat a vy°adφme Form2 z automaticky vytvß°en²ch formulß°∙; je takΘ zapot°ebφ  hlaviΦkov² soubor druhΘho formulß°e vlo╛it do jednotky prvnφho formulß°e):
    static int Citac;
    TForm2* Form2 = new TForm2(this);
    Citac++;
    Form2->Caption = Form2->Caption + ' ' + IntToStr(Citac);
    Form2->Show();
    Po spu╣t∞nφ aplikace m∙╛eme otev°φt n∞kolik pod°φzen²ch oken. Pov╣imn∞te si, ╛e se jejich seznam objevuje v nabφdce Okno (je to urΦeno vlastnostφ WindowMenu). Zjist∞te, co se stane, otev°eme-li jich vφce ne╛ 9. Jestli╛e n∞kterΘ z pod°φzen²ch oken zav°eme, pak v seznamu oken stßle existuje (nenφ zru╣eno). Toto vy°e╣φme v dal╣φ verzi aplikace.
  3. V∞t╣ina MDI aplikacφ obsahuje v nabφdce Okno volby pro kaskßdovitΘ a dla╛dicovitΘ uspo°ßdßnφ otev°en²ch pod°φzen²ch oken. Pro obsluhu t∞chto voleb m∙╛eme pou╛φt n∞kterΘ vlastnosti a metody, kterΘ jsou u formulß°e s vlastnostφ FormStyle nastavenou na fsMDIForm. Jsou to: metoda Cascade (kaskßdovitΘ °azenφ), metoda Tile (dla╛dicovitΘ °azenφ), vlastnost TileMode (urΦuje jak bude pracovat Tile) a metoda ArrangeIcons (uspo°ßdßnφ ikon minimalizovan²ch oken). Toto jsou metody a vlastnosti odvozenΘ od Windows. Builder definuje n∞kterΘ dal╣φ: vlastnost ActiveMDIChild (urΦuje aktivnφ okno; tato vlastnost je urΦena pouze pro Φtenφ), metoda Next (aktivuje nßsledujφcφ okno), metoda Previous (aktivuje p°edchozφ okno), vlastnost MDIChildCount (souΦasn² poΦet pod°φzen²ch oken) a vlastnost MDIChildren (pole pod°φzen²ch oken; pomocφ cyklu m∙╛eme prochßzet v╣emi pod°φzen²mi okny).

  4. Na zßv∞r p°edchozφho zadßnφ jsme se zmφnili o nedostatku (nezru╣enφ uzav°enΘho pod°φzenΘho okna). Tuto zßvadu odstranφme vytvo°enφm obsluhy udßlosti OnClose pod°φzenΘho formulß°e s p°φkazem:
    Action = caFree;
    Toto je jedinß metoda pod°φzenΘho okna. Rßm MDI aplikace nynφ vybavφme nßsledujφcφ nabφdkou:
    Soubor Okno
    NovΘ Kaskßda
    ---- Dla╛dice
    Konec Uspo°ßdat ikony
    Obsluhy voleb v nabφdce ji╛ vytvo°te sami.
  5. Nynφ se pokusφme vytvo°it dal╣φ MDI aplikaci. ZaΦneme v²voj novΘ aplikace. U formulß°e zm∞nφme tyto vlastnosti: Name nastavφme na MainForm, Caption na Prohlφ╛eΦ obrßzk∙, Height na 450, Width na 575 a FormStyle na fsMDIForm. K formulß°i p°idßme takΘ nabφdku. Na formulß° vlo╛φme komponentu MainMenu, zm∞nφme jejφ vlastnost Name na MainMenu a dvojit²m kliknutφm na tΘto komponent∞ zobrazφme Nßvrhß° nabφdky. V mφstnφ nabφdce Nßvrhß°e zvolφme Insert from Template a ze seznamu nabφdek vybereme MDI Frame Menu. Na╣e nabφdka bude v angliΦtin∞. Okno Nßvrhß°e nabφdky ji╛ m∙╛eme uzav°φt. Na formulß° p°idßme dßle komponentu OpenPictureDialog (zm∞nφme Name na OpenDialog a Title na Otev°enφ obrßzku) a komponentu SavePictureDialog (zm∞nφme Name na SaveDialog a Title na Ulo╛enφ obrßzku.

  6. Dßle se budeme zab²vat obsluhou voleb File | Open a File | Save As. Obsluha volby File | Open je tvo°ena p°φkazy:
    if (OpenDialog->Execute()) {
      TChild* child = new TChild(this);
      child->Image->Picture->LoadFromFile(OpenDialog->FileName);
      child->ClientWidth = child->Image->Picture->Width;
      child->ClientHeight = child->Image->Picture->Height;
      child->Caption = ExtractFileName(OpenDialog->FileName);
      child->Show();
    }
    Nejprve je provedeno dialogovΘ okno otev°enφ souboru. Pokud jej uzav°eme stiskem tlaΦφtka OK, pak je vytvo°en nov² objekt TChild (t°φda, kterou vytvo°φme pozd∞ji). Soubor obrßzku je zaveden do komponenty Image na pod°φzenΘm formulß°i, klientskß oblast je zm∞n∞na na rozm∞ry obrßzku a vlastnost Caption je nastavena na jmΘno zobrazovanΘho souboru. Funkce ExtractFileName je pou╛ita k extrakci samotnΘho jmΘna souboru obsa╛enΘho ve vlastnosti FileName komponenty OpenDialog. K zφskßnφ jin²ch Φßstφ specifikace souboru existujφ dal╣φ funkce: ExtractFilePath, ExtractFileDir, ExtractFileDrive a ExtractFileExt.
    Nesmφme zapomenout na na╣i p°edchozφ diskusi o volßnφ delete pro v╣echny objekty vytvo°enΘ pomocφ new. Je p°edchozφ k≤d v²jimkou z tohoto pravidla? Ve skuteΦnosti nenφ, proto╛e VCL p°ebφrß zodpov∞dnost za uvol≥ovßnφ pam∞ti alokovanΘ pro pod°φzenΘ okno MDI. Konstruktor TChild p°ebφrß parametr this, kter² °φkß VCL, ╛e vlastnφkem pod°φzenΘho okna MDI je okno hlavnφho formulß°e MDI. P°i uzav°enφ aplikace je takΘ zaji╣t∞no zru╣enφ v╣ech pod°φzen²ch objekt∙ MDI.
    Obsluha volby File | Save As bude vypadat takto:
    TChild* child = dynamic_cast<TChild*>(ActiveMDIChild);
    if (!child) return;
    if (SaveDialog->Execute()) {
      child->Image->Picture->SaveToFile(SaveDialog->FileName);
    }
    Prvnφ dva °ßdky tohoto k≤du zjistφ, zda pod°φzenΘ okno MDI je aktivnφ. Pokud ano, pak je zobrazeno dialogovΘ okno ulo╛enφ souboru a obrßzek je ulo╛en. V p°edchozφm k≤du je pou╛it specißlnφ operßtor C++ dynamic_cast. Tento operßtor se pou╛φvß k p°etypovßnφ ukazatele t°φdy p°edka na ukazatel na odvozenou t°φdu. Vlastnost ActiveMDIChild vracφ ukazatel na objekt TForm. V na╣em p°φpad∞, pokud se jednß o ukazatel na TChild (typ uveden² ve ╣piΦat²ch zßvorkßch; na╣e t°φda pod°φzenΘho okna MDI je odvozenß od TForm), pak zp°φstupnφme vlastnost Image pod°φzenΘho formulß°e. Pokud nenφ mo╛no provΘst p°etypovßnφ, je vrßceno NULL. P°etypovßnφ pomocφ dynamic_cast je lep╣φ (bezpeΦn∞j╣φ) ne╛ star² zp∙sob p°etypovßnφ.
    Obsluhy voleb Tile, Cascade a Arrange All vytvo°te sami.
    Nynφ ji╛ m∙╛eme vytvo°it pod°φzen² formulß° MDI. K aplikaci p°idßme nov² formulß° a zm∞nφme u n∞j vlastnosti Name na Child, Caption nechßme beze zm∞ny (je nastavovßn za b∞hu) a FormStyle na fsMDIChild. Na tento formulß° vlo╛φme komponentu Image, jejφ vlastnost Name zm∞nφme na Image, vlastnost Stretch na true, Align na alClient.
    Do jednotky hlavnφho formulß°e je takΘ nutno p°idat hlaviΦkov² soubor pod°φzenΘho okna. Aplikace je hotova, ale mß zatφm n∞kolik nedostatk∙. N∞kterΘ volby v nabφdce nejsou obslou╛eny, tφm se ji╛ ale nebudeme zab²vat. Dal╣φ nedostatek je automatickΘ vytvo°enφ pod°φzenΘho formulß°e p°i spu╣t∞nφ aplikace. Pod°φzen² formulß° je nutno vy°adit ze seznamu pod°φzen²ch formulß°∙ (tφm p°ebφrßme odpov∞dnost za jeho vytvo°enφ). ProblΘmy takΘ vznikajφ, kdy╛ otev°eme soubor, kter² nenφ obrßzkem. T∞mito problΘmy se ji╛ nebudeme zab²vat.
  7. Pro MDI aplikace (nap°. textov² editor) pot°ebuje hlavnφ nabφdka zφskßvat prvky nabφdky z jin²ch (pod°φzen²ch formulß°∙). Tomuto procesu °φkßme sluΦovßnφ nabφdek. P°i prßci s nabφdkami pou╛φvßme vlastnost Menu formulß°e a vlastnosti GroupIndex prvk∙ nabφdky. Vlastnost Menu urΦuje aktivnφ nabφdku formulß°e (m∙╛eme ji m∞nit i za b∞hu aplikace). Vlastnost GroupIndex urΦuje po°adφ, ve kterΘm sluΦujeme prvky nabφdky. SluΦovanΘ prvky mohou nahradit prvky na hlavnφm °ßdku nabφdky (stejnß hodnota GroupIndex) nebo mohou b²t vlo╛eny.

  8. SluΦovßnφ nabφdek si ukß╛eme na jednoduchΘ aplikaci (nejednß se o MDI aplikaci). Hlavnφ formulß° bude obsahovat nabφdku (v zßvorkßch jsou uvedeny hodnoty vlastnostφ GroupIndex):
    Soubor (0) E-Mail (1)  Nßpov∞da (2)
    Nov² Zobraz modßln∞  O aplikaci
    Otev°φt Zobraz nemodßln∞
    Ulo╛it Zav°i nemodßlnφ
    -----
    Konec
    Volbu Zav°i nemodßlnφ zakß╛eme. K aplikaci p°idßme dal╣φ formulß°, kter² bude mφt nabφdku:
    E-Mail Soubor (1)
    Otev°φt
    Ulo╛it
    ------
    Zav°φt
    Abychom si ukßzali, ╛e tento p°φstup funguje s modßlnφm i nemodßlnφm formulß°em, jsou v nabφdce E-Mail volby pro zobrazenφ okna ob∞ma zp∙soby. Obsluha volby Zobraz modßln∞ je tvo°ena p°φkazem:
    Form2->ShowModal();
    Formulß°e tohoto programu jsou vytvo°eny p°i spu╣t∞nφ aplikace. Kdy╛ program zobrazφ druh² formulß° jako modßlnφ, pak nenφ mo╛no pou╛φvat nabφdku hlavnφho formulß°e. Pokud formulß° zobrazφme nemodßln∞, m∞li bychom zakßzat ruΦn∞ volby Zobraz modßln∞ a Zobraz nemodßln∞ (v tomto p°φpad∞ nenφ vhodnΘ umo╛nit vφcenßsobnΘ zobrazenφ formulß°e). Obsluha volby Zobraz nemodßln∞ tedy bude tvo°ena p°φkazy:
    Zobrazmodln1->Enabled = false;
    Zobraznemodln1->Enabled = false;
    Zavinemodln1->Enabled = true;
    Form2->Show();
    Poslednφ volba v nabφdce E-Mail provßdφ zav°enφ nemodßlnφho formulß°e. Obsluha bude tvo°ena p°φkazem:
    Form2->Close();
    Po uzav°enφ nemodßlnφho formulß°e, bychom ale m∞li vrßtit nabφdku do p∙vodnφho stavu. Formulß° lze ale uzav°φt mnoha zp∙soby. Mφsto opakovßnφ k≤du pro povolenφ voleb nabφdky na mnoha mφstech je m∙╛eme napsat pouze do obsluhy udßlosti OnClose pro druh² formulß°:
    Form1->Zobrazmodln1->Enabled = true;
    Form1->Zobraznemodln1->Enabled = true;
    Form1->Zavinemodln1->Enabled = false;
    Nynφ se ale programovΘ jednotky obou formulß°∙ odkazujφ na sebe navzßjem. Do jednotky druhΘho formulß°e musφme tedy p°idat vlo╛enφ hlaviΦkovΘho souboru prvnφho formulß°e. Pro druh² formulß° vytvo°φme je╣t∞ obsluhu volby Zav°φt s p°φkazem Close();. Nynφ ji╛ aplikaci m∙╛eme vyzkou╣et (zatφm se je╣t∞ nejednß o sluΦovßnφ nabφdek). Na tomto p°φklad∞ vidφme, ╛e obsluha modßlnφch formulß°∙ je jednodu╣╣φ ne╛ nemodßlnφch formulß°∙.
    Aby na╣e aplikace m∞la n∞jak² v²znam, umφst∞te na hlavnφ formulß° komponentu ListBox s telefonnφmi Φφsly sv²ch znßm²ch a na druh² formulß° takΘ ListBox, tentokrßt s E-Mail adresami. Vytvo°te takΘ ostatnφ obsluhy voleb v nabφdce (uklßdßnφ seznam∙ do soubor∙, otevφrßnφ souboru atd.).
  9. V p°edchozφ aplikaci m∞ly oba formulß°e vlastnφ nabφdky. C++ Builder ale podporuje sluΦovßnφ nabφdek. Je to provßd∞no takto. Hlavnφ formulß° mß stßle nabφdku. Ostatnφ formulß°e majφ nabφdky s nastavenou vlastnostφ AutoMerge na true (jejich nabφdka potom nebude zobrazovßna ve formulß°i, ale bude spojena s hlavnφ nabφdkou). SluΦovßnφ prob∞hne podle hodnot vlastnostφ GroupIndex. V na╣em p°φklad∞ nabφdka E-Mail Soubor nahradφ nabφdku E-Mail (ob∞ majφ stejnou hodnotu GroupIndex). SluΦovßnφ nabφdek mß v²znam pouze pro nemodßlnφ formulß°e (u modßlnφch formulß°∙ se k nabφdce nedostaneme, tak╛e C++ Builder sluΦovßnφ neprovßdφ). Po uzav°enφ nemodßlnφho formulß°e se ale neobnovφ p∙vodnφ hlavnφ nabφdka (formulß° nenφ zru╣en, pouze se skryl). ProblΘm vy°e╣φme zßsadnφ zm∞nou p°φstupu k obsluze druhΘho formulß°e. Mφsto vytvß°enφ objektu formulß°e p°i spou╣t∞nφ aplikace jej musφme vytvo°it a zru╣it poka╛dΘ, kdy╛ mß b²t zobrazen nebo skryt. V dialogovΘm okn∞ Project Options na strßnce Forms zru╣φme automatickΘ vytvß°enφ druhΘho formulß°e. Abychom mohli formulß° zobrazit jako modßlnφ, musφme jej vytvo°it, nastavit jeho vlastnosti a pozd∞ji jej zru╣it. Obsluha volby Zobraz modßln∞ bude tedy tvo°ena p°φkazy:

  10. Form2 = new TForm2(this);
    Form2->MainMenu1->AutoMerge = false;
    Form2->ShowModal();
    Form2->Free();
    Pro Zobraz nemodßln∞ to bude:
    Form2 = new TForm2(this);
    Form2->MainMenu1->AutoMerge = true;
    Form2->Show();
    P°i tΘto volb∞ formulß° zru╣en nenφ (nenφ zde ji╛ nutnΘ zakazovat volby v nabφdce). Aby p°i uzav°enφ formulß°e byl formulß° opravdu zru╣en, musφme je╣t∞ u udßlosti OnClose druhΘho formulß°e nastavit hodnotu parametru Action na caFree. Nynφ je ji╛ aplikace hotova.
  11. Zatφm vytvo°enΘ MDI aplikace neprovßd∞ly nic rozumnΘho. Obdr╛eli jsme program s typick²m chovßnφm MDI, ale s ╛ßdn²m praktick²m u╛itkem. S pod°φzen²m formulß°em m∙╛eme ale provßd∞t cokoliv. M∙╛eme p°idat r∙znΘ komponenty, vytvo°it editory apod. Kter²koli z program∙, kterΘ jsme zatφm vytvo°ili m∙╛eme p°evΘst na MDI aplikaci (u n∞kter²ch to ale nedßvß smysl). Na╣φ skuteΦnou prvnφ MDI aplikacφ bude jednoduchß verze grafickΘho programu. Tento program na mφst∞ kliknutφ my╣φ zobrazφ kruh. Pod°φzenΘ okno obsahuje tuto nabφdku (v aplikaci ji╛ pou╛ijeme sluΦovßnφ nabφdek):
  12. Kruh
    Barva v²pln∞ ...
    Barva okraje ...
    ⌐φ°e okraje ...
    ---------------
    Zφskej pozici
    D∙le╛itΘ je to, ╛e p°i programovßnφ pod°φzenΘho formulß°e nemusφme brßt v ·vahu existenci jin²ch formulß°∙ (vΦetn∞ formulß°e rßmu). Jedin² specißlnφ p°φpad je sluΦovßnφ nabφdek. Vezmeme rßm ze druhΘho zadßnφ tΘto kapitoly s jedinou zm∞nou, kterou v n∞m provedeme je nastavenφ vlastnostφ GroupIndex pro nabφdku Soubor na 1 a pro nabφdku Okno na 3. To je v╣e, co na tomto formulß°i zm∞nφme. GroupIndex u nabφdky Kruh v pod°φzenΘm formulß°i nastavφme na 2. U pod°φzenΘho formulß°e nastavφme tyto vlastnosti: Caption na Pod°φzenΘ okno, Color na clTeal, FormStyle na fsMDIChild, Menu na MainMenu1 a Position na poDefault. Do soukromΘ Φßsti pod°φzenΘho formulß°e p°idßme deklarace:
    int XStred, YStred;
    int SireOkraje;
    TColor BarvaOkraje, BarvaVyplne;
    Nynφ ji╛ zb²vß vytvo°it n∞kolik obsluh udßlostφ. Obsluha OnCreate formulß°e je tvo°ena p°φkazy:
    XStred = -200;
    YStred = -200;
    SireOkraje = 1;
    BarvaOkraje = clBlack;
    BarvaVyplne = clYellow;
    Obsluhu OnPaint vytvo°φme p°φkazy:
    Canvas->Pen->Width = SireOkraje;
    Canvas->Pen->Color = BarvaOkraje;
    Canvas->Brush->Color = BarvaVyplne;
    Canvas->Ellipse(XStred-30, YStred-30, XStred+30, YStred+30);
    Obsluhu OnMouseDown tvo°φ p°φkazy:
    XStred = X;
    YStred = Y;
    Repaint();
    Obsluha OnClose je stejnß jako v p°edchßzejφcφ MDI aplikaci. Zb²vß je╣t∞ vytvo°it n∞kolik obsluh voleb v nabφdce. Nap°. obsluhu volby ⌐φ°eokraje tvo°φ p°φkazy:
    AnsiString VstupniRetezec = IntToStr(SireOkraje);
    if (InputQuery("Okraj", "Zadej ╣φ°ku", VstupniRetezec)){
      SireOkraje = VstupniRetezec.ToIntDef(SireOkraje);
      Repaint();
    }
    Ostatnφ obsluhy voleb vytvo°te sami. V²pis informacφ volbou Zφskej pozici provßd∞jte funkcφ ShowMessage. Aplikaci m∙╛eme vyzkou╣et. Ka╛d² pod°φzen² formulß° m∙╛e obsahovat pouze jeden kruh. Pod°φzen²ch formulß°∙ m∙╛eme otev°φt vφce.
  13. Obecn∞ mohou MDI aplikace obsahovat vφce druh∙ pod°φzen²ch formulß°∙. Ukß╛eme si to na roz╣φ°enφ p°edchozφ aplikace. Budeme muset vytvo°it nov² pod°φzen² formulß°. Tentokrßt vytvo°φme formulß° s pohybujφcφm se Φtvercem, kter² se bude odrß╛et od okraj∙. K p°edchozφ aplikaci p°idßme dal╣φ formulß°, p°idßme k n∞mu nßsledujφcφ nabφdku:
  14. ╚tverec Pohyb
    Barva v²pln∞ ... Start
    --------------- Stop
    Zφskej pozici
    U obou t∞chto nabφdek nastavφme GroupIndex na 2 a volbu Start zakß╛eme. U formulß°e nastavφme tyto vlastnosti: AutoScroll na False, Caption na Pohybujφcφ se Φtverec, Color na clAqua, FormStyle na fsMDIChild, Menu na MainMenu1, Position na poDefault a Visible na True. Na formulß° vlo╛φme dßle komponentu Shape a nastavφme pro nφ vlastnosti: Left na 40, Top na 48, Width a Height na 30, Brush.Pen na clFuchsia, Pen.Color na clBlue, Pen.Width na 2 a Shape na stSquare. Na formulß° p°idßme je╣t∞ komponentu Timer a nastavφme jeho vlastnost Interval na 200. Nynφ se ji╛ m∙╛eme zab²vat pohybem Φtverce. Nejprve nadefinujeme v²Φtov² typ Smery s mo╛n²mi sm∞ry pohybu Φtverce. Deklaraci tohoto typu umφstφme do hlaviΦkovΘho souboru p°ed deklaraci typu formulß°e:
    enum Smery {nahoru_vpravo, dolu_vpravo, dolu_vlevo, nahoru_vlevo};
    Jako soukromou polo╛ku t°φdy formulß°e p°idßme:
    Smery Smer;
    Obsluhu OnCreate bude tvo°it p°φkaz:
    Smer = dolu_vlevo;
    a obsluha OnClose je tvo°ena obvykl²m p°φkazem. Obsluhu volby nabφdky Start tvo°φ p°φkazy:
    Timer1->Enabled = true;
    Start1->Enabled = false;
    Stop1->Enabled = true;
    Obsluhy ostatnφch voleb v nabφdce vytvo°te sami. Zb²vß je╣t∞ vytvo°it obsluhu udßlosti OnTimer ΦasovaΦe. V tΘto obsluze budeme m∞nit sou°adnice Φtverce. ZaΦßtek obsluhy je tvo°en p°φkazy:
    switch (Smer){
      case nahoru_vpravo:
        Shape1->Left += 3;
        Shape1->Top -= 3;
        if (Shape1->Top <= 0) Smer = dolu_vpravo;
        if (Shape1->Left+Shape1->Width>=ClientWidth) Smer = nahoru_vlevo;
        break;
      case nahoru_vlevo:
      ...
    }
    Zbytek obsluhy vytvo°te sami. Tφm je hotov druh² pod°φzen² formulß°. Musφme je╣t∞ zm∞nit hlavnφ formulß°. Zm∞nφme zde nabφdku:
    Soubor Okno
    Nov² kruh Kaskßda
    Nov² Φtverec Dla╛dice vodorovn∞
    Uzav°φt v╣e Dla╛dice svisle
    --------------- Uspo°ßdat ikony
    Konec PoΦet
    V nabφdce Soubor si ukß╛eme obsluhu volby Uzav°φt v╣e (ostatnφ vytvo°te sami):
    for (int I = MDIChildCount - 1; I >= 0; I--) MDIChildren[I]->Close();
    Volba Dla╛dice vodorovn∞ bude obslou╛ena p°φkazy:
    TileMode = tbHorizontal;
    Tile();
    Obdobn∞ vytvo°te obsluhu volby Dla╛dice svisle (tbVertical). Obsluhu volby PoΦet tvo°φ p°φkazy:
    int NCtverec = 0, NKruh = 0;
    for (int I = 0; I < MDIChildCount; I++)
     if (MDIChildren[I]->ClassNameIs("TForm3")) NCtverec++;
     else NKruh++;
    ShowMessage("Jsou zde "+IntToStr(MDIChildCount)+" pod°φzenΘ formulß°e.\n"
                +IntToStr(NKruh)+" je pod°φzen²ch oken kruh∙ a \n" +
                IntToStr(NCtverec) + " pod°φzen²ch oken Φtverc∙.");
    Ostatnφ obsluhy vytvo°te sami a aplikaci vyzkou╣ejte.
19. MDI