Félévközi feladatok 1. Az anidraw animációs program kiegészítése Programozás 2 2008/2009 II. Félév A program animációk futtatására szolgál. (Leírását ld. a feladatok után!) Beadandó: Windows-os program esetén a két header fájl: alak.h és program.h. valamint egy animációs program, Linux alá a teljes project, egy animációs program és a végrehajtható fájl. Mindezek ZIP formátumban a következő formájú fájl névvel: XXXX_Név_Prog2_1.ZIP Ahol XXXX a beküldő Neptun kódja, és Név a neve. Ezeket a
[email protected] címre kell elküldeni az utolsó oktatási hét végéig. FIGYELEM! Más néven, ill. formátumban küldött fájlokat tartalmazó leveleket megnézés nélkül letörlök! A feladat tökéletes megoldásával elérhető pontszám 15, pont ill. Linux alatt 22 pont. A következő részfeladatokat kell megoldani: 1. A program működésének megértése és az alak.h és program.h fájlok beli program– szöveg magyarázatokkal, megjegyzésekkel (comment-ekkel) való kiegészítése. Max 5 pont. 2. újabb alakzatok definiálása az alak.h-ban. Ezek a: NEGYZET a KOR és a PALCIKAEMBER. Próbálják meg ezeket minimális számú paraméterrel leírhatóvá tenni. Minden alakzatnak van két kötelező paramétere ezek az azonosítója (ID) és a színe, tehát csak a további paramétereket lehet szabadon megadni. Pl. a NEGYZET megadható az ID-n és a szín-en kívül az oldalhosszával, hiszen elegendő egy tengelyekkel párhuzamos oldalú négyzetet definiálni, az ugyanis elforgatható a Rotate() függvényével. A KOR-hoz pedig elég a sugara. A NEGYZET és a KOR megvalósítása 1-1 pontot ér. A PALCIKAEMBER 2 –t Teljes elérhető pontszám: 4 pont 3. Ennek megfelelően a következő új parancsokkal kell kiegészíteni a jelenlegi parancsokat: „NEGYZET”„ PALCIKAEMBER”, és „KOR”. Mindegyik helyes megvalósítása 1 pont. A KOR megvalósítható mint egy „valódi” kör, vagy mint egy N oldalú poligon. Az előbbi esetben a 6. alfeladatot is meg kell oldani, utóbbi esetben viszont Windows alatt a 6. ponttal nem kell foglalkozni. Teljes elérhető pontszám 3 pont. 4. A bool Scale(double factor) függvény megvalósítása az összes alakzatra 0,5 pont
5. A SCALE(id, faktor) parancs megvalósítása 0,5 pont 6. Windows alatt és poligonként megadott KOR alakzat esetén nem kell az itt leírtakkal foglalkozni és nem is jár pont érte! A következő két alpont közül csak az egyikét kell megoldani! a) linux alatti grafika: graphs.cpp és graphs.h megvalósítása 7 pont vagy b) „valódi” kör rajzolása (súgó:a kör egy speciális ellipszis, ha a belsejét háttérszínnel akarjuk kitölteni használni kell a CreateBrushIndirect() Windows-os függvényt) 4 pont 7. Animációs program fájl készítése. (Nem az általam adott mintapéldát beadni!) 2 pont
Az anidraw program rövid ismertetője:
I. Használata: A program animációk futtatására szolgál. Az animációk leírását a parancssorból, vagy egy animációs fájlból veszi. Az animációs fájl igen egyszerű szerkezetű alakzat definíciókat és az alakzatok transzformációit tartalmazza. Minden alakzatnak egy 0 -nál nagyobb egyedi azonosítója kell legyen. A lehetséges alakzatok: PONT(id, szín, x, y), POLIGON(id, szín, zárt-e, x1,y1, x2,y2,...), HAROMSZOG(id, szín, x1,y1, x2,y2, x3,y3), NEGYZET(id, szín, oldal) KOR(id, szín, sugar), PALCIKAEMBER(id, szín, ? ? ?) - szabadon választható A lehetséges parancsok: :cimke, JUMP(:cimke), SHOW(id), HIDE(id), MOVE(id, x, y), ROTATE(id,szög), SCALE(id,faktor) Akárhány parancs lehet egy sorban, de több sorra is szétbonthatjuk a parancsokat. Példa: Rajzoljunk fel egy piros háromszöget és egy kék kört, majd mozgassuk a háromszöget a képernyőn ciklikusan 5-ször. Ekkor a parancs fájl tartalma HAROMSZOG(1,0xFF0000, 100,100, 300,200, 300, 100) KOR(2, KEK, 100, 300, 50) Show(1) Show(2) :CIMKE MOVE(1, 100,100) MOVE(1, 150,150) MOVE(1, 200,150) MOVE(1, 250,150) MOVE(1, 300,150) JUMP(:CIMKE, 5) Mint a példából látható a parancsokat egy-vagy több betűköz, vagy soremelés választja el és a cimkét kivéve - minden parancs paramétereit zárójelben kell megadni. Alakzatok első paramétere az azonosítója, második paramétere a színe, ezt követi a többi paraméter. A színeket megadhatjuk decimálisan,
hexadecimálisan, sőt egyes esetekben nevükkel is. Ciklusokat cimkékkel és JUMP –okkal hozhatunk létre, a JUMP-ok esetében megadhatjuk az ugrások számát. Pl. a :CIMKE1 ... további parancsok 1... :CIMKE2 ... további parancsok 2... JUMP(:CIMKE2, 3) .... ... további parancsok 3... JUMP(:CIMKE1, 5) programrész szerint először a ... további parancsok 1..., utána háromszor a ... további parancsok 2..., majd a ... további parancsok 3... parancsok hajtódnak végre és ez ötször ismétlődik.
II. Program felépítés Az anidraw program teljes, Visual C++-os forrása, és ez a feladatleírás letölthető a http://www.fat.bme.hu/student oldalról. A ZIP-ben található egy olyan verzió, ami futtatni tudja az anidraw könyvtárban található prg.txt fájlt. Másoljuk be mellé és próbáljuk ki!
Az egyes fájlok: 1. alak.h Az ALAK és a belöle leszármaztatott osztályok (PONT, POLIGON, HAROMSZOG) deklarációja és definíciója. Egyaránt hasznáható Windows és Linux alatt. Ide kell belerakni az új alakzatok deklarációját és definícióját, illetve a Scale() függvényt. 2. program.h Az animációs parancsok és az animációs program osztályainak deklarációja és definíciója. Egyaránt hasznáható Windows és Linux alatt. Ide kell berakni az új alakzatok definiáló parancsait, valamint a SCALE parancsot. Az alakzatok kódjai enum ként, a parancsok illetve a színek struktúra tömbként vannak megadva. Három fajta parancs létezik: az egyik fajta létrehoz egy alakzatot, a másik fajta parancsok ezzel az alakzattal operálnak, a harmadik fajta parancsok a programciklus megvalósítása. A PARANCS osztály Feladata a parancssorból a következő parancs és paramétereinek beolvasása szintaktikus ellenörzéssel és hibakezeléssel. Csak constructort, destructort, illetve értékadás operátort tartalmaz. A constructor egy a parancs sorba mutató mutatót vár, onnan veszi ki a parancs leírását. Az objektum létrehozása mellett mellékhatásként a kapott mutatót a feldogozott parancs utánra állítja, ahonnan a következő parancsot olvashatjuk be. A PROGRAM osztály felelős a parancsok listájának létrehozásáért és azok futtatásáért. Constructor-a teljes program szövegére mutató mutatót vár és ezzel létrehozza a parancsok listáját (tömbjét). Run() függvénye végigmegy a parancsok listáján és a) alakzat definiáló parancsok esetén létrehozza a megfelelő alakzatot
amennyiben az még nem létezett, b) a :CIMKE parancsra nem csinál semmit, míg a JUMP parancsra megkeresi a megfelelő cimkét és az utántól folytatja a parancsok végrehajtását c) Minden egyéb esetben meghívja az adott ID-jű alakzat megfelelő függvényét Paint() függvénye végigmegy a parancsok listáján és az éppen látható alakzatokat megkéri rajzolják ki magukat. Erre a függvényre olyan ablakkezelő rendszereken (pl. Windows, XWindow) van szükség, amelyek nem jegyzik meg az ablakok tartalmát (pl. amikor egy másik ablak egészében, vagy részben elfedi a vizsgált ablakot), hanem amikor az eltakart részek újra láthatóvá válnak (pl. a felső ablakot becsuktuk) újra kirajzoltatják az ablak tartalmát. 3. graphs.cpp és graphs.h A megjelenítéshez szükséges grafikus rendszertől (Windows, XWindow, ASCII-grafika) függő fájl Windows-os grafikai megvalósítása. A megjelenítés teljesen le van választva a program többi részéről, amelyek a rajzolást az ezekben a fájlokban definiált GRAFIKA osztály segítségével végzik. Vagyis e két fájl lecserélésével a program bármilyen grafikus megjelenítéssel és operációs rendszer alatt működik. Funkciói: grafika inicializálás, színbeállítások, rajzolás és törlés. 4. anidraw.cpp Csak Windows alatt működő keret program. Linux, stb alá meg kellene írni. Ebben az esetben szinte változtatás nélkül átvehető a bool DoReadProgram(HWND hWnd, const char *name) függvény, ill. az ezt használó programrészletek. A program működése: ( a Windows-os sallangok nélkül) a) parancssor, vagy parancsfájl beolvasása. Fájl olvasás esetén a sorokat elválasztó CR (13) és LF (10) karakterek betűközökre kell lecserélni! b) PROGRAM osztály létrehozása c) PROGRAM futatása, ill. amikor szükséges minden alakzat újra rajzolása A Windows specifikus programrészek a hagyományos Windows programozás útját követik. Az újabb toolkit-ek és könyvtárak az itt használt dolgok nagy részét elrejtik a szemünk elől, de valójában azok is ezeket használják. Minden Windows-os program a WinMain() függvénnyel kezdődik. Ennek fő feladatai: az alkalmazás (program) fő ablak osztályának regisztrálása. A regisztrálás lényege az, hogy megmondjuk a létrehozandó ablak paramátereit és megadjuk azt a fügvényt ( Windows Procedure – amit a mi esetünkben WndProc()-nak hívnak, de bármi lehetne a neve), amit a Windows meghív minden egyes alkalommal, amikor valamilyen esemény (pl. egér mozgás, gomb megnyomás, időzítés, ablak tartalom kirajzolási igény) bekövetkezik. Ezt úgy mondjuk, hogy a Windows egy üzenetet küld az ablaknak.
A fő ablak létrehozása. Az egyes ablakokat a RegisterClass() függvény hívása után a CreateWindow() függvénnyel hozzuk létre, a ShowWindow() függvénnyel jelenítjük meg és tartalmát az UpdateWindow() függvénnyel rajzoltatjuk ki. A Windows egy alapvetően ojektum orientált rendszer, és már az előtt is az volt, mielőtt az objektum orientált programozási nyelvek elterjedtek volna. Így a CreateWindow() csak egy ablak azonosítót (HWND – WiNDow Handle) add vissza, az ablak osztály tulajdonságai el vannak rejtve előlünk.
Az ablak üzeneteinek lekezelése A fő üzenet kezelési ciklus: while (GetMessage(&msg, NULL, 0, 0)) { if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } }
Ez minden Windows-os programban ugyanaz, ezért alapvetően érthetetlen miért kell láthatónak lennie a programozó számára. A GetMessage() függvény megnézi érkezett-e üzenet a Windowstól a programunk számára. Amennyiben a fő ablakot pl. a felhasználó bezárja (és az erről szóló WM_CLOSE üzenetre az ablak engedélyezéssel válaszol) ez a függvény 0-val tér vissza és a programunk kilép. Minden más esetben megnézi a TranslateAccelerator() függvény, hogy nem egy – az anidraw.rc fájlban definiált - gyorsító billentyűkombinációt (pl. az Open menűnél általában ez a Ctrl+O gombkombináció) nyomtunk-e be. Amennyiben igen, akkor ez a függvény azonnal lekezelteti ezt az ablak WndProc függvényével és nem 0 értékkel tér vissza. Ellenkező esetben a TranslateMessage() átalakítja az ún. virtuális gombok kódjait valódi karakter kódokra, majd meghívjuk a DispatchMessage(&msg) függvényt, ami az üzenetet elküldi a WndProc-nak. Az alkalmazás által létrehozott egyes ablakok mindegyike saját Windows Procedure-rel rendelkezik. Ezek 4 paramétert várnak: • az aktuális ablak objektum handle jét (azonosítóját). Ez a C++ beli this mutatónak felel meg. Így az ugyanazon osztályba tartozó – tehát ugyanazzal a WndProc-cal rendelkező - ablakok mindegyike tudja magáról ő melyik. • Az üzenet kódját. Ezek általában szimbolikus, a windos.h ban definiált konstansok. Nevük WM_ –al kezdődik. Pl. WM_PAINT – ablak újrarajzolás, WM_COMMAND – menű parancsok. • Az üzenet két paraméterét. Ezek egyike, lParam egy long, a másik wParam egy word A WndProc-on belül belül hagyományosan egy switch() konstrukció gondoskodik az egyes üzenetek lekezeléséről. Ez az a hely, ahol - a WM_PAINT üzenet esetén meghívjuk a PROGRAM Paint() függvényét, egy BeginPaint() - EndPaint() pár közé illesztve. - WM_COMMAND üzenet esetén meghívjuk a megfelelő menű lekezelő függvényt. 5. anidraw.rc A dialógus ablakok, menük és gombok leírása. Csak Windows alá. 6. stdafx.h, stdafx.cpp, stb Microsoft Visual Studio specifikus segédfájlok.
2. Saját HTML oldal készítése Az oldal szerkezetét a html, kinézetét egy CSS fájl mondja meg. Javascript használata engedélyezett.
• • •
3 hasáb: bal oldalt menü, középen a tartalom, jobb oldalt más oldalakra mutató linkek, érdekességek, hírek Legyen rajta kép A linkek ne legyenek aláhúzva, csak, ha föléjük visszük az egeret
A pontozás: 1. Három oszlopos megjelenítés 2 pont 2. Működő saját linkek bal oldalon 2 pont 3. Működő külső linkek jobb oldalon 2 pont 4. Képek 2 pont 5. CSS használata minden elem megjelenítéséhez 3 pont 6. A linkek csak akkor hűzódjanak alá, ha az egérmutató felettük van 2 pont 7. Oldal kinézete 2 pont Összesen: 15. pont