My First Program, and it won't run!

I just started trying to learn OpenGL today. I’ve been following some tutorials that I linked to from this site and after a few hours I got my first program written and free of syntax errors.
I am running Windows XP (no service packs), I have a 64 MB Geforce 3 for a graphics card(I’m not sure if that matters or not).

After the program starts I get an error telling me “Unable to get a Rendering Context”. This is from a message box that I put in myself, but since I know almost nothing about OpenGL it doesn’t help me much.

I’ll post my code, and hopefully someone can give me a bit of input. It’s kind of long(4xx lines), so its okay if I don’t here from anyone.

The error occurs in the function:
BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag)

which is called from WinMain

Here’s all the code, and thanks in advance to anyone who helps me out!


//HEADER FILES
#include <windows.h> //header files for windows
#include <gl\gl.h> //header file for the OpenGL32 library
#include <gl\glu.h> //header file for the GLu32 Library
#include <gl\glaux.h> //header file fo the GLaux Library

//GLOBAL VARIABLES
HGLRC hRC = NULL; //permanent rendering context
HDC hDC = NULL; //private GDI device context
HWND hWnd = NULL; //holds our window handle
HINSTANCE hInstance; //holds the applications instance

bool keys[256]; //array used for keyboard routines
bool active = true; //Window active flag set to true by default
bool fullscreen = true; //Fullscreen flag set to true by default

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); //declaration for WndProc

GLvoid ReSizeGLScene(GLsizei width, GLsizei height) //resize and initialize the GL window
{

if(height == 0)						//prevent a divide by zero error	
	height = 1;

glViewport(0,0,width,height);		//reset the current veiwport


glMatrixMode(GL_PROJECTION);		//select the projection matrix so that the next lines of code	
									//will affect it
glLoadIdentity();

//calculate the aspect ratio of the window
gluPerspective(45.0f, (GLfloat)width/(GLfloat)height, 0.1f, 100.0f);	


glMatrixMode(GL_MODELVIEW);			//switch back to the model view matrix
glLoadIdentity();					//reset the modelview matrix

}

int InitGL(GLvoid) //all setup for OpenGL goes here
{

glShadeModel(GL_SMOOTH);		//allows smooth shading

glClearColor(0.0f,0.0f,0.0f,0.0f);	//Set background color to black (Red, Green, Blue, Alpha) to ba
									//1.0f is bright, 0.0f is dark

glClearDepth(1.0f);				//Depthbuffer setup
glEnable(GL_DEPTH_TEST);		//enables depth testing
glDepthFunc(GL_LEQUAL);			//the type of depth test to do


glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);		//Let openGL do the best perspective testing for us, with a performance hit


return true;  //initialization went well

}

int DrawGLScene(GLvoid) //Here is where we do all the drawing
{

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);		//Clear the screne and the depth buffer
glLoadIdentity();										//Reset the current modelview matrix
return true;											//Everything went well

}

