asm
asm
25. ledna 2002, 00.00 | Ukážeme si jak jednoduše pracovat s textem, pozadím a s fonty a jejich atributy. Dozvíme co je to kontext zařízení.
1. Úvod

Uživatel komunikuje s Windows pomocí GUI (Graphic user interface) - grafického uživatelského rozhraní,
což vyžaduje mnohem komplikovanější řešení než byl textový režim v MS-DOSu. Programy ve Windows
využívají funkcí (jsou obsaženy v knihovně GDI32.dll) rozhraní GDI (Graphics device interface). To je
univerzální programová vrstva zajišťující komunikaci mezi konkrétní aplikací a hardwarem.
Univerzální proto, že její funkce jsou hardwarově nezávislé a lze je tedy použít pro všechny typy grafických karet.
Tato univerzálnost je ovšem také vítězstvím nad rychlostí a proto není možné využívat těchto funkcí např.
při programování her, od toho tu máme třeba funkce DirectX API. (Téměř) každá aplikace je tvořena oknem
do jehož klientské oblasti můžeme kreslit, neboli spíše často musíme, protože okno může být např. překryto
jiným oknem a protože Windows si neukládají obsah překryté oblasti, musí být celá oblast po odkrytí znovu
překreslena. O nutnosti takového překreslení jsme informování zprávou WM_PAINT. Dostane-li program
takovou zprávu, znamená to, že nějakou část klientské oblasti je nutno překreslit, tzn. že tato oblast je tzv.
označena za neplatnou.
2. Kontext zařízení
Kontext zařízení (device contect) je určitá struktura obsahující informace o typu písma, jeho velikosti,
barvě štětce, atd. Většina funkcí požaduje jako jeden z parametrů handle kontextu zařízení. Po využití
kontextu zařízení nějakou funkcí by se měl tento handle uvolnit:
invoke BeginPaint , hWin, ADDR ps
push eax
pop hdc
...
invoke EndPaint , hWin, ADDR ps
BeginPaint - tato funkce získá handle kontextu zařízení a naplní strukturu PAINTSTRUCT.
Vyvolání této funkce také způsobí vymazání neplatné oblasti.
EndPaint znamená konec kreslení
Tento postup se používá pro ošetření zprávy WM_PAINT. Překreslená oblast bude oblast určená v proměnné
rcPaint typu RECT Proto je tento postup nevhodný pro použití v situaci, kdy chceme překreslit i jinou oblast než jen tu neplatnou.
V takovém případě je možné označit tuto oblast za neplatnou pomocí funkce
InvalidateRect. Potom jsou dvě možnosti zápisu:
a/ Pomocí
BeginPaint a
EndPaint:
wmpaint: |
   invoke BeginPaint, hWin, ADDR ps |
   push eax |
   pop hdc |
   invoke GetClientRect, hWin, ADDR rect |
   invoke InvalidateRect, hWin, ADDR rect, FALSE |
   invoke GetStockObject, DKGRAY_BRUSH |
   push eax |
   pop hBrush |
   invoke FillRect, hdc, ADDR rect, hBrush |
   invoke EndPaint , hWin, ADDR ps |
ret |
|
b/ Bez použití
BeginPaint a
EndPaint:
wmpaint: |
   invoke GetDC, hWin |
   push eax |
   pop hdc |
   invoke GetStockObject, DKGRAY_BRUSH |
   push eax |
   pop hBrush |
   invoke GetClientRect, hWin, ADDR rect |
   invoke FillRect, hdc, ADDR rect, hBrush |
   invoke ReleaseDC, hWin,hdc |
ret |
|
Pokud použijeme nevhodně možnost b/ dochází ke značnému zpomalení běhu aplikace, protože se pokaždé považuje za neplatnou
celá klientská oblast, kterou získáme funkcí
GetClientRect.
Použijeme-li funkci
GetWindowDC, můžeme kreslit i mimo
klientskou oblast. Pro zápis znaků máme k dispozici dvě funkce
TextOut
a
DrawText. Obě požadují jako parametr handle kontextu zařízení a adresu
řetězce,
TextOut ale navíc jeho přesnou délku,
DrawText
může mít v parametru nCount uvedeno -1, což znamená, že řetězec je ukončen nulou a není třeba udávat jeho
délku, navíc umožňuje zadat základní formátovací údaje týkající se vhodného umístění textu.
3. Barvy

