PDA

View Full Version : Strange behaviour very basic OpenGL app



Heiko
08-27-2009, 01:21 PM
I'm fairly new to Microsoft Windows programming, but I'm trying to create a portable (Linux and Windows) window class. To create an OpenGL window in Windows I started out from the example in the OpenGL Superbible and that worked. But now I wanted to put the window creation code in a class and things started to get ugly. Everything worked until I started changing class member variables from the message handling switch... below is the relevant code:



/************************************************** ***********
* A static member function of the class Window that
* creates and returns a new window.
* This function is called from WinMain.
************************************************** **********/
Window &Window::createWindow(HINSTANCE hInstance)
{
WNDCLASS wc;

wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;

// use a static member function for WNDPROC
wc.lpfnWndProc = reinterpret_cast<WNDPROC>(&amp;Window::staticWndProc);
wc.cbClsExtra = 0;

// reserve extra room for a pointer to a Window instance
wc.cbWndExtra = sizeof(Window *);
wc.hInstance = hInstance;
wc.hIcon = NULL;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "myApp";

if (RegisterClass(&amp;wc) == 0)
throw std::string("error");

HWND hWnd = CreateWindow(
"myApp",
"myApp",
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
100, 100,
250, 250,
NULL,
NULL,
hInstance,
NULL);

if (hWnd == NULL)
throw std::string("error");

Window *win = new Window;

// store a pointer to the Window instance in DWLP_USER
SetWindowLongPtr(hWnd, DWLP_USER, reinterpret_cast<long>(win));

ShowWindow(hWnd, SW_SHOW);
UpdateWindow(hWnd);

return *win;
}


/************************************************** ***********
* The static wndProc member function of the class Window.
* Handles all messages for the window.
* It just gets the stored pointer to the Window instance and
* passes the message to the instance.
************************************************** **********/
LRESULT CALLBACK Window::staticWndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
// get the pointer that was stored in DWLP_USER
Window *wnd = reinterpret_cast<Window *>(GetWindowLongPtr(hWnd, DWLP_USER));

// pass the message along to the Window instance
return wnd->wndProc(hWnd, message, wParam, lParam);
}


/************************************************** ***********
* A (non-static) member function of class Window.
* Gets the message to be handled from the static wndproc
* member function.
*
* If a member variable of the class Window is changed within
* this code, things start going wrong.
************************************************** **********/
LRESULT CALLBACK Window::wndProc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam)
{
switch (message)
{
case WM_CREATE:
{
HDC hDC = GetDC(hWnd);
setDCPixelFormat(hDC);

HGLRC hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);

SetTimer(hWnd, 33, 1, NULL);
break;
}
case WM_DESTROY:
{
KillTimer(hWnd, 101);

HDC hDC = GetDC(hWnd);
wglMakeCurrent(hDC, NULL);

HGLRC hRC = wglGetCurrentContext();
wglDeleteContext(hRC);

PostQuitMessage(0);
break;
}
case WM_SIZE:
{
//ChangeSize(LOWORD(lParam), HIWORD(lParam));
break;
}
case WM_TIMER:
{
//IdleFunction();


// this line causes a `test.exe has stopped working'
++d_count;



InvalidateRect(hWnd, NULL, false);
break;
}
case WM_PAINT:
{
//RenderScene();


// this line causes the Window not to be updated
// (contents of the desktop can be seen through the window)
++d_count;

HDC hDC = GetDC(hWnd);
SwapBuffers(hDC);


// if I put the statement overhere, everything seems ok...
++d_count;

ValidateRect(hWnd, NULL);
break;
}
default:
return (DefWindowProc(hWnd, message, wParam, lParam));
}

return (0L);
}

In the final function you can see various `++d_count' statements that cause problems. The variable d_count is a size_t member variable of the class Window that is properly initialized to 0 when the constructor of the class is called.

Does anybody have a clue why this is causing problems?

Heiko
08-27-2009, 10:16 PM
It looks like I have it working. I'm using GWLP_USERDATA now instead of DWLP_USER to store the pointer to the instance. So far no strange behaviour.