Image
29.6.2016 0 Comments

C++ pod Windows / Serializácia aplikácií MDI / 22. časť

Späť na úvod >> Späť na programovanie >> Späť na seriál

Nastal máj, lásky čas. Dúfam, že keď čítate tieto riadky, počasie sa už umúdrilo a je pekne teplo a slnečno, tak ako sa na máj patrí. A prečo som začal práve o počasí? Práve keď píšem tieto riadky, vonku už asi piaty deň za sebou na striedačku prší alebo sneží, Dunaj má blízko k 9 metrom a sila vetra je takisto pozoruhodná. Ideálny čas sedieť doma s nejakou dobrou knihou/manuálom , prípadne počítačovou hrou. Týchto vecí sa teraz zriekam, aby som sa s vami podelil o ďalšie vedomosti z oblasti programovania. Opíšeme si aplikácie MDI a na príklade si ukážeme ich reálne použitie.  

MDI. MDI je skratka pre Multiple Document Interface aplikácie, čiže také, ktoré môžu obsahovať viacero objektov dokumentu (iná, menej presná definícia hovorí, že sú to také aplikácie, ktoré môžu mať vo svojom rámcovom okne ešte ďalšie „okienka“). S príchodom 16-bitových Windows 3.0 (s ktorými sa uviedol aj štandard MDI) sa hovorilo, že aplikácie MDI sú tým pravým a predstavujú štandard, ktorý by mala dodržiavať každá aplikácia Windows. Táto predstava spôsobila menšiu „davovú“ psychózu medzi programátormi a každý sa za každú cenu snažil čo najviac využívať „štandard MDI“ vo svojich aplikáciách. Keď prišli nové Windows s ponukou Štart, čím sa zjednodušilo prepínanie medzi aplikáciami, prišla s nimi aj nová teória: načo je niekomu veľa okienok v jednej aplikácii (kde sme obmedzení veľkosťou zobraziteľnej plochy na monitore), keď sa môže jednoducho prepínať medzi tou istou aplikáciou a pracovať tak s jej X okienkami naraz? (Túto filozofiu v praxi dobre vidieť napr. vo Windows CE, ktoré aplikácie MDI ani nepodporujú). Výsledkom bola „psychóza 2“, keď zase všetci prepisovali svoje aplikácie MDI na SDI. V súčasnosti opäť upadá SDI a čoraz viac sa začína presadzovať štandard MDI. A aké ponaučenie z toho plynie? Neriaďte sa zbytočne „módou“, tá je v programovaní veľmi nestála a premenlivá a nesnažte sa do bodky dodržiavať všetky najnovšie štandardy. Lepšie urobíte, keď na prvom mieste budete mať funkčnosť vašej aplikácie. Ušetríte si tak mnoho starostí. Ale to som odbočil. Vo Windows môžete nájsť mnoho príkladov aplikácií MDI [napr. súčasti Visual Studia (VC++, VB...), súčasti Office (Word, Excel, Access...)]. Najlepšie bude, ak si teraz bez ďalšej teórie jednu aplikáciu MDI vytvoríme, aby ste chápali, o čom tu píšem.

PRÍKLAD 1 – MDI MYNOTEPAD. Keď si spomeniete na predchádzajúcu časť, tam sme vytvárali jednoduchý SDI textový editor (ktorý možno teraz používate namiesto klasického notepadu ). Jeho základnú funkčnosť sme dosiahli bez napísania jediného riadka kódu, preto si teraz vytvoríme jeho verziu MDI. Do Workspace Editors pridajte nový projekt [typ – MFC AppWizard (Exe)] s názvom MDIMyNotepad. V prvom kroku nechajte zaškrtnuté defaultné nastavenie (Multiple Documents). Pokračujte do kroku 4/6 (nemeňte nijaké nastavenia), kde kliknite na Advanced... a do poľa File Extension vpíšte text: mxt. Ďalej v kroku 6/6 vyberte pre triedu pohľadu CMDIMyNotepadView zo zoznamu Base class: základnú triedu CEditView. Keď dokončíte tvorenie aplikácie, preložte a spustite ju.

