Ebben a fejezetben ismertetni szeretnénk a Windows alatti rajzolással rajzolással kapcsolatos problémákat. Mivel a nyomtatás a Windows alatt teljesen ugyanúgy végezhető el mint a képernyőre való rajzolás, ezért a nyomtatással kapcsolatos tudnivalókat is ebben a fejezetben ismertetjük.
Windows-ban a rajzolási rutinok a "gdi.exe" DLL-ben helyezkednek el. Ez a DLL kb 200 rutint tartalmaz és a Windows indításakor töltődik be a memóriába. Amikor a mi programunk egy kört vagy egy négyszöget rajzol, akkor ennek a DLL-nek valamelyik függvényét hívja meg. Természetesen a GDI nem egyedül végzi ezeket a műveleteket, hiszen a fizikai ezsközöket kezelő driverek fölött helyezkedik el (13. ábra). Ezek a driverek transzformálják a GDI függvényeket a fizikai eszköz által érthető nyelvvé. Ez eredményezi az eszköz függetlenségi programozást a Windows alatt. Ugyanaz a GDI függvény tud rajzolni pl. egy négyszöget egy EGA monitoron mint VGA-n vagy SVGA-n vagy nyomtatón. Amikor egy új pl. VGA kártyát akarunk betenni a gépünkbe, általában az a szokás, hogy a kártyához a saját driverét installáljuk fel. Az új driver kezeli le 17217j94r gjobban az új kártyát, hiszen erre van optimalizálva. Az új driver installálása után nem kell törődnünk azzal, hogy ez hogyan kezeli a kártyát és természetesen a programunkat sem kell módosítani. A GDI-nek az a hátránya, hogy nem támogatja az animációt, csak kétdimenziós és csak egész számokat használ.
A GDI függvények a következő csoportokba sorolhatók :
vektor rajzolási függvények (line, rectangle, ellipse, stb.)
bitmap manipulálási függvények
szöveg megjelenítési függvények
paletták menedzselése ( ez általában az SVGA esetén van szerepe)
A GDI által támogatott eszköz függetlenségnek egyik fontos előnye, hogy segítségével könnyen lehet transzformálni a rajzokat egyik eszközről a másikra, hiszen az eszközöknek a felbontása különböző (Pl. Nyomtató és képernyő). Ennek megvalósítására a GDI koordináta leképezést használ. Ez a leképezés lehetővé teszi, hogy a rajzainkat olyan koordinátákban adjuk meg, amelyek a számunkra legkényelmesebbek a feladat megvalósításához. Az egész rajzolási művelet úgy végezhető el, mintha papíron rajzolnánk.
A DC a kulcsa a GDI-nek az eszköz függetlenség megvalósításához. Minden GDI függvény egy handle-t (integer) igényel argumentumként. A DC-t úgy foghatjuk fel mint egy általánosított modellje az output eszköznek. Valójában a DC egy adat struktúra, amely az eszközön való rajzoláshoz szükséges információkat tartalmazza. Pl. Háttérszín, toll, font, kitöltési minta, stb. Mivel a DC egy grafikus eszközt reprezentál, ezért megosztott eszközként használható. Ahhoz, hogy tudjunk rajzolni, szükségünk van olyan függvényre, amely visszaadja a DC leíróját (HDC) ennek a függvénynek kell megelőznie bármilyen rajzolási függvényt. A rajzolás végén fel kell szabadítani a leírót. A Windows egyszerre 5 DC-t enged meg. Természetesen nem applikációnként, hanem összesen . A következő tábla összefoglalja a DC elemeit és a default értékeit.
Név |
Default érték |
Megjegyzés |
Background color |
fehér |
A háttérszíne |
Background mode |
OPAQUE |
A háttér festi a háttérszínnel |
Bitmap | ||
Brush |
WHITE_BRUSH |
ecset (festési) szín |
Brush origin | ||
Device origin |
Bal felső sarok | |
Color palette |
DEFAULT_PALETTE | |
Drawig mod |
R2_COPYPEN |
hogyan kombinálja a pen színét a meglévő színnel |
Font |
SYSTEM_FONT | |
Mapping mode |
MM_TEXT |
1 logikai egység = 1 pixel |
Pen |
BLACK_PEN | |
Text color |
Black | |
Viewport origin | ||
Window origin |
Eszközkapcsolatot hozhatunk létre:
az érvénytelen területek újrafestésére,
az ablak aktív területének újrafestésére,
a teljes ablak újrafestésére,
az egész képernyő újrafestésére,
nyomtatók használatára,
információ szerzésre
virtuális memória eszközre
metafájl használatára
Mint említettem az előbb, a rajzolás általában egy eszközkapcsolat meghatározásával kezdődik. Az eszközkapcsolat meghatározása a céltól függ, vagyis főleg attól, hogy a fent felsorolt 8 eset közül melyiket akarjuk használni. Minden esetben más-más függvényt kell használnunk a kapcsolat létrehozására és megszüntetésére. Általában az ablak illetve képernyő frissítést a WM_PAINT üzenet kezelésében szokás megvalósítani. Tehát minden esetben a rutinunk a következőképpen néz ki:
hdc=létrehozás(...,...,..., );
rajzolás(hdc,....);
kapcsolatfelbontás(...,...);
az érvénytelen területek újrafestése esetén
hdc=BeginPaint(hwnd, &ps);// a ps egy PAINTSTRUCT típusú, amely tartalmazza az újrafestendő terület nagyságát is. A hwnd az ablak leíró.
EndPaint(hwnd, &ps);
az ablak aktív területének újrafestése esetén
hdc = GetDC(hwnd);// ha a hwnd NULL, akkor a képernyő átveszi az aktív ablak szerepét
int ReleaseDC(hwnd, hdc); (az aktív ablak a menü alatti rész). A visszatérési érték 1 ha sikerült a felbontás, különben 0
a teljes ablak területének újrafestése esetén
hdc = GetWindowDC(hwnd);
ReleaseDC(hwnd, hdc); //ilyenkor a nem aktív területeket is újra kell festeni, tehát kezelni kell a WM_NCPAINT üzenetet is
a teljes képernyő újrafestése esetén
hdc = CreateDC(LPCSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszOutput, const void FAR * lpInitData);
DeleteDC(hdc);
lpszDriver : a meghajtóprogramot tartalmazó fájlneve
lpszDevice : az eszköz neve
lpszOutput : a fizikai output eszköz specifikálja pl LPT1:
lpInitData : DEVMODE típusú struktúrára mutató pointer. NULL-t kell használni ha az eszköz nem igényel beállításokat.
a nyomtatás esetén
ugyanaz mint az előző esetben. Majd visszatérünk rá.
a virtuális memória használata
Sok esetben hasznos, ha létrehozunk a memóriában egy a specializált eszközzel kompatibilis memória eszközt. Arra használható, hogy előkészítsük a rajzot a megjelenítése előtt.
hdc = CreateCompatibleDC(hwnd);
DeleteDC(hwnd, hdc);
a metafájl használata
A metafájl nem más, mint grafikus adatok tárolása binárisan kódolt, paraméterezett grafikus rutinok segítségével. A metafájlban tárolt utasítások akármilyen eszközkapcsolatra kiküldhetők
HDC hdc; HMETAFILE hmf;
hdc=CreateMetaFile(NULL);
rajzolás();
hmf=CloseMetaFile(hdc);
hdc=BeginPaint(hwnd, &ps);
PlayMetaFile(hdc,hmf);
DeleteMetaFile(hmf);
EndPaint(hwnd, ps);
Amikor egy HDC-t létrehozunk és beállítjuk annak paramétereit, akkor ezek a beállítások addig érvényesek, amíg nem bontjuk fel a kapcsolatot. A jól beállított HDC elmentésére és visszanyerésére a SaveDC és RestoreDC függvények használhatók.
nSaveDC = SaveDC(HDC hdc);
RestoreDC(hdc, nSaveDC)
int GetDeviceCaps(hdc, iCapability)
Az iCapability argumentumtól függ az, hogy mit akarunk lekérdezni. Pl. HORZSIZE és VERTSIZE esetén a visszatérési érték a fizikai eszköz vízszintes és függőleges mérete mm-ben. A HORZRES és VERTRES esetén pedig a fizikai eszköz vízszintes és függőleges mérete pixelben.
Ahhoz, hogy tudjunk rajzolni a DC-re, ki kell választani a rajzolási objektumot. Ez azt jelenti, hogy ha a default beállításoktól eltérő stílussal akarunk rajzolni, akkor az adott az objektumot ki kell választani és a paramétereit beállítani. A grafikus objektumok a következők:
Pen (toll) : meghatározza a vonalak színét, vastagságát és stílusát
Brush(ecset) : a rajzok feltöltési színét és stílusát állítja be
Font : betűtípus (nagysága, szélessége, vastagsága, stb..)
Palette : szín tömb. A tömb indexe azonosítja a szint.
Bitmap
Region (régiók)
Az adott objektum kiválasztására a SelectObject függvényt használjuk.
Minden objektumra a következő állítások érvényesek:
Az objektum típusa általában az objektum nevéből és előtte egy "H" betűből áll (természetesen nagybetűvel). HPEN, HBRUSH, HFONT, HPALETTE, HBITMAP, HRGN.
Az objektum létrehozásához Createxxxx() függvény létezik. CreatePen, CreateSolidBrush, CreateHatchBrush, CreatePalette, CreateFont, CreateBitmap, CreateRectRgn. Mindegyik függvény visszatérési értékének a típusa megegyezik az objektum típusával. A függvények argumentumai különbözőek, de általában az objektum szükséges beállításait tartalmazzák.
Minden objektum a SelectObject függvénnyel választható ki.
A kiválasztás addig érvényes, amíg nem választunk ki egy másikat.
Minden objektumot törölni kell, ha már nincs szükségünk rá. Erre a DeleteObject függvényt használjuk.
A SelectObject visszatérési értéke mindig az előzőleg beállított objektumot adja vissza. Érdemes ezt a végén visszaállítani.
Minden objektum esetén vannak előre definiált konstansok, amelyeket különböző beállításokra lehet használni. Ezek általában több szóból állnak. A szavak között "_" jel található és az utolsó szó mindig az objektum neve. Pl. BLACK_PEN, WHITE_BRUSH, SYSTEM_FONT, DEFAULT_PALETTE.
16.1.3.1. Pen (Toll)
A toll létrehozásához a
HPEN CreatePen(int style, int width, COLORREF clrref)
függvényt használjuk, ahol a width a vonal vastagságát határozza meg, a COLORREF struktúrának 3 eleme van RGB, ami a színt határozza meg( Lásd példa). A Style pedig meghatározza a toll stílusát ,ez lehet:
PS_SOLID : folytonos vonal
PS_DASH : szaggatott vonal
PS_DOT : pontozott vonal
PS_DASHDOT : pont-vonal
PS_DASHDOTDOT : pont-pont-vonal
PS_NULL : láthatatlan vonal
PS_INSIDEFRAME : ha a vonalvastagság nagyobb mint 1, akkor a folytonos vonal a poligonok belsejébe kerül.
Példa: A következő példa létrehoz kétpontos vastagságú piros szaggatott tollat és ezzel rajzol egy téglalapot.
HDC hdc; HPEN hOldPen, hPen;
hdc=GetDC(hwnd);
hPen= CreatePen(PS_DASH, 2, RGB(255,0,0);
hOldPen=SelectObject(hdc,hPen);
Rectangle(hdc, 20,20,120,120);
SelectObject(hdc,hOldPen);
DeleteObject(hPen);
ReleadeDC(hwnd);
16.1.3.2. Brush (Ecset)
Az ecset létrehozásához a
HBRUSH CreateSolidBrush(COLORREF clrref) illetve
HBRUSH CreateHatchBrush(int nstyle, COLORREF clrref)
függvényt használjuk. A COLORREF a színt határozza meg. Az nstyle a sraffozási stílust határozza meg , ez lehet:
BS_HATCHED : Az ecset sraffozott területet fest.
BS_HOLLOW : Hézagosan fest az ecset.
BS_PATTERN : A memóriában elhelyezett bittérkép definiálja az ecsetet.
BS_SOLID : Egyszínű területeket fest az ecset.
BS_DIBPATTERN : Az ecset bittérképe eszköz független módon definiált.
Példa: A következő példa létrehoz kétpontos vastagságú piros szaggatott tollat kék ecsetet és ezzel rajzol egy téglalapot.
HDC hdc; HPEN hOldPen, hPen; HBRUSH hOldBrush, hBrush;
hdc=GetDC(hwnd);
hPen= CreatePen(PS_DASH, 2, RGB(255,0,0);
hOldPen=SelectObject(hdc,hPen);
hBrush=CreateSolidBrush(RGB(0,0,255));
hOldBrush=SelectObject(hdc,hBrush);
Rectangle(hdc, 20,20,120,120);
SelectObject(hdc,hOldPen);
DeleteObject(hPen);
SelectObject(hdc,hOldBrush);
DeleteObject(hBrush);
ReleadeDC(hwnd);
16.1.3.3. Region (Régió)
A régió egy képernyő terület, amely poligonok, téglalapok és ellipszisek kombinációjaként jön létre. Ezt a területet a GDI önállóan használja kifestésre, vágások elvégzésére, stb. Ezt úgyis foghatjuk fel, mintha külön viewport lenne. A GDI ugyanúgy kezeli a régiót mint bármilyen más rajzolási objektumot. Létrehozzuk, használjuk, és töröljük. Létrehozására sok függvény létezik attól függ, hogy milyen alakú régiót akarunk létrehozni. Itt csak egyet említünk a sok közül. Egy téglalap alakú régió létrehozásához a következő függvényt használjuk.
HRGN CreateRectRgn(int nLeft, int nTop, int nRight, int nBottom)
16.1.3.4. Font
Létrehozására a CreateFont függvényt használjuk. Később a szöveg megjelenitésnél részletesebben foglalkozunk vele
16.1.3.5. Palette (Paletta)
Létrehozására a CreatePalette függvényt használjuk. Később részletesebben fejtjük ki
A GDI 2 fajta koordináta rendszert támogat: A fizikai és a logikai. Az eszközkapcsolat koordináta rendszer (amit a BeginPaint, GetDC, GetWindowDC, CreateDC függvényekkel hoztuk létre) az eszköztől függ és rögzítve van. Egy adott ablak esetén a képernyőn a kliens terület bal felső sarka képezi az eszközkapcsolat középpontját, az x tengely pozitív iránya jobb felé mutat az y-é pedig lefelé. A mértékegysége képpont vagy pixel. A fizikai rendszernek a középpontja mindig megadható az eszközkapcsolat középpontjához képest. A Windows a grafikus alakzatok megjelenítése előtt a logikai koordinátákat fizikai koordináta rendszerbe képezi le. A GDI függvényekben szereplő koordináták mind logikai rendszerben értendők. Két fogalmat vezetünk be : viewport és window. A viewport a fizikai koordináta rendszert jelenti, egy képernyő téglalap, amelynek az origója az eszközkapcsolathoz képest megadható fizikai egységekben (pixelek). A window egy téglalap alakú képernyő terület, amely logikai rendszer és az egységei logikai egységek. A logikai koordináta rendszer origója a fizikai koordináta rendszerben definiálható. A leképezési mód meghatározására nyolc lehetőség kínálkozik:
leképezési mód |
logikai egység |
x tengely iránya |
y tengely iránya |
MM_TEXT(default) |
képpont |
jobbra |
lefelé |
MM_LOMETRIC |
0,1mm |
jobbra |
felfelé |
MM_HIMETRIC |
0,01mm |
jobbra |
felfelé |
MM_LOENGLISH |
0,1 inch |
jobbra |
felfelé |
MM_HIENGLISH |
jobbra |
felfelé |
|
MM_TWIPS |
1/1440 inch |
jobbra |
felfelé |
MM_ISOTROPIC |
x=y |
választható |
választható |
MM_ANISOTROPIC |
x<>y |
választható |
választható |
A leképezési mód a SetMapMode függvény segítségével állítható be.
int SetMapMode(hdc, int fnmode)
a visszatérési értéke a régi mód. A lekérdezése pedig a GetMapMode(hdc) függvénnyel történhet. Beállíthatjuk azt, hogy a fizikai koordináta rendszer (0,0) pontja milyen logikai koordinátának feleljen meg, a SetWindowOrg függvénnyel.
DWORD SetWindowOrg(HDC hdc, int nxOrigin, int nyOrigin)
A SetViewportOrg függvénnyel beállíthatjuk azt, hogy a fizikai koordináta rendszernek, hol legyen a középpontja az eszközkapcsolat középpontjához képest.
DWORD SetViewportOrg(HDC hdc, int nxOrigin, int nyOrigin)
A GDI számos rajzolási függvényt tartalmaz. Ezek pontok, vonalak, zárt alakzatok, stb. rajzolására szolgálnak. A GDI függvények közös jellemzője, hogy az első paramétere az eszköz leíró (HDC típusú változó). A pontok rajzolására a SetPixel, a vonalakra, MoveTo és LineTo, körív illetve zárt alakzatokra pedig az : Arc, Circle, Ellipse, Rect, RoundRect, Polygon, stb. függvények alkalmasak.
Amikor rajzolunk a megjelenítési mód határozza meg azt, hogy milyen módon kombinálódjanak a toll illetve az ecset színek a meglévő színekkel. A Windows 16 előre definiált konstanst használ. Ezek a konstansok R2_-vel kezdődnek. A default érték az R2_COPYPEN.
A színek leírására a Windows API a COLORREF típust definiálja. Ez egy 32 bites érték, amely tartalmazza a szín RGB kombinációit. Az alsó byte reprezentálja a pirost (R) ,utána jön a zöld (G) és utána a kék (B). A felső byte jelzi a szín típusát. (0=explicit RGB szín, 1 =logikai paletta index, 2=RGB a palettából). Tehát ez a szám 0x00bbggrr felépítésű. A Windowsban gyakran használjuk az RGB makrót, amely az RGB intenzitásokból adja vissza a COLORREF (32 bites számot). Pl. Az RGB (255,0,0) a következőt adja vissza: 0x000000ff.
A VGA, SVGA, XVGA és 8514/A videó kártyák megfelelő jeleket generálnak, hogy sok szín jelenjen meg egy színes monitoron. Az egyszerre megjeleníthető színek száma hardver okok miatt korlátozott. Ezeknek a száma attól függ, hogy hány biten tároljuk a pixel színét. A standard VGA esetén minden pixelt 4 biten tárolunk. Ez azt jelenti, hogy egyszerre 16 szint láthatunk. Az SVGA esetén a bitek száma 8, tehát a színek száma 256. A videó kártya konvertál minden pixel tartalmat egy színre és ez nem más mint egy tábla index. Ezt a táblát szin palettának hívjuk.
A Windows definiál olyan speciális palettát, amelyet rendszer palettának (system palette) hívunk. Ez a paletta 16 előredefiniált színt tartalmaz az EGA és VGA esetén és húszat az SVGA esetén.
A Windows 3.0-tól felfelé a Windows támogatja a logikai paletta fogalmát. Ennek az az előnye, hogy segítségével olyan színeket is meg tudunk jeleníteni, amelyek nincsenek benne a rendszer palettában. A Windows támogatja a kiterjesztett paletta használatát, amely utánozza a hardver palettát. A Windows automatikusan 20 belépést foglal az új palettában, amely megfelel a rendszer palettában levő színeknek. Amikor egy logikai palettát hozunk létre, akkor a Windows leképezi az összes logikai paletta színeit a kiterjesztett palettába a következőképpen:
ha a szín létezik a rendszer palettában, akkor ezt oda képezi le
ha nincsen benne, akkor hozzáadja
ha a rendszer paletta tele lett, akkor a logikai paletta színe a hozzá legközelebb eső szinre lesz leképezve a rendszer palettában.
A szöveg megjelenítése előtt be lehet állítani a háttérszínét (SetBkColor), a szöveg színét (SetTextColor) valamint a font paramétereit (SelectObject(hdc, CreateFont(...)). A szöveg megjelenítéséhez használhatók a következő függvények:
int DrawText( HDC hdc, LPCSTR lpsz, int cb, RECT FAR* lprc, UINT fuFormat)
BOOL TextOut(HDC hdc, int nxStart, int nyStart, LPCSTR lpsz, int cb)
Továbbá használható a TabbedTextOut függvény, amely tabulátorokkal ellátott sztringeket jeleníti meg. A tabulátorok pozíciói logikai koordinátákban adhatók meg. A font létrehozása során testreszabott paraméterű fontot is kialakíthatunk. Megadhatjuk a magasságát, szélességét, a betű dőlési szögét, vastagságát, a szöveg irányát, stb.
Gyakran felmerülhet az az igény, hogy egy bitmapet jelenítsünk meg a képernyőn. Természetesen az erőforrások tárgyalásánál említettük azt, hogy a bitmap is egy erőforrás és az erőforrásfájlban kell szerepelnie. Mivel erőforrás, a betöltésére a LoadBitmap függvényt használjuk. A bitmap megjelenítése kicsit több munkát igényel mint az ikoné vagy a kurzoré. A betöltés után a függvény visszatérési értéke egy HBITMAP típusú változó, amely tartalmazza az adott bitmap leíróját. A megjelenítéshez a következő lépések szükségesek.
Eszközkapcsolat létrehozása a képernyőn való megjelenítéshez.
Egy képernyő eszközkapcsolattal ekvivalens memória eszközkapcsolat létrehozása, ami a bitmap tárolására szolgál annak megjelenítéséig.
A bitmap behelyezése a memória eszközkapcsolatba.
A bitmapnek a memória eszközkapcsolatból az ablak eszközkapcsolatba másolása. Ez a lépés eredményezi a bitmap tényleges megjelenítését a képernyőn.
A következő példa szemlélteti a bitmap megjelenítését végző lépéseket:
HBITMAP hBitmap1;
HDC hdc, hmemdc;
hBitmap1=LoadBitmap(hInstance,"MYBITMAP) // lásd resource fejezet
hdc=GetDC(hwnd);
memdc=CreateCompatibleDC(hdc);
SelectObject(hmemdc, hBitmap1);
BitBlt(hdc,10,10,200,200,hmemdc,0,0,SRCCOPY);
ReleaseDC(hwnd,hdc);
DeleteDC(hmemdc);
a CreateCompatibleDC létrehozza az ablak eszközkapcsolattal kompatibilis memória eszközkapcsolatot.
HDC CreateCompatibleDC(HDC)
A SelectObject hozzárendeli a betöltött bitmapet a memória eszközkapcsolathoz. A BitBlt függvény másolja a memória eszközkapcsolat tartalmát az ablak eszközkapcsolatra.
BOOL BitBlt(HDC hDest, int X, int Y, int Width, int Height, HDC hSource, int Sourcex, int Sourcey, DWORD dwRaster)
a dwRaster értéke azt határozza meg, hogy a bitmap bitről bitre adott tartalma milyen módszerrel kerül kirajzolásra. Néhány leggyakoribb értéke a következők:
SCRCOPY A bitmapet a képernyőre másolja az információ felülírásával
SCRAND AND kapcsolat
SCRPAINT OR kapcsolat
SCRINVERT XOR kapcsolat
Amikor eltakarjuk az ablakot és újból előhozzuk, akkor az ablakunk egy WM_PAINT üzenetet kap. Ezt az üzenetet programból is tudjuk generálni a
BOOL InvalidateRect (HWND hwnd, CONST RECT *lpRect ,BOOL bErase)
függvény segítségével. A WM_PAINT üzenet kezelésében gondoskodnunk kell az újra frissítésről, hogy az ablakunk tartalma újból látható legyen.
Felmerül ilyenkor az a kérdés, vajon minden esetben amikor frissíteni kell az ablakot (pl. egy üzenetablak -MessageBox- után) újra kell-e rajzolnom vagy létezik egy másik módszer, ami esetleg gyorsabb megjelenítést biztosít nekünk?
Az ablak tartalmának visszanyerésére több módszer kínálkozik. Az első módszer az újrarajzolás, ami kis rajzok esetén nem okoz problémát. Ez a módszer nem használható, ha a rajzoló ciklus időigényes. Ilyenkor ajánlatos a virtuális ablakok módszere. Mit is jelent ez? Ez azt jelenti, hogy a rajzolást egyszer hajtjuk végre erre a virtuális ablakra és amikor kell, akkor átmásoljuk ennek az ablaknak a tartalmát a képernyőre. Tehát ez a módszer a következő lépésekből áll:
Létrehozunk egy ablak eszközkapcsolatot, ahova szeretnénk rajzolni.
Ezzel kompatibilis memória eszközkapcsolatot hozunk létre.
Minden rajzolás és más GDI függvényt erre a memória eszközkapcsolatra rajzoljuk
A WM_PAINT üzenet kezelésében ennek a memória eszközkapcsolatnak a tartalmát másoljuk az ablak eszközkapcsolatra.
Mielőtt rátérnénk a virtuális ablak módszerének szemléltetésére szolgáló példára érdemes megemlíteni a PatBlt és CreateCompatibleBitmap függvényeket, amelyekre szükségünk lesz a példa során. A CreateCompatibleBitmap egy eszközkapcsolattal kompatibilis bitmapet hoz létre. Ezt a bitmapet bármelyik CreateCompatibleDC függvénnyel létrehozott memória eszközkapcsolat használhatja. A PatBlt egy ecsettel specifikált minta és szín segítségével ,egy négyszöget tölt ki.
HBITMAP CreateCompatibleBitmap(HDC hdc, int width, int height)
BOOL PatBlt(HDC hdc, int X, int Y, int width, int Height, DWORD dwRaster)
A dwRaster értéke azt adja meg, hogy az ecsetet hogyan kell használni a kitöltés során. A lehetséges értékei:
BLACKNESS A tartomány fekete (az ecset nem számít)
WHITENESS A tartomány fehér (az ecset nem számít)
PATCOPY másolás
PATINVERT XOR kapcsolat
DSTINVERT A tartomány invertálódik (az ecset nem számít)
A virtuális ablak módszere esetén a létrehozás általában a WM_CREATE üzenet kezelésében szokás megvalósítani. Természetesen máshol is lehetséges. A virtuális ablakba való rajzolás bárhol lehetséges a programunkban. A megjelenítést a WM_PAINT üzenet kezelésében érdemes megvalósítani.
Példa: a következő példa szemlélteti a virtuális ablak módszer megvalósítását.
// a létrehozás
case WM_CREATE:
// a képernyő koordináták lekérdezése
maxX=GetSystemMetrics(SM_CXSCREEN);
maxY= GetSystemMetrics(SM_CYSCREEN);
// egy képtároló memóriarész létrehozása
hdc=GetDC(hwnd);
hmemdc=CreateCompatibleDC(hdc);
hbit=CreateCompatibleBitmap(hdc,maxX,maxY);
SelectObject(hmemdc,hbit);
hbrush=GetSockObject(WHITE_BRUSH);
SelectObject(hmemdc, hbrush);
PaltBlt(hmemdc,0,0,maxX,maxY,PATCOPY);
ReleaseDC(hwnd,hdc);
break;
// a rajzolás
hPen=CreatePen(PS_SOLID,2,RGB(255,0,0));
SelectObject(hmemdc,hPen);
Rectangle(hmemdc,20,20,200,200);
SetTextColor(hmemdc,RGB(0,0,255));
SetBkColor(hmemdc, RGB(0,255,0));
TextOut("Üdvözlöm a Szoftvertechnika csapatot",36);
//frissítsük a képernyőt
InvalidateRect(hwnd,NULL,1); //a NULL= teljes képernyő frissítés, 1= //törölje előtte a képernyőt
//megjelenítés
case WM_PAINT:
hdc=BeginPaint(hwnd, &ps);
BitBlt(hdc, 0, 0, maxX, maxY, memdc, 0, 0, SRCCOPY);
EndPaint(hwnd, &ps);
break;
A nyomtatás esetén be kell inkludolni a "print.h" fájlt a programunk elején, amelyben printelési rutint írunk. A rajzolás és a nyomtatás hasonló műveletek a Windows alatt csak más eszközre rajzolunk és más driverrel kommunikálunk. A nyomtatás során a GDI modullal és a Print Managerrel állunk kapcsolatban. Miután létrehoztuk az eszközkapcsolatot a majdnem mindegy, hogy hova írányítjuk a rajzolást a képernyőre vagy nyomtatóra.
A VC++ részben a nyomtatást részletesebben fogjuk tárgyalni, ezért itt csak röviden említjuk meg.
Vázlatosan a nyomtatási folyamat a következő lépésekből áll:
A CreateDC függvénnyel hozzuk létre a nyomtató eszközkapcsolat leíróját. Ennek a függvénynek a paramétereit általában a win.ini fájlból lehet kiolvasni. Az ini fájlok kezelésére a GetProfileStringe, WriteProfileString, GetPrivateProfileString WritePrivateProfile függvények használhatók. Ilyenkor a vezérlő program betöltődik a memóriába, ha addig nem volt bent.
Az Escape függvény meghívása a STARTDOC jelzővel. A nyomtatási folyamat kezdődik. Innentől kezdve minden rajzolási művelet ugyanúgy hajtható végre, mintha a képernyőre rajzolnánk. A nyomtatandó adatok a lemezen metafájl szerkezetben tárolódnak.
Az Escape függvény meghívása a NEWFRAME jelzővel, jelezve a tényleges nyomtatás kezdete
Az Escape függvény meghívása az ENDDOC jelzővel jelezve a nyomtatás végét.
Az Escape függvény szintaxisa a következő:
int Escape(hdc, nEscape, cbInput, lpszInData, lpvOutData)
HDC hdc; /* handle of device context */
int nEscape; /* specifies escape function */
int cbInput; /* size of structure for input */
LPCSTR lpszInData; /* address of structure for input */
void FAR* lpvOutData; /* address of structure for output */
The Escape function allows applications to access capabilities of a particular device that are not directly available through the graphics device interface (GDI). Escape calls made by an application are translated and sent to the driver.
Parameter Description
hdc Identifies the device context.
nEscape Specifies the escape function to be performed.
cbInput Specifies the number of bytes of data pointed to by the lpszInData parameter.
lpszInData Points to the input structure required for the specified escape.
lpvOutData Points to the structure that receives output from this escape. This parameter should be NULL if no data is returned.
Returns
The return value specifies the outcome of the function. It is greater than zero if the function is successful, except for the QUERYESCSUPPORT printer escape, which checks for implementation only. The return value is zero if the escape is not implemented. A return value less than zero indicates an error.
Errors
If the function fails, the return value is one of the following:
Value Meaning
SP_ERROR General error.
SP_OUTOFDISK Not enough disk space is currently available for spooling, and no more space will become available.
SP_OUTOFMEMORY Not enough memory is available for spooling.
SP_USERABORT User terminated the job through Print Manager.
Az Escape függvény jelzői, nEscape argumentumként:
ABORTDOC |
Superseded: use AbortDoc function |
BANDINFO |
Obsolete in Windows 3.1 |
BEGIN_PATH |
Opens a path |
CLIP_TO_PATH |
Defines clip region bounded by path |
DEVICEDATA |
Same as PASSTHROUGH escape |
DRAFTMODE |
Superseded: Use DEVMODE structure |
DRAWPATTERNRECT |
Creates pattern on PCL printers |
ENABLEDUPLEX |
Superseded: use DEVMODE structure |
ENABLEPAIRKERNING |
Enables or disables kerning |
ENABLERELATIVEWIDTHS |
Enables or disables relative char widths |
ENDDOC |
Superseded: Use EndDoc function |
END_PATH |
Ends a path |
ENUMPAPERBINS |
Superseded: Use DeviceCapabilities function |
ENUMPAPERMETRICS |
Superseded: Use DeviceCapabilities function |
EPSPRINTING |
Allows EPS printing only |
EXT_DEVICE_CAPS |
Superseded: Use GetDeviceCaps function |
EXTTEXTOUT |
Superseded: Use ExtTextOut function |
FLUSHOUTPUT |
Obsolete in Windows 3.1 |
GETCOLORTABLE |
Obsolete in Windows 3.1 |
GETEXTENDEDTEXTMETRICS |
Gets extended text metrics |
GETEXTENTTABLE |
Superseded: Use GetCharWidth function |
GETFACENAME |
Gets face name of current font |
GETPAIRKERNTABLE |
Gets kerning-pair structures |
GETPHYSPAGESIZE |
Gets size of physical page |
GETPRINTINGOFFSET |
Gets offset where printing starts |
GETSCALINGFACTOR |
Gets scaling factors for printer |
GETSETPAPERBINS |
Superseded: Use DeviceCapabilities function |
GETSETPAPERMETRICS |
Superseded: Use ExtDeviceMode function |
GETSETPRINTORIENT |
Superseded: Use ExtDeviceMode function |
GETSETSCREENPARAMS |
Gets or sets halftoning parameters |
GETTECHNOLOGY |
Gets technology type |
GETTRACKKERNTABLE |
Gets track-kerning table |
GETVECTORBRUSHSIZE |
Gets size of plotter brush |
GETVECTORPENSIZE |
Gets size of plotter pen |
MFCOMMENT |
Adds comment to metafile |
MOUSETRAILS |
Enables or disables mouse trails |
NEWFRAME |
Superseded: Use StartPage and EndPage functions |
NEXTBAND |
Finished band, get next band |
PASSTHROUGH |
Sends data directly to printer |
POSTSCRIPT_DATA |
Same as PASSTHROUGH escape |
POSTSCRIPT_IGNORE |
Flag for suppressing output |
QUERYESCSUPPORT |
Queries whether escape is supported |
RESTORE_CTM |
Restores current transformation matrix |
SAVE_CTM |
Saves current transformation matrix |
SELECTPAPERSOURCE |
Superseded: Use DeviceCapabilities function |
SETABORTPROC |
Superseded: Use SetAbortProc function |
SETALLJUSTVALUES |
Superseded: Use ExtTextOut function |
SET_ARC_DIRECTION |
Sets arc-drawing direction |
SET_BACKGROUND_COLOR |
Sets and gets background color |
SET_BOUNDS |
Sets bounding rectangle |
SET_CLIP_BOX |
Sets or restores clipping rectangle |
SETCOLORTABLE |
Sets RGB color-table entry |
SETCOPYCOUNT |
Superseded: Use ExtDeviceMode function |
SETKERNTRACK |
Sets kerning track |
SETLINECAP |
Sets line-end style |
SETLINEJOIN |
Sets line-intersection style |
SETMITERLIMIT |
Sets line-intersection bevel angle |
SET_POLY_MODE |
Sets mode for Polygon and Polyline functions |
SET_SCREEN_ANGLE |
Sets current screen angle |
SET_SPREAD |
Sets trapping for spot separations |
STARTDOC |
Superseded: Use StartDoc function |
STRETCHBLT |
Superseded: Use StretchBlt function |
TRANSFORM_CTM |
Modifies current transformation matrix |
|