Image
26.6.2016 0 Comments

C++ pod Windows / Dialógy IV / 12. časť

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

A je to tu! Seriál C++ pod Windows oslavuje prvé výročie. Verte alebo nie, stretávame sa už po celý jeden rok, čo pri seriáloch, ktorých maximálna dĺžka života sú dva roky, určite nie je na zahodenie. Niet sa čomu čudovať, programovanie v jazyku C++ pod operačným systémom Windows je rozsiahla téma, ktorá sa nedá zvládnuť za krátke časové obdobie. Začali sme od úplných základov, postupne sme sa prepracovali ku knižnici MFC. Už viete, ako urobiť „oknovú“ aplikáciu, viete, ako pracuje, viete, čo s čím súvisí a čo je najdôležitejšie, viete ju urobiť v „profesionálnom“ vývojovom prostredí využitím „profesionálneho“ programovacieho jazyka (teda aspoň dúfam). Takéto vedomosti určite nie sú na zahodenie. Ak ich chcete mať viac, chcete byť „niekým“ v prostredí profesionálneho programovania, vzdelávajte sa, získavajte ďalšie vedomosti. Úprimne dúfam, že vám v tom pomôže aj tento seriál.

DOMÁCA ÚLOHA. Na začiatku sa ešte vráťme k predchádzajúcej časti. Za úlohu ste mali doplniť funkciu OnLButtonDown v triede pohľadu o makrá TRACE, ktoré by po zavretí dialógu vypísali hodnoty členských premenných dialógu BigDlg. Inak povedané, zobrazia to, čo bolo vidieť v dialógu. Akúsi pomoc ste už v tejto funkcii mali, po zavretí dialógu vypísalo makro TRACE návratovú hodnotu funkcie DoModal. Kód uvedený ďalej je riešením domácej úlohy. Dopíšte ho do existujúcej funkcie OnLButtonDown. Všetky volania makier TRACE je v kóde potrebné umiestniť až za volanie funkcie DoModal.

// ... funkcia OnLButtonDown ...
// vyvoláme dialóg
int ret=BigDlg.DoModal();
 
TRACE("DoModal vratil: %d\n", ret);
TRACE("Meno: %s, Rodné číslo: %d/%d\n",
               BigDlg.m_strMeno, BigDlg.m_nRodc1, BigDlg.m_nRodc2); 
TRACE("Poznámka: %s\n", BigDlg.m_strPozn);
TRACE("Kategória: %d\n", BigDlg.m_nCat);
TRACE("Vlastník: Štandardné PC: %d, Notebook: %d, Apple: %d\n",
       BigDlg.m_bSpc, BigDlg.m_bNot, BigDlg.m_bApl);  
TRACE("Budúce zamestanie: %s\n", BigDlg.m_strZamest);
TRACE("Zameranie: %s\n", BigDlg.m_strZam);
TRACE("Vydelanie: %s\n", BigDlg.m_strVzd);
TRACE("Pref. jazyk: %d\n", BigDlg.m_nJaz);

Ďalšou úlohou bolo, aby sa po kliknutí na tlačidlo IDC_BTNINF zobrazil informačný dialóg s nejakou správou. Pomocou Class Wizardu bolo treba pridať obsluhu správy BN_CLICKED pre toto tlačidlo v triede CBigDialog. Tu je výpis funkcie na obsluhu tejto správy:

void CBigDialog::OnBtninf()
{
      MessageBox("Nad týmto tlačidlom môžete nájsť fotku.", "Informácia", MB_ICONINFORMATION);
}

Toľko domáce úlohy, ideme ďalej.