Běžná grafická karta skládá každý bod buď ze 24 bitů (true color), kdy je pro každou barevnou
složku určeno 8 bitů nebo z 16 bitů (high color), v tom případě je zelené barvě vyhrazeno 6 bitů
a červené s modrou po 5 bitech. Pokud je počet barev pouze 256 (oblíbený DOSovský mód), tj.
8 bitů potom jsou čísla 0-255 indexy do tabulky barev (palety), což znamená, že současně lze
zobrazit maximálně 256 jakýchkoliv barev. Barevnému schématu na obrázku odpovídá i následující struktura:
RGBQUAD STRUCT
rgbBlue BYTE ?
rgbGreen BYTE ?
rgbRed BYTE ?
rgbReserved BYTE ?
RGBQUAD ENDS
Můžeme použít registr eax do něhož umístíme barvu pomocí makra:
RGB MACRO red,green,blue
XOR EAX,EAX
MOV AL,blue
SHL EAX,8
MOV AL ,green
SHL EAX,8
MOV AL,red
ENDM
Takto získanou barvu využijeme pro vyplnění plochy. Nejdříve vytvoříme štětec
voláním funkce
CreateBrushIndirect, jehož parametrem
je ukazatel na strukturu LOGBRUSH:
LOGBRUSH STRUCT
lbStyle DWORD ?
lbColor DWORD ?
lbHatch DWORD ?
LOGBRUSH ENDS
Parametr lbColor je barva a lbHatch vzorek na pozadí.
Další funkcí, kterou použijeme je
SetBkColor určující barvu pozadí a
SetTextColor pro barvu textu.
4. CreateFont

Tato funkce vytváří logické písmo, tzn. že v rámci parametrů této funkce vytvoří modifikaci některého
z fontů obsaženém ve Windows (adresář C:\WINDOWS\FONTS). Lze jí nastavit výšku, šířku, tloušťku,
kurzívu, podtržení, přeškrtnutí, úhel (pod WinNT), atd. Lze použít také funkci
CreateFontIndirect,
která má místo 14 parametrů parametr jediný - adresu struktury LOGFONT. Následující výpis vytvoří písmo, které je vidět na
obrázku. Posledním parametrem je adresa řetězce obsahujícího název fontu : "New Time Romance". Ostatní parametry viz. WIN32 Help.
invoke CreateFont, 40,10,0,0,0,0,0,0,EASTEUROPE_CHARSET,OUT_DEFAULT_PRECIS,
LIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE,ADDR szFontName
invoke SelectObject, hdc, eax
Funkce vrací handle logického fontu, který pomocí funkce
SelectObject přiřadíme
do kontextu zařízení. Zrušení provedeme voláním funkce
DeleteObject.
Celý výpis obsluhy zprávy WM_PAINT vypadá potom následovně:
wmpaint: |
   invoke BeginPaint, hWin, ADDR ps |
   push eax |
   pop hdc |
   invoke GetStockObject, DKGRAY_BRUSH |
   push eax |
   pop hbrush |
   mov lb.lbStyle, BS_HATCHED |
   RGB 0FFh,0FFh,0h |
   mov lb.lbColor, eax |
   mov lb.lbHatch, HS_CROSS |
   invoke CreateBrushIndirect, ADDR lb |
   push eax |
   pop hbrush |
   RGB 0FFh, 0Dh, 044h |
   invoke SetBkColor, hdc, eax |
   RGB 00h, 0FFh, 0FFh |
   invoke SetTextColor, hdc, eax |
   invoke GetClientRect, hWin, ADDR rect |
   invoke FillRect, hdc, ADDR rect, hbrush |
   invoke CreateFont, 40,10,0,0,0,0,0,0,EASTEUROPE_CHARSET,OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,PROOF_QUALITY,FF_DONTCARE, ADDR sFontName |
   invoke SelectObject, hdc, eax |
   invoke TextOut, hdc, 10, 10, ADDR sText, SIZEOF sText |
   invoke EndPaint, hWin, ADDR ps |
ret |
|
Download zdrojáků naleznete
zde.