Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

# 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 = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
    00123                                 LoadIcon( NULL, IDI_APPLICATION ),
    00124                                 LoadCursor( NULL, IDC_ARROW ),
    00125                                 (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
    00126                                 TEXT(strTitle.c_str()) };
    00127                         RegisterClass( &wndClass );
    00128
    00129                         // Create our main window
    00130                         // Pass pointer to self
    00131                         HWND hWnd = CreateWindowEx(bFullScreen?WS_EX_TOPMOST:0, TEXT(strTitle.c_str()), TEXT(strTitle.c_str()),
    00132                                 dwStyle, m_nLeft, m_nTop, m_nWidth, m_nHeight, 0L, 0L, hInst, this);
    00133                         m_HWnd = hWnd;
    00134
    00135                         GetClientRect(m_HWnd,&rc);
    00136                         m_nWidth = rc.right;
    00137                         m_nHeight = rc.bottom;
    00138
    00139             if (bFullScreen)
    00140             {
    00141                             DEVMODE DevMode;
    00142                             DevMode.dmSize = sizeof(DevMode);
    00143                             DevMode.dmBitsPerPel = m_nColourDepth;
    00144                             DevMode.dmPelsWidth = m_nWidth;
    00145                             DevMode.dmPelsHeight = m_nHeight;
    00146                             DevMode.dmDisplayFrequency = nDisplayFrequency;
    00147                             DevMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
    00148                             if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
    00149                                     ILogger::Log("WARNING - ChangeDisplaySettings error");
    00150                     }
    00151                 }
    00152                 else
    00153         {
    00154                         m_HWnd = externalHandle;
    00155                         RECT rc;
    00156                         GetClientRect(m_HWnd, &rc);
    00157                         m_nWidth = rc.right;
    00158                         m_nHeight = rc.bottom;
    00159                         m_nLeft = rc.left;
    00160                         m_nTop = rc.top;
    00161                 }
    00162
    00163                 ShowWindow(m_HWnd, SW_SHOWNORMAL);
    00164                 UpdateWindow(m_HWnd);
    00165
    00166                 m_strName = strName;
    00167                 m_bIsDepthBuffered = bDepthBuffer;
    00168                 m_bIsFullScreen = bFullScreen;
    00169
    00170                 HDC hdc = GetDC(m_HWnd);
    00171
    00172         ILogger::Log("Created CWin32Window '%s' : %dx%d, %dbpp",
    00173                      m_strName.c_str(), m_nWidth, m_nHeight, m_nColourDepth);
    00174
    00175         PIXELFORMATDESCRIPTOR pfd = {
    00176                         sizeof(PIXELFORMATDESCRIPTOR),
    00177                         1,
    00178                         PFD_DRAW_TO_WINDOW |
    00179                         PFD_SUPPORT_OPENGL |
    00180                         PFD_DOUBLEBUFFER,
    00181                         PFD_TYPE_RGBA,
    00182                         m_nColourDepth,
    00183                         0, 0, 0, 0, 0, 0,
    00184                         0,
    00185                         0,
    00186                         0,
    00187                         0, 0, 0, 0,
    00188                         32,                          // 32-bit depth-buffer (will be emulated in 16-bit colour mode)
    00189                         8,                                   // 8-bit stencil buffer
    00190                         0,
    00191                         PFD_MAIN_PLANE,
    00192                         0,
    00193                         0, 0, 0};
    00194
    00195                 int nPixelFormat = ChoosePixelFormat(hdc, &pfd);
    00196                 if (!nPixelFormat)
    00197             OGL_EXCEPT("ChoosePixelFormat", "CWin32Window::Create");
    00198
    00199                 if (!SetPixelFormat(hdc, nPixelFormat, &pfd))
    00200             OGL_EXCEPT("SetPixelFormat", "CWin32Window::Create");
    00201
    00202                 HGLRC glrc = wglCreateContext(hdc);
    00203                 if (!glrc)
    00204                         OGL_EXCEPT("wglCreateContext", "CWin32Window::Create");
    00205                 if (!wglMakeCurrent(hdc, glrc))
    00206                         OGL_EXCEPT("wglMakeCurrent", "CWin32Window::Create");
    00207
    00208                 m_Glrc = glrc;
    00209                 m_HDC = hdc;
    00210
    00211         //@todo Faire fonctionner
    00212                 //m_nOldSwapIntervall = wglGetSwapIntervalEXT();
    00213                 //if (bVsync)
    00214                 //      wglSwapIntervalEXT(1);
    00215                 //else
    00216                 //      wglSwapIntervalEXT(0);
    00217
    00218                 m_bReady = true;
    00219     }
    00220
    00221     //-----------------------------------------------------------------------
    00222     void CWin32Window::Destroy(void)
    00223     {
    00224         //wglSwapIntervalEXT(m_nOldSwapIntervall);
    00225
    00226                 if (m_Glrc) {
    00227                         wglMakeCurrent(NULL, NULL);
    00228                         wglDeleteContext(m_Glrc);
    00229                         m_Glrc = NULL;
    00230                 }
    00231                 if (m_HDC) {
    00232                         ReleaseDC(m_HWnd, m_HDC);
    00233                         m_HDC = NULL;
    00234                 }
    00235                 if (m_bIsFullScreen)
    00236                 {
    00237                         ChangeDisplaySettings(NULL, 0);
    00238                 }
    00239             DestroyWindow(m_HWnd);
    00240         m_bActive = false;
    00241     }
    00242
    00243     //-----------------------------------------------------------------------
    00244     bool CWin32Window::IsClosed() const
    00245     {
    00246         return m_bClosed;
    00247     }
    00248
    00249     //-----------------------------------------------------------------------
    00250     void CWin32Window::Reposition(int left, int top)
    00251     {
    00252         // @todo
    00253     }
    00254
    00255     //-----------------------------------------------------------------------
    00256     void CWin32Window::Resize(uint nWidth, uint nHeight)
    00257     {
    00258                 m_nWidth = nWidth;
    00259                 m_nHeight = nHeight;
    00260
    00261                 // @todo resize window
    00262     }
    00263
    00264     //-----------------------------------------------------------------------
    00265         void CWin32Window::WindowMovedOrResized()
    00266         {
    00267                 RECT temprect;
    00268                 ::GetClientRect(GetWindowHandle(),&temprect);
    00269                 Resize(temprect.right-temprect.left,temprect.bottom-temprect.top);
    00270         }
    00271
    00272     //-----------------------------------------------------------------------
    00273     void CWin32Window::SwapBuffers(bool bWaitForVSync)
    00274     {
    00275         ::SwapBuffers((HDC)m_HDC);
    00276     }
    00277
    00278         //-----------------------------------------------------------------------
    00279         LRESULT CWin32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    00280         {
    00281                 CWin32Window* win;
    00282
    00283                 // look up window instance
    00284                 if( WM_CREATE != uMsg )
    00285                         win = (CWin32Window*)GetWindowLong( hWnd, 0 );
    00286
    00287                 switch( uMsg )
    00288                 {
    00289                 case WM_ACTIVATE:
    00290                         if( WA_INACTIVE == LOWORD( wParam ) )
    00291                                 win->m_bActive = false;
    00292                         else
    00293                                 win->m_bActive = true;
    00294                         break;
    00295
    00296                 case WM_CREATE: {
    00297                         // Log the new window
    00298                         // Get CREATESTRUCT
    00299                         LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
    00300                         win = (CWin32Window*)(lpcs->lpCreateParams);
    00301                         // Store pointer in window user data area
    00302                         SetWindowLong( hWnd, 0, (long)win );
    00303                         win->m_bActive = true;
    00304
    00305                         return 0; }
    00306                         break;
    00307
    00308                 case WM_PAINT:
    00309                         // If we get WM_PAINT messges, it usually means our window was
    00310                         // comvered up, so we need to refresh it by re-showing the contents
    00311                         // of the current frame.
    00312                         if( win->m_bActive && win->m_bReady )
    00313                                 win->Update();
    00314                         break;
    00315
    00316                 case WM_MOVE:
    00317                         // Move messages need to be tracked to update the screen rects
    00318                         // used for blitting the backbuffer to the primary
    00319                         // *** This doesn't need to be used to Direct3D9 ***
    00320                         break;
    00321
    00322                 case WM_ENTERSIZEMOVE:
    00323                         // Previent rendering while moving / sizing
    00324                         win->m_bReady = false;
    00325                         break;
    00326
    00327                 case WM_EXITSIZEMOVE:
    00328                         win->WindowMovedOrResized();
    00329                         win->m_bReady = true;
    00330                         break;
    00331
    00332                 case WM_SIZE:
    00333                         // Check to see if we are losing or gaining our window.  Set the
    00334                         // active flag to match
    00335                         if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
    00336                                 win->m_bActive = false;
    00337                         else
    00338                         {
    00339                                 win->m_bActive = true;
    00340                                 if( win->m_bReady )
    00341                                         win->WindowMovedOrResized();
    00342                         }
    00343                         break;
    00344
    00345                 case WM_GETMINMAXINFO:
    00346                         // Prevent the window from going smaller than some minimu size
    00347                         ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
    00348                         ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
    00349                         break;
    00350         // On arrete le rendu lorsque l'on appuie sur Echap
    00351         // Provisoire en attendant une gestion plus fine des "Input"
    00352                 case WM_KEYDOWN:
    00353             switch (wParam)
    00354             {
    00355                         case VK_ESCAPE :win->m_bClosed = true; break;
    00356                         case VK_F1 :     CConsole::Instance().Enable(true);  break; // F1 = activer la console
    00357             case VK_F2 :     CConsole::Instance().Enable(false); break; // F2 = désactiver la console
    00358             }
    00359                     break;
    00360         // Caractère = envoi à la console
    00361         case WM_CHAR :
    00362             CConsole::Instance().SendChar(static_cast<char>(LOWORD(wParam)));
    00363             return 0;
    00364
    00365                 case WM_CLOSE:
    00366                         DestroyWindow( win->m_HWnd );
    00367                         win->m_bClosed = true;
    00368                         return 0;
    00369                 }
    00370
    00371                 return DefWindowProc( hWnd, uMsg, wParam, lParam );
    00372         }
    00373
    00374 } // namespace Keos