ZAPOJENIE POSUVNÍKOV. Ak v terajšej verzii dialógu BigDlg kliknete na posúvacie pásky, nestane sa nič. Kód pre obsluhu posuvníkov musíme pridať sami, nikto to za nás neurobí (tým nikým myslím vizuálne nástroje Visual C++). Pri posuvníkoch sledujeme ich rozsah a pozíciu. Ak nastavíme rozsah od 0 po 100, hodnota 50 bude presne v strede. Keď kliknete na jednu zo šípok posuvníkov alebo keď ťaháte tlačidlo posuvníka, prípadne keď kliknete do vnútra posuvníka (priamo na rolovaciu pásku), ten posiela správy WM_HSCROLL alebo  WM_VSCROLL (podľa toho, či ide o horizontálny alebo vertikálny posuvník). A to sú práve správy, ktorých obslužné funkcie využijeme na napísanie kódu, ktorý obsluhuje posuvníky. V našom prípade ešte chceme, aby sa po kliknutí na posuvník IDC_ROCNIK aj vypísalo na popise IDC_STATIC_ROCNIK číslo ročníka. Musíme teda rozlišovať, na ktorý posuvník sme klikli. Najprv si však vysvetlíme, ako kód pridať, a až potom sa budeme zaoberať tým, ako pracuje.

PRIDANIE KÓDU. Do hlavičkového súboru triedy CBigDialog pridajte dve verejné členské premenné, ktoré určujú rozsah posuvníkov:

public:
enum { Min=0 };
      enum { Max=4 };

Pretože máme dva rôzne posuvníky, musíme použiť aj dva rôzne ukazovatele na ne. Pre lepšiu prehľadnosť pridajte aj tieto dve deklarácie do verejnej časti toho istého hlavičkového súboru:

            CScrollBar* pSBP;
      CScrollBar* pSBR;

Spusťte Class Wizard a do triedy CBigDialog pridajte obsluhu správy WM_HSCROLL (keďže máme horizontálne posuvníky). V zdrojovom súbore tejto triedy pridajte tento kód do funkcie OnInitDialog, ktorý má na starosti nastavenie rozsahov posuvníkov podľa premenných MinMax a zobrazenie nultého ročníka v popise IDC_STATIC_ROCNIK. Všimnite si, že tu musíme používať dva rôzne ukazovatele!

// Nastavíme rozsah posuvníkov
pSBP = (CScrollBar*) GetDlgItem(IDC_PROSPECH);
pSBP->SetScrollRange(Min, Max);
 
pSBR = (CScrollBar*) GetDlgItem(IDC_ROCNIK);
pSBR->SetScrollRange(Min, Max);
 
// Počiatočný ročník (nultý ročník)
SetDlgItemText(IDC_STATIC_ROCNIK, "0.");

Nakoniec pridajte kód do obslužnej funkcie správy WM_HSCROLL, ako vidíte na listingu.

void CBigDialog::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
      int pom1, pom2;
      CString strText;
     
      pom1 = pScrollBar->GetScrollPos();
 
      // identifikujeme, o ktorý posuvník sa jedná
      if (pScrollBar==pSBP)
      {
            switch(nSBCode)
            {
            // klikneme na ľavú šípku posuvníka
            case SB_LINELEFT:
                  pom2 = (Max - Min) / 4;
                  if ((pom1 - pom2) > Min)
                        pom1 -= pom2;
                  else
                        pom1 = Min;
                  pScrollBar->SetScrollPos(pom1);
                  break;
            // klikneme na pravú šípku posuvníka
            case SB_LINERIGHT:
                  pom2 = (Max - Min) / 4;
                  if ((pom1 + pom2) < Max)
                        pom1 += pom2;
                  else
                        pom1 = Max;
                  pScrollBar->SetScrollPos(pom1);
                  break;
            }
      }
     
      // ak sa jedná o posuvník ročníka, meníme
      // aj príslušný popis
      if (pScrollBar==pSBR)
      {
            switch(nSBCode)
            {
            // klikneme na ľavú šípku posuvníka
            case SB_LINELEFT:
                  pom2 = (Max - Min) / 4;
                  if ((pom1 - pom2) > Min)
                  {
                        pom1 -= pom2;
                        // integerový pom1 prevedieme
                        // na stringový strText
                        // vhodný pre SetDlgItemText
                        strText.Format("%d.", pom1);
                        SetDlgItemText(IDC_STATIC_ROCNIK, strText);
                  }
                  else
                  {
                        pom1 = Min;
                        strText.Format("%d.", pom1);
                        SetDlgItemText(IDC_STATIC_ROCNIK, strText);
                  }
                  pScrollBar->SetScrollPos(pom1);
                  break;
            // klikneme na prvú šípku posuvníka
            case SB_LINERIGHT:
                  pom2 = (Max - Min) / 4;
                  if ((pom1 + pom2) < Max)
                  {
                        pom1 += pom2;
                        // integerový pom1 prevedieme
                        // na stringový strText
                        // vhodný pre SetDlgItemText
                        strText.Format("%d.", pom1);
                        SetDlgItemText(IDC_STATIC_ROCNIK, strText);
                  }
                  else
                  {
                        pom1 = Max;
                        strText.Format("%d.", pom1);
                        SetDlgItemText(IDC_STATIC_ROCNIK, strText);
                  }
                  pScrollBar->SetScrollPos(pom1);
                  break;
            }
      }
}

