Image
23.6.2016 0 Comments

C++ pod Windows / Dialógy I / 9. časť

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

Začal sa nám mesiac apríl, alebo ako ho mnohí nazývajú, mesiac bláznov. A práve titulom „blázni“ mnohí označujú nás – počítačových nadšencov. Veď prečo nie? Každý je svojím spôsobom blázon do niečoho iného. Niekto si kupuje každý mesiac nový mobil, iný zas nové auto (teda ten lepšie zarábajúci ), niekto sa „vytešuje“ z novej kroniky ľudstva, iný z krásnej novej gitary, niekto pozerá Star Trek 325-krát za sebou a takto by sme mohli ísť donekonečna. Otázkou však je, prečo niektorí ľudia uvažujú takto: „Tebe sa páči vážna hudba, mne nie, a preto sa s tebou už nikdy viac nebudem baviť.“ Alebo: „Ako môžeš vidieť krásu v tom, celý deň rozoberať rádiá a potom ich znova skladať? Zbohom!“ A čo je pritom zaujímavé, ten istý človek môže vysloviť aj takúto vetu: „Máš pekný oblek, my si určite budeme rozumieť!“ Nezdá sa vám to trochu „strelené“? Čo keby sme tak skúsili posudzovať ľudí nie podľa toho, ako hovoria a ako sa obliekajú, ale podľa toho, čo hovoria a ako rozmýšľajú. Ak sa vám tieto slová zdajú povedomé, máte pravdu. Naozaj sú to trošku upravené slová z  manifestu istej komunity, ktorá sa zaoberá vecami okolo počítačov. Či sú pravdivé a správne, nechám na posúdenie každému z vás.

No vráťme sa radšej k Visual C++. Ako vidieť z nadpisu, začíname preberať rozsiahlu tému, ktorá je nepochybne jednou z najzaujímavejších pre začiatočníkov v programovaní vo Visual C++, ale aj v iných prostrediach. Je to totiž jedna z prvých príležitostí, keď môžete vidieť výsledky svojej práce, čo vás určite minimálne motivuje na ďalšiu prácu. Na začiatok tejto časti si však ešte niečo povieme o objektoch GDI a triedach kontextu zariadenia knižnice MFC.

Ako ste si určite všimli, zmizla časť Tipy na WWW, keďže som vyčerpal takmer celú zásobu dobrých linkov. Tipy na stránky sa, samozrejme, budú naďalej vyskytovať, ale budú začlenené buď do úvodu, alebo záveru. Nová vec, ktorú som pridal, je FAQ. Tento výraz označuje (ako iste všetci viete) po anglicky Frequently Asked Questions čiže často kladené otázky. V tejto časti budeme uverejňovať odpovede na vaše otázky, ktoré došli e-mailom (a je ich už neúrekom) a sú všeobecnejšieho charakteru, takže môžu pomôcť aj iným. Je to taká menšia obdoba Programátorskej poradne pre Visual C++. Vaše otázky sa môžu, ale nemusia týkať práve preberanej témy v tej-ktorej časti seriálu (musia sa, samozrejme, týkať programovania v C++). Takže píšte mi a pýtajte sa na všetko, čo vám nebude jasné, prípadne čo neviete vo Visual C++ urobiť. Nezabudnite, kto sa nič nepýta, nič sa nedozvie!

Kontext zariadenia a objekty GDI v MFC. V seriáli sme už pracovali s kontextom zariadenia a dokonca aj s objektmi GDI. Vo funkcii OnDraw sme odovzdávali ukazovateľ na kontext zariadení (pDC),  vo funkcii OnLButtonDown sme vytvárali objekt kontextu zariadení (CClientDC dc(this);) a používali sme objekty GDI systémového zásobníka

(SelectStockObject(GRAY_BRUSH);).

