Alakzatok rajzolása

Mint arról már korábban szó volt, a GDI rajzolási műveletek igen széles skáláját bocsátja az alkalmazások rendelkezésére. Ezen rajzolóműveletek egy része mintákkal kitöltött és vonalakkal körülhatárolt alakzatok rajzolására használható.

Az Ellipse() GDI függvény ellipszisek - és nyilvánvalóan annak speciális változatai, azaz pl. körök - rajzolására használható. Az ellipszis egy zárt görbe, amelynek minden egyes pontjára igaz, hogy az ellipszis két fókuszpontjától (f1, f2) mért távolságuk összege (d1+d2) állandó. Az Ellipse() függvény paramétereiként azonban nem ezeket a jellemzőket, hanem az ellipszist befoglaló téglalap bal felső és jobb alsó sarkának koordinátáit kell megadni. (A befoglaló téglalap az a legkisebb téglalap, amely az alakzat - adott esetben az ellipszis - minden egyes pontját magában foglalja. Az ellipszis körvonalát az aktuálisan kiválasztott tollal rajzolja meg, belsejét pedig az éppen kiválasztott ecset felhasználásával tölti ki a GDI.

A Chord() függvény egy ellipszisdarab, pontosabban az ellipszis körvonala és egyik húrja által határolt zárt alakzat rajzolására használható. Az alakzat kirajzolásához az alkalmazás az ellipszis befoglaló téglalapjának koordinátáin kívül két, az ellipszis középpontjából (tengelyeinek metszéspontjából) kiinduló félegyenes, azaz sugár végpontjait adja meg. A kirajzolásra kerülő zárt alakzatot az ellipszis körvonala és a két sugár metszéspontja között húzott szakasz, valamint a szakasz két végpontja közé eső ellipszisív-darab határolja. Az alakzat körvonalának kirajzolásahoz a céleszközkörnyezetben éppen kiválasztott tollat, belsejének kitöltéséhez pedig az aktuális ecsetet használja a GDI.

A Pie() függvény ellipsziscikkely, azaz az ellipszisből két sugár által kimetszett darab kirajzolására használható. A függvény paramétereiként az ellipszis befoglaló téglalapját meghatározó koordinátapáron kívül a két sugár végpontjának koordinátáit kell megadni. Az cikkely körvonalát az aktuálisan kiválasztott tollal rajzolja meg, belsejét pedig az éppen kiválasztott ecset felhasználásával tölti ki a GDI.

Tetszőleges sokszögek kirajzolásához a GDI a Polygon() illetve PolyPolygon() függvényeket bocsátja az alkalmazások rendelkezésére. A sokszögek tetszőleges számú szakasz által határolt zárt alakzatok, melyeket az alkalmazásoknak a szakaszok végpontjainak, azaz a sokszög csúcspontjainak koordinátáival, valamint azok "összekötési sorrendjével", azaz a sokszöget határoló szakaszokkal kell meghatározniuk. A sokszögek körvonalának kirajzolásahoz a céleszközkörnyezetben éppen kiválasztott tollat használja fel a GDI. A határolt terület kitöltésének módja az éppen aktuális sokszög-kitöltési módtól függ. Az alapértelmezett ún. váltó (alternate) módban a komplex sokszögek egymást átfedő területei állapotot váltanak, azaz a GDI kizárólag a páros és a páratlan számú poligon-határoló oldalak között tölti ki a területet. Ezzel szemben az ún. "kanyargó" (winding) módban minden olyan terület kitöltésre kerül amelyet legalább egyszer teljesen körbejár a toll a sokszög kirajzolása során. Az aktuális sokszögkitöltési mód lekérdezésére a GetPolyFillMode(), míg megváltoztatására a SetPolyFileMode() függvény segítségével van mód.

Bár téglalapok kirajzolására a Polygon() függvény is alkalmas, a Rectangle() sokkal egyszerűbb módon nyújt lehetőséget az alkalmazások részére e művelet elvégzésére. A bal felső és jobb alsó sarkának koordinátáival meghatározott téglalap körvonalát a GDI az aktuálisan kiválasztott tollal rajzolja meg, belsejét pedig az éppen kiválasztott ecset felhasználásával tölti ki.

Lekerekített sarkú téglalapok kirajzolására használható a RoundRect() függvény, amely a téglalapot meghatározó sarokkoordinátákon kívül annak az ellipszisnek a szélességét és magasságát várja paraméterként, amelynek ívdarabjai a téglalap sarkainak helyén kerülnek kirajzolásra. A GDI a téglalap körvonalát az eszközkörnyezetben éppen kiválasztott tollal rajzolja meg, belsejét pedig az aktuális ecsettel tölti ki.

A FillRect() a sarokpontjaival megadott téglalap belsejét tölti ki a paraméterként meghatározott ecset segítségével, míg a FrameRect() a megadott téglalap körül rajzol egy vonalat a megadott ecsettel egy logikai egység szélességben. Az InvertRect() függvény a paraméterként megadott téglalap alakú terület színeit invertálja.

Szöveges rajzolóműveletek

A szöveges rajzolóműveletek a leggyakrabban alkalmazott GDI rajzolóműveletek közé tartoznak. A GDI szöveges műveleteit alapvetően két csoportba lehet sorolni. Az első csoportba a szöveg formázásával kapcsolatos, annak megjelenítését előkészítő műveletek tartoznak, míg a második csoportot a tényleges megjelenítést, a szöveges információ kirajzolását végző műveletek alkotják. A formázó műveletekkel a szöveg és a betűk igazítását, a megjelenítés során használt háttér- és szövegszín beállítását végezhetik az alkalmazások. A rajzoló műveletek karakterek, vagy komplett karakterláncok megjelenítését végzik.

A formázó műveletek további három alcsoportra oszlanak, attól függően, hogy a szöveg-formázási jellemzők lekérdezését és beállítását, a karakterek képére vonatkozó információkat lekérdezését, vagy teljes sztringek kiterjedésének megállapítását teszik lehetővé.

A szöveges rajzolóműveletek során használt szöveg- és háttérszín lekérdezése illetve beállítása a GetTextColor() és SetTextColor() illetve GetBkColor() és SetBkColor() függvényekkel lehetséges. A szöveges rajzoló műveletek a szöveg karaktereihez tartozó képpontokat a szövegszínnel jelenítik meg.

Azt, hogy a szöveg befoglaló téglalapján belül elhelyezkedő egyéb képpontokat a GDI a háttérszínűre festi, avagy a rajzolás során változatlanul hagyja az aktuális háttérmód határozza meg, amelyet a GetBkMode()/SetBkMode() függvénypárossal lehet lekérdezni illetve beállítani. Az alapértelmezett ún. átlátszatlan (opaque) módban a GDI a szöveg befoglaló téglalapját a kirajzolás előtt háttérszínűre festi, míg az átlátszó (transparent) mód esetén azt változatlanul hagyja, így a megjelenítés során csakis a szöveghez tartozó képpontok színe módosul.

A karakterfüzérek kirajzolása során az egyes karakterek közötti normál közön felül az alkalmazás tetszőleges plusz (vagy éppen minisz) karakterközt határozhat meg a SetTextCharacterExtra() függvény segítségével. Az itt látható ábra ugyanannak a szövegnek az alapértelmezett és egy attól eltérő karakterközzel kirajzolt formáját mutatja. A mindenkor aktuális karakterközt az alkalmazás a GetTextCharacterExtra() függvény hívásával kérdezheti le.

Az alkalmazás a megjelenítésre kerülő szöveg igazítását is befolyásolhatja. A SetTextJustification() függvény segítségével egy, a teljes sorban a törés-karakterek (tipikusan a szóköz) mentén egyenletesen elosztásra kerülő extra helyközt határozhat meg. (Ezt tipikusan a sorkizárt megjelenítéshez szokás felhasználni.) Ezzel összefüggésben a megjelenítésre kerülő szöveg a szövegdobozon belüli vertikális és horizontális igazítását a GetTextAlign()/SetTextAlign() függvénypárossal tudja az alkalmazás lekérdezni/beállítani.

A második, azaz a karakterek képére vonatkozó információk lekérdezésére szolgáló csoportba a GetCharWidth32(), GetCharWidthFloat() illetve a GetCharABCWidths() és GetCharABCWidthsFloat() függvénypárosok tartoznak, melyek mindegyike ugyanannak az aktuálisan kiválaszott betűkészlet bizonyos karaktereire vonatkozó jellemzőnek a fix illetve lebegőpontos formában történő lekérdezését teszik lehetővé. A GetCharWidth32() és GetCharWidthFloat() függvények egy vagy több karakter eltolási szélességét (advance width) adja meg, azaz azt, hogy az aktuális rajzolási pozíciót mennyivel kell arrébtolni a karakterfüzér következő elemének megjelenítéséhez. A csak TrueType betúkészletekhez használható GetCharABCWidths() illetve a bármely font esetén használható GetCharABCWidthsFloat() függvények ennél jóval bővebb információt nyújtanak a karakterekről. Az ún. ABC struktúrában ugyanis külön-külön megtalálhatóak a karakter képének (glyph) rajzolása előtt alkalmazandó eltolás mértéke, a karakter képének szélessége, illetve a karakter kirajzolása után annak jobb oldalán hagyandó köz mérete. A teljes eltolás mértékét az A+B+C kifejezés adja meg, amely azonban akár a karakter képének szélességénél (B) kisebb értékét is eredményezhet negatív A és/vagy C komponensek esetében, amelyek alul- illetve túlnylást jeleznek (amint az a mellékelt ábrán az "f" betű esetében jól látható). Fontos megjegyezni, hogy egy teljes karakterlánc horizontális és vertikális kiterjedése nem áll szoros összefüggésben az azt alkotó karakterek szélességeinek összegével illetve a magasságok maximumával, mert a karakterfüzér kirajzolása során speciális ún. kerning párok és egyéb, az írásképet egyenletesebbé, szebbé tevő tipográfiai eljárások is alkalmazásra kerülhetnek, melyek jelentősen befolyásolhatják a végső eredményt.

Karakterfüzérek esetén inkább a harmadik csoportot alkotó, teljes karakterfüzérek kiterjedéseinek lekérdezésére használható függvények alkalmazására van szükség. A GetTextExtentPoint32() függvény a paraméterként átadott karakterfüzér az éppen kiválasztott betűkészlet meletti kiterjedéseit (szélességét és magasságát) állapítja meg, melybe az esetlegesen a SetTextCharacterExtra()-val megadott plusz karakterközt is beleszámítja, ugyanakkor nem veszi figyelembe az esetlegesen alkalmazott elforgatási jellemzőket. A GetTabbedTextExtent() függvény ehhez nagyon hasonló módon, de tabulátorpozíciók figyelembevételével állapítja meg a karakterfüzér teljes kiterjedését. A paraméterként átadott szöveget karakterről karakterre dolgozza fel, és amikor egy tabulátor karaktert talál, akkor az aktuális pozíciót a szintén paraméterként kapott tabultáropozíciókat tartalmazó tömb következő elemének megfelelő pontra állítja, és onnan folytatja a feldolgozást. Amennyiben a szöveg nem tartalmaz egyetlen tabulátort sem, úgy a függvény működése gyakorlatilag megegyezik a GetTextExtentPoint32()-ével.

A GetTextExtentExPoint() komplex tördelési műveletekhez használható fel: a megadott szöveget egy a paraméterként meghatározott maximális szélességű darabokra osztja fel, és ezen darabok szélességét tárolja el a paraméterként kapott pufferben.

A kiterjedésen túl jóval részletesebb információkkal szolgál a paraméterként kapott karakterfüzér megjelenítési jellemzőiről a GetTextMetrics() illetve a GetOutlineTextMetrics() függvény, amelyek segítségével már igen komoly tipográfiai igazítások is elvégezhetővé válnak.

A megfelelő betűkészlet kiválasztása és a megjeleníteni kívánt információ igazításának, tördelésének és egyéb jellemzőinek meghatározása illetve megállapítása után az alkalmazás nekiláthat a szöveg tényleges kirajzolásának. AGDI ehhez mindösszesen öt rajzoló funkciót bocsát az alkalmazások rendelkezésére, amelyek azonban tökéletesen elegendőek bármilyen szöveges rajzolási művelet elvégzésére.

A legegyszerűbb TextOut() függvény mindössze a megjeleníteni kívánt szöveget illetve annak a pontnak a koordinátáit várja, ahonnan kezdve a rajzolást az alkalmazás kezdeni kívánja. A TabbedTextOut() függvény ezen felül egy, a kirajzolás során alkalmazandó tabulátor-pozíciókat tartalmazó tömböt is kap paraméterként, amelyet a GetTabbedTextExtent()-nél megismert módon dolgoz fel. A ExtTextOut() függvénnyel az alkalmazások a megjelenítendő szöveget tetszőleges téglalapra vághatják, sőt, akár az egyes karakterek között alkalmazandó karakterközt is meghatározhatják.

A legkomplexebb, rengeteg opcióval rendelkező DrawText() illetve DrawTextEx() függvényekkel a szöveg tetszőleges igazítás mellett téglalapba tördeltethető, és számos módon formázható.

(folytatjuk)