Unuk 1.0
src/libUnuk/Win32Window.cpp
Go to the documentation of this file.
00001 #include <ctime>
00002 #include <iostream>
00003 #include <windows.h>
00004 #include <GL/gl.h>
00005 #include "../Libs/wglext.h"
00006 #include "Win32Window.h"
00007 #include "../Unuk/Game.h"
00008 
00009 typedef HGLRC(APIENTRYP PFNWGLCREATECONTEXTATTRIBSARBPROC) (HDC, HGLRC, const int*);
00010 PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
00011 
00012 Win32Window::Win32Window(HINSTANCE hInstance) {
00013   m_isRunning = false;
00014   m_game      = NULL;
00015   m_hinstance = hInstance;
00016   m_lastTime  = 0;
00017 }
00018 
00019 Win32Window::~Win32Window(void) {
00020 
00021 }
00022 
00023 bool Win32Window::Create(int width, int height, int bpp, bool fullscreen) {
00024   DWORD dwExStyle;
00025   DWORD dwStyle;
00026   
00027   m_isFullscreen = fullscreen;
00028 
00029   // Set up the window values.
00030   m_windowRect.left   = (long) 0;
00031   m_windowRect.right  = (long) width;
00032   m_windowRect.top    = (long) 0;
00033   m_windowRect.bottom = (long) height;
00034 
00035   // Set up the window class structure.
00036   m_windowClass.cbSize          = sizeof(WNDCLASSEX);
00037   m_windowClass.style           = CS_HREDRAW | CS_VREDRAW;
00038   m_windowClass.lpfnWndProc     = Win32Window::StaticWndProc; // Our static method is the event handler.
00039   m_windowClass.cbClsExtra      = 0;
00040   m_windowClass.cbWndExtra      = 0;
00041   m_windowClass.hInstance       = m_hinstance;
00042   m_windowClass.hIcon           = LoadIcon(NULL, IDI_APPLICATION);
00043   m_windowClass.hCurser         = LoadCursor(NULL, IDC_ARROW);
00044   m_windowClass.hbrBackground   = NULL;
00045   m_windowClass.lpszMenuName    = NULL;
00046   m_windowClass.lpszClassName   = "Unuk";
00047   m_windowClass.hIconSm         = LoadIcon(NULL, IDI_WINLOGO);
00048 
00049   // Register the window class.
00050   if(!RegisterClassEx(&m_windowClass)) {
00051     return false;
00052   }
00053 
00054   // We need to change the display mode if we are running fullscreen.
00055   if(m_isFullsceen) {
00056     // This is the device mode.
00057     DEVMODE dmScreenSettings;
00058     memset(&dmScreenSettings, 0, sizeof(smScreenSettings));
00059     dmScreenSettings.dmSize = sizeof(dmScreenSettings);
00060 
00061     // Set the screen width/height/bpp.
00062     dmScreenSettings.dmPelsWidth  = width;
00063     dmScreenSettings.dmPelsHeight = height;
00064     dmScreenSettings.dmBitsPerPel = bpp;
00065     dmScreenSettings.dwFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
00066 
00067     if(ChangeDisplaySettings(&dScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) {
00068       // Setting display mode failed, we will switch to windowed mode.
00069       MessageBox(NULL, "Display mode failed", NULL, MB_OK);
00070       m_isFullscreen = false;
00071     }
00072   }
00073 
00074   // Check to see if we are still in fullscreen mode.
00075   if(m_fullscreen) {
00076     dwExStyle = WS_EX_APPWINDOW;
00077     dwStyle   = WS_POPUP;
00078     ShowCursor(false);
00079   } else {
00080     // fullscreen mode must have failed.
00081     dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00082     dwStyle   = WS_OVERLAPPEDWINDOW
00083   }
00084 
00085   // Adjusted the window to the requested size.
00086   AdjustWindowRectEx(&m_windowRect, swStyle, false, dwExStyle);
00087 
00088   // Now the class is regestered we can finaly create the window.
00089   m_hWnd = CreateWindowEx(NULL, "Unuk", dwStyle | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0,
00090                         m_windowRect.right - m_windowRect.left, m_windowRect.bottom - m_windowRect.top,
00091                         NULL, NULL, m_hinstance, this);
00092 
00093   // Let's make sure the window creation went as planned.
00094   if(!m_hWnd) return 0;
00095 
00096   m_hdc = GetDC(m_hWnd);
00097 
00098   // We know everything is ok, display and update the window now.
00099   ShowWindow(m_hWnd, SW_SHOW);
00100   UpdateWindow(m_hWnd);
00101  
00102   m_lastTime = GetTickCount() / 1000.0f;
00103   return true;
00104 }
00105 
00106 void Win32Window::Destroy(void) {
00107   // If we are in fullscreen we want to switch back to desktop, and show the mouse cursor.
00108   if(m_isFullscreen) {
00109     ChangeDisplaySettings(NULL, 0);
00110     ShowCursor(true);
00111   }
00112 }
00113 
00114 void Win32Window::AttachGame(Game* game) {
00115   m_game = game;
00116 }
00117 
00118 bool Win32Window::IsRunning(void) {
00119   return m_isRunning;
00120 }
00121 
00122 void Win32Window::ProccessEvents(void) {
00123   MSG msg;
00124   
00125   // While there are messages in the queue, store them in msg.
00126   while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
00127     // Process the messages one at a time.
00128     TranslateMessage(&msg);
00129     DispatchMessage(&msg);
00130   }
00131 }
00132 
00133 void Win32Window::SetupPixelFormat(void) {
00134   int pixelFormat;
00135   
00136   PIXELFORMATDESCRIPTOR pfd = {
00137     sizeof(PIXELFORMATDESCRIPTOR),      // Size.
00138         1,                              // Version.
00139         PFD_SUPPORT_OPENGL |            // OpenGL window.
00140         PFD_DRAW_TO_WINDOW |            // Render to window.
00141         PFD_DOUBLEBUFFER,               // Double buffer.
00142         PFD_TYPE_RGBA,                  // Color type.
00143         32,                             // Color Depth.
00144         0, 0, 0, 0, 0, 0,               // Color bits (ignored).
00145         0,                              // No alpha buffer.
00146         0,                              // Alpha bits (ignored).
00147         0,                              // No accumulation buffer.
00148         0, 0, 0, 0,                     // Accumulation bits (ignored).
00149         16,                             // Depth buffer.
00150         0,                              // No stencil buffer.
00151         0,                              // No auxiliary buffers.
00152         PFD_MAIN_PLANE,                 // Main layer.
00153         0,                              // Reserved.
00154         0, 0, 0,                        // No layer, visible, damage masks.
00155   };
00156 
00157   pixelFormat = ChoosePixelFormat(m_hdc, &pfd);
00158   SetPixelFormat(m_hdc, pixelFormat, &pfd);
00159 }
00160 
00161 LRESULT Win32Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
00162   switch(uMsg) {
00163   // Create the window.
00164   case WM_CREATE:
00165     m_hdc = GetDC(hWnd);
00166     SetupPixelFormat();
00167 
00168     // Setup the OpenGL version. We want to use 3.0.
00169     int attribs[] = {
00170       WGL_CONTEXT_MAJOR_VERSION_ARB, 3,
00171       WGL_CONTEXT_MINOR_VERSION_ARB, 0,
00172       0
00173     };
00174 
00175     // Create a temporary context so we can get a pointer to the function.
00176     HGLRC tmpContext = wglCreateContext(m_hdc);
00177     // Make it the current.
00178     wglMakeCurrent(m_hdc, tmpContext);
00179     
00180     // Get the function pointer.
00181     wglCreateContextAttribsARB = (PFNWGLCCREATECONTEXTATTRIBSARBPROC) wglGetProcAddress("wglCreateContextAttribsARB");
00182 
00183     // If it is NULL, then GL 3.0 is not supported.
00184     if(!wglCreateContextAttribsARB) {
00185       Debug::logger->message("\nOpenGL 3.0 is not supported, falling back to GL 2.1");
00186       m_hglrc = tmpContext;
00187     } else {
00188       // Create an OpenGL 3.0 context using the new function.
00189       m_hglrc = wglCreateContextAttribsARB(m_hdc, 0, attribs);
00190       // Delete then temp context.
00191       wglDeleteContext(tmpContext);
00192     }
00193 
00194     // Make the GL3 context current.
00195     wglMakeCurrent(m_hdc, m_hglrc);
00196     // Our window is now running.
00197     m_isRunning = true;
00198     break;
00199   case WM_DESTROY:
00200   case WM_CLOSE:
00201     wglMakeCurrent(m_hdc, NULL);
00202     wglDeleteContext(m_hglrc);
00203     m_isRunning = false;
00204     PostQuitMessage(0);
00205     return 0;
00206     break;
00207   case WM_SIZE:
00208     // Get the width and height.
00209     int height = HIWORD(lParam);
00210     int width  = LOWORD(lParam);
00211     getAttachedExample()->onResize(width, height);
00212     break;
00213   case WM_KEYDOWN:
00214     // If we detect the escape key, then please close the window.
00215     if(wParam == VK_ESCAPE) {
00216       DestroyWindow(m_hwnd);
00217     }
00218     break;
00219   default:
00220     break;
00221   }
00222   return DefWindowProc(hWnd, uMsg, wParam, lParam);
00223 }
00224 
00225 LRESULT CALLBACK Win32Window::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
00226   Win32Window* window = NULL;
00227 
00228   // If we see the create message.
00229   if(uMsg == WM_CREATE) {
00230     // Then get the pointer we stored during create.
00231     window = (Win32Window)(LPCREATESTRUCT)lParam)->lpCreateParams;
00232     // Associate the window pointer with the hWnd for the other events to access.
00233     SetWindowLongPtr(hWnd, GWL_USERDAA, (LONG_PTR)window);
00234   } else {
00235     // If this aint a creation event, then we should have stored a pointer to the window.
00236     window = (Win32Window)GetWindowLongPtr(hWnd, GWL_USERDATA);
00237     if(!window) {
00238       return DefWindowProc(hWnd, uMsg, wParam, lParam);
00239     }
00240   }
00241   // Call our window's member WndProc (allows us to access member variables).
00242   return window->WndProc(hWnd, uMsg, wParam, lParam)
00243 }
00244 
00245 float Win32Window::getElapsedSeconds() {
00246   float currentTime = float(GetTickCount()) / 1000.0f;
00247   float seconds     = float(currentTime - m_lastTime);
00248   m_lastTime        = currentTime;
00249   return seconds;
00250 }
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Defines