AKO TO PRACUJE? Tak, kód už máme, už ho len pochopiť, však? Nemalo by vám to robiť veľký problém. Ako z kódu vidno, pomocou tretieho parametra funkcie OnHScroll identifikujeme, o ktorý posuvník ide (teda ktorý „vysiela“ správu WM_HSCROLL). Za povšimnutie hádam ešte stojí členská funkcia triedy CString, funkcia Format. Ak máme nejaký číselný (alebo iný) údaj a chceme ho previesť na reťazec, nemusíme zbytočne volať konverzné funkcie. Všetko zabezpečí funkcia Format, ktorá má syntax podobnú s funkciou printf (dúfam, že máte zopakované).

Ako sa používa, vidíte vo výpise ďalej. Táto funkcia má, samozrejme, takisto svoje „muchy“, takže si ju radšej podrobnejšie pozrite v helpe.

POSLEDNÁ ÚPRAVA V BIGDIALOGU. Pri praktickom používaní tohto dialógu sa stretneme ešte s jedným problémom. Pri vypisovaní položky (napríklad textového poľa IDC_MENO) a následnom stlačení Enter sa dialóg zavrie. Je to spôsobené tým, že tlačidlo IDOK má vo svojich vlastnostiach nastavenú vlastnosť Default button [záložka (karta) Styles] a Windows po stlačení Enteru hľadajú najprv aktívne tlačidlo (to, na ktorom „stojíme“ – má bodkovaný okraj), a keď ho nenájdu, potom hľadajú defaultné tlačidlo (má hrubší okraj), čo je v našom prípade tlačidlo OK. Kláves Enter pre nich znamená, že vykonajú presne to, ako keby sme na tlačidlo OK klikli myšou. Dobre, a čo keby sme nenastavili žiadne defaultné tlačidlo? Skúste si to a uvidíte sami. Dialóg sa aj tak zavrie. A to preto, lebo keď Windows nenájdu žiadne aktívne ani žiadne defaultné tlačidlo, aj tak zavolajú funkciu OnOK, ktorá vymení dáta medzi dialógom a aplikáciou a dialóg uzavrie (a to dokonca aj vtedy, keď dialóg neobsahuje nijaké tlačidlo OK). Klasickým spôsobom, ako obísť tento nedostatok (čiže zavretie dialógu, aj keď nemáme žiadne tlačidlo defaultné), je napísať prázdnu funkciu OnOK  štandardnému tlačidlu OK a cez Class Wizard mu pridať obsluhu správy BN_CLICKED. Potom v programe namiesto štandardného ID tlačidla OK (IDOK) zvoliť iné a tomu takisto pridať obsluhu správy BN_CLICKED. A až z tejto funkcie (samozrejme, že sa musí volať inak ako štandardná funkcia OnOK.) budeme volať funkciu OnOK. Teraz budeme mať zaručené, že len pri kliknutí na tlačidlo OK sa aktivuje „uzavieracia sekvencia“.   

