Alright, firstly I run compile the NeHe Lesson 01 as-is just fine. The difference between the code I'm having a problem with and the NeHe code is primarily that I put my version into a class. Other than that it's pretty much the same thing. I stepped through my code and it fails getting a DC and quits. So my question: Why does the way I did it not work! I can't say for sure what the problem is so I'm just including everything, but my guess is that the problem lies in the fact that I used classes at all and something just isn't in a place where it is supposed to be... The basic rundown of what's going on: 1. The OpenGLWindow class is most of NeHe's openGL window creation code. The functions have slightly different names but they're pretty similar. 2. The OpenGLWindow class is instantiated with global scope with a pointer to the OpenGLWindow object. 3. The object's Create function is called from WinMain, and it makes it up to trying to get a DC, and fails to get it. OpenGLWindow.h (sorry for the formatting on this one, it appears source tags don't like my style of tabbing)
#ifndef __OpenGLWindow__
#define __OpenGLWindow__
#include <windows.h>
#include <gl\gl.h>
#include <gl\glu.h>
LRESULT CALLBACK WindowProcedure(HWND, UINT, WPARAM, LPARAM);
class OpenGLWindow
{
private:
HGLRC rendering_context;
HDC device_context;
HWND window_handle;
HINSTANCE application_instance;
bool keys[256];
bool active;
bool fullscreen;
public:
OpenGLWindow();
~OpenGLWindow();
void Resize(GLsizei, GLsizei);
void InitializeOpenGL();
void Close();
void Draw();
bool Create(char*, int, int, int, bool);
HGLRC GetRenderingContext() { return rendering_context; }
HDC GetDeviceContext() { return device_context; }
HWND GetWindowHandle() { return window_handle; }
HINSTANCE GetApplicationInstance() { return application_instance; }
void SetRenderingContext(HGLRC rc) { rendering_context = rc; }
void SetDeviceContext(HDC dc) { device_context = dc; }
void SetWindowHandle(HWND wh) { window_handle = wh; }
void SetApplicationInstance(HINSTANCE ai) { application_instance = ai; }
bool KeyDown(unsigned char vk) { return keys[vk]; }
void SetKeyDown(WPARAM vk) { keys[vk] = true; }
void SetKeyUp(WPARAM vk) { keys[vk] = false; }
bool GetActive() { return active; }
bool GetFullscreen() { return fullscreen; }
void SetActive(bool a) { active = a; }
void SetFullscreen(bool f) { fullscreen = f; }
};
extern OpenGLWindow* MainWindow;
#endif // __OpenGLWindow__
OpenGLWindow.cpp
#include "OpenGLWindow.h"
OpenGLWindow* MainWindow = new OpenGLWindow;
OpenGLWindow::OpenGLWindow()
{
active = true;
fullscreen = true;
}
OpenGLWindow::~OpenGLWindow()
{
}
void OpenGLWindow::Resize(GLsizei width, GLsizei height)
{
if (height == 0)
{
height = 1;
}
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}
void OpenGLWindow::InitializeOpenGL()
{
glShadeModel(GL_SMOOTH);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
void OpenGLWindow::Close()
{
if (fullscreen)
{
ChangeDisplaySettings(NULL, 0);
ShowCursor(TRUE);
}
if (rendering_context)
{
if (!wglMakeCurrent(NULL, NULL))
{
// Release of DC and RC failed
}
if (!wglDeleteContext(rendering_context))
{
// Release of RC failed
}
rendering_context = NULL;
}
if (device_context && !ReleaseDC(window_handle, device_context))
{
// Release DC failed
device_context = NULL;
}
if (window_handle && !DestroyWindow(window_handle))
{
// Release hWnd failed
window_handle = NULL;
}
if (!UnregisterClass((LPCTSTR)"OpenGL", application_instance))
{
// Could not unregister class
application_instance = NULL;
}
}
void OpenGLWindow::Draw()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
}
bool OpenGLWindow::Create(char* title, int width, int height, int bits, bool fullscreen_flag)
{
GLuint pixel_format;
WNDCLASS window_class;
DWORD dwExStyle;
DWORD dwStyle;
RECT window_rect;
window_rect.left = (long)0;
window_rect.right = (long)width;
window_rect.top = (long)0;
window_rect.bottom = (long)height;
fullscreen = fullscreen_flag;
application_instance = GetModuleHandle(NULL);
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
window_class.lpfnWndProc = (WNDPROC)WindowProcedure;
window_class.cbClsExtra = 0;
window_class.cbWndExtra = 0;
window_class.hInstance = application_instance;
window_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
window_class.hCursor = LoadCursor(NULL, IDC_ARROW);
window_class.hbrBackground = NULL;
window_class.lpszMenuName = NULL;
window_class.lpszClassName = "brknogl";
if (!RegisterClass(&window_class))
{
// Couldn't register the window class
return false;
}
if (fullscreen)
{
DEVMODE screen_settings;
memset(&screen_settings, 0, sizeof(screen_settings));
screen_settings.dmSize = sizeof(screen_settings);
screen_settings.dmPelsWidth = width;
screen_settings.dmPelsHeight = height;
screen_settings.dmBitsPerPel = bits;
screen_settings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
if (ChangeDisplaySettings(&screen_settings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
{
// Fullscreen mode failed
fullscreen = false;
}
}
if (fullscreen)
{
dwExStyle = WS_EX_APPWINDOW;
dwStyle = WS_POPUP;
ShowCursor(FALSE);
}
else
{
dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
dwStyle = WS_OVERLAPPEDWINDOW;
}
AdjustWindowRectEx(&window_rect, dwStyle, FALSE, dwExStyle);
CreateWindowEx( dwExStyle,
"brknogl",
title,
WS_CLIPSIBLINGS |
WS_CLIPCHILDREN |
dwStyle,
0, 0,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
NULL,
NULL,
application_instance,
NULL
);
if (!window_handle)
{
// Couldn't create the window
Close();
return false;
}
static PIXELFORMATDESCRIPTOR pixel_format_descriptor =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW |
PFD_SUPPORT_OPENGL |
PFD_DOUBLEBUFFER,
PFD_TYPE_RGBA,
bits,
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
16,
0,
0,
PFD_MAIN_PLANE,
0,
0, 0, 0
};
device_context = GetDC(window_handle);
if (!device_context)
{
// Couldn't get DC
Close();
return false;
}
pixel_format = ChoosePixelFormat(device_context, &pixel_format_descriptor);
if (!pixel_format)
{
// Couldn't find matching pixel format
Close();
return false;
}
if (!SetPixelFormat(device_context, pixel_format, &pixel_format_descriptor))
{
// Couldn't set pixel format
Close();
return false;
}
rendering_context = wglCreateContext(device_context);
if (!rendering_context)
{
// Couldn't get RC
Close();
return false;
}
if (!wglMakeCurrent(device_context, rendering_context))
{
// Couldn't activate rendering context
Close();
}
ShowWindow(window_handle, SW_SHOW);
SetForegroundWindow(window_handle);
SetFocus(window_handle);
Resize(width, height);
InitializeOpenGL();
return true;
}
LRESULT CALLBACK WindowProcedure(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_ACTIVATE:
{
if (!HIWORD(wParam))
{
MainWindow->SetActive(true);
}
else
{
MainWindow->SetActive(false);
}
return 0;
}
case WM_SYSCOMMAND:
{
switch (wParam)
{
case SC_SCREENSAVE:
case SC_MONITORPOWER:
return 0;
}
break;
}
case WM_CLOSE:
{
PostQuitMessage(0);
return 0;
}
case WM_KEYDOWN:
{
MainWindow->SetKeyDown(wParam);
return 0;
}
case WM_KEYUP:
{
MainWindow->SetKeyUp(wParam);
return 0;
}
case WM_SIZE:
{
MainWindow->Resize(LOWORD(lParam), HIWORD(lParam));
return 0;
}
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
WinMain.cpp
#include "OpenGLWindow.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG message;
bool quit = false;
#ifdef FULLSCREEN
MainWindow->SetFullscreen(true);
#else
MainWindow->SetFullscreen(false);
#endif
MainWindow->Create("OpenGL Window", 640, 480, 16, MainWindow->GetFullscreen());
while (!quit)
{
if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
{
if (message.message == WM_QUIT)
{
quit = true;
}
else
{
TranslateMessage(&message);
DispatchMessage(&message);
}
}
else
{
if (MainWindow->GetActive())
{
if (MainWindow->KeyDown(VK_ESCAPE))
{
quit = true;
}
else
{
MainWindow->Draw();
SwapBuffers(MainWindow->GetDeviceContext());
}
}
if (MainWindow->KeyDown(VK_F1))
{
MainWindow->SetKeyUp(VK_F1);
MainWindow->Close();
MainWindow->SetFullscreen(!MainWindow->GetFullscreen());
MainWindow->Create("OpenGL Window", 640, 480, 16, MainWindow->GetFullscreen());
}
}
}
MainWindow->Close();
return (int)(message.wParam);
}