/* ball.cpp Demonstrates animated drawing */
#include <windows.h>
#include "ball.h" /* constants: VELOCITY, BALLRAD, MINRAD */
BOOL _bDrawOn = FALSE ; /* global to track if drawing is on or off */
int _nXSize, _nYSize ; /* window width and height */
int PASCAL WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow)
{
HWND hWnd ; /* the window's "handle" */
MSG msg ; /* a message structure */
WNDCLASS wndclass ; /* window class structure */
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, NULL) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH)GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = "MYMENU" ;
wndclass.lpszClassName = "MyClass" ;
if (!RegisterClass (&wndclass))
return 0 ;
hWnd = CreateWindow ("MyClass","Ball", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL) ;
ShowWindow (hWnd, nCmdShow) ;
UpdateWindow (hWnd) ;
while (TRUE) /* peek message loop */
{
if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
if (msg.message == WM_QUIT) /* if WM_QUIT, quit! */
return msg.wParam ;
else /* else, process message */
{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
}
else if (_bDrawOn) /*no msg so paint ball..*/
DrawBall (hWnd) ; /*if drawing enabled */
}
}
LRESULT CALLBACK WndProc (HWND hWnd, UINT wMessage,
WPARAM wParam, LPARAM lParam)
{
switch (wMessage) /* process windows messages */
{
case WM_CREATE: /* application starting, turn draw off */
_bDrawOn = FALSE ;
break ;
case WM_SIZE : /* get window client area size */
_nXSize = LOWORD (lParam) ;
_nYSize = HIWORD (lParam) ;
break ;
case WM_COMMAND: /* menu items selected */
switch (LOWORD(wParam))
{
case IDM_SHOW:
if (_bDrawOn)
_bDrawOn = FALSE ; /* toggle drawing on/off */
else
_bDrawOn = TRUE ;
break ;
case IDM_QUIT:
DestroyWindow (hWnd) ;
break ;
}
break ;
case WM_DESTROY:
PostQuitMessage (0) ;
break ;
default:
return DefWindowProc (hWnd, wMessage, wParam, lParam) ;
}
return (0) ;
}
/* DrawBall() draws a red ball on the window hWnd every time the */
/* function is called. The ball is BALLRAD in radius. The walls */
/* (client area size) are from 0,0 to nXSize,nYsize. The location */
/* is moved each time by VELOCITY units. The signs of the X and Y */
/* velocity terms nVelX,nVelY are reversed each time the ball gets */
/* within MINRAD units of a wall. This causes the ball to appear */
/* to bounce off the wall. Drawing the ball at the new location */
/* causes the old ball to be erased, as the ball is drawn using a */
/* white pen for the outline that is 1.5 * VELOCITY in width. The */
/* white pen ends up painting over any portion of the ball that is */
/* otherwise visible from the previous location. */
void DrawBall (HWND hWnd)
{
HDC hDC ;
HPEN hPen, hOldPen ;
HBRUSH hBrush, hOldBrush ;
static int nX = 2 * BALLRAD, nY = 2 * BALLRAD, /* starting X,Y */
nVelX = VELOCITY, nVelY = VELOCITY; /* X,Y velocity */
int i, j; /* delay loop counters */
nX = nX + nVelX ; /* compute new center X,Y of ball */
nY = nY + nVelY ;
if (nY > _nYSize) /* check if user moved walls and hid ball */
nY = 2 * BALLRAD ; /* put the ball back at the starting.. */
if (nX > _nXSize) /* position if it is not going to be.. */
nX = 2 * BALLRAD ; /* visible with the new window size */
if (nY < MINRAD || nY > _nYSize - MINRAD) /* check if ball hit wall */
nVelY = -1 * nVelY ; /* if so, change direction */
if (nX < MINRAD || nX > _nXSize - MINRAD)
nVelX = -1 * nVelX ;
hDC = GetDC (hWnd) ; /* get the device context handle */
/* Create a thick white pen and a red brush */
hPen = CreatePen (PS_SOLID, VELOCITY + VELOCITY/2, RGB(255,255,255) );
hBrush = CreateSolidBrush (RGB (255, 0, 0)) ;
hOldPen = (HPEN)SelectObject (hDC, hPen) ; /* select into the DC */
hOldBrush = (HBRUSH)SelectObject (hDC, hBrush) ;
/* draw the ball in the new location */
/* the outline pen erases around ball */
Ellipse (hDC, nX - BALLRAD, nY - BALLRAD, nX + BALLRAD, nY + BALLRAD) ;
/* wait for a while to slow things down */
Sleep(10) ;
/* delete all objects and free DC */
SelectObject (hDC, hOldPen) ;
DeleteObject (hPen) ;
SelectObject (hDC, hOldBrush) ;
DeleteObject (hBrush) ;
ReleaseDC (hWnd, hDC) ;
}