Image
28.6.2016 0 Comments

C++ pod Windows / Serializácia SDI aplikácií II. / 21. časť

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

Vítam vás pri ďalšom pokračovaní nášho rozprávania o programovaní pod Windows. V tejto časti uvedením ukážkového príkladu dokončíme opis serializácie aplikácií SDI. Vytvoríme jednoduchý textový editor ŕ la Poznámkový blok (využitím triedy MFC CEditView). Sľubovaný druhý príklad (zložitejší textový editor s využitím triedy CRichEditView) zatiaľ neuvedieme. Používa niektoré zložitejšie prvky, ktoré by ste teraz mali problém pochopiť. Tento príklad si uvedieme až na záver seriálu, keď si preberieme veci ako tlač, vytváranie helpu, prípadne vytváranie inštalácií. Bude to komplexný príklad na záver, ktorý zhrnie väčšinu preberanej problematiky. Teraz si namiesto toho preberieme prácu s registrami Windows.

Trieda CeditView. Pri dialógoch sme sa stretli s ovládacím prvkom textové pole (Edit Box – trieda CEdit). Je to ovládací prvok Windows, do ktorého je možné zadávať text. Trieda CEditView sa správa podobne ako textové pole, ibaže jej pole pôsobnosti je iné. Zjednodušene by sa dalo povedať, že umožňuje aplikovať ovládací prvok textové pole na celý pohľad. V skutočnosti je to, samozrejme, zložitejšie. Dôležité je zbytočne nehľadať súvislosti medzi týmito triedami. CEditView je trieda pohľadu (ako napríklad už známe CScrollView, CFormView) odvodená od CView. CEdit je trieda ovládacieho prvku (odvodená priamo od CWnd). CEditView dokáže bez akéhokoľvek nášho programovania obsluhovať (okrem iných) príkazové správy, ako vidíte v tab. 1. Ide o štandardný balík funkcií každého textového editora. O tom, ako túto funkčnosť sprístupniť a využiť, si povieme v príklade 1. Podrobnejšie informácie o triede CEditView nájdete v helpe. Odporúčam pozrieť si vlastnosti tejto triedy.

ID_EDIT_SELECT_ALL

ID_EDIT_FIND

ID_EDIT_PASTE

ID_EDIT_COPY

ID_EDIT_REPLACE

ID_EDIT_REPEAT

Tab 1  Implicitná funkčnosť v CEditView

Predpríprava na príklady. Vytvorte nové Workspace s názvom Editors. Doň pridajte ukážkový príklad 1 z tejto časti. Neskôr nám bude slúžiť aj na druhý príklad, vytváraný na základe triedy CRichEditView.

Obr. 1  Výber základnej triedy pre pohľad

PRÍKLAD 1 – MyNotepad. Do Workspace Editors pridajte pomocou App Wizardu nový projekt s názvom MyNotepad. Pri tvorení kostry projektu vyberte na začiatku možnosť SDI Application, v kroku 4/6 kliknite na tlačidlo Advanced. V dialógu Advanced Options vpíšte do poľa File extension: mxt, ostatné nastavenia nechajte na default. Pre názornosť som pre náš program zvolil odlišnú príponu súborov namiesto klasickej txt. Program dokáže pracovať aj s klasickými textovými súbormi (prípona *.txt – pozri ďalej – Nastavenie filtra). Dialóg zavrite a pokračujte na posledný krok 6/6 tvorenia kostry aplikácie pomocou App Wizardu (všetky ostatné vlastnosti projektu nechajte na default). V kroku 6/6 vyberte zo zoznamu ako základnú triedu pre pohľad triedu CEditView (obr. 1). Kliknite na Finish. Ak projekt MyNotepad teraz skompilujete a zlinkujete, máte funkčný program, ktorý vám umožní písať do jeho pohľadu text, ten ukladať, resp. čítať do/zo súboru (áno, máme fungujúcu serializáciu a nemuseli sme nič kódovať!). Skúste si MyNotepad spustiť, napíšte do jeho okna nejaký text, ten uložte, potom otvorte (vyskúšajte si ho otvoriť všetkými tromi spôsobmi, ako sme si opisovali v predchádzajúcej časti, t. j. cez menu File – Open, otvorením priamo z Explorera a pomocou drag and drop). Čo na to poviete? Dostali sme relatívne veľa funkčnosti, a to bez napísania jediného riadka kódu.

