Выбрать главу

  {

If we were unable to delete the Rendering Context the code below will pop up a message box letting us know that deleting the RC was unsuccessful. hRC will be set to NULL.

   MessageBox(NULL,"Release Rendering Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

  }

  hRC=NULL; // Set RC To NULL

 }

Now we check to see if our program has a Device Context and if it does, we try to release it. If we're unable to release the Device Context an error message will pop up and hDC will be set to NULL.

 if (hDC && !ReleaseDC(hWnd,hDC)) // Are We Able To Release The DC

 {

  MessageBox(NULL,"Release Device Context Failed.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

  hDC=NULL; // Set DC To NULL

 }

Now we check to see if there is a Window Handle and if there is, we try to destroy the Window using DestroyWindow(hWnd). If we are unable to destroy the Window, an error message will pop up and hWnd will be set to NULL.

 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; // Set hWnd To NULL

 }

Last thing to do is unregister our Windows Class. This allows us to properly kill the window, and then reopen another window without receiving the error message "Windows Class already registered".

 if (!UnregisterClass("OpenGL",hInstance)) // Are We Able To Unregister Class

 {

  MessageBox(NULL,"Could Not Unregister Class.","SHUTDOWN ERROR",MB_OK | MB_ICONINFORMATION);

  hInstance=NULL; // Set hInstance To NULL

 }

}

The next section of code creates our OpenGL Window. I spent a lot of time trying to decide if I should create a fixed fullscreen Window that doesn't require a lot of extra code, or an easy to customize user friendly Window that requires a lot more code. I decided the user friendly Window with a lot more code would be the best choice. I get asked the following questions all the time in emaiclass="underline" How can I create a Window instead of using fullscreen? How do I change the Window's title? How do I change the resolution or pixel format of the Window? The following code does all of that! Therefore it's better learning material and will make writing OpenGL programs of your own a lot easier!

As you can see the procedure returns BOOL (TRUE or FALSE), it also takes 5 parameters: title of the Window, width of the Window, height of the Window, bits (16/24/32), and finally fullscreenflag TRUE for fullscreen or FALSE for windowed. We return a boolean value that will tell us if the Window was created successfully.

BOOL CreateGLWindow(char* title, int width, int height, int bits, bool fullscreenflag) {

When we ask Windows to find us a pixel format that matches the one we want, the number of the mode that Windows ends up finding for us will be stored in the variable PixelFormat.

 GLuint PixelFormat; // Holds The Results After Searching For A Match

wc will be used to hold our Window Class structure. The Window Class structure holds information about our window. By changing different fields in the Class we can change how the window looks and behaves. Every window belongs to a Window Class. Before you create a window, you MUST register a Class for the window.

 WNDCLASS wc; // Windows Class Structure

dwExStyle and dwStyle will store the Extended and normal Window Style Information. I use variables to store the styles so that I can change the styles depending on what type of window I need to create (A popup window for fullscreen or a window with a border for windowed mode)

 DWORD dwExStyle; // Window Extended Style

 DWORD dwStyle; // Window Style

The following 5 lines of code grab the upper left, and lower right values of a rectangle. We'll use these values to adjust our window so that the area we draw on is the exact resolution we want. Normally if we create a 640×480 window, the borders of the window take up some of our resolution.

 RECT WindowRect; // Grabs Rectangle Upper Left / Lower Right Values

 WindowRect.left=(long)0; // Set Left Value To 0

 WindowRect.right=(long)width; // Set Right Value To Requested Width

 WindowRect.top=(long)0; // Set Top Value To 0

 WindowRect.bottom=(long)height; // Set Bottom Value To Requested Height

In the next line of code we make the global variable fullscreen equal fullscreenflag. So if we made our Window fullscreen, the variable fullscreenflag would be TRUE. If we didn't make the variable fullscreen equal fullscreenflag, the variable fullscreen would stay FALSE. If we were killing the window, and the computer was in fullscreen mode, but the variable fullscreen was FALSE instead of TRUE like it should be, the computer wouldn't switch back to the desktop, because it would think it was already showing the desktop. God I hope that makes sense. Basically to sum it up, fullscreen has to equal whatever fullscreenflag equals, otherwise there will be problems.

 fullscreen=fullscreenflag; // Set The Global Fullscreen Flag

In the next section of code, we grab an instance for our Window, then we define the Window Class.

The style CS_HREDRAW and CS_VREDRAW force the Window to redraw whenever it is resized. CS_OWNDC creates a private DC for the Window. Meaning the DC is not shared across applications. WndProc is the procedure that watches for messages in our program. No extra Window data is used so we zero the two fields. Then we set the instance. Next we set hIcon to NULL meaning we don't want an ICON in the Window, and for a mouse pointer we use the standard arrow. The background color doesn't matter (we set that in GL). We don't want a menu in this Window so we set it to NULL, and the class name can be any name you want. I'll use "OpenGL" for simplicity.

 hInstance = GetModuleHandle(NULL); // Grab An Instance For Our Window

 wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window

 wc.lpfnWndProc = (WNDPROC) WndProc; // WndProc 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 Arrow Pointer

 wc.hbrBackground = NULL; // No Background Required For GL

 wc.lpszMenuName = NULL; // We Don't Want A Menu

 wc.lpszClassName = "OpenGL"; // Set The Class Name

Now we register the Class. If anything goes wrong, an error message will pop up. Clicking on OK in the error box will exit the program.

 if (!RegisterClass(&wc)) // Attempt To Register The Window Class

 {

  MessageBox(NULL,"Failed To Register The Window Class.","ERROR",MB_OK|MB_ICONEXCLAMATION);

  return FALSE; // Exit And Return FALSE

 }

Now we check to see if the program should run in fullscreen mode or windowed mode. If it should be fullscreen mode, we'll attempt to set fullscreen mode.

 if (fullscreen) // Attempt Fullscreen Mode?

 {

The next section of code is something people seem to have a lot of problems with… switching to fullscreen mode. There are a few very important things you should keep in mind when switching to full screen mode. Make sure the width and height that you use in fullscreen mode is the same as the width and height you plan to use for your window, and most importantly, set fullscreen mode BEFORE you create your window. In this code, you don't have to worry about the width and height, the fullscreen and the window size are both set to be the size requested.