You are on page 1of 32

Windows GDI Programming

CIS 487/587
Bruce R. Maxim
UM-Dearborn
1

Validating
Whenever either you or Windows disturbs a
window a WM_PAINT message is sent
The area to be repainted is the invalid
rectangle
The coordinates of the invalid rectangle are
shipped with the WM_PAINT message as part
of the validating process

Processing WM_PAINT
BeginPaint( ) EndPaint( )
Advantage: all needed validating done
automatically
Disadvantage: invalid rectangle is same as
clipping rectangle (cant draw outside
invalid rectangle)
This approach fools Windows into believing
you fixed the invalid rectangle whether you
have drawn anything or not
3

Processing WM_PAINT
GetDC( ) ReleaseDC( )
Advantage:you can draw outside the invalid
rectangle
Disadvantage: you need to validate every
rectangle manually using ValidateRect( )

Note: With either method you need to be sure


that windows does not fill in your Background
to avoid losing your drawing
4

Invalidating Entire Window


case WM_PAINT:
{
// NULL is pointer to invalid rectangle
// meaning entire window
ValidateRect(hwnd,NULL);
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// fixes go here
EndPaint(hwnd,&ps); // end painting
return(0); // return success
} break;

Validating Entire Window


case WM_PAINT:
{
// NULL is pointer to invalid rectangle
// meaning entire window
ValidateRect(hwnd,NULL);
// simply validate the window without
// doing any drawing
return(0); // return success
} break;

Avoid Repaint
case WM_PAINT:
{
hdc = GetDC(hwnd);
// do graphics here
ReleaseDC(hwnd,hdc);
// validate the window to clear message
ValidateRect(hwnd,hdc);
return(0); // return success
} break;

Display Surface Basics


Resolutions in pixels
640x480, 800x600, 1024x768,

