32bit-es Free Pascal grafika VGFX-el Windows alá

Azoknak ajánlom e cikket, akik pascalban programoznak, de már megunták a beépített 16 színű, lajhár lassúságú graph.tpu-t, viszont még nem kezdtek neki a sokkal bonyolultabb OpenGL-hez. Ebben a cikkben ugyanis a 32bites FreePascal alá írt VGFX grafikával fogunk megismerkedni. Egy kis ízelítő: akármekkora felbontás (csak a monitor bírja!), 16bit színmélység, teljeskörű sprite(kép) kirakó eljárások(alpha blending, transparency-), villámgyors assembly eljárások, teljes Windows kompatibilitás...

 

Miért írok?

Énnekem, Incze Attilának, aki 15 éves tanulója a szegedi Radnóti Miklós gimnáziumnak, is meg kellett küzdenem azért, hogy szerezzek egy grafikai unitot pascal alá, ami ténylegesen jó, gyors, és nem utolsó sorban nyílt forráskódú. Több(!) hónapig kerestem a megfelelőt, mígnem rátaláltam a VGFX-re. Bár a VGFX egyszerű, de mivel nagyjából semmilyen leírás nem volt hozzá, a készítőjével (egy német egyetemistával) kellett tartanom a kapcsolatot, hogy kérdéseket tehessek fel neki, melyek segítségével mára sikerült teljesen kiismernem a VGFX-et. Azért írom e cikket, hogy másnak ne kelljen bejárnia ezt a rögös utat, ami eddig az állapotig vezetett.

 

Mi az a 32bites FreePascal?

A FreePascal a Pascal kibővített, és mint ahogy a neve is mutatja, szabadabb változata. 32bites, mivel 32bites operációs rendszer alá íródott, és mivel a 80386 alapú processzort használja, ami 32 biten dolgozik. A Windowsok a 95-től kezdve mind 32bitesek, tehát kompatibilitási problémába valószínűleg nem fogunk ütközni. A továbbiakban nem írom ki külön a 32bites jelzőt, mostantól csak egy fajta FreePascal-ról fogok beszélni. Habár a FreePascal Linux alá is tud fordítani, a VGFX-et nem tudjuk majd ott használni, mivel az a Windows-os DirectDraw módszert használja a képernyő kezelésére.

Ha érdekel a dolog, akkor olvasd tovább! Sikeres próbálkozást a VGFX-el!

 

A VGFX-ről

Mi is az a VGFX?

A VGFX egy grafikai unit FreePascal alá. Képernyőkezelési módszerként a DirectDraw-ot használja, ami Windows specialitás, ezért jó csak Windows alá. Unit, tehát saját programunkban használhatjuk fel és ahhoz hasonló eljárások találhatók benne, mint a jól megszokott sima pascal grafikában. FONTOS: Csak akkor kezdj az egésznek neki, ha a géped processzora támogatja az MMX technológiát, (ez kb. 266Mhz-től már biztos van!) ugyanis a VGFX ezt használja, hogy gyorsabb legyen. Egyébként a közvetlen képernyőre kirakó eljárás az fpcx.dll-ben van (ezt Toxic Avenger / AINC írta). Éppen ezért minden VGFX-es programunk exe-je mellé kell mellékelni ezt a dll-t.

„Honnan” van?

A VGFX-et Christian T. Magnus írta 19 évesen. A VGFX-et szabadon lehet terjeszteni és módosítani a GNU Library General Public License feltételei alapján, amiket a Free Software Foundation tett közzé. (Magyarul átírhatod, másnak is adhatod, viszont pénzes ügyletek kizárva, és ha a programot üzleti célból írod, egyeztetni kell Magnus-szal (chtm@gmx.de))

A FreePascal-ról

Ebben a részben a FreePascal néhány újítását mutatom be a mezei pascalhoz képest. Ha netán ismernéd a FreePascalt, akkor ezt átugorhatod.

Help

A www.vgfx.ini.hu -ról letöltheted a FreePascal egyik hivatalos helpjét (angol nyelvű), én most ebből a legeslegfontosabbakat emelem ki, mivel a teljes help becsomagolva 4MB!

Szintakszis

A FreePascal szintakszisa teljesen ugyanaz, mint a sima pascalé, viszont van néhány új dolog, ami szintaktikai újításnak tűnhet, viszont más vonatkoztatása is van.Pl.:

