trouble using windows setTimer function with opnGL

I am trying to use the ‘setTimer’ function to set the speed of my openGL application. I create a timer, which generates a WM_TIMER message in my message loop every second. My windows procedure then calls an update() function whenever this message is sent, but there is a problem. The update function isn’t called every second, its called continuously. Even more peculiar, if i insert into the update() function a statement to display a windows dialog box: MessageBox(0,“hello world!”,“MessageBox”,0); a new messagebox is generated every second (regardless of whether the old one was closed) and the application runs at the correct speed in the background.

Why should creating a dialog box in my WM_TIMER event function cause the application to update at the correct speed?

Here is a stripped down version of my program which has the same problem… The timer is created in the WM_CREATE event of the windows procedure, using SetTimer( hwnd, TIMER, 1000, NULL ); This generates a WM_TIMER message every 1000 milliseconds and this event calls my update() function.


#include "stdafx.h"
#include "openGLpractice.h"

#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include <iostream>

#define TIMER 1

bool done;
float angle=0.0f;
HDC g_HDC;

int SCENE_WIDTH, SCENE_HEIGHT;
int VIEWPORT_WIDTH, VIEWPORT_HEIGHT;


void update()
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glLoadIdentity();

	angle=angle+5.0f; // rotate triangle
	if (angle >= 360) angle=0;

	glTranslatef(0.0f,0.0f,-5.0f);
	glRotatef(angle, 0.0f,0.0f,1.0f);
	glColor3f(1.0f,0.0f,0.0f);
	
	glBegin(GL_TRIANGLES);
		glVertex3f(0.0f,0.0f,0.0f);
		glVertex3f(1.0f,0.0f,0.0f);
		glVertex3f(1.0f,1.0f,0.0f);
	glEnd();
	
	SwapBuffers(g_HDC);
	
	// comment out this statement, and the timer no longer works!
	MessageBox(0,"hello world!","MessageBox",0);
}

void reshape (int w, int h)
{ 
   VIEWPORT_WIDTH = w;
   VIEWPORT_HEIGHT = h;
   SCENE_WIDTH = 640; // arbitrary
   SCENE_HEIGHT = (int)(SCENE_WIDTH*h/((float)w));
   glViewport (0, 0, (GLsizei) VIEWPORT_WIDTH, (GLsizei) VIEWPORT_HEIGHT);
   glMatrixMode (GL_PROJECTION);
   glLoadIdentity ();   
   gluPerspective(30.0f, SCENE_WIDTH/(float)SCENE_HEIGHT, 1, 1000);

   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}

void SetupPixelFormat(HDC hDC)
{
	int nPixelFormat;

	static PIXELFORMATDESCRIPTOR pfd = {
		sizeof(PIXELFORMATDESCRIPTOR),
		1,
		PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER,
		PFD_TYPE_RGBA, 32, 0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,
		PFD_MAIN_PLANE,
		0,0,0,0};

	nPixelFormat=ChoosePixelFormat(hDC, &pfd);
	SetPixelFormat(hDC,nPixelFormat,&pfd);
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
	static HGLRC hRC;
	static HDC hDC;
	int width, height;

	switch(message)
	{
		case WM_CREATE:
			
			hDC=GetDC(hwnd);
			g_HDC=hDC;
			SetupPixelFormat(hDC);
			hRC=wglCreateContext(hDC);
			wglMakeCurrent(hDC,hRC);
			SetTimer( hwnd, TIMER, 1000, NULL ); // create the timer, once every second
		return 0;
		break;

		case WM_CLOSE:
			wglMakeCurrent(g_HDC,0);
			wglDeleteContext(hRC);
			KillTimer( hwnd, TIMER );
			done=true;
		return 0;
		break;

		case WM_SIZE:
			height=HIWORD(lParam);
			width=LOWORD(lParam);
			reshape(width,height); // call my own reshape function

		return 0;
		break;
	
		case WM_TIMER:
			update(); // rotate and draw the triangle
		            
		return 0;
		break;
			
		default:
			break;
	}
	return (DefWindowProc(hwnd, message,wParam,lParam));
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
	
	
	WNDCLASSEX windowClass;
	HWND hwnd;
	MSG msg;
	
	windowClass.cbSize=sizeof(WNDCLASSEX);
	windowClass.style=CS_HREDRAW | CS_VREDRAW;
	windowClass.lpfnWndProc=WndProc;
	windowClass.cbClsExtra=0;
	windowClass.cbWndExtra=0;
	windowClass.hInstance=hInstance;
	windowClass.hIcon=LoadIcon(NULL,IDI_APPLICATION);
	windowClass.hCursor=LoadCursor(NULL,IDC_ARROW);
	windowClass.hbrBackground=NULL;
	windowClass.lpszMenuName =NULL;
	windowClass.lpszClassName="MyClass";
	windowClass.hIconSm=LoadIcon(NULL,IDI_WINLOGO);

	if (!RegisterClassEx(&windowClass))
		return 0;
		
	hwnd=CreateWindowEx(NULL, "MyClass", "The OpenGL Window Application", 
						WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
						100,100,
						400,400,
						NULL,
						NULL,
						hInstance,
						NULL);
	if (!hwnd)
		return 0;
	
	ShowWindow(hwnd,SW_SHOW);
	UpdateWindow(hwnd);
	
	done=false;

	while (!done)
	{
		PeekMessage(&msg,hwnd,NULL,NULL, PM_REMOVE);

		if (msg.message==WM_QUIT)
			done=true;
		else
		{
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}
	}
	return msg.wParam;
}

You simply flood Windows to translate+dispatch messages that you’ve already processed. PeekMessage() returns false when there’s nothing to peek :slight_smile: .
So, change that line into


if(!PeekMessage(&msg,hwnd,NULL,NULL, PM_REMOVE))continue;