Color depth (# color bits per pixel)


6, 16, 24, 32

Color space (actual # available colors)


8 bits = 256 colors, 16 bits = 65536

Display Modes
RGB mode
True RGB values are encoded for each
pixel displayed

Palletized mode
Color indirection scheme
256 colors available
Value 0 to 255 is stored with each pixel
Color value looked up in CLUT
9

Color Objects
Windows uses to data structures
COLOREF: byte structure allows you to
create colors on the fly
PALETTEENTRY: all creation of pallets
with control flag components

Complete control of pallets is best done


using DirectX
10

Drawing Text
TextOut( )
No formatting or processing of text string is
done before it is displayed

DrawText( )
Allows justification, clipping, etc. prior to
displaying text string

11

LaMothe Examples

12

TextOut Example
main_window_handle = hwnd; // save main window handle
HDC hdc = GetDC(hwnd);
// get the dc and hold it
// set the foreground color to random
SetTextColor(hdc, RGB(rand()%256,rand()%256,rand()%256));
// set the background color to black
SetBkColor(hdc, RGB(0,0,0));
// finally set the transparency mode to transparent
SetBkMode(hdc, TRANSPARENT);
// draw some text at a random location
TextOut(hdc,rand()%400,rand()%400,
"GDI Text Demo!", strlen("GDI Text Demo!"));
ReleaseDC(hwnd,hdc);

// release the dc

13

What about WM_PAINT?


case WM_PAINT:
{
// simply validate the window
hdc = BeginPaint(hwnd,&ps);
// you would do all your painting here
EndPaint(hwnd,&ps);
// return success
return(0);
} break;

14

Additional Issues
You should consider saving the old
values for foreground, ground, and
transparency so that you can restore
them after you set them
Example we might declare the following:
COLORREF old_fcolor, // old foreground
old_bcolor; // old background
int old_tmode;
// old transparency

15

TextOut Example 2
main_window_handle = hwnd; // save main window handle
HDC hdc = GetDC(hwnd);
// get the dc and hold it
// save old attributes and set new
old_fcolor = SetTextColor(hdc,RGB(255,255,255));
old_bcolor = SetBkColor(hdc, RGB(0,0,0));
old_tmode= SetBkMode(hdc, TRANSPARENT);
// draw some text at a random location
TextOut(hdc, 120, 200, Hello", strlen(Hello"));
// Restore the old values
SetTextColor(hdc, old_fcolor);
SetBkColor(hdc, old_bcolor);
SetBkMode(hdc, old_tmode);
ReleaseDC(hwnd,hdc);
// release the dc

16

Text Metrics
The function GetTextMetrics can be used to
query the system for things like

Font height
Average width
Max width
First character defined in font
Last character defined in font

Set of values returned in fields of a parameter


of type tagTEXTMETRIC
17

Drawing Shapes
GDI allows you to draw things like

Points
Lines
Circles and ellipses
Rectangles
Curves
Polygons
Bitmaps
Metafiles (instructions that can be replayed)
18

Pens
Pens are GDI objects used to draw lines
Pens have two attributes
RGB color
Styles like

PS_DASH
---PS_DOT
....
PS_DASHDOT _ . _ .
PS_NULL

19

Using a Pen
// get the graphics device context
hdc = GetDC(hwnd);
// create a red colored pen
HPEN red_pen = CreatePen(PS_SOLID,1,RGB(255, 0, 0));
// selecting pen and saving old value
HPEN old_hpen = (HPEN)SelectObject(hdc,red_pen);
// draw with pen
// deleting pen
SelectObject(hdc,old_hpen);
DeleteObject(red_ pen);
// release the device context
ReleaseDC(hwnd,hdc)

20

Brushes
Brushes are used to fill in line objects
Examples
// creating a solid brush
HBRUSH blue_brush = CreateSolidBrush(RGB(0,0,255));
// creating a patterned brush
HBRUSH green_brush =
CreateHatchBrush(HS_DIAGCROSS, RGB(0,255,0));
// creating a bitmap brush (8x8)
HBRUSH bitmap_brush =
CreatePatternBrush(hBitMap);

21

Selecting and Destroying


Brushes
// select brush and save old brush
HBRUSH old_brush = SelectObject(hdc, red_brush);
// use the brush
// restore old brush
SelectObject(hdc, old_brush);
DeleteObject(red_brush);

22

Plotting Points
hdc = GetDC(hwnd); // get the dc for the window
// draw 1000 pixels
for (int index=0; index < 1000; index++)
// get random position
int x = rand()%400;
int y = rand()%300;

COLORREF color = RGB(rand()%255,rand()%255,rand()


%255);
SetPixel(hdc, x,y, color);
} // end for index
ReleaseDC(hwnd, hdc); // release the dc

23

Drawing Lines
// create pen
HPEN red_pen = CreatePen(PS_SOLID,1,RGB(255, 0, 0));
// selecting pen and saving old value
SelectObject(hdc,red_pen);
// move to starting point
MoveToEx(hdc,rand()%WINDOW_WIDTH,rand()%WINDOW_HEIGHT,NULL);
// draw the line
LineTo(hdc,rand()%WINDOW_WIDTH,rand()%WINDOW_HEIGHT);

24

Drawing Rectangles
hdc = GetDC(hwnd); // get the graphics device context
RECT rect; // used to hold rect info
// create a random rectangle
rect.left
= rand()% WINDOW_WIDTH;
rect.top
= rand()% WINDOW_HEIGHT;
rect.right = rand()% WINDOW_WIDTH;
rect.bottom = rand()% WINDOW_HEIGHT;
// create a random brush
HBRUSH hbrush = CreateSolidBrush(RGB(100, 50, 80));
// draw either a filled rect or a wireframe rect
if ((rand()%2)==1)
FillRect(hdc,&rect,hbrush);
else
FrameRect(hdc,&rect,hbrush);
DeleteObject(hbrush); // now delete the brush
ReleaseDC(hwnd,hdc);// release the device context

25

Drawing Circles and Ellipses