Preskúmajte jej možnosti (File – New, File – Open, menu Window). Skúste zavrieť všetky okná vnútri rámcového okna a sledujte, ako sa zmení menu. Vyskúšajte funkčnosť Drag & Drop otvorenia súboru a otvorenie súboru priamo cez Explorer. Poznámka: Pri spustení cez Explorer pravdepodobne natrafíte na problém, že sa bude spúšťať predchádzajúca SDI verzia MyNotepadu. Môžete ho vyriešiť napr. tak, že v kroku 4/6 tvorenia aplikácie napíšete inú príponu ako mxt. Takýmto prístupom by ste však mali vo Windows za chvíľu zaregistrovaných  zbytočne veľké množstvo prípon a takisto to nepredstavuje najoptimálnejšie riešenie problému (čo ak naozaj potrebujete už používanú príponu?). Lepším riešením je „premapovať“ príponu mxt na náš nový program. Tu je postup pre Windows 2000 (pre iné OS si pozrite help): z menu Explorera vyberte Tools -> Folder Options..., kliknite na kartu File types tam v zozname nájdite príponu mxt a kliknite na Delete. Odklepnite varovné hlásenie. Teraz, keď ukončíte a opätovne spustíte program MDIMyNotepad, bude už všetko fungovať, tak ako má (program si pri spustení zápisom do registrov zaistí asociáciu teraz už „neobsadenej“ prípony).

Jednotlivé okná, ktoré sa nachádzajú vnútri rámcového okna aplikácie MDI, sa nazývajú detské okná (z angl. child windows). Detských okien môžete mať v jednom rámcovom okne ľubovoľne veľa, ale len jedno z nich môže byť aktívne. Do tohto aktívneho okna smeruje aplikačný systém všetky správy/príkazy. 

MDI detailnejšie. Už vieme, ako aplikácie MDI navonok vyzerajú, teraz sa na ne poďme pozrieť „zvnútra“. Ak kliknete na kartu ClassView vo Visual Studiu a porovnáte obsah projektov MyNotepad a MDIMyNotepad, zistíte, že sa líšia len v triede CChildFrame, ktorá je navyše v projekte MDI. CChildFrame, ktorá je odvodená od triedy CMDIChildWnd, predstavuje triedu pre každé detské okno (jej objekt je tvorený zakaždým, keď otvárame nové detské okno). Detské okná zdieľajú menu s hlavným rámcovým oknom (trieda CMainFrame). V  aplikácii MDI je trieda hlavného rámcového okna odvodená od triedy CMDIFrameWnd. Obsahuje už menu a vždy je vytvorený len jeden objekt rámcového okna (vo funkcii InitInstance pri spustení aplikácie):

// create main MDI Frame window
      CMainFrame* pMainFrame = new CMainFrame;
      if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
            return FALSE;
      m_pMainWnd = pMainFrame;

Teda ak budete chcieť modifikovať vzhľad a správanie sa detských okien, budete editovať triedu CChildFrame. Pri zmenách hlavného rámca budete zase editovať triedu CMainFrame. Ďalšie triedy v oboch projektoch sú zhodné – je tu trieda dokumentu, pohľadu a aplikácie. Keď sa pozriete do funkcie InitInstance v implementačnom súbore triedy aplikácie, narazíte na odlišné vytváranie objektu šablóny dokumentu oproti aplikácii SDI:

CMultiDocTemplate* pDocTemplate;
      pDocTemplate = new CMultiDocTemplate(
            IDR_MDIMYNTYPE,
            RUNTIME_CLASS(CMDIMyNotepadDoc),
            RUNTIME_CLASS(CChildFrame), // custom MDI child frame
            RUNTIME_CLASS(CMDIMyNotepadView));
      AddDocTemplate(pDocTemplate);
           
