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
 
Nothing wrong with the code snippet given. Perhaps you could give a full program reproducing the problem?
 
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:
Why not just run your code through a debugger. Then break it and you'll see where the infinite loop is occuring.
 
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