P R O G R A M U J E M EPrvá z vlastností predstavuje udalos, ku ktorej nikdy nedôjde, a druhá obsahuje uda−los, ktorá je vyvolávaná neustále.Toto teda boli základné funkcie a vlastnosti z triedy DAStatics, ktoré budeme pouíva <strong>na</strong>definovanie rôznych druhov vyvolávaných udalostí. Samozrejme, pre úplný preh¾ad a monosvyuívania funkcie lib.Predicate(bool) sa budeme venova aj triede DABoolean. Následne saešte raz pozrieme <strong>na</strong> tzv. Picking (definovanie a obsluha udalostí súvisiacich s výberom, resp.kliknutím <strong>na</strong> objekt), ktorý sme si priblíili v jednej z predchádzajúcich èastí.Ešte predtým si však zatrieïme predchádzajúce funkcie pod¾a toho, aký druh udalostidefinujú.1. Výroky (Predicates). Sú to èasovo závislé logické vyjadrenia (v prostredí DirectAni−mation ide o objekty DABoolean) konvertované <strong>na</strong> udalos. Tieto udalosti sú vyvolané vmomente zmeny logického vyjadrenia z hodnoty FALSE <strong>na</strong> hodnotu TRUE. Na definova−nie takýchto udalostí budeme pouíva práve funkciu lib.Predicate(bool). Jednoduchúudalos zadefinujeme <strong>na</strong>pr. takto:booleanVar = lib.LT(hodnota1, hodnota2);udalost1 = lib.Predicate(booleanVar);Pouitá funkcia lib.LT() je jed<strong>na</strong> z funkcií triedy DAStatics relevantných k triedeDANumber, ktorá u bola ve¾akrát spomí<strong>na</strong>ná, ale <strong>do</strong>posia¾ sme sa jej nevenovali. Tátofunkcia vracia hodnotu typu DABoolean. Vrátená hodnota je TRUE, pokia¾ platí vzahhodnota1 < hodnota2. V opaènom prípade bude vrátená hodnota, a teda <strong>na</strong>ša premen−ná booleanVar obsahova FALSE. Na základe druhého riadka zápisu, pokia¾ bude tentovzah plati, dôjde k udalosti udalos1.2. Vstavané udalosti (Built−in Events). Ide o udalosti vyvolané pouívate¾om, ako klik−nutie, stlaèenie tlaèidla a výber objektu (Picking). Udalos vyvolanú kliknutím tlaèidla mô−eme definova <strong>na</strong>príklad aj <strong>na</strong>sledujúcim zápisom:udalost2 = lib.LeftButtonDown;Existuje aj iný spôsob definovania tejto udalosti, ktorú si ukáeme pri opise triedyDABoolean.3. Èasové udalosti, ktoré sú vyvolané po uplynutí stanoveného èasu. Ak chceme, aby<strong>do</strong>šlo k vyvolaniu udalosti <strong>na</strong>pr. po desiatich sekundách, pouijeme tento zápis:udalost3 = lib.Timer(10);4. Zloené udalosti. Vo všeobecnosti ide o udalosti pozostávajúce, resp. zloené ziných udalostí. Napríklad pomocou funkcií lib.AndEvent(), lib.OrEvent a lib.NotEvent()jednoducho vytvoríme konjunkciu, disjunkciu a negáciu z pôvodných udalostí.Zápisomudalost4 = lib.OrEvent(udalost1, udalost3);zadefinujeme novú udalos udalos4, ktorá <strong>na</strong>stane v prípade, e <strong>na</strong>stala aspoò jed<strong>na</strong> zudalostí udalos1, udalos3.TRIEDA DABOOLEAN. Objekty triedy DABoolean obsahujú logickú (booleovskú) hod−notu TRUE alebo FALSE. Jediná funkcia z tejto triedy je funkcia:DABooleanObj.Extract,ktorá „vytiahne“ hodnotu z objektu triedy DABoolean a vráti hodnotu typu boolean. V tomtoprípade však objekt DABoolean musí by statický, teda jeho hodnota sa nesmie meni.FUNKCIE A VLASTNOSTI RELEVANTNÉ K TRIEDE DABOOLEAN. K základ−ným vlastnostiam z triedy DAStatics patria:lib.DAFalse,lib.DATrue.Ide o read−only vlastnosti vracajúce objekt triedy DABoolean s hodnotou FALSE, resp.TRUE.Vlastnostilib.LeftButtonState,lib.RightButtonStatevracajú hodnotu TRUE, pokia¾ je stlaèené ¾avé, resp. pravé tlaèidlo <strong>na</strong> myši. V opaènomprípade vracajú hodnotu FALSE (resp. objekt triedy DABoolean s hodnotou FALSE).Tieto vlastnosti môeme poui <strong>na</strong>pr. <strong>na</strong> definovanie udalostí vyvolaných pouívate−¾om takto:udalost1 = lib.Predicate(lib.LeftButtonState);Tento spôsob je však zloitejší oproti pouitiu vlastnosti relevantnej k triede DAEventlib.LeftButtonDown.Po<strong>do</strong>bne môeme zisova stlaèenie niektorého z klávesov. Pouijeme <strong>na</strong> to funkciulib.KeyState(KeyCode).Funkcia vráti objekt triedy DABoolean s hodnotou TRUE, ak bol stlaèený príslušný klá−ves pod¾a KeyCode. Hodnoty KeyCode boli uvedené pri opise triedy DAEvent. Udalos vy−volanú v momente stlaèenia klávesu ESC zadefinujeme <strong>na</strong>sledujúcim zápisom v JScripte:udalost2 = lib.Predicate(lib.KeyState(27));Ak budeme chcie konvertova hodnotu typu boolean z funkcie JScriptu, resp. proce−dúry VBScriptu <strong>na</strong> zodpovedajúci objekt typu DABoolean, máme k dispozícii funkciulib.DABoolean(bool).Parameter bool je premenná typu boolean pouívaná spomí<strong>na</strong>nými skriptovacími ja−zykmi. S logickými hodnotami typu DABoolean môeme vykonáva základné logické operá−cie ako s jej ekvivalentmi typu boolean. Ide o funkcie:lib.And(b1, b2),lib.Or(b1, b2),lib.Not(b).Sú to známe funkcie logickej konjunkcie, disjunkcie a negácie. Parametre b, b1 a b2sú objekty triedy DABoolean.OBSLUHA UDALOSTÍ. Teraz u poznáme triedy DAEvent a DABoolean, a teda <strong>do</strong>ká−eme definova celý rad udalostí vyvolaných pouívate¾om v závislosti od èasu alebo stavuobjektu DABoolean.Definovanie udalostí je jed<strong>na</strong> vec, ich obsluha druhá vec. Na zaèiatku tejto èasti, keïsom hovoril o reaktívnych a nereaktívnych objektoch, spomenul som, e ide o tzv. objek−ty správania sa (behaviors). Akýko¾vek objekt, ktorý vytvoríme, èi u ide o objekt DAImage,DAString, DATransform2, DAColor, DABoolean, alebo iné, je objektom správania sa (be−havior). Predstavme si nejakú triedu, ktorá je <strong>na</strong> vrchole hierarchie a z nej sú potom odvode−né a rozšírené ostatné triedy. Tá trieda <strong>na</strong> vrchole je trieda DABehavior a ostatné triedy, akoDAImage, DAString a iné, sú potom triedy odvodené od triedy DABehavior. Samozrejme, preprogramátorov v objektovo orientovaných jazykoch, ako C++ a Java, je jasné, e ide o základ−nú vlastnos týchto jazykov, ktorou je dediènos, a e k týmto objektom môeme pristupovaako k objektom príslušnej odvodenej triedy i ako k objektom rodièovskej triedy DABehavior.Pre tých ostatných postaèí, ak si zapamätajú, e funkcie a vlastnosti triedy DABehavior savzahujú aj <strong>na</strong> objekty ostatných odvodených tried, ako DAImage, DAString, DATransform2 ainé, a e ak je parametrom nejakej funkcie objekt triedy DABehavior, z<strong>na</strong>mená to, e nímmôe by aj objekt ostatných menovaných odvodených tried.Zákla<strong>do</strong>m pre obsluhu udalostí sú funkcie relevantné k triede DABehavior, a to kon−krétne funkcie lib.Until(a, e, b) a lib.UntilEx(a, e).Tieto funkcie budeme pouíva <strong>na</strong> vytváranie reaktívnych objektov. Funkcia lib.Until()vracia objekt (behavior) pod¾a parametra a <strong>do</strong>vtedy, kým ne<strong>na</strong>stane udalos pod¾a para−metra e. Po vyvolaní udalosti e funkcia vracia behavior uvedený ako parameter b.Ukáeme si, ako vytvoríme reaktívny behavior triedy DAImage, ktorý zmení farbu zcolor1 <strong>na</strong> color2, ak <strong>na</strong>stane udalos, ktorou bude uplynutie t sekúnd.behavior1 = lib.SolidColorImage(color1);behavior2 = lib.SolidColorImage(color2);tEvent = lib.Timer(t);reactBehavior = lib.Until(behavior1, tEvent, behavior2);V tomto zápise sme vytvorili dva objekty triedy DAImage, behavior1 a behavior2. Reaktívnyobjekt triedy DABehavior, resp. triedy DAImage postupne predstavoval jeden z týchto objek−tov. Samozrejme, týmto sme ne<strong>do</strong>siahli presne to, èo sme chceli, teda objekt triedy DAImagenemenil farbu, ale menil sa jeden objekt za druhý. Pozrime sa <strong>na</strong> tento zápis.tEvent = lib.Timer(t);reactBehavior = lib.Until(color1, tEvent, color2);behavior1 = lib.SolidColorImage(reactBehavior);Teraz je všetko, ako má by. Behavior1 je objekt triedy DAImage, ktorý mení farbu zcolor1 <strong>na</strong> color2. Týmto som chcel ukáza hlavne tým, ktorým pojem dediènos tried ve¾anehovorí, e za objekt triedy DABehavior (v <strong>na</strong>šom prípade reactBehavior) sa povauje ajakýko¾vek objekt odvodenej triedy.Teraz by vás asi zaujímalo, ktoré triedy, ktorými sme sa zaoberali <strong>do</strong>teraz, sú odvode−né od triedy DABehavior. Tu je ich kompletný zoz<strong>na</strong>m aj s tými, ktoré ešte nepoznáte.Tab. è. 2 Triedy odvodené od triedy DABehaviorDAArray DABox2 DABox3 DABooleanDACamera DAColor DADashStyle DAEndStyleDAGeometry DAImage DAJoinStyle DALineStyleDAMatte DAMicrophone DAMontage DANumberDAPath2 DAPoint2 DAPoint3 DASoundDAString DATransform2 DATransform3 DATupleDAUserData DAVector2 DAVector3Nabudúce budeme s reaktívnymi objektmi pokraèova. Ukáeme si zopár jednodu−chých príkla<strong>do</strong>v s jednotlivými druhmi vyvolávaných udalostí. Takisto sa blišie pozrieme<strong>na</strong> triedu DABehavior.Andrej Luchava7/2003 PC REVUE 117
P R O G R A M U J E M EWin<strong>do</strong>ws API / 4. èas: Basic ElementsV tejto èasti sa pozrieme <strong>na</strong> základné elementy vo WTL, s ktorými sa v oblasti GUI bude−te stretáva zrejme <strong>na</strong>jèastejšie. Ide o commandbar, toolbar, rebar a statusbar. Keïe<strong>do</strong> pre<strong>do</strong>šlej èasti sa mi u nezmestil praktický príklad, nájdete ho <strong>na</strong> <strong>na</strong>sledujúcichriadkoch. Zdrojové kódy k tejto èasti nájdete <strong>na</strong> stránke <strong>www</strong>.pcrevue.sk v sekcii Prog−ramujeme.MINMAX WINDOW. Niekedy je potrebné obmedzi minimálne a maximálne zväèšu−júcu sa ve¾kos ok<strong>na</strong> a aj pozíciu a ve¾kos maximalizovaného ok<strong>na</strong>. Riešenie je pomernejednoduché a mono ho zrealizova spracovaním správy WM_GETMINMAXINFO a zme−nou štruktúry MINMAXINFO.Správa WM_GETMINMAXINFO je poslaná oknu, keï sa zmení jeho ve¾kos alebo pozí−cia. Aplikácia môe poui túto správu <strong>na</strong> anulovanie štandardnej maximalizovanej ve¾−kosti a pozície ok<strong>na</strong> alebo štandardnej, minimálne a maximálne sa zväèšujúcej ve¾kosti ok<strong>na</strong>.WM_GETMINMAXINFOlpmmi = (LPMINMAXINFO) lParam; // address of structurelpmmi – hodnota lParam. Ukazovate¾ <strong>na</strong> štruktúru MINMAXINFO, ktorá obsahuje štan−dardnú maximálnu pozíciu a rozmery a štandardnú minimálne a maximálne zväèšujúcusa ve¾kos ok<strong>na</strong>. Aplikácia môe anulova štandardné <strong>na</strong>stavenia èlenov tejto štruktúry.typedef struct tagMINMAXINFO { // mmiPOINT ptReserved;POINT ptMaxSize;POINT ptMaxPosition;POINT ptMinTrackSize;POINT ptMaxTrackSize;} MINMAXINFO;ptReserved – rezervované; nepouíva sa.ptMaxSize – urèuje maximálnu šírku (point.x) a maximálnu výšku (point.y) ok<strong>na</strong>.ptMaxPosition – urèuje pozíciu ¾avej strany maximalizovaného ok<strong>na</strong> (point.x) a pozíciuvrchnej èasti maximalizovaného ok<strong>na</strong> (point.y).ptMinTrackSize – urèuje minimálnu, zmenšujúcu sa šírku (point.x) a minimálnu,zmenšujúcu sa výšku (point.y) ok<strong>na</strong>.ptMaxTrackSize – urèuje maximálnu, zväèšujúcu sa šírku (point.x) a maximálnu, zväèšu−júcu sa výšku (point.y) ok<strong>na</strong>.V <strong>na</strong>šom príklade spracujeme správu WM_GETMINMAXINFO takto:LRESULT CMainFrame::OnMinMaxWin<strong>do</strong>w(UINT uMsg, WPARAM wParam, LPARAMlParam, BOOL& bHandled){ LPMINMAXINFO minmax;switch ( uMsg ){case WM_GETMINMAXINFO:minmax = (LPMINMAXINFO) lParam;minmax−>ptMaxSize.x = 500;minmax−>ptMaxSize.y = 500;minmax−>ptMaxPosition.x = 200;minmax−>ptMaxPosition.y = 200;minmax−>ptMaxTrackSize.x = 500;minmax−>ptMaxTrackSize.y = 500;minmax−>ptMinTrackSize.x = 310;minmax−>ptMinTrackSize.y = 220;break;}if (IsWin<strong>do</strong>wVisible()) {RECT r;GetWin<strong>do</strong>wRect(&r);CString str;str.Format("position.x=%i, position.y=%i, width=%i,height=%i",r.left, r.top, r.right−r.left, r.bottom−r.top);m_wndStatusBar.SetPaneText(ID_DEFAULT_PANE, str);}return DefWin<strong>do</strong>wProc(uMsg, wParam, lParam);}Obr. 1 Spracovanie správyWM_GETMINMAXINFONa obrázku 1 môete vidie spraco−vanie správy WM_GETMINMAXINFO.Minimál<strong>na</strong> ve¾kos ok<strong>na</strong> je ve¾kos, zaktorú u nie je moné dané okno zmen−ši (pozri ptMinTrackSize.x a ptMinTrack−Size.y). Naopak, maximál<strong>na</strong> ve¾kos ok<strong>na</strong>je ve¾kos, za ktorú u nie je monédané okno zväèši (pozri ptMaxTrackSi−ze.x a ptMaxTrackSize.y). Do tohto prí−kladu som zapracoval aj zobrazovaniepozície a ve¾kosti ok<strong>na</strong>. Tieto informá−cie sa vypisujú <strong>do</strong> tzv. stavového riad−ka aplikácie (angl. StatusBar). Keïeo òom budeme hovori v nie−ktorej z <strong>na</strong>sledujúcich èastí,nebudem to tu teraz zvláš vy−svet¾ova. Samozrejme, niè vámnebráni preskúma kód týkajúcisa vypisovania údajov o okne<strong>do</strong> tohto ovládacieho prvku. Kódpre výpis údajov som umiestnil<strong>do</strong> funkcie <strong>na</strong> spracovanie sprá−vy WM_GETMINMAXINFO z to−ho dôvodu, e táto funkcia saObr. 2 Základné elementy WTLvykoná vdy, keï okno zmenísvoju pozíciu alebo ve¾kos. Musíme však myslie <strong>na</strong> to, e informácie o pozícii a ve¾kostiok<strong>na</strong> sa môu zobrazi, a keï je okno vidite¾né. To <strong>do</strong>siahneme pomocou funkcieIsWin<strong>do</strong>wVisible(). Keby sme tak neurobili, dôjde k chybe.BASIC ELEMENTS. Ako som u v úvode spomenul, základnými GUI prvkami vo WTLsú CommandBar, ToolBar, ReBar a StatusBar (pozri obrázok 2). Všetky tieto prvky sa dajúpomocou ATL/WTL AppWizarda prida <strong>do</strong> vašej aplikácie (pozri prvú èas – PCR è. 4/2003– obrázok 4). CommandBar vyzerá rov<strong>na</strong>ko ako menu Win<strong>do</strong>ws s bitmapovými obrázka−mi pri jednotlivých polokách. Pouitie triedy CCommandBarCtrl vo vašom WM_CREATEmôe by takéto:LRESULT CMainFrame::OnCreate(UINT, WPARAM, LPARAM, BOOL&){// m_CmdBar is of type CCommandBarCtrl, defined in AtlCtrlw.hHWND hWndCmdBar = m_CmdBar.Create(m_hWnd, rcDefault,0, ATL_SIMPLE_CMDBAR_PANE_STYLE);// Let command bar replace the current menum_CmdBar.AttachMenu(GetMenu());m_CmdBar.LoadImages(IDR_MAINFRAME);SetMenu(NULL);// First create a simple toolbarHWND hWndToolBar = CreateSimpleToolBarCtrl(m_hWnd,IDR_MAINFRAME,FALSE,ATL_SIMPLE_TOOLBAR_PANE_STYLE);// Set m_hWndToolBar memberCreateSimpleReBar(ATL_SIMPLE_REBAR_NOBORDER_STYLE);// Add a band to the rebar represented by m_hWndToolBarAddSimpleReBarBand(hWndCmdBar);// Add another band to the m_hWndToolBar rebarAddSimpleReBarBand(hWndToolBar, NULL, TRUE);// Create the usual statusbarCreateSimpleStatusBar();return 0;}CCommandBarCtrl je trieda WTL, ktorá zapuzdruje funkcio<strong>na</strong>litu komponentu Com−mandBar. Trieda CCommandBarCtrl dedí z <strong>na</strong>dradenej triedy CCommandBarCtrlImpl. K dis−pozícii máte <strong>na</strong>sledujúci zoz<strong>na</strong>m metód:CCOMMANDBARCTRLIMPL METHODSpublic:CCommandBarCtrlImpl() //constructor~CCommandBarCtrlImpl() //destructor AtribútyDWORD GetCommandBarExtendedStyle() constDWORD SetCommandBarExtendedStyle(DWORD dwExtendedStyle, DWORD dwMask = 0)CMenuHandle GetMenu() constCOLORREF GetImageMaskColor() constCOLORREF SetImageMaskColor(COLORREF clrMask)bool GetImagesVisible() constbool SetImagesVisible(bool bVisible)void GetImageSize(SIZE& size) constbool SetImageSize(SIZE& size)HWND GetCmdBar() const MetódyHWND Create(HWND hWndParent, RECT& rcPos, LPCTSTR szWin<strong>do</strong>wName = NULL,DWORD dwStyle = 0, DWORD dwExStyle = 0,UINT nID = 0, LPVOID lpCreateParam = NULL)BOOL AttachToWin<strong>do</strong>w(HWND hWnd)BOOL LoadMenu(_U_STRINGorID menu)BOOL AttachMenu(HMENU hMenu)BOOL LoadImages(_U_STRINGorID image)BOOL LoadMappedImages(UINT nIDImage, UINT nFlags = 0, LPCOLORMAP lpColorMap =NULL, int nMapSize = 0)BOOL _LoadImagesHelper(_U_STRINGorID image, bool bMapped, UINT nFlags = 0, LPCO−LORMAP lpColorMap = NULL, int nMapSize = 0)BOOL AddBitmap(_U_STRINGorID bitmap, int nCommandID)BOOL AddBitmap(HBITMAP hBitmap, UINT nCommandID)BOOL AddIcon(HICON hIcon, UINT nCommandID)BOOL ReplaceBitmap(_U_STRINGorID bitmap, int nCommandID)118 PC REVUE 7/2003