Kontext zariadenia: Základná trieda pre kontext zariadenia je trieda CDC. Od nej sú potom odvodené ďalšie: CClientDC, CWindowDC, CPaintDC... (podrobne pozri help). Rozdiely medzi týmito triedami sú nepatrné, napríklad objekt triedy CClientDC môže pristupovať len ku klientskej časti okna, ale objekt triedy CWindowDC môže pristupovať aj ku klientskej, aj k neklientskej časti okna. Takže je len na vás, ako programátoroch, akú triedu si vyberiete pre vašu aplikáciu. Keď ešte presne neviete, čo sa bude od vašej aplikácie požadovať, odporúčam vám najprv používať objekt triedy CDC (čiže tej základnej triedy pre kontext zariadenia) a neskôr, keď si už budete istí, rozhodnite sa pre niektorého potomka triedy CDC. Azda len pripomeniem, že ukazovateľ na objekt, ktorý sa odovzdáva ako parameter funkcie OnDraw, je ukazovateľom na objekt triedy CDC.

Objekty GDI: Základná trieda pre všetky objekty GDI (Graphic Device Interface) systému Windows je abstraktná trieda CGdiObject. Každá ďalšia trieda nejakého objektu GDI je odvodená od tejto triedy. Opis týchto odvodených tried je v helpe, takže na tomto mieste si ich len vymenujeme: CBitmap, CBrush, CFont, CPallete, CPen, CRgn. S niektorými sme dokonca už aj pracovali (napr. CPen).

Práca s objektmi triedy CDC. Je dôležité vedieť pracovať s objektmi kontextu zariadenia. Keď budeme potrebovať napríklad niečo napísať do okna aplikácie (a to sa stáva veľmi často) a potrebujeme tak urobiť z funkcie, ktorá nemá ako parameter ukazovateľ na objekt triedy kontextu zariadenia, musíme vedieť, ako vytvoriť a zrušiť takýto objekt. Naopak, ak používame kontext zariadení v nejakej funkcii, kde sa ukazovateľ na objekt kontextu zariadení odovzdáva ako parameter (napr. funkcia OnDraw), nemusíme sa vôbec starať o konštrukciu a deštrukciu (rušiť takýto objekt dokonca ani nesmieme!) tohto objektu, aplikačný systém s MFC urobia túto prácu za nás. Ale ak napríklad vytvárame náš vlastný kontext zariadenia vo funkcii OnLButtonDown (robili sme tak v programoch First a Hi), musíme si tento objekt sami skonštruovať a v istých prípadoch ho musíme aj sami zrušiť. Rušenie objektov kontextu zariadenia je nesmierne dôležité, pretože Windows má obmedzený počet kontextov zariadení, ktoré môže vytvoriť a pri ich nedôslednom používaní sa môže ľahko stať, že váš program spadne, lebo nemohol vytvoriť ďalší kontext zariadenia (a verte mi, takéto chyby sa odhaľujú pomerne ťažko). Existujú dva spôsoby vytvorenia nového objektu kontextu zariadenia. Prvým je vytvorenie na stacku (tento spôsob bol použitý aj v programoch First a Hi). Má tú výhodu, že sa nemusíme starať o zrušenie takto vytvoreného objektu. Aplikačný systém to urobí za nás pri ukončení funkcie, v ktorej sme objekt vytvárali (teda napr. OnLButtonDown). Ukážku tohto spôsobu vidíte tu::

void CKontextView::OnLButtonDown(UINT nFlags, CPoint point)
{
      // vytvoríme objekt dc na stacku
      CClientDC dc(this);
 
      dc.TextOut(0, 0, "Tu som");
} // objekt dc je zrušený  

Parametrom konštruktora objektu dc je ukazovateľ na okno (aby bolo systému jasné, ktorého okna sa týka vytvorenie nového objektu kontextu zariadenia).

No ak z rôznych príčin nechceme vytvárať objekt na stacku, môžeme ho vytvoriť aj pomocou funkcie GetDC, ktorá je členskou funkciou triedy CWnd (toto je ten druhý spôsob). V tomto prípade získame ukazovateľ na kontext zariadenia. Tu je príklad:

void CKontextView::OnLButtonDown(UINT nFlags, CPoint point)
{
      // vytvoríme ukazovateľ na kontext zariadenia
      CDC* pDC=GetDC();
 
      pDC->TextOut(0, 0, "Tu som");
 
      // Dôležité! Musíme uvoľniť kontext zariadenia
      ReleaseDC(pDC);
}

