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;
}