Ha egy eljárásnak, vagy egy függvénynek nincs paramétere, akkor is használhatunk zárójeleket az eljárás/függvény hívásakor (pl: ’InitWindows;’ helyett ’InitWindows();’ ). Ennek akkor van szerepe, amikor egy pl. „a” nevű függvényen belül „while a > 4”-ot írsz. Ekkor ugyanis TurboPascal rekurzívan értelmezi a dolgot, meghívja az „a” függvényt, viszont a FreePascal csak akkor értelmezi rekurzívan, ha „while a() > 4”-et írsz. Egyébként számol „a”-val (a függvény értékével) tovább, nem történik semmi különös.

Lehet eljárást/függvényt ’overload’-olni, azaz két ugyanolyan nevű eljárást csinálni, amiknek mások a paramétereik, és a program futás közben azt hívja meg, amelyikhez illeszkednek a paraméterek. FONTOS: Éppen ezért egy unit készítésekor ügyelni kell arra, hogy amit az ’interface’ résznél megadtunk eljárás deklarációt, azt szóról-szóra kell átmásolni az ’implementation’ részbe, mivel egyébként a fordító azt hiszi, egy másik eljárásról van szó.

Megjegyzést a FreePascalban 3-féleképpen is tudunk. Ez elsőt biztos ismered: ’{’, ’}’. A második a ’(*’, ’*)’. Ez a kettő ugyanúgy viselkedik. A harmadik a ’//’, amivel egy egész sort „el tudunk harapni”, azaz, ami utána van a sorban, azt a fordító nem figyeli.

Memóriakezelés

A FreePascalnak nagyon fogsz örülni a memóriakezelés terén, mivel akármekkora tömböket definiálhatsz vele (ez nem vicc, több tíz megabájtos tömböket definiálhatsz a „var” résznél, és nem kell „getmem”, meg hasonlóakat alkalmazni). Egyébként annyi memóriát használhatsz maximum, amennyi csak van (a RAM + virtuális mem, ami Win XP alatt akár a winchester egész üres területe is lehet!!!). Nem rossz mi??? Felejtsd el a 64K-os maximalizálást egy változóra nézve!

Új típusok

A FreePascalban van néhány új változó típus, az egyik ilyen a PChar, ez a stringnek a párja, csak a windowsos eljárások ezt szokták használni. Konverzió lehetséges a kettő típus között, így semmilyen problémába nem ütközhetünk használata miatt.

Források

Ez eddig mind rendben van, de honnak vegyek VGFX-et meg FreePascalt???

Beszerezhetőség

Az egész csomagot (FreePascal fordító + szerkesztő + VGFX) feltöltöttem a www.vgfx.ini.hu - ra (~6MB), onnan úgy, ahogy van letöltheted!

A kezdetek...

Kezdjük el! Ehhez a részhez eléggé szükséges a letöltött csomag (www.vgfx.ini.hu).

A struktúra

Lássuk, hogyan épül fel a letöltött csomag!

Ha megvan a FreePascal.zip csomag, azt csomagold ki egy tetszőleges könyvtárba. FONTOS: A zip-et egy olyan helyre csomagold ki, aminek az elérési útvonala nem tartalmaz ékezetet!!! A „Free Pascal 32bit” könyvtáron belül találod a Devpas.exe-t. A Dev-Pascal egy fantasztikus szerkesztő Free Pascal alá (a FreePascal önmagában nem tartalmaz szerkesztőt). Az egész környezet a Dev-Pas köré van építve, a következőben bemutatom a könyvtárszerkezetet, amit a DevPas használ:

Még egy fontos dolog: a VGFX-es „tartozékok” felsorolása, és röviden leírásuk:

Az első indítás-

Ha ezekkel megvagyunk, akkor mehetünk tovább. Indítsuk el a Devpas.exe-t. Amint látjuk a felület teljesen windowsos. Elsőnek kattintsunk az „Options”, majd azon belül a „Compiler options” menüpontra. Ami beugrik ablak, rögtön a „Directories” fülön leszünk. Itt állítsuk be a „Bin directory” részt arra az útvonalra, ahol a DevPas.exe van + ’\Bin\’ (pl: Ha a devpas.exe útvonala ’C:\Free Pascal 32bit\’, akkor ide ’C:\Free Pascal 32bit\Bin\’-t írjunk.). Ezek alapján töltsük ki az alatta lévő két helyet, csak ide a ’\Bin\’ helyett ’\Units\’-ot tegyünk hozzá. Eztán OK-ézzük le, és már nyomulhatunk is. A „File” menüben az „Open project or file” menüpontra kattintsunk rá. Itt nyissuk meg a „VGFX_Proba.pp” nevű fájlt.