Ako sme už uviedli, nesmieme zabudnúť takto vytvorený ukazovateľ aj sami zrušiť pomocou funkcie ReleaseDC.

Takže teraz už viete, ako postupovať pri vytváraní a rušení objektov kontextu zariadenia, a nemal by byť pre vás problém z hocijakej funkcie realizovať výstup na obrazovku.

Práca s objektmi GDI. Každý objekt GDI má iný konštruktor, a preto sa nebudeme bližšie zaoberať opisom každého z nich (tu vás opäť odporučím na help). Spomenieme si len, ako sa rušia tieto objekty. Ak čakáte nejakú funkciu  podobnú ReleaseDC, ste na omyle (táto funkcia v určitých prípadoch dokáže odstrániť aj objekty GDI – pozri ďalej).  Pri vytváraní, ale i rušení objektov GDI sa využíva funkcia SelectObject. Pri vytváraní nám táto funkcia vracia ten objekt GDI, ktorý je v nej aktuálne vložený, a zároveň vkladá novo vytvorený objekt, no a pri rušení využijeme tento vrátený predchádzajúci objekt, ktorým jednoducho prepíšeme náš nový vložený objekt (ak máte v tom mierny chaos, pozrite si tento príklad):

void CKontextView::OnLButtonDown(UINT nFlags, CPoint point)
{
      // vytvoríme nový kontext zariadenia
      CDC *pDC=GetDC();
 
      // vytvoríme objekt GDI pera
      // použijeme ho na vykreslenie elipsy
      CPen newPen(PS_SOLID, 6, RGB(0, 0, 255));     
 
      // získame aktuálny objekt GDI (oldPen), ktorý neskôr použijeme na
      // odstránenie objektu GDI newPen
      // zároveň tento aktuálny objekt GDI (oldPen) nahradíme
      // novým objektom GDI newPen
      CPen *oldPen=pDC->SelectObject(&newPen);
     
      // vykreslíme elipsu pomocou objektu GDI newPen
      pDC->Ellipse(0, 0, 400, 200);
     
     
// z kontextu zariadenia vyberieme nový objekt GDI newPen
      // a vložíme tam predchádzajúci objekt GDI oldPen
      pDC->SelectObject(oldPen);  
 
      // uvoľníme kontext zariadenia
      ReleaseDC(pDC);
}

Ešte pár slov o funkcii ReleaseDC.  Táto funkcia, ako už viete, odstráni kontext zariadenia, ktorý jej odovzdáme ako parameter (presnejšie povedané, odovzdávame ukazovateľ na tento kontext zariadenia, v tomto prípade je ním pDC). No ak máme k tomuto kontextu zariadenia priradené nejaké objekty GDI, odstránia sa aj tie? Odpoveď znie: áno. Ak teda viete a ste si istí, že kontext zariadenia bude zrušený skôr ako objekty GDI k nemu priradené, nemusíte tieto objekty GDI už rušiť, stačí zrušiť kontext zariadenia.

Existuje ešte jeden spôsob, ako zrušiť objekty GDI, a to použitím objektov GDI systémového zásobníka. Tento postup sme si už opisovali vo štvrtej časti, takže sa k nemu nebudem vracať (skúste si však na domácu úlohu prerobiť funkciu CKontextView::OnLButtonDown tak, aby ste využívali objekt GDI systémového zásobníka).

Začíname dialógmi. Na začiatok si hádam ujasnime, čo to vlastne dialóg je. Dialóg je okno ako každé iné, môže spracúvať správy, môžeme s ním robiť operácie ako s každým iným oknom (zavrieť, premiestniť, zmeniť veľkosť). V systéme Windows existujú dva druhy dialógov: modálnenemodálne. Modálne dialógy sú bežnejšie. Tento typ dialógov neumožňuje používateľovi vykonávať ďalšiu činnosť v danej aplikácii, pokým ho neuzavrie (príkladom takýchto dialógov sú dialógy Open, Save as, ale aj tzv. informačné dialógy, napr. This program has performed an illegal operation...). Nemodálne dialógy, ako už istotne tušíte, sa líšia od modálnych v tom, že umožňujú ďalšiu prácu s aplikáciou (napr. dialóg Find vo Worde). Z hľadiska knižnice MFC sa však tieto dva typy dialógov nijako zvlášť nelíšia. Obidva majú základnú triedu CDialog, rozdiel je len v ich vytváraní a rušení. Teraz začneme s tým najjednoduchším, čo nám knižnica MFC ponúka, a síce budú to informačné dialógy, inak známe ako Messageboxy.

