C++ Timers

Soldato
Joined
7 Apr 2004
Posts
4,212
Hey,

Can someone tell me why this dosnt work, im trying to start a simple timer using SetTimer(), heres some code segments:

Code:
...
#define ID_TIMER 8001

...

CASE WM_CREATE:
     SetTimer(hWnd, ID_TIMER, 1000, NULL);
break;
case WM_TIMER:
     //execution code here
break;
case WM_DESTROY:
     KillTimer(hWnd, ID_TIMER);
break;

I get no compile errors, its just my code in WM_TIMER is never executed, i have also tried making a TIMERPROC but its never executed either, i tried chaing the ID to and that made no difference, any idea why it isnt working :confused:

Thanks
 
Hey ive just checked and my program is maxing one of my CPU cores, Not sure why this is happening, i havnt done c++ for a few years, just trying to make a GUI snake game. I assume it could be down to excessive looping in the WM_PAINT message, or incorect use of GDI functions :confused: Could you possibly look through the code and tell me what ive done wrong.

Code:
#include <windows.h>

#define WIN32_LEAN_AND_MEAN

#define ID_STARTBTN 8000
#define ID_TIMER	8001

const LPCWSTR g_szClassName = TEXT("SNAKEGAME");
const LPCWSTR g_szWindowName = TEXT("Snake Game");
HINSTANCE mhInst;

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
void PlaceSnakeCell(HDC hdc, int x_square, int y_square);
void ClearSnakeCell(HDC hdc, int x_square, int y_square);
void MoveSnakeCell(HDC hdc, int direction);