Az első program

Lássuk a programot! Ez egy primitív kis szemléltető programocska, de arra pont jó, hogy segítségével könyebben ismerjük ki magunkat VGFX világában.

A program eleje a következővel kezdődik:

{$ASMMODE INTEL}
{$APPTYPE GUI}
{$MODE FPC}
{$Q-}
{$R-}
{$S-}
{$D-}

Ezek fordító direktívák, amiket minden VGFX-es programunk elejére be kell szúrni. (copy+paste). Ne kérdezd melyik miért kell, kell azt kész! Természetesen, ha kell, még szúrhatsz be közéjük mást is! Nézzük tovább:

Program   VGFX_Proba;

Uses           Windows,
                   VGFX,
                   VGFX_2D,
                   VGFX_Sprites,
                   VGFX_Text,
                   VGFX_win32,
                   VGFX_Files,
                   VGFX_Errors,
                   BigFile2,
                   SysUtils;

Az első sor elég triviális(nyilvánvaló), aztán jön a második olyan rész, amibe jobb, ha nem kötünk bele: a használt unitok, ha VGFX-es programot csinálunk, ezt úgy ahogy van másoljuk át, persze bővíthetjük is a listát.

Const         Alkalmazas_Nev  : PChar = 'VGFX próba';
                   Kep_Szelesseg                    : Longint = 800;
                   Kep_Magassag                   : Longint = 600;

Az „Alkalmazas_Nev” lesz az a szöveg, amit a programunk futásakor a tálcán, meg a feladatkezelőben (CTRL+ALT+DEL) látunk. A PChar-t már korábban említettem. Hogy ide miért PChar kell? Kicsit lejjebb majd meglátod. A „Kep_Szelesseg” meg a „Kep_Magassag” lesz a képernyő felbontása futáskor. FONTOS: Amikor majd programot írsz, figyelj rá, hogy nehogy túl nagy felbontást állíts be, mert ha a monitor nem bírja, akkor akár károsodhat is! (a 800x600-at mindegyik bírja) Menjünk tovább:

Var            Sprite01                  : VirtualWindow;
                   Sprite02                 : VirtualWindow;
                   Hatter                    : VirtualWindow;
                   Eredmeny               : VirtualWindow;

                   i                           : Integer;

A „VirtualWindow” egy type, ami a VGFX.pp-ben van definiálva. Ezt akár meg is nézheted, a VGFX.pp a Devpas könyvtárban van, a próbaprogramunkkal egy könyvtárban. Nyissuk meg, a fájl 100. soránál kezdődik a VirtualWindow type definíciója. Azért a biztonság kedvéért ide is beszúrtam:

Type           VirtualWindow = Record
                                   VWOffset                             : Longint;
                                   Size                                        : Longint;
                                   Breite                                     : Longint;
                                   BreiteMinus1                       : Longint;
                                   BreiteDiv2                            : Longint;
                                   BreiteMod2                          : Longint;
                                   ByteBreite                            : Longint;
                                   Hoehe                                   : Longint;
                                   HoeheDiv2                           : Longint;
                                   HoeheMinus1                      : Longint;
                                   Active                                   : Boolean;
                                   OptionalPath                        : String;
                   End;

Láthatjuk, hogy egy recordról van szó. A VirtualWindow a VGFX talán legfontosabb eleme, ugyanis ez egy kép a memóriában. Nézzük sorra a változókat! A „VWOffset” a kép címe a memóriában. A „Size” a memóriában elfoglalt mérete. A „Breite” német szó magyarul szélességet jelent. Ezáltal érthetővé válik a „Breite”, „BreiteMinus1”, „BreiteDiv2” és  a „BreiteMod2” változók értelme.(Az első a kép szélessége, a következő (Breite-1), azutáni pedig (Breite div 2), és az utolsó (Breite mod 2)). Ugyanezeket mondhatjuk el a „Hoehe”-s változókról, csak itt a magasság van a középpontban. Az „Active”-et soha nem kell használnunk, és az „OptionalPath”-ot sem, ezek a VGFX-re tartoznak. Bár ezek közül egy átlagos programban csak az „VWOffset”-ről és a „Breite”-ről meg a „Hoehe”-ről kell tudnunk. A VirtualWindow végülis egy kép a memóriában, és ezekkel a képekkel tudunk „műveleteket” végezni, azaz egyiket kitenni a másikra, a képernyőre, stb. Majd a továbbiakban több is kiderül róluk. Visszatérve a változók deklarációjához, mint láthatjuk 4 VirtualWindowot és egy integert deklaráltunk. Viszont most nézzük tovább a VGFX_Proba.pp-t:

