A grafikai programozást ma már nagyban leegyszerűsítik a rendelkezésre álló eszközök. Elvárjuk, hogy egy kép formra rajzolásának egyszerű és biztonságos megoldása legyen. A Delphiben a VCL (Visual Component Library) ebben nyújt segítséget előre elkészített komponensek segítségével. Nézzünk meg néhány ilyen komponenst, mielőtt elkezdenénk a példákat.
A Shape komponenssel (Tool palette – Additional - TShape) egyszerű alakzatokat jeleníthetünk meg. Használata könnyű, csak rá kell tenni a formra és megváltoztatni a Brush, Pen és Shape értékeket. A Shape beállításával lehet kört, ellipszist, téglalapot és lekerekített sarkú téglalapot rajzolni. A Brush a háttérszínt, a Pen pedig a határoló vonal szélességét és színét határozza meg.
Az Image komponens képek megjelenítésére használható. Ez a komponens hasznos számos grafikus feladat megoldásában, mint például háttérképek beállítása. A TImage osztály Picture tulajdonsága egy példánya a TPicure osztálynak. A megjeleníteni kívánt képet beállíthatjuk az Object Inspector segítségével a tervezés alatt, de természetesen megadható futási időben is. Például:
A Strech tulajdonság igazra állításával mindig a teljes képet láthatjuk a komponens méretétől függetlenül. A Center tulajdonság mindig a kép közepét jeleníti meg a komponensben, az AutoSize-zal pedig a komponenst igazíthatjuk a kép méretéhez.
Végül nézzük a PaintBox komponenst. Ha csak egy bizonyos részre akarunk rajzolni, megadhatunk vele egy célterületet. Ebből adódóan a legfontosabb tulajdonsága a PaintBox komponensnek a Canvas (vászon). Ez a tulajdonság a TCanvas osztály egy példánya. A TCanvas osztály nélkülözhetetlen a Delphi VCL grafikában, ezért most vizsgáljuk meg közelebbről.
A Windows az eszközkörnyezet kifejezést használja a vászonra, amire rajzolunk. Egy eszközkörnyezettel számos felületre rajzolhatunk, például:
· egy ablak kliens területére vagy egy frame-re
· az asztalra
· a memóriába
· a nyomtatóra vagy más kimeneti eszközre
Természetesen léteznek egyéb eszközkörnyezetek is (például menük), de a felsoroltak azok, amikkel a legtöbbször foglalkozunk.
Az API szintjén használni egy eszközkörnyezetet kissé bonyolult lehet. Hiszen először meg kell tanulni, hogyan érhetjük el a Windowsból, majd különböző objektumokat kell hozzárendelnünk (toll (pen), ecset (brush), betű (font)), és csak ezután kezdhetünk neki a rajzolásnak. Ha befejeztük, az eszközkörnyezet törlése előtt fel kell szabadítanunk minden hozzárendelt objektumot, különben azok bennmaradnak a memóriában.
Szerencsére a VCL biztosítja számunkra a TCanvas osztályt, ami kapcsolatot teremt helyettünk az eszközkörnyezettel. Nézzünk egy rövid példát. A következő kód a Windows API-t használja egy piros belsejű, kék szélű kör megrajzolásához:
Ez a kód ugyan nem olyan vészes, de még így is elfelejthetjük felszabadítani valamelyik objektumot, ha figyelmetlenek vagyunk. Most nézzük meg ugyanezt VCL-lel:
Nemcsak rövidebb és olvashatóbb lett a kód, hanem sokkal robosztusabb is. A TCanvas osztály felszabadítja a már nem használt erőforrásokat, így azzal nekünk már nem kell foglalkozni. Ez a módszer egyszerűbb és hatékonyabb, mint az API használata.
A TCanvas osztály sok tulajdonsággal (property) és eljárással rendelkezik. Nézzük meg röviden ezek mire valók:
tulajdonság |
Leírás |
Brush |
Az ecsetszín vagy minta, amit a területek kitöltésére használunk. |
ClipRect |
A canvas jelenlegi vágó téglalapja. Csak ebbe a téglalapba lehet rajzolni. |
CopyMode |
Meghatározza a rajzolás módját (normál, inverz, xor stb.). |
Font |
A canvas ezzel a betűvel rajzol. |
Handle |
A canvas leíró tulajdonság. Ezt használjuk a Windows API direkt hívásához. |
Pen |
Meghatározza a rajzolandó vonalak stílusát és színét. |
PenPos |
A rajzolás pozíciója x és y koordinátával. |
Pixels |
Egy tömb a canvas pixeleiből. |
eljárások |
Leírás |
Arc |
A jelenlegi tollal ívet rajzolhatunk. |
BrushCopy |
Megjelenít egy képet áttetsző háttérrel. |
CopyRect |
Egy képrészletet másol a megadott helyre. |
Draw |
A memóriából a megadott helyre másol egy képet. |
Ellipse |
Ellipszis a jelenlegi tollal és ecsettel. |
FloodFill |
Kitölt egy területet az ecsettel. |
LineTo |
A jelenlegi pozícióból húz egy vonalat a megadott koordinátába. |
MoveTo |
Beállítja a jelenlegi rajzpozíciót. |
Pie |
Körszeletet rajzol. |
Polygon |
Kitöltött sokszög rajzolása egy koordináta tömbből. |
Polyline |
Vonal rajzolása egy koordináta tömbből. |
Rectangle |
Kitöltött téglalap. |
RoundRect |
Kitöltött, lekerekített sarkú téglalap. |
StretchDraw |
Kép másolása a memóriából a megadott helyre. A kép az eredeti méretétől függetlenül ki fogja tölteni a cél téglalapot. |
TextExtent |
Visszaadja a paraméterben megadott szöveg méretét pixelben. Az érték számításakor mindig a jelenlegi Font beállítást használja. |
TextWidth |
Visszaadja a paraméterben megadott szöveg szélességét, magasságát pixelben. Az érték számításakor mindig a jelenlegi Font beállítást használja. |
TextOut |
A jelenlegi betűvel szöveget rajzol a meghatározott helyre. |
TextRect |
Szöveget rajzol egy megadott téglalapon belülre. |
Természetesen a most felsorolt tulajdonságok és eljárások a lehetőségek csak kis részét érintik, de az esetek többségében ezek elegendőek a problémánk megoldására. Mielőtt mélyebben megnézzük TCanvas osztályt, először foglalkozzunk a Windows programozásban használatos grafikus objektumokkal.
A Windows Grafikus Eszköz Interfész (Graphics Device Interface - GDI) olyan objektumokat tartalmaz, melyek ismerik a különböző eszközkörnyezetek működését. A legismertebb GDI objektumok a tollak, ecsetek és betűk, de ide tartoznak a paletták, bitképek és területek (region) is.
Nézzük meg ezen objektumok működését részletesebben.
A toll egy olyan objektum, mellyel vonalat rajzolhatunk. Ez lehet egyszerű vonal, mely két pontot köt össze, vagy téglalapok, ellipszisek, sokszögek széle. A toll a TCanvas osztály Pen tulajdonságán keresztül érhető el. Nézzük a fontosabb tulajdonságait.
tulajdonság |
Leírás |
Color |
A vonal színe. |
Handle |
A toll leíró tulajdonsága (HPEN). A GDI közvetlen meghívásához használjuk. |
Mode |
Meghatározza a vonalrajzolás módját (normál, inverz, xor, stb.). |
Style |
A toll stílusa. Lehet tömör (solid), pontozott (dotted), szaggatott (dashed), dash-dot, clear, stb. |
Width |
A toll szélessége pixelben |
Általában ezek a tulajdonságok úgy viselkednek, ahogy az elvárható tőlük. Például így rajzolhatunk egy piros szaggatott vonalat.
A szaggatott és pontozott stílusok csak 1-es szélességű tollal használhatók. A psClear stílus használható a téglalapok, ellipszisek és kitöltött sokszögek szélének eltüntetéséhez.
Az ecset egy grafikus alakzat kitöltéséért felel. Az ecset lehet több egy egyszerű színnél. Lehet minta (pattern) vagy kép (bitmap) is. A TCanvas osztály Brush tulajdonságának beállításával szabályozhatjuk az aktuális kitöltést, ez egy példánya a TBrush osztálynak.
tulajdonságok |
leírás |
Bitmap |
Kép beállítása az ecset háttereként. |
Color |
Ecset színe. |
Handle |
Az ecset leírója (HBRUSH). Közvetlen GDI híváshoz. |
Style |
Az ecset stílusa. Lehet tömör (solid), clear, vagy egy a minták (patterns) közül. |
A stílus alapértelmezett értéke bsSolid. A stílusnak beállítható különböző minták a következők lehetnek: bsHorizontal, bsVertical, bsFDiagonal, bsBDiagonal, bsCross, vagy bsDiagCross. A képen látható mintát könnyedén létrehozhatjuk:
Másik érdekes lehetőség egy háttérkép beállítása:
A kód első sora létrehoz egy TBitmap objektumot és hozzárendeli az ecset Bitmap tulajdonságához. Erre azért van szükség, mert ez alapbeállításként nem áll rendelkezésünkre. A harmadik sorban megrajzoljuk az ellipszist. Ezután még fel kell szabadítanunk a létrehozott TBitmap objektumot. Mivel mi hoztuk létre, a VCL ezzel nem törődik.
Előfordul, hogy „tiszta” ecsetre van szükségünk. Ilyenkor az alakzatok belseje átlátszóvá válik. A „tiszta” ecset használatához, állítsuk a Style-t bsClear-re. Nézzük az előző példát, de most adjunk hozzá egy második kört, aminél ezt az ecsetet használtuk.
Az ecsettel még aprólékosabban dolgozhatunk, ha közvetlenül az API-t használjuk. De az esetek többségében a VCL TBrush osztálya gyorsabb, megbízhatóbb és ugyanúgy alkalmas a feladat megoldására.
A betűk használata nagyon egyszerű és az eddigiek elolvasása után ismerős is lesz. TCanvas osztály Font tulajdonságával dolgozunk, amelyet a következőképpen állíthatunk át:
Ebben a példában a „Teszt” szót „Courier New” betűtípussal, 14-es méretben és félkövéren fogjuk kirajzolni.
A TCanvas osztály ClipRect tulajdonsága éppen a kivágott területet tartalmazza, de ez csak olvasható. A kivágandó terület megváltoztatásához a Windows API-t kell használni. Nézzünk egy példát a vágás használatára, ahol csak a kép egy 200x200 pixeles részletét rajzoljuk ki:
A kép ezután ugyanazon a helyen fog megjelenni, de csak a 20, 20, 220, 220 koordináták közötti részét láthatjuk. Ennek a területnek (régiónak) nem kell feltétlenül téglalapnak lennie. Ha az előző példában az RGN változónak más értéket adunk, lehet a vágás alakja például kör vagy ellipszis is.
De megadhatunk bármilyen sokszöget is egy koordináta tömb formájában, erre nézzünk egy példát:
A CreatePolygonRgn függvény alakítja területté a pontsorozatunkat. Ez a pontsorozat bármilyen hosszú lehet. Nem kell külön jeleznünk a záró koordinátát, mivel függvény automatikusan összekapcsolja az első és utolsó pontot.
Mint azt már láthattuk, a képek megjelenítése Delphiben elég egyszerű feladat. A TCanvas osztálynak számos eljárása foglalkozik képekkel. A leggyakrabban használt a Draw, mellyel egy meghatározott helyre rajzolhatunk ki képeket. Bár már használtuk korábban, tekintsük meg a kódot, amit bővíteni fogunk:
Ez a kód létrehoz egy TBitmap objektumot, betölti a megnevezett fájlt, majd megjeleníti azt a form bal felső sarkában. A kép méretének megváltoztatására jó a StretchDraw eljárás. Használatakor megadjuk, mekkora téglalapot töltsön ki a kép:
Az egyik legáltalánosabb eljárás a CopyRect. Itt lehetőségünk van nemcsak a cél, hanem a forrás téglalap meghatározására is. Ez lehetővé teszi a kép részekre bontott megjelenítését. Nézzünk erre egy példát:
Képrészletek másolása elterjedt grafikus programozási technika. Ha egy nagyobb képet felosztunk kisebb egységekre, a CopyRect eljárással mindig azt a részletet tudjuk megjeleníteni, amelyikre éppen szükségünk van.