GLvoid KillGLWindow(GLvoid) //properly ‘kill’ (close) the window
{
if(fullscreen) //check to see if we are in fullscreen mode
{
ChangeDisplaySettings(NULL,0);
ShowCursor(true);
}

if(hRC)						//do we have a rendering context
{

	if(!wglMakeCurrent(NULL,NULL))		//Try to free it, and check if freeing it was successful (the hDC and hRC )
	{
		MessageBox(NULL, "Release of DC and RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
	}

	if(!wglDeleteContext(hRC))			//can we delete the rendering context?
	{
		MessageBox(NULL, "Release of Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
	}

	hRC = NULL;			//set it to null


}
//Check to see if our program has a device context, and try to release it if it does

if(hDC && !ReleaseDC(hWnd,hDC))	//are we able to release the DC
{
	MessageBox(NULL, "Release of Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
	hDC = NULL;			//set DC to NULL
}

//Check to see if we have a window handle, and if so try to destroy it

if(hWnd && !DestroyWindow(hWnd))	//are we able to destroy the window?
{	
	MessageBox(NULL, "Could not release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
	hWnd = NULL;
}

//Unregister the WindowClass

if(!UnregisterClass("OpenGL", hInstance))	
{
	MessageBox(NULL, "Could not unregister the Windows Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
	hInstance = NULL;
}

}

bool CreateGLWindow(char *title, int width, int height, int bits, bool fullscreenflag)
{
GLuint PixelFormat; //The pixelformat that windows gives us when we ask for it
WNDCLASS wc; //holds are windowclass structure that stores all the information about our window

DWORD		dwExStyle;			//Window extended style(full screen)
DWORD		dwStyle;			//Window style (popup window for border style)

RECT		WindowRect;			//Grabs the upper left and upper right of the window
WindowRect.left = (long)0;
WindowRect.right = (long)width;
WindowRect.top = (long)0;
WindowRect.bottom = (long)height;

fullscreen = fullscreenflag;	//set the global fullscreen variable

//Grab an instance for our window and then define the window class

hInstance = GetModuleHandle(NULL);					//Grab an instance for our window
wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;		//Draw on a move, and has its own DC
wc.lpfnWndProc = (WNDPROC) WndProc;					//Set the window proc that handles messages
wc.cbClsExtra = 0;									//No extra window data
wc.cbWndExtra = 0;									//No extra window data

wc.hInstance = hInstance;							//Set the instance
wc.hIcon = LoadIcon(NULL, IDI_WINLOGO);				//Load the default icon
wc.hCursor = LoadCursor(NULL, IDC_ARROW);			//Load the default cursor
wc.lpszMenuName = NULL;								//No menu
wc.hbrBackground = NULL;							//No background
wc.lpszClassName = "OpenGL";						//Set the window class name

//Now we register the class, if anything goes wrong a message box will pop up and the program will exit
if(!RegisterClass(&wc))
{
	MessageBox(NULL, "Unable to register the Window Class wc.", "STARTUP ERROR", MB_OK | MB_ICONINFORMATION);
	return false;
}

if(fullscreen)			//attempt fullscreen mode
{
	// make sure the width and height is the same as that of your window, and make sure to set it before you create your window
	
	//Clear room to store our video settings and set the width, height, and bits that we want the screen to switch to
	
	DEVMODE dmScreenSettings;								//Device Mode
	memset(&dmScreenSettings,0, sizeof(dmScreenSettings));	//makes sure that memory is cleared
	dmScreenSettings.dmSize = sizeof(dmScreenSettings);		// Size of the DEVMODE structure
	dmScreenSettings.dmPelsWidth = width;					//Select the screen width
	dmScreenSettings.dmPelsHeight = height;					//Select the screen height
	dmScreenSettings.dmBitsPerPel = bits;					//Select the bits per pixel
	dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSHEIGHT | DM_PELSWIDTH;		
	

	//Try to set Selected Mode(that we set above) and get results.  Note:  CDS_FULLSCREEN Gets rid of the start bar
	if(ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
	{
		//if the mode cannot be set then this code will be run 
		if(MessageBox(NULL, "The requested full screen mode is not supported by

your video card. Do you wish to use windowed mode instead?", “NO FULLSCREEN”, MB_YESNO | MB_ICONEXCLAMATION )==IDYES)
{
fullscreen = false; //select windowed mode by changing the global variable
}
else
{
//pop up a message letting the user know that the program is closing
MessageBox(NULL, “The Program will now close.”, “ERROR”, MB_OK | MB_ICONSTOP);
return false; //exit and return false
}
}

}

if(fullscreen) //Check one last time since the user might have encountered an error above and changed
{			   //to window mode
	dwExStyle = WS_EX_APPWINDOW;		//windows extended style, forces a top level window to the taskbar once our window is active
	dwStyle = WS_POPUP;					//Windows style, this has no border on it so its perfect for full screen
	ShowCursor(false);					//hide the mouse cursor since the program is not interactive
}
else //we are in windowed mode
{
	dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;  //WS_EX_WINDOWEDGE give the window a more -3d- look to it
	dwStyle = WS_OVERLAPPEDWINDOW;					 //WS_OVERLAPPEDWINDOW gives a title bar, sizing borders, window menu, and minimize / maximize buttons
	
}


//adjust the window depending on what style we are using, it will also make our window the 
//exact resolution that we requested
AdjustWindowRectEx(&WindowRect, dwStyle, NULL, dwExStyle);


//Now CREATE the window and make sure that its created correctly
if(!(hWnd = CreateWindowEx(	dwExStyle,				//Extended Style for the window
							"OpenGL",				//Class Name
							title,					//Window Title
							WS_CLIPSIBLINGS | WS_CLIPCHILDREN| //Required Window Style
							dwStyle,						//Required window style
							0,0,							//Window x,y starting coors (upper left)
							WindowRect.right - WindowRect.left, //Calculate adjusted window height
							WindowRect.bottom - WindowRect.top,	//calculate adjusted window width
							NULL,					//No parent window
							NULL,					//No menu
							hInstance,				//The Instance of the window
							NULL
							)))					//Don't pass anythign to WM_CREATE
{//Run this code if the window failed to be created
	KillGLWindow();							//reset the display, we wrote this function
	MessageBox(NULL, "Window Creation Error.", "ERROR", MB_OK | MB_ICONEXCLAMATION);  // inform the user
	return false;	//exit the program
}


static PIXELFORMATDESCRIPTOR pfd = 
{												//tell the window how we want stuff to be
	sizeof(PIXELFORMATDESCRIPTOR),				//Size of the pixel format descriptor
	1,											//version number
	PFD_DRAW_TO_WINDOW |						//Format must support the window
	PFD_SUPPORT_OPENGL |						//Format must support OpenGL
	PFD_DOUBLEBUFFER,							//Format must support double buffering
	PFD_TYPE_RGBA,								//Request and Red Green Blue Alpha format
	bits,										//Select our color depth
	0,0,0,0,0,0,								//Color bits ignored
	0,											//No alpha buffer
	0,											//Shift bit ignored
	0,											//No accumulation buffer
	0,0,0,0,									//Accumulation bits ignored
	16,											//16 bit z-buffer, depth buffer
	0,											//no stencil buffer
	0,											//no auxilary buffer
	PFD_MAIN_PLANE,								//Main drawing layer
	0,											//reserved
	0,0,0										//layer masks ignored
};

//now we will attempt to get a an OpenGL Device Context
if(!(hDC = GetDC(hWnd)))		//Did we get a device context
{
	KillGLWindow();			//reset the display
	MessageBox(NULL, "Can't create a GL device context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
	return false;			//exit the program
}

//now we will try to get a pixel format like the one describe above.  If windows cannot find one
//the program will display a message and exit

if(!(PixelFormat = ChoosePixelFormat(hDC,&pfd))) //are we able to set the pixel format
{
	KillGLWindow();
	MessageBox(NULL, "Windows could not find a pixel format that matched.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
	return false;
}


//Now we attempt to get a rendering context
if(!(hRC = wglCreateContext(hDC)))
{
	KillGLWindow();
	MessageBox(NULL, "Unable to get a Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
	return false;
}

//activate the rendering context

if(!wglMakeCurrent(hDC,hRC))
{
	KillGLWindow();
	MessageBox(NULL, "Cannot Activate the GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
	return false;
}

//everything has gone okay, so show the window and set focus to it

ShowWindow(hWnd, SW_SHOW);			//show it
SetForegroundWindow(hWnd);			//set its as the front most window
SetFocus(hWnd);						//set focus to the window
ReSizeGLScene(width,height);		//Set up our perspective

if(!InitGL())  //call the initial setup routine that we wrote earlier
{
	KillGLWindow();
	MessageBox(NULL, "Initialization Failed.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
	return false;
}


return true;  //Yay!  We made it this far and everything worked

}

LRESULT CALLBACK WndProc( HWND hWnd, //Handle for this window
UINT uMsg, //Message for this window
WPARAM wParam, //aditional message info for this window
LPARAM lParam)//aditional message information
{

switch(uMsg)  //choose the message that we are handling this time around
{
case WM_ACTIVATE:					//Watch for the window activate message
	{
		if(!HIWORD(wParam))			//Check minimization status
		{
			active = true;			//Program is active
		}
		else
			active = false;			//Program is no longer active
		return 0;					//return to the message loop
	}

case WM_SYSCOMMAND:					//Intercept System Commands
	{
		switch(wParam)				//Check System calls
		{
		case SC_SCREENSAVE:			//Is a screensaver trying to start?
		case SC_MONITORPOWER:		//Is the monitor trying to enter powersaving mode?
			return 0;				//Prevent both of those from happening
		}
		break;
	}
case WM_CLOSE:						//The window has been closed
	{
		PostQuitMessage(0);			//Send a quit message
		return 0;					//Jump back to the message loop
	}
case WM_KEYDOWN:					//Is a key being held down?
	{
		keys[wParam] = true;		//If so, mark it as true
		return 0;					//Jump back to the message loop
	}
case WM_KEYUP:						//Has a key been let back up?
	{
		keys[wParam] = false;		//If so, mark it as false;
		return 0;					//Jump back to the message loop
	}

case WM_SIZE:						//We need to resize the OpenGL Scene if the window is resized
	{
		ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));		//LOWORD gives the width, HIWORD gives the height
		return 0;											//Jump back to the message loop
	}

}//end switch
	

//All messages that we dont care about will be passed to the default window procedure
return DefWindowProc(hWnd, uMsg, wParam, lParam);

}//End WndProc

int WINAPI WinMain(HINSTANCE hInstance, //Instance
HINSTANCE hPrevInstance, //Previous Instance
LPSTR lpCmdLine, //Command Line Parameters
int nShowCmd) //Window Show State
{

//set up two variables, msg will hang aroudn and check if there are any waiting messages
//done tells us when our program is done running, it is initially set to false

MSG msg;
bool done=false;

//Ask the user if they want Full Screen or Windowed Mode

if(MessageBox(NULL, "Would you like to run in full screened mode?", "Start FullScreen?", MB_YESNO | MB_ICONQUESTION) == IDNO)
{
	//This runs if the user chooses the no button and wants to run in windowed mode
	fullscreen = false;  //change the global variable
}

//Create the openGL window by passing the title, width, height, colordepth (16,24,32), and fullscreen
if(!CreateGLWindow("Jonathan's First OpenGL Window", 800, 600, 16, fullscreen))
{
	return 0;	//quit if window was not created
}


//here is the start of our loop, as long as done = false it will continue
while(!done)
{
	//first thing that we do is check to see if there are any messages waiting
	if(PeekMessage(&msg, NULL, 0,0, PM_REMOVE))		
	{
		//check to see if a WM_QUIT message was issued
		if(msg.message == WM_QUIT)		//Have we recieved a quit message?
		{
			done = true;				//if so, then we are done
		}
		else							//deal with the other window messages
		{
			TranslateMessage(&msg);		//translate the message
			DispatchMessage(&msg);		//Dispatch the message
		}
	}
	else //There are no messages, so we will draw our OpenGL scene
	{
		if(active)						//is the program active?
		{
			if(keys[VK_ESCAPE])			//was escape pressed?
			{
				done = true;			//if so, we must exit
			}
			else //we get to do cool stuff now
			{
				DrawGLScene();			//draw the scene
				SwapBuffers(hDC);		//swap buffers since we are double buffering
			}
		}
		
		
		//Allow users to switch between fullscreen and windowed mode
		
		if(keys[VK_F1])					//is F1 being pressed?
		{
			keys[VK_F1] = false;		//if so, make it false so we dont go through an infinite loop
			KillGLWindow();				//Destroy the window
			fullscreen = !fullscreen;	//Switch the fullscreen variable to its opposite
			if(!CreateGLWindow("Jonathan's First OpenGL Window", 800,600,16,fullscreen))  //recreate the window
			{
				return 0;  //quit if the window couldnt be created
			}

		}
	}
}

//Exit the program and shut down when the loop is exited
KillGLWindow();						//Kill the window
return(msg.wParam);					//exit the program

}//End WinMain


Well I did some digging around on the MSDN site and i found the answer.
I needed to put this line of code in:

SetPixelFormat(hDC,PixelFormat,&pfd)

which was missing from the tutorial.