Begin

    Window_RegisterClass( WIN_Normal );
    Window_Main_Handle:= Window_CreateClass( Alkalmazas_Nev, WIN_Normal );
    CheckWMCreate;

Az első sor triviális, aztán jön 3 nem mindennapi eljárás. Mint tudjuk, a letöltött FreePascal Windows alá fordít, éppen ezért itt már ne várjunk dos-os ablakokat, és lehetőség szerint „Write(x)”-et se használjunk, mivel x-et nem tudná hova kiírni szerencsétlen programunk! Viszont a „windowsosság” miatt érdemes ablakot létrehozni, hogy ne csak a feladatkezelőben lássuk, hanem a tálcán is ott legyen az alkalmazásunk. Ennek a lépéseit láthatjuk fent. Ez a 3 sor ismét csak olyan, amit nem szokás megváltoztatni. Minden programunk elejére szúrjuk be. (Természetesen az „Alkalmazas_Nev” helyett mást is használhatunk, vagy akár közvetlen a függvény paramétereként beírhatjuk annak értékét, de így stílusosabb-). És miért PChar-nak kell lennie a paraméternek? Mivel ez egy Windows Api hívás, és ezek a PChar-t részesítik előnyben a Stringgel szemben. A „Win_Normal” viszont egy windowsos konstans, amit nem illik piszkálni, ez mutatja meg a Windowsnak az alkalmazásunk típusát. Ez esetben egy átlagos, normál programról van szó (lehetne még képernyővédő, -). Menjünk hát tovább:

    Init_Graph( Kep_Szelesseg, Kep_Magassag );

    Load_Fonts( 'fonts.fnt' );

    Load_Pcx( 'image1.pcx', '', Sprite01 );
    Load_Pcx( 'image2.pcx', '', Sprite02 );

Az „Init_Graph( szelesseg, magassag: word )” eljárás hívásával juthatunk a megadott felbontású grafikus módba. Ezután betöltjük az alapértelmezett betűtípust, bár ezt nem lenne muszáj, azt csak akkor kell, hogyha használjuk az „OutText” eljárások valamelyikét. Egyébként ha majd a programodba szép betűket akarsz, akkor azokat majd képekként érdemes saját magadnak kitenned, mert ez a beépített betűtípus elég „szerény”. Ezek után betöltünk 2 pcx képet, az egyiket a sprite01-be, a másikat a sprite02-be. A Load_Pcx eljárás paraméterei a következők: elsőnek egy név, mégpedig a betöltendő fájl neve, másodiknak még egy név, de ez csak akkor aktuális, ha bigfile-ból (már említettem) töltünk be képet. Harmadiknak pedig egy inicializálatlan(később lesz róla szó) VirtualWindow-ot kell megadnunk.Ha nem bigfileból töltünk be, akkor a második paraméter helyére üres stringet írjunk(mint a példában). FONTOS: Csak 16bites pcx képeket töltsünk be, egyébként nem fog túlságosan örülni a program, ha mondjuk 32biteset próbálunk! Ajánlott szerkesztőprogram a Paint Shop Pro, mert azzal akármilyen formátumot konvertálhatunk pcx-re. Egyébként az image1.pcx-ben van a hátterünk, az image2.pcx-ben egy aranyos kis kép. Ha megértettük, menjünk tovább:

    Init_VW( Eredmeny, Kep_Szelesseg, Kep_Magassag, True );
    Init_VW( Hatter, Kep_Szelesseg, Kep_Magassag, True );

    ScaleSprite( Sprite01, Hatter );

    CursorVisible( False );