int gridcells[40][44] = {0};
int m_gridcells[40][44] = {0};


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;
	mhInst = hInstance;

    wc.cbSize        = sizeof(WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = WndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = g_szClassName;
    wc.hIconSm       = LoadIcon(NULL, IDI_APPLICATION);

    if(!RegisterClassEx(&wc))
    {
        MessageBox(NULL, TEXT("Window Registration Failed"), TEXT("Error"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }


    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        g_szWindowName,
		WS_OVERLAPPED | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, 451, 480,
        NULL, NULL, hInstance, NULL);

    if(hwnd == NULL)
    {
        MessageBox(NULL, TEXT("Window Creation Failed"), TEXT("Error"),
            MB_ICONEXCLAMATION | MB_OK);
        return 0;
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

   
    while(GetMessage(&Msg, NULL, 0, 0) > 0)
    {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

	return Msg.wParam;
}


LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
	HDC hDC;
	int i, j;

    switch(msg)
    {
		case WM_CREATE:
			CreateWindowEx(0,
						   TEXT("BUTTON"),
						   TEXT("Start"),
						   WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON,
						   370,
						   410, 
						   70,
						   25,   
						   hWnd, 
						   (HMENU) ID_STARTBTN,     
						   mhInst,
						   NULL);  
			SetTimer(hWnd, ID_TIMER, 1000, NULL);
		break;
		case WM_COMMAND:
			switch(wParam)
			{
			case ID_STARTBTN:
				hDC = GetDC(hWnd);
				SetBkMode(hDC, TRANSPARENT);
				PlaceSnakeCell(hDC, 2, 40);		// place start cell (2,40)
				ReleaseDC(hWnd, hDC);
			break;
			}
		break;
		case WM_TIMER:   // NEVER EXECUTED
			// move cell accordingly
			MessageBox(hWnd, TEXT("timer code"), TEXT("timer code"), NULL);
		break;
		case WM_PAINT:
			hDC = GetDC(hWnd);
			SetBkMode(hDC, TRANSPARENT);

			// draw horizontal grid 44x40
			for(i=10; i < 400; i = i+10)
			{
				MoveToEx(hDC, 0, i, NULL);
				LineTo(hDC, 440, i);
			}
			
			// draw verticle grid 44x40
			for(i=10; i<450; i=i+10)
			{
				MoveToEx(hDC, i, 0, NULL);
				LineTo(hDC, i, 400);
			}

			// control line
			MoveToEx(hDC, 0, 400, NULL);
			LineTo(hDC, 480, 400);

			// update filled cells
			for (i=1; i<44; i++)
			{
				for(j=1; j<40; j++)
				{
					if(gridcells[i][j] == 1)
					{
						PlaceSnakeCell(hDC, j, i);
					}
				}
			}

			ReleaseDC(hWnd, hDC);
		break;
		case WM_KEYDOWN:
			hDC = GetDC(hWnd);
			switch(wParam)
			{
				case VK_UP:
					MoveSnakeCell(hDC, 1);
				break;
				case VK_RIGHT:
					MoveSnakeCell(hDC, 2);
				break;
				case VK_DOWN:
					MoveSnakeCell(hDC, 3);
				break;
				case VK_LEFT:
					MoveSnakeCell(hDC, 4);
				break;

			}
			ReleaseDC(hWnd, hDC);
		break;
        case WM_CLOSE:
            DestroyWindow(hWnd);
        break;
        case WM_DESTROY:
            PostQuitMessage(0);
        break;
        default:
            return DefWindowProc(hWnd, msg, wParam, lParam);
    }
    return 0;
}

void PlaceSnakeCell(HDC hdc, int x_square, int y_square)
{

	int c_top;
	int c_left;

	if(y_square == 1)
	{
		c_top = (y_square * 10) - 10;
	}
	else
	{
		c_top = (y_square * 10) - 9;
	}

	if(x_square == 1)
	{
		c_left = (x_square * 10) - 10;
	}
	else
	{
		c_left = (x_square * 10) - 9;
	}



	RECT gridbox;
	gridbox.top = c_top;
	gridbox.left = c_left;
	gridbox.right = (x_square * 10);
	gridbox.bottom = y_square * 10;

	HBRUSH hbr;
	hbr = CreateSolidBrush(RGB(0,255,0));

	FillRect(hdc, &gridbox, hbr);
	DeleteObject(hbr);

	// update cell index
	gridcells[y_square][x_square] = 1;

}




void ClearSnakeCell(HDC hdc, int x_square, int y_square)
{
	int c_top;
	int c_left;

	if(y_square == 1)
	{
		c_top = (y_square * 10) - 10;
	}
	else
	{
		c_top = (y_square * 10) - 9;
	}

	if(x_square == 1)
	{
		c_left = (x_square * 10) - 10;
	}
	else
	{
		c_left = (x_square * 10) - 9;
	}

	RECT gridbox;
	gridbox.top = c_top;
	gridbox.left = c_left;
	gridbox.right = (x_square * 10);
	gridbox.bottom = y_square * 10;

	HBRUSH hbr;
	hbr = CreateSolidBrush(RGB(255,255,255));

	FillRect(hdc, &gridbox, hbr);
	DeleteObject(hbr);

	// update cell index
	gridcells[y_square][x_square] = 0;
}

void MoveSnakeCell(HDC hdc, int direction)
{
/*
direction 1: UP
direction 2: RIGHT
direction 3: DOWN
direction 4: LEFT
*/
	int temp = 0;

	switch(direction)
	{
	case 1:
			for(int i=1; i < 45; i++)
			{
				for(int j=1; j<41; j++)
				{
					if(gridcells[j][i] == 1)
					{
						if(j == 1)	// prevent cell movement above top line
						{ break; }
						else 
						{
							ClearSnakeCell(hdc, i, j); 
							PlaceSnakeCell(hdc, i, j-1);
						}
					}
				}
			}
		break;
		case 2:
			for(int i=1; i < 45; i++)
			{
				for(int j=1; j<41; j++)
				{
					if(gridcells[j][i] == 1 && m_gridcells[j][i] != 1)
					{	
						if(i == 44)
						{ break; }
						else
						{
							ClearSnakeCell(hdc, i, j); 
							PlaceSnakeCell(hdc, i+1, j);
							m_gridcells[j][i+1] = 1;
						}
					}
				}
			}
		break;
	case 4:
			for(int i=1; i < 45; i++)
			{
				for(int j=1; j<41; j++)
				{
					if(gridcells[j][i] == 1)
					{	
						if(i == 1)
						{ break; }
						else
						{
							ClearSnakeCell(hdc, i, j); 
							PlaceSnakeCell(hdc, i-1, j);
						}
					}
				}
			}
		break;
	case 3:
			for(int i=1; i < 45; i++)
			{
				for(int j=1; j<41; j++)
				{
					if(gridcells[j][i] == 1 && m_gridcells[j][i] != 1)
					{	
						if(j == 40) // prevent cell movement below base line
						{ break; }
						else
						{
							ClearSnakeCell(hdc, i, j); 
							PlaceSnakeCell(hdc, i, j+1);
							m_gridcells[j+1][i] = 1;
						}
					}
				}
			}
		break;
	}



	// reset moved cell array
	for(int i=1; i < 45; i++)
		{
			for(int j=1; j<41; j++)
			{
				m_gridcells[j][i] = 0;
			}
		}
}
 
Last edited:
No inifinite loop is occurring, your just not dealing with lots of window messages, so your message queue just keeps growing.

The return of your winproc should be:

Code:
return DefWindowProc(hWnd, msg, wParam, lParam);

to let the default message proc have access to the messages you recieve, instead of returning 0 (some messages do require you to do this though just not all).

Also your failing to handle WM_PAINT properly (msdn is your frined here...) the general structure should be:

Code:
PAINTSTRUCT ps;
...
case WM_PAINT: 
            hdc = BeginPaint(hwnd, &ps); 
            ... drawing code here
            EndPaint(hwnd, &ps); 
            return 0L;

Without BeginPaint() EndPaint(), you will just keep recieving WM_PAINT messages.
 
Last edited:
Back
Top Bottom