Tento kód umožňuje našej aplikácii používať viacero detských okien, ktoré sú napojené na objekt dokumentu a pohľadu. Je dôležité uvedomiť si, že MDI aplikácie dovoľujú existenciu viac ako jedného objektu dokumentu. (t. j. všetky detské okná a ich pohľady môžu byť napojené na jeden a ten istý objekt dokumentu, ale tiež môžu mať každé svoj vlastný objekt dokumentu. Toto sú už dosť náročné témy MFC [napr. ak chcete mať aplikáciu MDI, ktorá v jednom detskom okne zobrazí číselné údaje, v druhom ich reprezentáciu v stĺpcovom grafe, v ďalšom zase bude spojnicový graf  atď., stačí vám jeden dokument a tri rôzne pohľady, môžete použiť delené okná (Splitter Windows – trieda CSplitWnd – funguje aj v SDI, aj v MDI a pod.) a rôzne ďalšie „machinácie“]. Odporúčam vám pozrieť si ďalšie informácie o triede CMultiDocTemplate v helpe. Takisto si pozrite informácie o funkciách GetFirstDocPositionGetNextDoc, ktoré sú členskými funkciami triedy CDocTemplate a umožňujú pohyb po objektoch jednotlivých dokumentov.     

Ako to pracuje? Postup vykonávania aplikácie je zhruba rovnaký, aký sme opisovali v 20. časti. [Na dokonalé pochopenie odporúčam pridať debug výpisy do tých istých funkcií ako v 20. časti a porovnať poradie, v akom sa tieto funkcie volajú (+ pridajte debug výpisy aj do funkcií triedy CChildFrame); nakoniec skúste aplikáciu ešte odkrokovať.] Isté rozdiely sú vo funkcii CWinApp::OnFileNew. Táto funkcia v aplikáciách MDI najprv vytvára objekt dokumentu, potom objekt detského okna (nevytvára už objekt hlavného rámca, lebo ten je už vytvorený – pozri vyššie: // create main MDI Frame window).

Keď vytvára tento objekt, menu IDR_MAINFRAME je nahradené IDR_MDIMYNTYPE (podrobnejšie ďalej). Vytvára sa aj objekt pohľadu a prepojujú sa objekty dokumentu, hlavného rámca a pohľadu. Volajú sa funkcie CDocument::OnNewDocument pre objekt dokumentu, CView::OnInitialUpdate pre objekt pohľadu a CFrameWnd::ActivateFrame pre objekt detského rámca, ktorá toto okno zobrazí, aby sme s ním mohli pracovať. Situáciu, ktorá nastane po vybratí položky New Window z menu Window, sme ešte neopisovali (a ani sme nemohli, v SDI žiadne Menu Window nie je). Túto činnosť obsluhuje funkcia CMDIFrameWnd::OnWindowNew (pozri Technical note 22), ktorá zabezpečí otvorenie nového detského okna, čím vlastne vytvorí nový pohľad na už existujúci dokument (práve aktívny).

MDI a práca s dokumentom. Princíp práce s dokumentom (ako objektom) je v  aplikáciách MDI okrem jednej výnimky rovnaký ako v prípade SDI. Výnimkou je vytváranie nového dokumentu zakaždým, keď nahrávame súbor z disku (File -> Open), resp. keď vytvárame nový súbor (File -> New). Dokument sa teda už nereinicializuje ako v  aplikáciách SDI. Druhou odlišnosťou, ktorá však v SDI nemohla nastať, je, že objekt dokumentu je automaticky zrušený pri zavretí detského okna.

MDI a zdroje. Ak sa teraz pozriete na zdroje aplikácie MDIMyNotepad a porovnáte ich s verziou SDI, na prvý pohľad budete  vidieť, že pribudol jeden nový zdroj do menu (okrem IDR_MAINFRAME aj IDR_MDIMYNTYPE). Prvé menu sa zobrazí, ak neexistuje žiadne detské okno. Len čo otvoríme nejaké detské okno, je toto menu nahradené IDR_MDIMYNTYPE. Druhou, menej viditeľnou zmenou, ktorá však tiež súvisí s aktuálnym obsahom hlavného rámcového okna, je odlišný obsah zdroja String table. Ten v tomto prípade obsahuje záznam IDR_MAINFRAME (použitý, keď sa v hlavnom rámcovom okne nič nenachádza – obsahuje titulok okna, ku ktorému sa v prípade otvorenia nejakého súboru pripíše jeho meno) plus záznam IDR_MDIMYNTYPE (ten je použitý, ak sme už otvorili nejaké detské okná).

MDI študenti. Dúfam, že si ešte spomínate na projekt StudentList, ktorý predstavoval maličký „informačný systém“. Zbieral dáta o študentoch, ktoré ste mohli ukladať na disk a neskôr čítať. No povedzte, nebolo by pekné využiť pri tomto projekte teraz nadobudnuté skúsenosti s aplikáciami MDI a umožniť tak používateľovi mať naraz zobrazené informácie o viacerých študentoch a tie simultánne editovať? A ako to spraviť? Jednoducho... Štatistiky ukazujú, že najbežnejšia programovacia technika je technika Copy – Paste (čo tam po efektivite, hlavne že to beží). My túto štatistiku teraz potvrdíme. Vytvorte nový projekt s názvom MDIStudents, v kroku 4/6 kliknite na tlačidlo Advanced... a zadajte príponu slt. V kroku 6/6 zvoľte pre pohľad ako základnú triedu CFormView. Tým v AppWizarde skončíme. Zeditujte zdroje rovnako, ako je uvedené v 16. časti, do projektu pridajte súbory student.h a student.cpp a skopírujte obsah súborov StudentListDoc.h, StudentListDoc.cpp, StudentListView.h, StudentListView.cpp. Vykonajte triviálne zmeny, na ktoré prídete sami alebo vás na ne upozorní kompilátor/linker a to je všetko. Máte funkčnú verziu MDI aplikácie StudentList. (Na začiatku budúcej časti sa k tejto „domácej úlohe“ ešte vrátime a vysvetlíme si možné úskalia pri prepisovaní aplikácií SDI na MDI. Ale odporúčam vám pokúsiť sa o tento prepis už teraz, znalosti totiž nezískate len čítaním, ale musíte aj trochu popremýšľať. Na tomto príklade sa dá krásne pochopiť princíp fungovania MDI, takže smelo do toho!)

Tipy na doma. Okrem spomenutej aplikácie vám ďalej odporúčam v helpe si pozrieť informácie o triedach CMDIFrameWnd CMDIChildWnd. Pridajte do MDIMyNotepadu rozšírený filter, umožňujúci v dialógu FileOpen/FileSave priamo pracovať aj so súbormi, ktoré majú príponu txt.

Nabudúce. Opisom aplikácií MDI sme dokončili dlhú púť k pochopeniu architektúry Document/View knižnice MFC. Nepovedali sme si však všetko. Už spomenuté viacnásobné pohľady, dokumenty, delené pohľady a ďalšie nám zatiaľ ostávajú cudzie. Ale ako som už uviedol, tieto témy sa radia už k „vyššej matematike“ MFC a určite nepatria do základného balíka informácií, ktorý by vám mal poskytnúť tento seriál. Z mailov a otázok, ktoré mi prišli, vyplýva váš záujem o túto problematiku. Možno z nich vyberiem zopár otázok, ktoré umiestnim do FAQ, takže nezúfajte . Od budúcej časti až do konca seriálu (asi 4 – 5 častí) sa už budeme zaoberať len spomenutými „čerešničkami“ v programovaní Windows – bitmapami, knižnicami DLL, komponentmi ActiveX, tlačou. Pritom si zvolíme čisto praktický prístup => menej teórie a viac praktických informácií (how to...). Tešte sa teda spolu so mnou na ďalšie pokračovanie. 


Nechajte si posielať prehľad najdôležitejších správ emailom

Mohlo by Vás zaujímať

Ako na to

Ako zbaviť fotky hmly

08.12.2016 11:59

Hmla alebo dym sú často veľmi kreatívne nástroje. No všetkého veľa škodí. Fotka potom stráca kontrast a v podstate na nej nič nevidieť. Hmlu môžete neraz následnými úpravami odstrániť alebo zredukovať ...

Ako na to

Užitočné SW nástroje

08.12.2016 11:53

AllDup v4.0.3 Určenie: program na vyhľadávanie a odstraňovanie duplicitných súborov Vlastnosti: duplicitné súbory sa vyhľadávajú len na zvolených diskových jednotkách alebo len v rámci vybraných ...

Ako na to

Fotografovanie s bleskom

08.12.2016 11:47

Ak máte moderný fotoaparát so vstavaným alebo externým bleskom, zdá sa vám téma článku triviálna. Jednoducho nastavíte vhodný režim, vyberiete najlepšiu kompozíciu záberu, exponujete a o zvyšok sa už ...

Žiadne komentáre

Vyhľadávanie

Kyocera - prve-zariadenia-formatu-a4-s-vykonom-a3

Najnovšie videá