Vytvárame MessageBox. Použitie tohto typu modálnych dialógov si najlepšie ukážeme na príklade. Chceme, aby sa po stlačení ľavého tlačidla myši zobrazil informačný dialóg s nejakým textom a, samozrejme, s ikonkou. Pomocou AppWizardu si vytvorte novú aplikáciu s názvom Information. Typ aplikácie bude rovnaký, aký sme používali doteraz, čiže zvoľte Single Document Interface a ostatné parametre nechajte na default. Ak už máte vygenerovanú základnú kostru aplikácie, potom pomocou Class Wizardu pridajte obsluhu správy WM_LBUTTONDOWN do triedy CInformationView. Teraz zmeňte kód funkcie OnDraw v tejto triede takto:

void CInformationView::OnDraw(CDC* pDC)
{
      pDC->TextOut(0, 0, "Stlac lave tlacidlo mysi na zobrazenie informacneho dialogu.");
}

Teraz už používateľ bude vedieť, čo s aplikáciou robiť. A ako sa vlastne vyvolá zobrazenie informačného dialógu? Veľmi jednoducho: stačí zavolať funkciu MessageBox, pričom jej parametre sú:

MessageBox(„Text v informačnom okne“, „Titulok informačného okna“, Jeho typ);

Tretí parameter Jeho typ môže nadobúdať hodnoty, ako vidíte v tab. 1. Ttreba si uvedomiť, že tieto parametre môžeme kombinovať. Oddeľujeme ich operátorom |. Všetky nasledujúce volania funkcie MessageBox sú správne:

MessageBox("Môj prvý dialóg v prostredí Visual C++", "Hurá!",MB_ABORTRETRYIGNORE |
MB_DEFBUTTON2 | MB_ICONINFORMATION);
 
 
MessageBox("Môj prvý dialóg v prostredí Visual C++", "Hurá!",MB_ABORTRETRYIGNORE |
MB_SYSTEMMODAL | MB_DEFBUTTON3 | MB_ICONINFORMATION);
 
MessageBox("Môj prvý dialóg v prostredí Visual C++", "Hurá!",MB_YESNO | MB_DEFBUTTON2 |
MB_ICONWARNING);

Jeho typ

Ikona

Opis

MB_OK

-

zobrazí sa len tlačidlo OK

MB_OKCANCEL

-

zobrazia sa tlačidlá OK a Cancel

MB_RETRYCANCEL

-

zobrazia sa tlačidlá Retry a Cancel

MB_YESNO  

-

zobrazia sa tlačidlá Yes a No

MB_YESNOCANCEL   

-

zobrazia sa tlačidlá Yes, No a Cancel

MB_ABORTRETRYIGNORE   

-

zobrazia sa tlačidlá Abort, Retry a Ignore

MB_APPLMODAL

-

nebudete môcť pracovať s aplikáciou, pokým informačné okno nezavriete; môžete však pracovať s inými aplikáciami

MB_SYSTEMMODAL   

-

nebudete môcť pracovať so systémom ani s ďalšou aplikáciou, pokým nezavriete informačné okno (informačné okno zostáva stále na obrazovke aj pri práci s inou aplikáciou)

MB_TASKMODAL   

-

podobné ako APPLMODAL, neúčinný v aplikácii, ktorá využíva MFC

MB_DEFBUTTON1   

-

určuje „Default Button“ v dialógu (teda ten, ktorý sa aktivuje po stlačení enter); používa sa pri viactlačidlových informačných oknách (napr. MB_ABORTRETRYIGNORE); nastavuje prvé tlačidlo ako default   

MB_DEFBUTTON2   

-

Nastavuje druhé tlačidlo ako default

MB_DEFBUTTON3   

-

Nastavuje tretie tlačidlo ako default

