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>(&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(&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?