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 prog2@qchem52.fat.bme.hu 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