Az „Init_VW” eljárással VirtualWindowot tudunk inicializálni. Az inicializálás a VirtualWindow esetében azt jelenti, hogy feltöltjük a változók értékét, és lefoglaljuk a memóriában a szükséges helyet. Hála az égnek ezt mások már megírták, nekünk csak meg kell hívni az „Init_VW” eljárást. Ennek a paraméterei: az első az a VirtualWindow, amit inicializálni akarunk (figyeljünk oda, hogy ezt előtte még nem inizializáltuk!), a második a kívánt szélesség, aztán a magasság, a végén pedig egy boolean. Ha ezt True-ra állítjuk, akkor feketére törli az inicializált képet, ha False-ra, akkor nem csinál semmit a lefoglalt memóriaterülettel. A két VirtualWindow inicializálása után egy érdekes lépést csinálunk: A Sprite01-et átméretezzük a Hatter-be, azaz a Hatter-be kerül Sprite01, csak megfelelően nyújtva. Fontos, hogy a ScaleSprite() eljárás mindkét paraméterének inicializált VirtualWindownak kell lennie, különben nem tudná a VGFX, hogy mekkora méretűre nyújtsa a képet! Az eljárás hívására az első VirtualWindow-al nem történik semmi, a második tartalma elveszik, helyét az előbb megtárgyalt kép veszi át. A program működését tekintve ez a lépés azért fontos, hogy a kirajzoláskor a háttér megegyezzen a képernyő felbontással. Ezután egy „CursorVisible()” eljárás van, aminek egyetlenegy paramétere egy boolean kifejezés, ha True, akkor az egér láthatóvá válik, ha False, akkor elrejti az egeret. Ha ezekkel rendben vagyunk, akkor haladjunk tovább:

    i:= 100;

    Repeat

                   Flip_VW( Hatter.VWOffset, Eredmeny.VWOffset );

                   inc( i );

                   If ( i > 600 ) then i:= 100;

                   PutSprite( Eredmeny, Sprite02, i, 100 );
                   Flip_DD( Eredmeny.VWOffset );

                   GetAllMessages;
                   HandleMinimized;

    Until Not( ApplicationRunning ) or KTaste[13] or m_l;

Az első sor elég egyértelmű, ezután egy Repeat-Until ciklus következik, aminek a kilépési feltétele 3 boolean érték. Az első a Not( ApplicationRunning ). Az ApplicationRunning() egy windows beépített függvény, ami True-val tér vissza, ha fut az alkalmazásunk, False-val, ha nem. Hogyan lehetne false az értéke, mikor a programunk még fut? Úgy, hogy ha mondjuk a tálcán jobb gombbal kattintunk a programunkra, aztán meg a Bezárást választjuk, vagy Alt+F4-et nyomunk, akkor tér vissza false-val ez a függvény. Ha ezt a feltételt kihagynánk, és az előbbi módszerrel akarnánk bezárni a programot, akkor a „Program nem válaszol” felirattal lepne meg minket a windows. Nézzük a következő feltételt: KTaste[13]. A KTaste a VGFX_Win32-ben van dekralálva. Nézzük is meg:

Var            KTaste:  Array[0..256] of Boolean;