POZRIMA SA NA KÓD. Poďme sa teda pozrieť, čo nám to App Wizard všetko vygeneroval. Súbory Mainfrm.h a Mainfrm.cpp neobsahujú pre nás v tejto chvíli nič zaujímavé. Pozrite sa do súboru MyNotepad.cpp do funkcie InitInstance. Všetky funkcie, ktoré sme prácne pridávali v predchádzajúcej časti, za nás pridal App Wizard. Pridal ich na základe našej voľby prípony v kroku 4/6. Teraz otvorte súbor MyNotepadDoc.cpp. Tu sa nachádza celá „logika“ našej aplikácie. Začneme vo funkcii OnNewDocument, kde môžete vidieť tento zaujímavý riadok kódu:

((CEditView*)m_viewList.GetHead())->SetWindowText(NULL);

m_viewList je deklarovaná hlboko v útrobách MFC (súbor afxwin.h) ako premenná typu CPtrList. V 18. časti sme si CPtrList opisovali, takže už by ste mali vedieť, že premenná tohto typu bude predstavovať nešablónovú kolekciu typu zoznam (uchováva „prázdne“ – void ukazovatele – podrobne v helpe) . V našom prípade je m_viewList zoznamom ukazovateľov na pohľady. Riadok vo funkcii OnNewDocument získa „prvý“ pohľad v tomto zozname, pretypuje ho na CeditView (čo musí, keďže ide o „prázdny“ ukazovateľ) a pomocou funkcie SetWindowText nastaví text. Ako už viete zo 16. časti, OnNewDocument sa volá pri reinicializácii dokumentu, preto SetWindowText(NULL) vymaže akýkoľvek text, ktorý mohol byť v okne, a vytvorí tak „čistý“ dokument (rozumej: neobsahujúci text). Skúste si namiesto parametra NULL napísať nejaký text, napr.:

((CEditView*)m_viewList.GetHead())->SetWindowText("Mama ma Emu");

a potom spustiť program. Zmení sa niečo?

Teraz sa v súbore presuňte do funkcie Serialize. Celá serializácia je „vybavená“ jediným riadkom:

((CEditView*)m_viewList.GetHead())->SerializeRaw(ar);

SerializeRaw je členskou funkciou triedy CeditView. Je to špeciálna funkcia určená na ukladanie textu vo formáte raw a neumožňuje serializovať iné informácie (napr. informácie o objektoch, ako to robí štandardná funkcia Serialize). Túto funkciu nájdete v súbore viewedit.cpp (ak máte nainštalované Visual C++ vrátane zdrojových textov k MFC). Odporúčam si ju pozrieť [dostanete sa k nej pomocou Step Into (F11) počas debuggovania]. V tomto súbore preskúmajte aj funkcie WriteToArchiveReadFromArchive. Nie je nevyhnutné ich dokonale pochopiť, ale obsahujú niektoré finty, ktoré možno niekedy vo svojich programoch využijete.

SÚBOR MyNotepad.reg. Keď sa pozriete na kartu Files v okne Workspace, nájdete tam súbor s príponou reg. Tento súbor bol vygenerovaný App Wizardom a ukazuje nám, aké zmeny vykoná v registroch funkcia RegisterShellFileTypes. Už by ste mali vedieť, že táto funkcia zápisom v registroch asociuje súbory s príponou mxt s našou aplikáciou (pozri ďalej – Práca s registrami).  

ROZŠÍRENIE APLIKÁCIE MyNotepad. Teraz pridáme funkčnosť opísanú v tab. 1. Aj keď „pridať“ nie je v tomto prípade správne označenie, keďže mi túto funkčnosť len sprístupníme. Celé je to veľmi jednoduché. V editore zdrojov choďte do zložky Menu a rozkliknite IDR_MAINFRAME. Do menu Edit pridajte položky, ako vidíte na obr. 2. Ich hlavičku a ID vypíšte podľa tab. 2. Všimnite si, že automaticky po zadaní ID dokáže aplikačný systém identifikovať tento ovládací prvok a priradí mu opis (Prompt na záložke General).  Do hlavičky ste vpisovali aj skratkový kláves (\tXXX). Na jeho sfunkčnenie je ešte potrebné zeditovať takzvaný Accelerator.

Obr. 2 Menu Edit v aplikácii MyNotepad

