PDA

View Full Version : My First Program, and it won't run!



Jonsauce
04-10-2003, 04:56 PM
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\nyour 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

--------------------------------------------

Jonsauce
04-10-2003, 05:16 PM
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) http://www.opengl.org/discussion_boards/ubb/wink.gif

which was missing from the tutorial.