Spusťte Class Wizard a v triede CBigDialog v zozname Object IDs vyhľadajte IDOK. V zozname Messages vyberte BN_CLICKED a potom Add Function. (Meno nechajte implicitné čiže OnOK. Tým my „prepíšeme“ štandardnú funkciu OnOK.) V zdrojoch, konkrétne v dialog editore, zmeňte ID tlačidla IDOK povedzme na IDC_KLIKOK a opäť tomuto tlačidlu pridajte cez Class Wizard obsluhu správy BN_CLICKED. Pri kliknutí na Add Function je, samozrejme, potrebné zadať iné meno než OnOK, zmeňte ponúkané na OnKlikOK a dokončite pridávanie funkcie. Upravte kód týchto funkcií, ako vidíte ďalej. Ak náhodou máte nastavené tlačidlo teraz už IDC_OK ako default button, odznačte mu túto vlastnosť (inak by toto pridávanie kódu a funkcii bolo nanič). Skúste aplikáciu spustiť, malo by všetko fungovať.

void CBigDialog::OnOK()
{
      // Prázdna funkcia
}
 
void CBigDialog::OnKlikOK()
{
      // až z tejto funkcie zavoláme OnOK, ktorá
      // dialóg uzavrie
      CDialog::OnOK();
}  

Samozrejme, existujú aj iné spôsoby, ako Windows „oklamať“. Napríklad tento: Vytvorte v dialog editore hocijaké tlačidlo a umiestnite ho na dialóg. V jeho vlastnostiach na záložke General odznačte vlastnosť Visible a na záložke(karte) Styles zaškrtnite vlastnosť Default button. Program spusťte a teraz by sa dialóg tiež nemal zavrieť pri stlačení klávesu Enter, ale len pri kliknutí na tlačidlo OK. Líšia sa v niečom tieto dva spôsoby? Ak áno, v čom? Ktorý je podľa vás lepší? Skúste nad tým porozmýšľať.

FAQ

Q: Čo tvorí základ knižnice MFC?

A: Ľahká otázka, na ktorú sa však ťažko dá stručne odpovedať. Je ťažké určiť, ktoré triedy knižnice MFC sú tie „najzákladnejšie“. Vo všeobecnosti sa triedy knižnice MFC delia do kategórií, pričom jednotlivé kategórie môžu obsahovať viac či menej tried. Tieto kategórie vidíte na obr. 1. Rozhodol som sa uvádzať ich v „pôvodnom znení“ čiže v angličtine, lebo prekladať ich by aj tak nemalo zmysel a slovenský preklad by nebol veľmi výstižný.  Pod obrázkom 1 nájdete stručný opis týchto kategórií.

CObject – základná trieda takmer celej  knižnice MFC

Application Architecture – do tejto skupiny patria triedy, ktoré tvoria základ každej aplikácie MFC. Napríklad triedy CWinAppCDocument, CDocTemplate a i. Všetky sú odvodené, samozrejme, od CObject a hneď potom od CCmdTarget (pozri ďalej)

Exceptions – patria sem triedy, ktoré obsluhujú výnimky, ktoré môžu v aplikácii nastať (napríklad pri zápise do súboru, pri procesoch a pod.). Základnou triedou tejto skupiny je CException

File Services – ako možno s názvu vydedukovať, pôjde o triedy, ktoré sa zaoberajú čítaním/zápisom dát          z disku/na disk. Využívajú sa pri serializácii. Základnou triedou je CFile

Graphical Drawing – v tejto skupine sú triedy kontextov zariadení. Hlavnou je CDC, ďalšie sú napr. CClientDC, CPaintDC a i.

Control Support – trieda obsluhujúca stavy líšt (nástrojovej, stavovej) – CDocState a trieda obsluhujúca zoznamy obrázkov – CImageList

Graphical Drawing Objects – triedy objektov GDI (CPen, CBitmap, CBrush, CFont…) 

Menus – nepotrebuje komentár. Základnou triedou je CMenu 

Command Line – obsahuje jedinú triedu CCommandLineInfo, ktorá má na starosti spracovanie príkazového riadka pri štarte aplikácie