Otvorte zložku Accelerator a v nej rozkliknite opäť zdroj IDR_MAINFRAME. Mali by ste vidieť to, čo je na obr. 3. Tento zoznam obsahuje všetky skratkové klávesy, ktoré používa váš program. Dvakrát kliknite na prázdnu položku (na konci zoznamu), resp. z menu Insert vyberte New Accelerator. Objaví sa dialóg ako na obr. 4. Do položky ID vpíšte postupne ID pridaných položiek do menu Edit (tab. 2) a do položky Key zase jednotlivé skratkové klávesy (už bez CTRL, keďže CTRL je už štandardne zaškrtnuté – check Modifiers). Tým sme s úpravami menu Edit skončili, aplikáciu preložte, spusťte a vyskúšajte pridané veci. Opäť si uvedomte, že všetko sme dosiahli bez napísania jediného riadka kódu! 

&Find...\tCtrl+F

ID_EDIT_FIND

Replace…\tCtrl+H

ID_EDIT_REPLACE

Repeat\tCtrl+R

ID_EDIT_REPEAT

Select all\tCtrl+A

ID_EDIT_SELECT_ALL

Tab. 2 ID položiek menu

Nastavenie filtra. Pri práci s našou aplikáciou iste narazíte na jednu nepríjemnosť. Ak chcete otvoriť nejaký súbor, máte na výber len príponu mxt alebo všetky súbory (*.*). MyNotepad je však príkladom jednoduchého textového editora, preto by mal takto priamo dokázať pracovať aj s inými príponami, predovšetkým s txt. Nastavenie podpory pre rôzne prípony sa robí pomocou tzv. filtra. S týmto pojmom ste sa už stretli, keď sme si vysvetľovali spoločné dialógy Windows (File Dialog). Tam na nastavenie filtra stačilo upraviť konštruktor tohto dialógu.

Obr. 3 Zdroj skratkových klávesov

V aplikácii MFC, založenej na interakcii dokument – pohľad, musíme urobiť trochu viac. V prvom rade namapujte do triedy CMyNotepadDoc príkazovú správu na ID_FILE_OPEN (čím vlastne prepíšete štandardné volanie MFC). Jej telo zmeňte takto:

