KeosWin32Window.cpp

Go to the documentation of this file.
00001 /*
00002  * This source file is part of KEOS (Free 3D Engine)
00003  * For the latest info, see http://www.keosengine.org/
00004  * E-mails : thierry.vouriot@keosengine.org, yeri@keosengine.org
00005  *
00006  * This program is free software; you can redistribute it and/or modify it under
00007  * the terms of the GNU Lesser General Public License as published by the Free Software
00008  * Foundation; either version 2 of the License, or (at your option) any later
00009  * version.
00010  *
00011  * This program is distributed in the hope that it will be useful, but WITHOUT
00012  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00013  * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License along with
00016  * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00017  * Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00018  * http://www.gnu.org/copyleft/lesser.txt.
00019  *
00020  */
00021 
00022 #include "KeosWin32Window.h"
00023 #include "KeosOGLException.h"
00024 #include "KeosLogger.h"
00025 #include "KeosConsole.h"
00026 
00027 namespace Keos
00028 {
00029 
00030   //=======================================================================
00031   // CWin32Window implementation
00032   //=======================================================================
00033 
00034   //-----------------------------------------------------------------------
00035   CWin32Window::CWin32Window()
00036   {
00037     m_bIsFullScreen = false;
00038     m_HWnd = 0;
00039     m_bActive = false;
00040     m_bReady = false;
00041     m_bClosed = false;
00042   }
00043 
00044   //-----------------------------------------------------------------------
00045   CWin32Window::~CWin32Window()
00046   {
00047     Destroy();
00048   }
00049 
00050   //-----------------------------------------------------------------------
00051   void CWin32Window::Create(const String& strName, uint nWidth, uint nHeight, uint nColourDepth, bool bFullScreen)
00052   {
00053     HWND parentHWnd = 0;
00054     HWND externalHandle = 0;
00055     HINSTANCE hInst = GetModuleHandle(KEOS_OGL_LIB);
00056     bool bVsync = false;
00057     uint nDisplayFrequency = 0;
00058     String strTitle = strName;
00059     uint nLeft = 0; // Defaults to screen center
00060     uint nTop = 0; // Defaults to screen center
00061     bool bDepthBuffer = true;
00062 
00063     // Destroy current window if any
00064     if ( m_HWnd )
00065       Destroy();
00066 
00067     if (bFullScreen)
00068     {
00069       m_nColourDepth = nColourDepth;
00070     }
00071     else
00072     {
00073       // Get colour depth from display
00074       m_nColourDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
00075     }
00076 
00077     if (!externalHandle)
00078     {
00079       DWORD dwStyle = (bFullScreen ? WS_POPUP : WS_OVERLAPPEDWINDOW) | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
00080       RECT rc;
00081 
00082       m_nWidth = nWidth;
00083       m_nHeight = nHeight;
00084 
00085       if (!bFullScreen)
00086       {
00087         // Calculate window dimensions required to get the requested client area
00088         SetRect(&rc, 0, 0, m_nWidth, m_nHeight);
00089         AdjustWindowRect(&rc, dwStyle, false);
00090         m_nWidth = rc.right - rc.left;
00091         m_nHeight = rc.bottom - rc.top;
00092 
00093         // Clamp width and height to the desktop dimensions
00094         if (m_nWidth > (unsigned)GetSystemMetrics(SM_CXSCREEN))
00095           m_nWidth = (unsigned)GetSystemMetrics(SM_CXSCREEN);
00096         if (m_nHeight > (unsigned)GetSystemMetrics(SM_CYSCREEN))
00097           m_nHeight = (unsigned)GetSystemMetrics(SM_CYSCREEN);
00098 
00099         if (!nLeft)
00100         {
00101           m_nLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (m_nWidth / 2);
00102         }
00103         else
00104         {
00105           m_nLeft = nLeft;
00106         }
00107         if (!nTop)
00108         {
00109           m_nTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (m_nHeight / 2);
00110         }
00111         else
00112         {
00113           m_nTop = nTop;
00114         }
00115       }
00116       else
00117       {
00118         m_nTop = m_nLeft = 0;
00119       }
00120 
00121       // Register the window class
00122       WNDCLASS wndClass =
00123         {
00124           CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
00125           LoadIcon( NULL, IDI_APPLICATION ),
00126           LoadCursor( NULL, IDC_ARROW ),
00127           (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
00128           TEXT(strTitle.c_str())
00129         };
00130       RegisterClass( &wndClass );
00131 
00132       // Create our main window
00133       // Pass pointer to self
00134       HWND hWnd = CreateWindowEx(bFullScreen ? WS_EX_TOPMOST : 0, TEXT(strTitle.c_str()), TEXT(strTitle.c_str()),
00135                                  dwStyle, m_nLeft, m_nTop, m_nWidth, m_nHeight, 0L, 0L, hInst, this);
00136       m_HWnd = hWnd;
00137 
00138       GetClientRect(m_HWnd, &rc);
00139       m_nWidth = rc.right;
00140       m_nHeight = rc.bottom;
00141 
00142       if (bFullScreen)
00143       {
00144         DEVMODE DevMode;
00145         DevMode.dmSize = sizeof(DevMode);
00146         DevMode.dmBitsPerPel = m_nColourDepth;
00147         DevMode.dmPelsWidth = m_nWidth;
00148         DevMode.dmPelsHeight = m_nHeight;
00149         DevMode.dmDisplayFrequency = nDisplayFrequency;
00150         DevMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY;
00151         if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
00152           ILogger::Log("WARNING - ChangeDisplaySettings error");
00153       }
00154     }
00155     else
00156     {
00157       m_HWnd = externalHandle;
00158       RECT rc;
00159       GetClientRect(m_HWnd, &rc);
00160       m_nWidth = rc.right;
00161       m_nHeight = rc.bottom;
00162       m_nLeft = rc.left;
00163       m_nTop = rc.top;
00164     }
00165 
00166     ShowWindow(m_HWnd, SW_SHOWNORMAL);
00167     UpdateWindow(m_HWnd);
00168 
00169     m_strName = strName;
00170     m_bIsDepthBuffered = bDepthBuffer;
00171     m_bIsFullScreen = bFullScreen;
00172 
00173     HDC hdc = GetDC(m_HWnd);
00174 
00175     ILogger::Log("Created CWin32Window '%s' : %dx%d, %dbpp",
00176                  m_strName.c_str(), m_nWidth, m_nHeight, m_nColourDepth);
00177 
00178     PIXELFORMATDESCRIPTOR pfd = {
00179                                   sizeof(PIXELFORMATDESCRIPTOR),
00180                                   1,
00181                                   PFD_DRAW_TO_WINDOW |
00182                                   PFD_SUPPORT_OPENGL |
00183                                   PFD_DOUBLEBUFFER,
00184                                   PFD_TYPE_RGBA,
00185                                   m_nColourDepth,
00186                                   0, 0, 0, 0, 0, 0,
00187                                   0,
00188                                   0,
00189                                   0,
00190                                   0, 0, 0, 0,
00191                                   32,         // 32-bit depth-buffer (will be emulated in 16-bit colour mode)
00192                                   8,         // 8-bit stencil buffer
00193                                   0,
00194                                   PFD_MAIN_PLANE,
00195                                   0,
00196                                   0, 0, 0};
00197 
00198     int nPixelFormat = ChoosePixelFormat(hdc, &pfd);
00199     if (!nPixelFormat)
00200       OGL_EXCEPT("ChoosePixelFormat", "CWin32Window::Create");
00201 
00202     if (!SetPixelFormat(hdc, nPixelFormat, &pfd))
00203       OGL_EXCEPT("SetPixelFormat", "CWin32Window::Create");
00204 
00205     HGLRC glrc = wglCreateContext(hdc);
00206     if (!glrc)
00207       OGL_EXCEPT("wglCreateContext", "CWin32Window::Create");
00208     if (!wglMakeCurrent(hdc, glrc))
00209       OGL_EXCEPT("wglMakeCurrent", "CWin32Window::Create");
00210 
00211     m_Glrc = glrc;
00212     m_HDC = hdc;
00213 
00215     //m_nOldSwapIntervall = wglGetSwapIntervalEXT();
00216     //if (bVsync)
00217     // wglSwapIntervalEXT(1);
00218     //else
00219     // wglSwapIntervalEXT(0);
00220 
00221     m_bReady = true;
00222   }
00223 
00224   //-----------------------------------------------------------------------
00225   void CWin32Window::Destroy(void)
00226   {
00227     //wglSwapIntervalEXT(m_nOldSwapIntervall);
00228 
00229     if (m_Glrc)
00230     {
00231       wglMakeCurrent(NULL, NULL);
00232       wglDeleteContext(m_Glrc);
00233       m_Glrc = NULL;
00234     }
00235     if (m_HDC)
00236     {
00237       ReleaseDC(m_HWnd, m_HDC);
00238       m_HDC = NULL;
00239     }
00240     if (m_bIsFullScreen)
00241     {
00242       ChangeDisplaySettings(NULL, 0);
00243     }
00244     DestroyWindow(m_HWnd);
00245     m_bActive = false;
00246   }
00247 
00248   //-----------------------------------------------------------------------
00249   bool CWin32Window::IsClosed() const
00250   {
00251     return m_bClosed;
00252   }
00253 
00254   //-----------------------------------------------------------------------
00255   void CWin32Window::Reposition(int left, int top)
00256   {
00258   }
00259 
00260   //-----------------------------------------------------------------------
00261   void CWin32Window::Resize(uint nWidth, uint nHeight)
00262   {
00263     m_nWidth = nWidth;
00264     m_nHeight = nHeight;
00265 
00267   }
00268 
00269   //-----------------------------------------------------------------------
00270   void CWin32Window::WindowMovedOrResized()
00271   {
00272     RECT temprect;
00273     ::GetClientRect(GetWindowHandle(), &temprect);
00274     Resize(temprect.right - temprect.left, temprect.bottom - temprect.top);
00275   }
00276 
00277   //-----------------------------------------------------------------------
00278   void CWin32Window::SwapBuffers(bool bWaitForVSync)
00279   {
00280     ::SwapBuffers((HDC)m_HDC);
00281   }
00282 
00283   //-----------------------------------------------------------------------
00284   LRESULT CWin32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
00285   {
00286     CWin32Window* win;
00287 
00288     // look up window instance
00289     if ( WM_CREATE != uMsg )
00290       win = (CWin32Window*)GetWindowLong( hWnd, 0 );
00291 
00292     switch ( uMsg )
00293     {
00294       case WM_ACTIVATE:
00295         if ( WA_INACTIVE == LOWORD( wParam ) )
00296           win->m_bActive = false;
00297         else
00298           win->m_bActive = true;
00299         break;
00300 
00301       case WM_CREATE:
00302       {
00303         // Log the new window
00304         // Get CREATESTRUCT
00305         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
00306         win = (CWin32Window*)(lpcs->lpCreateParams);
00307         // Store pointer in window user data area
00308         SetWindowLong( hWnd, 0, (long)win );
00309         win->m_bActive = true;
00310 
00311         return 0;
00312       }
00313       break;
00314 
00315       case WM_PAINT:
00316         // If we get WM_PAINT messges, it usually means our window was
00317         // comvered up, so we need to refresh it by re-showing the contents
00318         // of the current frame.
00319         if ( win->m_bActive && win->m_bReady )
00320           win->Update();
00321         break;
00322 
00323       case WM_MOVE:
00324         // Move messages need to be tracked to update the screen rects
00325         // used for blitting the backbuffer to the primary
00326         // *** This doesn't need to be used to Direct3D9 ***
00327         break;
00328 
00329       case WM_ENTERSIZEMOVE:
00330         // Previent rendering while moving / sizing
00331         win->m_bReady = false;
00332         break;
00333 
00334       case WM_EXITSIZEMOVE:
00335         win->WindowMovedOrResized();
00336         win->m_bReady = true;
00337         break;
00338 
00339       case WM_SIZE:
00340         // Check to see if we are losing or gaining our window.  Set the
00341         // active flag to match
00342         if ( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
00343           win->m_bActive = false;
00344         else
00345         {
00346           win->m_bActive = true;
00347           if ( win->m_bReady )
00348             win->WindowMovedOrResized();
00349         }
00350         break;
00351 
00352       case WM_GETMINMAXINFO:
00353         // Prevent the window from going smaller than some minimu size
00354         ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
00355         ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
00356         break;
00357         // On arrete le rendu lorsque l'on appuie sur Echap
00358         // Provisoire en attendant une gestion plus fine des "Input"
00359       case WM_KEYDOWN:
00360         switch (wParam)
00361         {
00362           case VK_ESCAPE :
00363             win->m_bClosed = true;
00364             break;
00365           case VK_F1 :
00366             CConsole::Instance().Enable(true);
00367             break; // F1 = activer la console
00368           case VK_F2 :
00369             CConsole::Instance().Enable(false);
00370             break; // F2 = désactiver la console
00371         }
00372         break;
00373         // Caractère = envoi à la console
00374       case WM_CHAR :
00375         CConsole::Instance().SendChar(static_cast<char>(LOWORD(wParam)));
00376         return 0;
00377 
00378       case WM_CLOSE:
00379         DestroyWindow( win->m_HWnd );
00380         win->m_bClosed = true;
00381         return 0;
00382     }
00383 
00384     return DefWindowProc( hWnd, uMsg, wParam, lParam );
00385   }
00386 
00387 } // namespace Keos

Generated on Fri Mar 9 14:29:04 2007 for Keos by  doxygen 1.5.1-p1