PDA

View Full Version : trouble using windows setTimer function with opnGL



mikau
08-17-2009, 02:25 PM
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, &amp;pfd);
SetPixelFormat(hDC,nPixelFormat,&amp;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(&amp;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(&amp;msg,hwnd,NULL,NULL, PM_REMOVE);

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

Ilian Dinev
08-22-2009, 11:45 PM
You simply flood Windows to translate+dispatch messages that you've already processed. PeekMessage() returns false when there's nothing to peek :) .
So, change that line into


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