void CMyNotepadDoc::OnFileOpen()
{
      // konštrukcia objektu dialógu
      //(všetko jeden riadok)
      CFileDialog Fdlg(TRUE, NULL, NULL, NULL, "MyNotepad Files (*.mxt)|*.mxt
|Text Files (*.txt)|*.txt
|All Files (*.*)|*.*||");
 
      // otvoríme súbor
      if (Fdlg.DoModal()==IDOK)
      {
            AfxGetApp()->OpenDocumentFile(Fdlg.GetPathName());
      }
}

Keby ste OnFileOpen neprepísali, štandardná implementácia tejto funkcie volá funkciu CWinApp::DoPromptFileName, ktorá zobrazí klasický File-Open dialóg s údajmi, ktoré sa nachádzajú v zdroji IDR_MAINFRAME (String Table – pozri predchádzajúcu časť). Potom DoPromptFileName volá funkciu CWinApp::OpenDocumentFile, ktorá má ako parameter meno súboru, ktorý chceme otvoriť. Tá sa aj postará o jeho otvorenie. My preskočíme volanie funkcie DoPromptFileName a dáta, ktoré potrebuje OpenDocumentFile, získame z nami vytvoreného File dialógu (do ktorého sme pridali podporu viacnásobného filtra). Na jej volanie používame funkciu AfxGetApp, ktorá vracia ukazovateľ na objekt aplikácie (CWinApp).

Práca s registrami. S príchodom 32-[MŠ1] -bitových Windows došlo k viacerým podstatným zmenám. Jednou z nich bolo zavedenie registrov namiesto dovtedy používaných súborov INI. Presný opis registrov a ich filozofiu si tu nebudeme vysvetľovať, podrobné informácie nájdete na internete, v helpe k VC++ alebo nejakej knihe. Nám bude stačiť predstaviť si registre ako nejakú hierarchickú databázu, ktorá slúži Windows na ukladanie systémových informácií o nich samotných a aplikáciám na ukladanie rôznych nastavení a záznamov. K jednotlivým informáciám v registroch sa pristupuje pomocou kľúčov (keys), v ktorých sú uložené nejako pomenované  hodnoty (value name), ktoré môžu obsahovať ďalšie dáta (value data). Pre nás ako programátorov je najdôležitejšie vedieť, ako do registrov zapisovať a čítať z nich údaje. Ukážeme si to na príklade aplikácie MyNotepad.

Príklad 2 – MyNotepad a registre. Ako som už spomenul, registre slúžia ako náhrada súborov INI z čias 16-bitových Windows. Ale aj terajšie aplikácie často používajú súbory INI (prácu s nimi sme si ukázali v 17. časti).

Obr. 4  Pridanie klávesovej skratky položke menu (resp. toolbaru)

Preto aj aplikácie vygenerované App Wizardom umožňujú presmerovať zápis do registrov (prednastavený) na zápis do súboru INI. Otvorte súbor MyNotepad.cpp a vo funkcii InitInstance nájdite riadok:

SetRegistryKey(_T("Local AppWizard-Generated Applications"));

Tento riadok vytvára v registroch kľúč: Local AppWizard-Generated Applications, v ktorom vytvorí ďalší kľúč s názvom aplikácie a doň ukladá informácie (pozrite sa do HKEY_CURRENT_USER\Software, čo tam všetko je). Ak si v helpe prečítate podrobnejšie informácie o funkcii  SetRegistryKey, zistíte, že jej vynechaním sa namiesto do registrov budú tieto informácie zapisovať do súboru INI. To stojí za vyskúšanie. Okomentujte volanie tejto funkcie, aplikáciu spusťte, otvorte nejaký súbor a potom ju uzavrite. Choďte do adresára Windows a nájdite tam súbor MyNotepad.ini. Malo by v ňom byť zaznamenané meno otvoreného súboru (v položke Recent File List). Ak volanie SetRegistryKey znova sprístupníte a zopakujete otvorenie nejakého súboru v programe MyNotepad, informácia o tom sa už zapíše do registrov.

My však nechceme, aby naša „premakaná“ aplikácia MyNotepad bola v registroch pod nič nehovoriacim kľúčom Local AppWizard... Zmeňte preto volanie funkcie SetRegistryKey takto:

SetRegistryKey(_T("PC REVUE"));

Teraz sa budú všetky informácie ukladať do kľúča s názvom PC REVUE (jeho pozícia je opäť HKEY_CURRENT_USER\Software).

Na prácu s registrami slúžia funkcie GetProfileInt, WriteProfileInt, GetProfileString, WriteProfileString a i. (napr. WriteProfileBinary), všetko metódy CWinApp – nájdete v helpe). V 17. časti sme opisovali podobné funkcie, ibaže mali vo svojom názve ešte slovíčko Private. Tie môžete, samozrejme, takisto použiť na zápis údajov do registrov. Použitie členských funkcií CWinApp je však trochu pohodlnejšie, keďže nemusíte vypisovať celú cestu ku kľúču. Napríklad zápis reťazca môj textový editor do kľúča (key) Settings do hodnoty menom (value name) AboutString prislúchajúceho našej aplikácii by ste vykonali volaním funkcie WriteProfileString napr. z InitInstance takto:

AfxGetApp()->WriteProfileString("Settings", "AboutString", "môj textový editor :-)");

Čítanie a zápis iných druhov informácií sú veľmi jednoduché a nevyžadujú, aby sme ich opisovali. Určite však všetko vyskúšajte.

Tipy na doma. Všetky úpravy preveďte do aplikácie MyNotepad. Pridajte na toolbar tie položky, čo ste pridávali do menu. Pohrajte sa s ikonou dokumentu, skúste vytvoriť vlastnú. Pridajte podporu viacnásobného filtra aj na ukladanie súboru (položka menu File-Save, resp. File-Save as... (Návod: pozrite si v helpe, ako sa prepisujú štandardné príkazy MFC – Technical Note 22 – Standard Commands Implementation). V helpe si pozrite informácie o funkciách DoPromptFileName a OpenDocumentFile (všetky metódy CWinApp). Toto cvičenie odporúčam spraviť: Do registrov do kľúča Settings pridajte dve položky: AboutString a AboutInt. AboutString bude predstavovať reťazec, ktorý natiahnete do dialógu O aplikácii... a AboutInt bude číslo verzie (takisto zobrazené v About dialógu) – čiže keď používateľ vyberie z menu Help-About MyNotepad..., všetky informácie okrem ikony natiahnete z registrov. Ak budete mať chuť, môžete sa pohrať aj so zápisom a čítaním iných ako celočíselných hodnôt (napr. skúste nejako z registrov prečítať číslo verzie 1.13 – reálne číslo).

Nabudúce. O mesiac sa pozrieme na zúbky aplikáciám MDI. Dovidenia v máji. 


Zobrazit Galériu

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á