Win32Window.cpp

Go to the documentation of this file.
00001 #include "MercuryDisplay.h"
00002 #include "Win32Window.h"
00003 #include <windows.h>
00004 #include "MercuryLog.h"
00005 #include "MercuryINI.h"
00006 #include "crash/crashDefines.h"
00007 #include "MercuryInputWin32.h"
00008 
00009 bool active = false;
00010 bool W32W_KEYS[256];
00011 
00012 //These two only work on Win32; it's for the input grabbing.
00013 int g_iWindowX, g_iWindowY;
00014 
00015 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);   // Declaration For WndProc
00016 
00017 Win32Window::Win32Window()
00018 :MercuryWindow(0, 0, false)
00019 {
00020     m_extendedStyle = (DWORD)NULL;
00021     m_style = (DWORD)NULL;      
00022     m_fullscreen = false;
00023     m_hRC = NULL;
00024     m_hDC = NULL;
00025     m_hWnd = NULL;
00026     m_hInstance = NULL; 
00027     active = false;
00028     memset(W32W_KEYS, false, 256);
00029 
00030 //  SetPriorityClass(GetCurrentProcess(), HIGH_PRIORITY_CLASS);
00031 //  SetProcessPriorityBoost(GetCurrentProcess(), true);
00032 }
00033 
00034 Win32Window::~Win32Window()
00035 {
00036     ShowCursor(true);
00037     DestroyWindowAndRender();
00038 }
00039 
00040 bool Win32Window::Update(const float dTime)
00041 {
00042     RECT t;
00043     GetWindowRect( (HWND)m_hWnd, &t );
00044     g_iWindowX = t.left; g_iWindowY = t.top;
00045 
00046     while (PeekMessage(&m_message, NULL, 0, 0, PM_REMOVE))
00047     {
00048         // Stop Update if the user is trying to quit
00049         if (m_message.message == WM_QUIT)
00050             return false;
00051         else
00052         {
00053             TranslateMessage(&m_message);               // Translate The Message
00054             DispatchMessage(&m_message);                // Dispatch The Message
00055         }
00056     }
00057     return true;
00058 }
00059 
00060 bool Win32Window::MakeWindow(const char* title, int width, int height, int bits, bool fullscreen)
00061 {
00062     m_bits = bits;
00063     m_width = width;
00064     m_height = height;
00065     m_fullscreen = fullscreen;
00066     SetTitle(title);
00067 
00068     //Dimensions
00069     m_rect.left = (long)0;
00070     m_rect.top = (long)0;
00071     m_rect.right = (long)m_width;
00072     m_rect.bottom = (long)m_height;
00073 
00074     m_fullscreen = fullscreen;
00075 
00076     m_hInstance         = GetModuleHandle(NULL);
00077     m_win.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00078     m_win.lpfnWndProc   = (WNDPROC)WndProc;
00079     m_win.cbClsExtra    = 0;
00080     m_win.cbWndExtra    = 0;
00081     m_win.hInstance     = m_hInstance;
00082     m_win.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
00083     m_win.hCursor       = LoadCursor(NULL, IDC_ARROW);
00084     m_win.hbrBackground = NULL;
00085     m_win.lpszMenuName  = NULL;
00086     m_win.lpszClassName = GetTitle();
00087 
00088     if (!RegisterClass(&m_win))
00089     {
00090         LOG.Warn(ssprintf("Failed To Register Window Class %s", GetTitle()));
00091         return false;
00092     }
00093 
00094     if (m_fullscreen)
00095     {
00096         DEVMODE dmScreenSettings;
00097         memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
00098         dmScreenSettings.dmSize = sizeof(dmScreenSettings);
00099         dmScreenSettings.dmPelsWidth    = width;
00100         dmScreenSettings.dmPelsHeight   = height;
00101         dmScreenSettings.dmBitsPerPel   = bits;
00102         dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
00103 
00104         if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
00105             m_fullscreen = false;
00106     }
00107 
00108     if (m_fullscreen)
00109     {
00110         m_extendedStyle = WS_EX_APPWINDOW;
00111         m_style = WS_POPUP;
00112         ShowCursor(false);
00113     }
00114     else
00115     {
00116         m_extendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00117         m_style = WS_OVERLAPPEDWINDOW;
00118     }
00119 
00120     AdjustWindowRectEx(&m_rect, m_style, false, m_extendedStyle);
00121 
00122     m_hWnd = (void*)CreateWindowEx(m_extendedStyle,
00123                                 GetTitle(),                         // Class Name
00124                                 title,
00125                                 m_style |                           // Defined Window Style
00126                                 WS_CLIPSIBLINGS |                   // Required Window Style
00127                                 WS_CLIPCHILDREN,                    // Required Window Style
00128                                 0, 0,                               // Window Position
00129                                 m_rect.right-m_rect.left,           // Width
00130                                 m_rect.bottom-m_rect.top,           // Height
00131                                 NULL,                               // No Parent Window
00132                                 NULL,                               // No Menu
00133                                 m_hInstance,
00134                                 NULL);                              // Dont Pass Anything To WM_CREATE
00135 
00136     if (!m_hWnd)
00137     {
00138         LOG.Warn("Window Creation Error.");
00139         DestroyWindowAndRender();
00140         return false;
00141     }
00142 
00143     ShowWindow((HWND)m_hWnd,SW_SHOW);
00144     SetForegroundWindow((HWND)m_hWnd);                  // Slightly Higher Priority
00145     SetFocus((HWND)m_hWnd);                             // Sets Keyboard Focus To The Window
00146 
00147     return true;
00148 }
00149 
00150 bool Win32Window::MakeRender(const char* title, int width, int height, int bits, bool fullscreen, RendererType rt)
00151 {
00152     m_brt = rt;
00153 
00154     MakeWindow( title, width, height, bits, fullscreen );
00155     if ( rt == RT_OGL )
00156     {
00157         if (!RestoreDevice())
00158             return false;
00159 
00160         if (!(m_hRC=wglCreateContext(m_hDC)))
00161         {
00162             LOG.Warn("GL Rendering failed.");
00163             DestroyWindowAndRender();
00164             return false;
00165         }
00166 
00167         return MakeRenderCurrent();
00168     }
00169 
00170     if( rt == RT_D3D )
00171     {
00172         if( !RestoreDevice())
00173         {
00174             return false;
00175         }
00176         //No code here.
00177         return true;
00178     }
00179 
00180     if( rt == RT_SW )
00181     {
00182         if( !RestoreDevice() )
00183             return false;
00184         m_compatDC = CreateCompatibleDC( m_hDC );
00185         m_hbm = CreateCompatibleBitmap( m_hDC, width, height );
00186         SelectObject( m_compatDC, m_hbm );
00187         m_BackBuffer = new unsigned char[width * height * bits / 8];
00188         return true;
00189     }
00190 
00191     return false;
00192 }
00193 
00194 bool Win32Window::MakeRenderCurrent()
00195 {
00196     if(!wglMakeCurrent(m_hDC,m_hRC))
00197     {
00198         LOG.Warn("Rendering Context failed.");
00199         DestroyWindowAndRender();
00200         return false;
00201     }
00202     return true;
00203 }
00204 
00205 #ifndef WM_MOUSEWHEEL
00206 # define WM_MOUSEWHEEL (WM_MOUSELAST + 1)
00207 #endif
00208 
00209 LRESULT CALLBACK WndProc(   HWND    hWnd,
00210                             UINT    uMsg,
00211                             WPARAM  wParam,
00212                             LPARAM  lParam)
00213 {
00214     /* I should replace this section with some sort of messaging system. */
00215     switch (uMsg)                                   // Check For Windows Messages
00216     {
00217         case WM_MOUSEWHEEL:
00218             //Ok, this is where wheel stuff happens.  Not sure how to implement it yet.
00219             //We probably should look at wParam and lParam
00220         case WM_ACTIVATE:                           
00221             if (!HIWORD(wParam))                    
00222                 active = true;                      
00223             else
00224                 active = false;
00225             return 0;
00226             break;
00227         case WM_SYSCOMMAND:                         // Intercept System Commands
00228             switch (wParam)
00229             {
00230                 case SC_SCREENSAVE:
00231                 case SC_MONITORPOWER:
00232                 return 0;
00233             }
00234             break;
00235         case WM_CLOSE:
00236             PostQuitMessage(0);                     // Quit Message
00237             return 0;
00238         case WM_KEYDOWN:                            // Is A Key Being Held Down?
00239             W32W_KEYS[wParam] = true;               // If So, Mark It As TRUE
00240 
00241             //Key repeat
00242             if( lParam & 0x40000000 )
00243                 DeviceKeyboardW32::TickRepeat( wParam );
00244             return 0;
00245         case WM_KEYUP:                              // Has A Key Been Released?
00246             W32W_KEYS[wParam] = false;              // If So, Mark It As FALSE
00247             return 0;
00248         case WM_SIZE:                               // Resize The OpenGL Window
00249             DISPLAY->Resize(LOWORD(lParam),HIWORD(lParam));  // LoWord=Width, HiWord=Height
00250             return 0;
00251     }
00252 
00253     return DefWindowProc(hWnd,uMsg,wParam,lParam);
00254 }
00255 
00256 bool Win32Window::RestoreDevice()
00257 {
00258     static  PIXELFORMATDESCRIPTOR pfd =
00259     {
00260         sizeof(PIXELFORMATDESCRIPTOR),
00261         1,                                          // Version?
00262         PFD_DRAW_TO_WINDOW |                        // Window
00263         PFD_SUPPORT_OPENGL |                        // OpenGL
00264         PFD_DOUBLEBUFFER,                           // Double Buffering
00265         PFD_TYPE_RGBA,                              // RGBA
00266         m_bits,
00267         0, 0, 0, 0, 0, 0,                           // Color Bits Ignored
00268         0,                                          // No Alpha Buffer
00269         0,                                          // Shift Bit Ignored
00270         0,                                          // No Accumulation Buffer
00271         0, 0, 0, 0,                                 // Accumulation Bits Ignored
00272         16,                                         // 16Bit Z-Buffer (Depth Buffer)  
00273         8,                                          // 8bit Stencil Buffer
00274         0,                                          // No Auxiliary Buffer
00275         PFD_MAIN_PLANE,                             // Main Drawing Layer
00276         0,                                          // Reserved
00277         0, 0, 0                                     // Layer Masks Ignored
00278     };
00279 
00280     if (!(m_hDC = GetDC((HWND)m_hWnd))) // Did We Get A Device Context?
00281     {
00282         LOG.Warn("Create A GL Device failed.");
00283         DestroyWindowAndRender();
00284         return false;
00285     }
00286 
00287     if (!(m_pixelFormat = ChoosePixelFormat(m_hDC,&pfd)))   // Did Windows Find A Matching Pixel Format?
00288     {
00289         LOG.Warn("PixelFormat failed.");
00290         DestroyWindowAndRender();
00291         return false;
00292     }
00293 
00294     if(!SetPixelFormat(m_hDC, m_pixelFormat, &pfd))     // Are We Able To Set The Pixel Format?
00295     {
00296         LOG.Warn("Set PixelFormat failed.");
00297         DestroyWindowAndRender();
00298         return false;
00299     }
00300 
00301     return MakeRenderCurrent();
00302 }
00303 
00304 void Win32Window::DestroyWindow()
00305 {
00306     if (m_fullscreen)
00307     {
00308         ChangeDisplaySettings(NULL,0);                  // Desktop
00309         ShowCursor(true);
00310     }
00311 
00312     if (m_hDC && !ReleaseDC((HWND)m_hWnd,m_hDC))
00313     {
00314         LOG.Log("Release Device Context Failed.");
00315         m_hDC = NULL;
00316     }
00317 
00318     if (m_hWnd && !::DestroyWindow((HWND)m_hWnd))
00319     {
00320         LOG.Log("Could Not Release hWnd.");
00321         m_hWnd = NULL;
00322     }
00323 
00324     if (!UnregisterClass(GetTitle(),m_hInstance))
00325     {
00326         LOG.Log(ssprintf("Could Not Unregister Class %s", GetTitle()));
00327         m_hInstance = NULL;
00328     }
00329 }
00330 
00331 void Win32Window::DestroyWindowAndRender()
00332 {
00333     if (m_hRC)
00334     {
00335         if (!wglMakeCurrent(NULL,NULL))                 // Release The DC And RC Contexts?
00336             LOG.Log("Release Of DC And RC Failed.");
00337 
00338         if (!wglDeleteContext(m_hRC))
00339             LOG.Log("Destroy m_hRC failed");
00340 
00341         m_hRC = NULL;
00342     }
00343 
00344     DestroyWindow();
00345 }
00346 
00347 bool Win32Window::HasFocus()
00348 {
00349     return ( GetForegroundWindow() == this->m_hWnd );
00350 }
00351 
00352 void Win32Window::SwapBuffersInternal()
00353 {
00354     if( m_brt == RT_SW )
00355     {
00356         SetBitmapBits( m_hbm,m_width*m_height*m_bits/8,m_BackBuffer );
00357         BitBlt( m_hDC,0,0,m_width,m_height,m_compatDC ,0,0,SRCCOPY );
00358         UpdateWindow( (HWND)m_hWnd );
00359         return;
00360     }
00361 
00362 	::SwapBuffers(m_hDC);
00363 }
00364 
00365 unsigned char * Win32Window::GetBackDirectBuffer()
00366 {
00367     if( m_brt == RT_SW )
00368         return m_BackBuffer;
00369     else
00370         return NULL;
00371 }
00372 
00373 
00374 /* Much thanks to the NeHe lesson one tutorial for explaining how to create
00375  * and set up an OpenGL window for Windows.
00376  * http://nehe.gamedev.net/data/lessons/lesson.asp?lesson=01
00377  *
00378  * 
00379  * Copyright (c) 2005-2006, Joshua Allen
00380  * All rights reserved.
00381  *
00382  * Redistribution and use in source and binary forms, with or
00383  * without modification, are permitted provided that the following
00384  * conditions are met:
00385  *  -   Redistributions of source code must retain the above
00386  *      copyright notice, this list of conditions and the following disclaimer.
00387  *  -   Redistributions in binary form must reproduce the above copyright
00388  *      notice, this list of conditions and the following disclaimer in
00389  *      the documentation and/or other materials provided with the distribution.
00390  *  -   Neither the name of the Mercury Engine nor the names of its
00391  *      contributors may be used to endorse or promote products derived from
00392  *      this software without specific prior written permission.
00393  *
00394  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00395  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00396  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00397  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
00398  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00399  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
00400  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00401  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00402  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
00403  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00404  */
00405 

Hosted by SourceForge.net Logo