ODBC Database Support – obsahuje triedy, ktoré umožňujú spojenie k zdroju dát, cez ktorý môžete potom tieto dáta obsluhovať (napríklad trieda CDatabase)

DAO Database Support – triedy umožňujúce pripojenie k databázam cez Data Access Objects

Synchronization – triedy na prácu s procesmi, semaformi atď. 

Windows Sockets – obsluhuje Windows Socket API

Arrays, Lists, Maps – súhrnne sa tieto triedy nazývajú triedy kolekcií; obsahujú prvky na prácu a riadenie dátových abstrakcií (polia, zoznamy, kolekcie mapovaných objektov)

Internet Services – ide o triedy zabezpečujúce pripojenie a správu internetových pripojení

CCmdTarget – základná trieda pre mapu správ a pre správy a udalosti

Window Support -  patria sem triedy pre správu okien. Základnou triedou je CWnd, od ktorej sú postupne odvodzované napríklad CFrameWnd, CDialog(aj dialóg je okno)

Frame Windows – triedy pre správu okien. Patria sem napríklad CFrameWnd, CMDIChildWnd a i.

Control Bars – triedy na vytváranie nástrojových, stavových a iných líšt (CStatusBar, CToolBar...)

Property Sheets – obsahuje dve triedy, ktoré slúžia na vytváranie a správu dialógov s kartami (záložkami). Takéto dialógy sa nazývajú property sheets alebo aj tab dialog boxes.  Triedy sú CPropertySheetCPropertySheetEx

DialogBoxes – v tejto kategórii sú triedy, ktoré potrebujeme pri práci s dialógmi. Hlavnou je, samozrejme, CDialog, od ktorej sú odvodené ďalšie. Patria sem aj tzv. spoločné dialógy Windows, ako napr. dialóg tlače (trieda CPrintDialog), dialóg výberu farby (trieda CColorDialog) a ďalšie.

Views – skupina zahrnujúca všetky pohľady. Sú tu triedy Cview (základná pre všetky pohľady), CscrollView (tie už poznáme), potom napr. CEditView, CRichEditView (slúžiace na programovanie textových editorov) a ďalšie.

Controls – tu sú triedy ovládacích prvkov, ktoré sme pridávali (a ešte aj budeme pridávať) do dialógov. Každý ovládací prvok musí mať, samozrejme, aj svoju triedu, napr. pre editačné okno to je trieda CEdit, pre tlačidlo CButton a pod. Spomeňte si, ako sme v predchádzajúcej časti deklarovali premenné pre tlačidlo s bitmapou (Fotka). Robili sme tak pomocou triedy CBitmapButton, ktorá sem takisto patrí. Rovnako aj v tejto časti rozlišujeme posuvníky pomocou premenných odvodených od základnej triedy pre posuvníky: CScrollBar.

TIPY NA DOMA. Doma skúste pridať do obsluhy posuvníkov reakciu na kliknutie dovnútra posuvníka (čiže priamo na rolovaciu pásku). Takisto pridajte popis k posuvníku IDC_PROSPECH, kde podľa polohy tohto posuvníka budete zobrazovať prospech slovami, teda výborný až nedostatočný. Rozšírte rozsah posuvníka IDC_ROCNIK tak, aby bolo možné zobraziť ročníky 0. až 6. Skúste pridať kód, ktorý bude obchádzať zavretie dialógu po stlačení klávesu ESC. Podobne, ako to bolo v prípade klávesu ENTER, kde sa volala funkcia OnOK, ak stlačíme ESC, volá sa funkcia OnCancel. Postupujte teda podobne ako v prípade funkcie OnOK.

NABUDÚCE. Táto časť bola síce oproti predchádzajúcej skôr monotematická, na druhej strane sme však uzavreli tému modálne dialógy a ich štandardné ovládacie prvky. V budúcej časti preberieme nové, spoločné ovládacie prvky systému Windows (tie, ktoré prišli až s Windows 95). Potom si v stručnosti opíšeme nemodálne dialógy a tým s dialógmi definitívne skončíme.

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á