Circle is special case of ellipse
To draw a circle at (100, 100) with diameter 20
Ellipse(hdc, 90, 90,110, 110);

To draw an ellipse centered at (100, 100) with major


axis 100 and minor axis 60
Ellipse(hdc, 100-50, 100-30, 100+50, 100+30);

26

Bouncing Ball
An old computer animators trick is to
Draw an object using the foreground color
Erase object by redrawing in the
background color
Change the object screen coordinates and
draw again in the foreground color

We can make use of this trick and use


Ellipse to draw a bouncing ball
27

Bouncing Ball
hdc = GetDC(hwnd);
// create the pens
HPEN
white_pen =
HPEN
black_pen =
HBRUSH green_brush
HBRUSH black_brush

and brushes
CreatePen(PS_SOLID, 1, RGB(255,255,255));
CreatePen(PS_SOLID, 1, RGB(0,0,0));
= CreateSolidBrush(RGB(0,255,0));
= CreateSolidBrush(RGB(0,0,0));

// starting position of ball


int ball_x = WINDOW_WIDTH/2;
int ball_y = WINDOW_HEIGHT/2;
// initial velocity of ball
int xv = -4+rand() % 8;
int yv = -4+rand() % 8;

28

Bouncing Ball
// ERASE the last position of the ball
// first select the black pen and brush into context
SelectObject(hdc, black_pen);
SelectObject(hdc, black_brush);
// draw the ball
Ellipse(hdc, ball_x, ball_y, ball_x + 32, ball_y + 32);
// MOVE the ball
ball_x+=xv;
ball_y+=yv;
// test for collisions, first x-axis
if (ball_x < 0 || ball_x > WINDOW_WIDTH - 32)
{
// invert x-velocity of ball
xv=-xv;
// push ball back
ball_x+=xv;
} // end if
else
// test for y-axis collisions
if (ball_y < 0 || ball_y > WINDOW_HEIGHT - 32)
{
// invert y-velocity of ball
yv=-yv;
// push ball back
ball_y+=yv;
} // end if
// now select the green and white colors for brush and pen
SelectObject(hdc, white_pen);
SelectObject(hdc, green_brush);
// DRAW the ball
Ellipse(hdc, ball_x, ball_y, ball_x + 32, ball_y + 32);
// main game processing goes here
if (KEYDOWN(VK_ESCAPE))
SendMessage(hwnd, WM_CLOSE, 0,0);
// slow system down a little
Sleep(10);
} // end while
// delete all the objects
DeleteObject(white_pen);
DeleteObject(black_pen);
DeleteObject(green_brush);
DeleteObject(black_brush);
// release the device context
ReleaseDC(hwnd,hdc);

29

Bouncing Ball
// ERASE the last position of the ball
// first select the black pen and brush into context
SelectObject(hdc, black_pen);
SelectObject(hdc, black_brush);
// draw the ball
Ellipse(hdc, ball_x, ball_y, ball_x + 32, ball_y + 32);
// MOVE the ball
ball_x+=xv;
ball_y+=yv;

30

Bouncing Ball
// test for collisions, first x-axis
if (ball_x < 0 || ball_x > WINDOW_WIDTH - 32)
{
xv=-xv;
// invert x-velocity of ball
ball_x+=xv;
// push ball back
} // end if
else
// test for y-axis collisions
if (ball_y < 0 || ball_y > WINDOW_HEIGHT - 32)
{
yv=-yv;
// invert y-velocity of ball
ball_y+=yv;
// push ball back
} // end if

31

Bouncing Ball
// select the green and white colors for brush and pen
SelectObject(hdc, white_pen);
SelectObject(hdc, green_brush);
// DRAW the ball
Ellipse(hdc, ball_x, ball_y, ball_x + 32, ball_y + 32);
DeleteObject(white_pen); // delete all the objects
DeleteObject(black_pen);
DeleteObject(green_brush);
DeleteObject(black_brush);
ReleaseDC(hwnd,hdc); // release the device context

32

You might also like