Tehát a KTaste egy 257 elemű tömb. Ez mindig akkor frissül, ha meghívjuk a GetAllMessages eljárást (később lesz róla szó). A KTaste-ben a billentyűk állapota van tárolva. A tömb index a billentyű azonosítója (pl. 13=ENTER, 32=SPACE, 27=ESC), az értéke pedig, hogy az adott billentyű le van-e nyomva vagy nem. Tehát a második feltétel, hogy le van-e nyomva ez ENTER. Ha ki, vége a ciklunak. De nézzük a harmadik feltételt! m_l, ugyancsak a GetAllMessages meghívására frissítődik, és ez egy boolean változó, akkor True, ha le van nyomva az egér bal gombja (Mouse_Left). Akár meg is nézhetjük a VGFX_Win32-ben a Var részlegen, de fölösleges. Egyébként az egérrel kapcsolatos további változók: m_r: jobb gomb, m_x: x koordináta, m_y: y koordináta, m_moved: true ha mozdult az egér a legutóbbi leolvasás óta, false ha nem; m_moved_diff: mennyit ment a legutóbbi leolvasás óta. Tehát akkor lép ki a cilusból a programunk, ha azt máshonnan bezárjuk, vagy bal gombot nyomunk, vagy leütjük az ENTER-t.Nézzük akkor mi van az ismétlődő részben! A Flip_VW() eljárás egy inicializált VirtualWindow-ot mozgat egy UGYANAKKORA méretű inicializált VirtualWindow-ba. A két paraméter közül az első a forrás, a második a cél. Mindkét paraméternek nem közvetlen a VirtualWindow-ot kell megadnunk, hanem a VirtualWindow.VWOffset-et. Ezt jól láthatjuk a példában. Ezt miért csináljuk? A Hatter-ben van tárolva a háttérképünk, , és hogy ezt ne „koszoljuk össze”, áttesszük egy minden ciklusban frissülő Eredmeny VirtualWindow-ba. Tehát eddig az Eredmeny tartalma a háttérkép önmagában. Eztán az Eredmeny-re rátesszük a Sprite02-t, amiben egy kis kép van. Ennek lépései: először növeljük az i-t, és 100-ra állítjuk, ha nagyobb 600-nál. Majd a fő lépés: PutSprite(), ennek az eljárásnak két inicializált VirtualWindow-ot, és két koordinátát(x,y) adunk meg. Itt a VirtualWindowot közvetlen adjuk meg. Elsőnek a cél VirtualWindowot kell, aztán a kirakandó képet, majd a kirakandó hely bal felső sarkának koorinátáját x, y sorrendben. Nézzük, hogy a programunkban ez hogy van. Az eredmeny-re rakjuk rá a Sprite02-t az (i, 100) pontra, azaz a kis kép a képernyőn balról jobbra fog mozogni. Azaz egyelőre csak az Eredmeny-en fog mozogni, ugyanis a képernyőre egy árva kukkot nem raktunk ki. Ezt a hiányosságot hivatott pótolni a következő parancs: Flip_DD( VirtualWindow.VWOffset: Longint ). Ennek az eljárásnak egy virtualwindow-nak a VWOffset-jét kel megadnunk, ahogy azt már korábban is láthattuk bizonyos eljárásoknál. FIGYELEM: inicializált virtualwidownak kell lennie, amit megadunk, és FONTOS, hogy a mérete megegyezzen a képernyő felbontásával, egyébként nemkívánatos hardverproblémákba ütközhetünk, amitől óvnék mindenkit. Ezzel az eljárással tehát kitettük az Eredmeny virtualwindow tartalmát a képernyőre, amin a háttér van + a kis kép. Ha ezekkel megvagyunk, akor már csak két parancs van hátra a ciklusunkból. Az egyik a GetAllMessages(), amiről már több szót is ejtettem (ez frissíti a billentyűlenyomásokat, az egeret-), és a HandleMinimized(), ami pedig a programunk minimalizására ügyel. Ezt a két eljárást érdemes minden hosszabb ideig futó ciklusba belerakni, ugyanis ez „tartja a kapcsolatot” a windows-zal. Kész is lennénk a programunk főciklusával.

    Kill_VW( Hatter );
    Kill_VW( Sprite01 );
    Kill_VW( Sprite02 );
    Kill_VW( Eredmeny );

    Kill_Graph();

    CheckMemory();

    Terminate();

Most tisztítjuk meg a memóriát azoktól a változóktól, amiket lefoglaltunk inicialáskor. Elsőnek a VirtualWindow-okat „nyírjuk ki”, sorba mindet, ezt soha ne felejtsd el, különben bennmaradnak a memben. Ezt a Kill_VW() eljárással tesszük meg, ennek paramétere egy inicializált VirtualWindow. Ezzel taz eljárással tudunk „uninicializálni” egy virtualwindow-ot. Ezután lehet újra felhasználni másra. Eztán búcsút intünk a grafikus módnak, és visszatérünk a windowsba. Majd jön még egy utasítás a programot bezáró Terminate() előtt: a CheckMemory(), ami a VGFX által lefoglalt memóriát ellenőrzi, hogy mindet felszabadítottuk-e, ha nem megteszi helyettünk egy aranyos kis „error” ablak kíséretében. Azonban ez csak a VGFX által lefoglalt memóriát ellenőrzi (pl.:VirtualWindow, -), a többiről nekünk kell gondoskodni. Ha ki akarjuk próbálni működését, töröljük ki az egyik Kill_VW() sort, és megláthatjuk! Még egy valami kimaradt:

End.

Akácsak a programnak, e havi részünknek is vége. Remélem hasznosítani tudjátok a VGFX-ről tanultakat. És ne feledjétek megnézni a Simson-programról szóló cikket, ugyanis az a program is VGFX grafikát használ, és nem is olyan rossz- A következő részben mát bonyolultabb eljárásokról is lesz szó (forgatás, alpha blending, -).

Incze Attila - atimb@freemail.hu