wParam ;
J
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
(
static int cxClient, cyClient ;
HBRUSH hBrush ;
HDC hdc ;
int i ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
(
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ;
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
// Rysuje gamê odcieni szaroœci
for ( i = 0 ; i < 65 ; i++)
(
rect.left = i * cxClient / 65 ;
rect.top = 0 ;
rect.right = (i + 1) * cxClient / 65 ;
rect.bottom = cyClient ;
hBrush = CreateSolidBrush (RGB (min (255, 4 * i),
min (255, 4 * i),
min (255, 4 * i))) ;
FillRect (hdc, &rect, hBrush) ;
Delete0bject (hBrush) ;
)
EndPaint (hwnd, &ps) ;
Rozdzia³ 16: Palette Manager 743
return 0 ;
case WM_DESTROY:
PostOuitMessage (0) :
return 0 ;
)
return DefWindowProc (hwnd, message, wParam, lParam) ;
Rysunek 16-1. Program GRAYSI
W trakcie wykonywania fragmentu kodu zwi¹zanego z komunikatem WM PA-
INT program wywo³uje 65-krotnie funkcjê FillRect, za ka¿dym razem tworz¹c
pêdzel o innym odcieniu szaroœci. Odcieniom szaroœci odpowiadaj¹ nastêpuj¹ce
wartoœci RGB: (0, 0, 0), (4, 4, 4), (8, 8, 8) itd. a¿ do ostatniego (255, 255, 255). Aby
ta ostatnia wartoœæ mog³a byæ osi¹gniêta, wywo³ywane jest specjalne makro min
w funkcji CreateSolidBrush.
Jeœli uruchomisz ten program w trybie 256 kolorów, na ekranie pojawi siê 65 od-
cieni szaroœci, od czerni do bieli, jednak ka¿dy z nich jest poddawany rendero-
waniu przy u¿yciu techniki symulowania (ang. dithering). Jedyne czyste kolory
to czarny, ciemnoszary (128, 128, 128), jasnoszary (192, 192, 192) i bia³y. Pozosta-
y
³e kolory to ró¿ne kombinacje ustawienia bitów w bajcie. Gdybyœmy zamiast w -
pe³ruonych obszarów wyœwietlali linie lub tekst, u¿ywaj¹c 65 odcieni szaroœci,
ry
Windows nie zastosowa³by techniki symulowania i zobaczylibyœmy tylko te czte
kolory. Gdybyœmy wyœwietlili mapê bitow¹, Windows u¿y³by oko³o 20 standar-
dowych kolorów. Mo¿esz siê o tym przekonaæ, uruchamiaj¹c jeden z programów
opisanych w ostatnim rozdziale. System Windows nie stosuje techniki symulo-
wania do bitmap.
Program GRAYS2 rzedstawion na r sunku 16-2 demonstruje najwa¿niejsze
p y y
funkcje Palette Managera.
GRAYS2.C
,*
GRAYS2.C - Odcienie szaroœci po zastosowaniu Palette Managera
(c) Charles Petzold, 1998
*/
ifinclude
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance.
.. PSTR szCmdLine, int iCmdShow)
(
static TCHAR szAppName[7 = TEXT ("Grays2") :
HWND hwnd :
MSG msg
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW þ CS VREDRAW :
wndclass.lpfnWndProc = WndProc ;
744 Czêœæ II: Grafika
(cigg dalszy ze strony 743)
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
(
MessageBox (NULL, TEXT ("This program requires Windows NT!"),
szAppName, MBþICONERROR) ;
return 0 ;
hwnd = CreateWindow (szAppName, TEXT ("Shades of Gray þ12"),
WS OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW USEDEFAULT, CWþUSEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hwnd, iCmdShow) ;
UpdateWindow (hwnd) ;
while (GetMessage (&msg, NULL, 0, 0))
(
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
)
return msg.wParam ;
)
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
(
static HPALETTE hPalette ;
static int cxClient, cyClient ;
HBRUSH hBrush ;
HDC hdc ;
int i ;
LOGPALETTE * p1p ;
PAINTSTRUCT ps ;
RECT rect ;
switch (message)
(
case WM CREATE:
// Ustalenie wartoœci pól struktury LOGPALETTE i utworzenie palety
plp = malloc (sizeof (LOGPALETTE) + 64 * sizeof (PALETTEENTRY)) ;
plp->palVersion = 0x0300 ;
plp->palNumEntries = 65 ;
for ( i = 0 ; i < 65 ; i++)
(
Rozdzia³ 16: Palette Manager 745
plp->palPalEntryCi].peRed = (BYTE) min (255, 4 * i) ;
plp->palPalEntryCi].pe0reen = (BYTE) min (255, 4 * i) ;
p1p->palPalEntryCi].peBlue = (BYTE) min (255, 4 * i) ;
plp->palPalEntryCi].peFlags = 0 :
hPalette = CreatePalette (plp) :
free (plp) ;
return 0 :
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
return 0 ; j;
i þ'..
case WM_PAINT:
hdc = BeginPaint (hwnd, &ps) ;
// Zaznacz i zrealizuj paletê w kontekœcie urzddzenia
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) :
i:.
// Rysuj gamê odcieni szaroœci
for ( i = 0 ; i < 65 ; i++)
(
rect.left = i * cxClient / 64 ;
rect.top = 0 ; !
rect.right = (i + 1) * cxClient / 64 ;
rect.bottom = cyClient ;
hBrush = CreateSolidBrush (PALETTERGB (min (255, 4 * i),
min (255, 4 * i),
min (255, 4 * i))) :
FillRect (hdc, &rect, hBrush) ;
Delete0bject (hBrush) ;
)
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_OUERYNEWPALETTE:
if (!hPalette)
return FALSE :
hdc = GetDC (hwnd) ;
SelectPalette (hdc, hPalette, FALSE) ;
RealizePalette (hdc) :
InvalidateRect (hwnd, NULL, TRUE) ;
ReleaseDC (hwnd, hdc) ;
Ih
return TRUE :
7
case WM_PALETTECHANGED:
;
if (!hPalette þþ (HWND) wParam == hwnd)
break :
þi:'.
hdc = GetDC (hwnd) :
SelectPalette (hdc, hPalette, FALSE) :
746 CzgϾ II: Grafika
(ci¹g dalszy ze strony 745)
RealizePalette (hdc)
UpdateColors (hdc) ;
ReleaseDC (hwnd, hdc) ;
break :
case WM_DESTROY:
Delete0bject (hPalette) ;
PostOuitMessage (0) ;
return 0 ;
)
return DefWindowProc (hwnd, message, wParam, lParam) ;
Rysunek 16-2. Program GRAYS2
Pierwszym krokiem, który nale¿y wykonaæ u¿ywaj¹c Palette Managera, jest utwo-
rzenie logicznej palety poprzez wywo³anie funkcji CreatePalette. Paleta logiczna
zawiera wszystkie kolory, tzn. 236 kolorów niezbêdnych dla aplikacji. Program
GRAYSI wykonuje to zadanie po wyst¹pieniu komunikatu 4VMþCREATE. Ini-
cjuje pola struktury LOGPALETTE ("paleta logiczna") i przekazuje funkcji Cre-
atePalette wskaŸnik do tej struktury. Funkcja CreatePalette zwraca uchwyt palety
logicznej. Uchwyt jest przechowywany w zmiennej statycznej hPalette.
Struktura LOGPALETTE jest zdefiniowana nastêpuj¹co:
typedef struct
(
WORD palVersion;
WORD palNumEntries;
PALETTEENTRY palPalEntry[1];
)
LOGPALETTE, *PLOGPALETTE;
Pierwsze pole struktury przyjmuje wartoϾ 0x0300, co oznacza zgodnoϾ z systemem
Windows 3.0. Drugie pole zawiera liczbê wartoœci znajduj¹cych siê w tablicy palety.