P R O G R A M U J E M EC++ pod Windows15. èas : Menu, ToolBar, StatusBarKým v predchádzajúcej èasti som písal, že leto sa nám pomaly konèí, teraz už môžem bezpochýb poveda , že leto je <strong>na</strong>dobro v ahu. Ale veï ani jeseò nie je zlá. Pre optimistovz<strong>na</strong>mená krásnu vôòu pestro sfarbeného popadaného lístia. Pre pesimistov zase neporiadok<strong>na</strong> chodníkoch, zapríèinený týmto popadaným a nepríjemne šuštiacim lístím, a ve¾aupršaných dní. Dúfam, že väèši<strong>na</strong> z vás patrí do tej prvej <strong>sk</strong>upiny, programovanie a vývojaplikácií si totiž èasto vyžaduje trocha zidealizovaný poh¾ad <strong>na</strong> vec, aby nás z toho <strong>na</strong>èistoneporazilo. JMENU, TOOLBAR, STATUSBAR. Náš preh¾ad tvorby GUI (grafického používate¾<strong>sk</strong>éhorozhrania) zakonèíme, keï si povieme o týchto troch neodmyslite¾ných súèastiachkaždej aplikácie Win. Èo je Menu, to je azda každému jasné; z poh¾adu MFC je toobjekt odvodený od triedy CMenu. Táto trieda má v sebe aj podporu viacúrovòových,pop-up a plávajúcich pop-up menu. ToolBar èiže panel nástrojov je z poh¾adu MFCobjekt odvodený od triedy CToolbar, ktorá je potomkom triedy CControlBar (spoloènejtriedy pre všetky objekty ovládacích prvkov líšt – bars) a tá je potomkom triedy CWnd(z toho vyplýva, že ToolBar a StatusBar sú okná). Presnejšie ToolBar je okno, ktoréumožòuje zobrazi <strong>na</strong> sebe tlaèidlá, kliknutím <strong>na</strong> ktoré vyvoláme nejakú operáciu.Kliknutie <strong>na</strong> položku v ToolBare má rov<strong>na</strong>ký úèinok ako výber nejakej položky v menu(generujú sa príkazové správy – podrobnejšie ne<strong>sk</strong>ôr). StatusBar alebo stavový riadokslúži <strong>na</strong> zobrazovanie stavových informácií. Môže to by ¾ubovo¾ný text, <strong>na</strong>pr. help kpoložkám v menu, súradnice kurzora myši a pod. Je to opä okno, ale <strong>na</strong> rozdiel odToolBaru nepodporuje vstup od používate¾a ani negeneruje nijaké správy alebo operácie.Prevažne slúži len <strong>na</strong> zobrazenie textu, prípadne ikon. Je to objekt odvodený od triedyCStatusBar, ktorá má rov<strong>na</strong>kých predkov ako trieda CToolBar. V prípade Menu aToolBaru je ich vytváranie v réžii editora zdrojov. Jediné, èo musíme doprogramova , jeobsluha správ, ktoré môžu vzniknú pri práci s nimi.SPRACOVANIE PRÍKAZOVÝCH SPRÁV. Príkazové správy sme už v struènostiopisovali a už viete, že vznikajú ako reakcia <strong>na</strong> vybratie položky v menu, stlaèenietlaèidla v paneli nástrojov a pri stlaèení klávesovej <strong>sk</strong>ratky (použití akcelerátora). Väèši<strong>na</strong>takýchto správ pochádza z rámcového ok<strong>na</strong>, ktorému koniec koncov patrí menu aj panelnástrojov. Èo však v takom prípade, keï chceme príkazovú správu obslúži v triedepoh¾adu alebo dokumentu?Aplikaèný systém so svojouarchitektúrou smerovania príkazov(command routing architecture)nám to, samozrejme,umožòuje. Keï zachytí príkazovúsprávu, jej obslužnú funkciuh¾adá v tomto poradí v triedach:Poh¾adu -> Dokumentu-> Hlavného rámcového ok<strong>na</strong>SDI -> Aplikácie (platí pre aplikácieSDI, o MDI ne<strong>sk</strong>ôr). Použitiepríkazových správ námopä výrazne u¾ahèuje ClassWizard,ktorý tento proces úplneautomatizuje. Jediné, èo musímeurobi , je <strong>na</strong>písa kód obslužnejfunkcie.Obr. 1 Informácie o novom projektePRÍKLAD. Teraz si <strong>na</strong> príkladeukážeme vytváranie a programovanieopísaných prvkov. Vytvoríme aplikáciu, ktorá po výbere položky v menu alebopo stlaèení príslušného tlaèidla panela nástrojov zobrazí dialóg buï <strong>na</strong> zadanie me<strong>na</strong>,alebo priezvi<strong>sk</strong>a. Zadaný text sa potom zobrazí v stavovom riadku. Pridáme funkènos ajpre plávajúce pop-up menu. Pomocou AppWizardu vytvorte nový projekt s názvom GUI.Jeho <strong>na</strong>stavenia vidíte <strong>na</strong> obr. 1 (všetko default, ibaže SDI).Pomocou editora zdrojov vytvorte dva zdroje dialógov (ID nechajte default: IDD_DIA-LOG1 – zadanie me<strong>na</strong> a IDD_DIALOG2 – zadanie priezvi<strong>sk</strong>a). Ovládacie prvky pridajtepod¾a obr. 2 a 3, <strong>na</strong> ktorých sú oba dialógy. Všetky ID a vlastnosti okrem Edit Boxovnechajte default. V IDD_DIALOG1 zmeòte ID tohto textového po¾a <strong>na</strong> IDC_MENO a vdruhom dialógu <strong>na</strong> IDC_PRIEZVISKO.Teraz spus te ClassWizard a vytvorte nové triedy postupne pre oba dialógy. Pre IDD_DIA-LOG1 bude ma trieda názov CGUIDialogM a pre IDD_DIALOG2 to bude trieda s názvomObr. 2 Dialóg <strong>na</strong> zadanie me<strong>na</strong> Obr. 3 Dialóg <strong>na</strong> zadanie priezvi<strong>sk</strong>aObr. 4 Vytvorenie novej triedypre zdroj dialóguCGUIDialogP. Keïže ide o jednoduché dialógy,do ktorých nejdeme pridáva nejakúsuper funkènos , môžu ma spoloèný hlavièkovýaj implementaèný súbor. Preto v dialóguvytvárania novej triedy pre oba zdroje v textovom poli File Name zvo¾te Change...a zadajte: GUIDialogs.h pre hlavièkový a GUIDialogs.cpp pre zdrojový súbor. (obr. 4 a 5). Aksa vám po pridaní náhodou tieto dve triedy nezobrazia v poh¾ade ClassView, potom z menuProject vyberte Add to Project, potom Files a nájdite a pridajte súbory GUIDialogs.h aGUIDialogs.cpp.Keï už máme pridané dialógy, už nám ostáva len prida nieèo, èo by ich vyvolalo.Zaèneme s Menu.Krok 1 – úprava Menu: V editorezdrojov v „zložke“ Menu dvakrát kliknite<strong>na</strong> zdroj menu IDR_MAINFRA-ME. Kliknite <strong>na</strong> položku menu Help astlaète kláves Insert. Tým pridáteïalšiu položku do menu. Dvakrát <strong>na</strong>òu kliknite (resp. pravé tlaèidlo aProperties) a do po¾a Caption <strong>na</strong>píštetext: &GUI (ampersand má vtomto prípade rov<strong>na</strong>ký úèinok akopri ovládacích prvkoch dialógov –pozri 11. èas seriálu). Všetky ostatnévlastnosti nechajte default. Podpoložku GUI pridajte ïalšiu s Caption:&Dialógy. Zaškrtnite jej vlastnos Pop-up. Ako pop-up menu k tejto položke vložtedve položky, ktorých Caption je: &Meno a &Priezvi<strong>sk</strong>o. Ich vlastnosti nechajte <strong>na</strong> default,ibaže vo vlastnostiach <strong>na</strong> záložke General vpíšte do po¾a Prompt pre Meno: Zobrazí dialógso zadaním me<strong>na</strong> a pre Priezvi<strong>sk</strong>o: Zobrazí dialóg so zadaním priezvi<strong>sk</strong>a (obr. 6).Tento text sa bude zobrazova v StatusBare ako nápoveï k týmto položkám menu.Na obr. 7 vidíte celú štruktúru položiek menu GUI v editore zdrojov.Nech vás netrápi, že v ID položiek Meno a Priezvi<strong>sk</strong>o je <strong>na</strong>miesto DIALÓGY len DIAL-GY. V ID totiž nemôžu by takéto špeciálne z<strong>na</strong>ky (akým je v tomto prípade dåžeò). Je tosíce len kozmetická chybièka, ale pri vývoji softvéru v <strong>na</strong>šich podmienkach si <strong>na</strong> to trebazvyknú .Keï už máme vizuálne veci za sebou, musíme ešte prida nejaký kód <strong>na</strong> „spojazdnenie“nových položiek menu. Pravým tlaèidlom kliknite <strong>na</strong> Meno a z plávajúceho pop-upmenu (áno, to je to plávajúce menu spomenuté <strong>na</strong> zaèiatku, ktoré si aj my ne<strong>sk</strong>ôr <strong>na</strong>programujeme)vyberte ClassWizard. Pridajte tejto položke Menu obsluhu príkazovejsprávy, ktorá je reakciou <strong>na</strong> kliknutie alebo „odenterovanie“ tejto položky (<strong>na</strong> COMMANDa Add Function). Túto funkènos pridajte do triedy CMainFrame (<strong>sk</strong>úste si doma pridaobsluhu týchto príkazových správ aj do triedy poh¾adu, od<strong>sk</strong>úšajte funkènos a potomich pridajte aj do triedy Dokumentu. Funguje to rov<strong>na</strong>ko? Je v tom nejaký rozdiel? Skúste<strong>na</strong>d tým porozmýš¾a , viac informácií v èasti Spracovanie príkazových správ). Názvyobslužných funkcií nechajte ponúkané. Ich kód zmeòte, ako vidíte tu:void CMainFrame::OnGuiDialgyMeno(){CGUIDialogM dlgM;}dlgM.DoModal();void CMainFrame::OnGuiDialgyPriezvi<strong>sk</strong>o(){CGUIDialogP dlgP;}dlgP.DoModal();Samozrejme, ešte nezabudnite prida <strong>na</strong> zaèiatok súboru MainFrm.cpp túto includedirektívu:#include „GUIDialogs.h“Obr. 6Obr. 7Obr. 5Zmenenie mien súborovpre triedy CGUIDialogMa CGUIDialogPVlastnosti položky v menuŠtruktúra položiekv menuProjekt preložte a spustite. Vy<strong>sk</strong>úšajte funkènos nových položiek menu (vrátane spomí<strong>na</strong>nejnápovede v stavovom riadku).Krok 2 – úprava ToolBaru: Znova sa vrá te do editora zdrojov a v „zložke“ Toolbar dvakrátkliknite <strong>na</strong> zdroj IDR_MAINFRAME. Tým spustíte editor. V òom <strong>na</strong> konci bitmapy124 PC REVUE 10/2001
P R O G R A M U J E M Epanela nástrojov vidíte prázdnepolíèko. Trochu ho myšou posuòtedoprava, aby bolo optickyoddelené od predchádzajúcich.Pomocou editora doò vpíšte M(po kliknutí <strong>na</strong> toto tlaèidlo toolbarusa zobrazí dialóg <strong>na</strong> zadanie Obr. 8 ToolTip pri tlaèidlách panela nástrojovMe<strong>na</strong>). Ved¾a tohto tlaèidla saobjavilo ïalšie prázdne a doò vpíšte P. Ak dvakrát kliknete <strong>na</strong> niektoré tlaèidlo panelanástrojov (ešte stále sa, samozrejme, <strong>na</strong>chádzame v editori), zobrazia sa jeho vlastnosti.Do políèka ID vpíšte rov<strong>na</strong>ké ID ako v prípade položiek menu (pre tlaèidlo M bude ID:ID_GUI_DIALGY_MENO a pre tlaèidlo P bude ID: ID_GUI_DIALGY_PRIEZVISKO). Ako somv úvode spomí<strong>na</strong>l, aplikaèný systém smeruje príkazové správy z menu a panela nástrojovrov<strong>na</strong>kým spôsobom (smerom), a preto môžeme použi rov<strong>na</strong>ké obslužné funkcie, èov tomto prípade zabezpeèíme rov<strong>na</strong>kým ID. Tým, že sme zvolili rov<strong>na</strong>ké ID, aj nápoveï vstavovom riadku bude rov<strong>na</strong>ká a už ju nemusíme zbytoène prepisova . Pre panel nástrojovexistuje ešte takzvaná ToolTip nápoveï (ak sa myšou zastavíte <strong>na</strong>d niektorým tlaèidlomToolBaru, zobrazí sa zvyèajne žltý pravouholník s textom, ktorý objasòuje funkciutlaèidla). Túto „funkènos “ pridáte jednoducho tak, že vo vlastnostiach tlaèidla do po¾aPrompt pridáte za nápoveï, ktorá sa zobrazuje v stavovom riadku, z<strong>na</strong>k nového riadka\n a za ním text ToolTipu (obr. 8). V <strong>na</strong>šom príklade pre tlaèidlo M pridajte ToolTip:Dialóg meno a pre tlaèidlo P zase Dialóg priezvi<strong>sk</strong>o. Kontrolná otázka: Myslíte si, že sazmenil Prompt aj vo vlastnostiach položiek Menu? Skúste <strong>na</strong>jprv odpoveda a až potomsa pozrie .Krok 3 – úprava StatusBaru: Dostali sme sa do predposlednej fázy úpravy projektu GUI.V nej spojíme dialógy pre zadanie me<strong>na</strong> a priezvi<strong>sk</strong>a so stavovým riadkom, <strong>na</strong> ktoromzobrazíme text zadaný v týchto dialógoch. Stavový riadok je definovaný v súboreMainFrm.cpp v statickom poli indicators. V <strong>na</strong>šom prípade definíciu predstavuje kód:static UINT indicators[] ={ID_SEPARATOR,ID_INDICATOR_CAPS,ID_INDICATOR_NUM,ID_INDICATOR_SCRL,};// status line indicatorIndikátory CAPS, NUM a SCRL sa aktivujú, keï stlaèíme príslušný kláves (ak ste sa stým ešte nestretli, spus te aplikáciu GUI a vy<strong>sk</strong>úšajte si to). Pre <strong>na</strong>še potreby nám budústaèi len dve „prázdne“ miesta v stavovom riadku, prièom v prvom (má index 0 a jev¾avo) sa bude zobrazova text z dialógu Meno a v druhom text z dialógu Priezvi<strong>sk</strong>o.Zmeòte preto definíciu stavového riadka takto:static UINT indicators[] ={ID_SEPARATOR,ID_SEPARATOR,};Pomocou ClassWizardu pridajte textovým poliam v dialógoch premenné, ako vidíte vtab. 1.Teraz už len pridajte tento riadok do funkcie OnGuiDialgyMeno:m_wndStatusBar.SetPaneText(0, dlgM.m_strMeno);a do funkcie OnGuiDialgyPriezvi<strong>sk</strong>o:m_wndStatusBar.SetPaneText(1, dlgP.m_strPriezvi<strong>sk</strong>o);Samozrejme, že tento kód musíte prida až za volanie funkcie DoModal. Premennám_wndStatusBar je deklarovaná v hlavièkovom súbore triedy CMainFrame ako premennátypu stavový riadok (CStatusBar m_wndStatusBar). To je všetko, po spustení aplikáciesa bude zobrazova v ¾avej èasti StatusBaru meno a v pravej priezvi<strong>sk</strong>o. Ako však uvidíte,tieto dva panely StatusBaru nie sú ve¾mi esteticky usporiadané. ¼avý je akýsi vypuklý aväèší ako pravý. To hneï <strong>na</strong>pravíme. Pridajte tieto dva riadky do súboru MainFrm.cpp niekdeku koncu funkcie OnCreate:m_wndStatusBar.SetPaneInfo(0, 0, 0, 300);m_wndStatusBar.SetPaneInfo(1, 0, 0, 300);ID ovládacieho prvku Èlen<strong>sk</strong>á premenná Typ Max. dåžkaIDC_MENO m_strMeno CString 10IDC_PRIEZVISKO m_strPriezvi<strong>sk</strong>o CString 15Tab. 1 Èlen<strong>sk</strong>é premenné dialógovTým sme <strong>na</strong>stavili rov<strong>na</strong>ký vzh¾ad a rozmery pre oba panely stavového riadka (viac ofunkciách stavového riadka sa doèítate v helpe).Krok 4 – pridanie plávajúceho pop-up menu: Ako som písal <strong>na</strong> zaèiatku, trieda CMenumá v sebe obsiahnutú podporu aj pre takýto typ menu (štandardne sa toto menupoužíva, ak kliknete pravým tlaèidlom myši do klient<strong>sk</strong>ej oblasti ok<strong>na</strong>). Pomocou editorazdrojov vložte nový zdroj menu do projektu (postupujte rov<strong>na</strong>ko ako pri vkladaní novéhodialógu). Nový zdroj <strong>na</strong>zvite IDR_MYMENU. Jeho položky vyplòte pod¾a obr. 9. Keïže ajtu platí rov<strong>na</strong>ké smerovanie príkazových správ ako v klasickom menu a ToolBare, IDpoložiek Meno a Priezvi<strong>sk</strong>o zvo¾te rov<strong>na</strong>ké ako v predchádzajúcom prípade. „Odde-¾ovaè“ (Separator, horizontál<strong>na</strong> èiara) vložíte do menu tak, že pri vkladaní novej položkymenu zaškrtnete vlastnos Separator <strong>na</strong> karte General (do po¾a Caption nemusíte niè vpisova). Pre položku About... <strong>na</strong>píšte jej ID: ID_APP_ABOUT, èo je opä rov<strong>na</strong>ké ako v prípadeklasického menu pre položku Help -> About GUI... Teraz pomocou ClassWizardupridajte zdroj IDR_MYMENU do už existujúcej triedy CMainFrame a pridajte obsluhusprávy WM_CONTEXMENU takisto do triedy CMainFrame. Kód jej obslužnej funkciezmeòte takto:void CMainFrame::OnContextMenu(CWnd* pWnd, CPoint point){CMenu MyMenu;MyMenu.LoadMenu(IDR_MYMENU);MyMenu.GetSubMenu(0)->TrackPopupMenu(TPM_CENTERALIGN | TPM_RIGHT-BUTTON, point.x, point.y, this);}Opis parametrov nosnej funkcie TrackPopupMenu nájdete v helpe. Výsledné menuvidíte <strong>na</strong> obr. 10.TIPY NA DOMA. Prepíšteaplikáciu GUI tak, aby dialógy <strong>na</strong>zadanie me<strong>na</strong> aj priezvi<strong>sk</strong>a bolinemodálne. Keï ich takto zmeníte,doprogramujte aj zaškrtnutietej položky menu, ktorej dialógbol vyvolaný. Zaškrtnutie sa robí<strong>na</strong>mapovaním správy UPDATE_COMMAND_UI pri položkách menu. V tele tejto funkciesa potom zaškrtnutie robí pomocou funkcie CCmdUI::SetCheck (podrobnejšie vhelpe). Existujú aj ïalšie funkcie, <strong>na</strong>príklad CCmdUI::E<strong>na</strong>ble, ktorá dokáže sprístupni ,resp. zneprístupni položku v menu.Pozrite sa <strong>na</strong> tieto funkcie, v praxisa dos èasto využívajú. Už ne-Obr. 10 Plávajúce pop-upmenuzostal priestor <strong>na</strong> opísanie akcelerátorov(klávesových <strong>sk</strong>ratiek).Pozrite sa <strong>na</strong> prácu s nimi, je jednoduchéich používa a aj programova (vo väèšine prípadov si vystaèíte s editoromzdrojov). Naprogramujte akcelerátory do <strong>na</strong>šej aplikácie pre <strong>na</strong>mi pridané položkymenu. Opä platí použitie rov<strong>na</strong>kých ID. Upravte StatusBar tak, aby mal tri položky.V prvej (index 0) sa bude zobrazova help k položkám menu a tlaèidlám ToolBaru, vdruhej text z dialógu meno a v tretej text z dialógu priezvi<strong>sk</strong>o. Tým opravíte prepisovanietextu dialógu meno nápoveïou a inými informáciami, ktoré aplikácia zobrazuještandardne v prvej položke.NABUDÚCE. S¾ubovanú prácu s triedou dokumentu si odložíme do budúcej èasti.Dovidenia v novembri.Marek ŠamajObr. 9Položky plávajúcehomenu10/2001 PC REVUE 125