MB_ICONASTERISK alebo MB_ICONINFORMATION

Zobrazí ikonu

MB_ICONEXCLAMATION alebo MB_ICONWARNING

Zobrazí ikonu

MB_ICONQUESTION

Zobrazí ikonu

MB_ICONHAND alebo MB_ICONSTOP alebo MB_ICONERROR

Zobrazí ikonu

Tab. 1 Typy informačných dialógov

Aby sme videli použitie funkcie MessageBox v praxi, dopíšte tento kód do funkcie OnLButtonDown v aplikácii Information.

void CInformationView::OnLButtonDown(UINT nFlags, CPoint point)
{
MessageBox("Môj prvý dialóg v prostredí Visual C++", "Hurá!", MB_OK |
MB_ICONINFORMATION);
}

Teraz sa po stlačení ľavého tlačidla myši v okne aplikácie zobrazí informačný dialóg, ako vidíte na obr. 1. Pohrajte sa trochu s týmto jedným riadkom, zmeňte parametre funkcie podľa tabuľky, vyskúšajte rôzne kombinácie. Toľko o dialógoch v tejto časti, nabudúce sa pozrieme na klasické modálne dialógy so všetkým, čo k nim patrí, vrátane mechanizmu výmeny údajov medzi ovládacími prvkami a premennými v programe a práce s editorom zdrojov.

Obr. 1 Informačný dialóg programu Information

FAQ. V tejto „podčasti“ seriálu C++ pod Windows dávam priestor vám čitateľom, aby ste kládli otázky o programovaní vo Visual C++,  na ktoré sa pokúsim odpovedať. V tejto časti uverejňujem dve otázky, ktoré mi prišli ešte v začiatkoch seriálu:

Q: Nejde mi skompilovať/zlinkovať program Hello z druhej časti seriálu.

A: Tu je návod, ako postupovať pri zostavovaní projektu Hello world z druhej časti seriálu: Ak máte spustené Visual C++, z menu File vyberte New. Kliknite na záložku Projects a vyberte Win32 Application. Do políčka Project Name zadajte Hello. Kliknite na OK. Objaví sa vám ďalší dialóg, na ktorom zvoľte: An Empty Project a kliknite na Finish. Potom sa vám zobrazia informácie o novom projekte. Opäť kliknite na OK. Potom z menu Project vyberte Add Tto Project a potom Files. Nájdite súbor, ktorý obsahuje zdrojový text programu a vyberte Add. Ak ešte nemáte napísaný zdrojový text, z menu Add To Project vyberte New a potom pod záložkou Files vyberte: C++ Source File. Na tom istom dialógu do políčka File name vpíšte: hello.c.  Je dôležité, aby prípona súboru bola *.c, a nie *.cpp. Potom napíšte zdrojový kód do tohto súboru. Projekt zostavte.

Q: Nejde mi skompilovať/zlinkovať program First zo štvrtej časti seriálu, pričom mi hlási nejaký problém  s knižnicou nafxcwd.lib.

A: Postup pri vytváraní nového projektu je podobný ako pri programe Hello (pozri predchádzajúcu odpoveď). Tu však ešte treba zvoliť podporu pre knižnicu MFC v danom projekte. Z menu Project vyberte Settings. V zozname Microsoft Fundation Classes vyberte namiesto Not Using MFC: Use MFC in a Shared DLL alebo Use MFC in a Static Library. Projekt nanovo skompilujte a zlinkujte  (Rebuild All).

Tipy na doma. Väčšinu tipov na doma nájdete v predchádzajúcom texte. Na tomto mieste vám len pripomeniem, aby ste nezabudli experimentovať (napr. s funkciou MessageBox), lebo len samotným čítaním bez programovania sa ďaleko nedostanete.

NABUDÚCE. O mesiac začneme naplno pracovať s dialógmi, vytvoríme veľký dialóg, ktorý bude obsahovať väčšinu štandardných ovládacích prvkov, ktoré sa dajú použiť v dialógoch. Vysvetlíme si mechanizmy DDX a DDV, a ak nám ostane priestor, začneme sa venovať aj spoločným ovládacím prvkom Windows (Windows Common Controls). Dovidenia o mesiac.

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á