Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreWin32Window.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2002 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 
00026 #include "OgreWin32Window.h"
00027 #include "OgreLogManager.h"
00028 #include "OgreRenderSystem.h"
00029 #include "OgreImageCodec.h"
00030 #include "OgreException.h"
00031 
00032 
00033 namespace Ogre {
00034 
00035     Win32Window::Win32Window()
00036     {
00037         mIsFullScreen = false;
00038         mHWnd = 0;
00039         mActive = false;
00040         mReady = false;
00041         mClosed = false;
00042         mExternalHandle = NULL;
00043     }
00044 
00045     Win32Window::~Win32Window()
00046     {
00047         destroy();
00048     }
00049 
00050     void Win32Window::create(const String& name, unsigned int width, unsigned int height, unsigned int colourDepth,
00051                            bool fullScreen, int left, int top, bool depthBuffer,
00052                            void* miscParam, ...)
00053     {
00054         HWND parentHWnd;
00055         HINSTANCE hInst = GetModuleHandle("RenderSystem_GL.dll");
00056         long tempPtr;
00057 
00058         // Get variable-length params
00059         // miscParam[0] = parent HWND
00060         // miscParam[1] = bool vsync
00061         // miscParam[2] = int displayFrequency
00062 
00063         va_list marker;
00064         va_start( marker, depthBuffer );
00065 
00066         tempPtr = va_arg( marker, long );
00067         Win32Window* parentRW = reinterpret_cast<Win32Window*>(tempPtr);
00068         if( parentRW == NULL )
00069             parentHWnd = 0;
00070         else
00071             parentHWnd = parentRW->getWindowHandle();
00072 
00073         tempPtr = va_arg( marker, long );
00074         bool vsync = (tempPtr != 0);
00075 
00076         tempPtr = va_arg( marker, long );
00077         unsigned int displayFrequency = static_cast<unsigned int>(tempPtr);
00078 
00079         va_end( marker );
00080 
00081         // Destroy current window if any
00082         if( mHWnd )
00083             destroy();
00084 
00085         if (fullScreen)
00086         {
00087             mColourDepth = colourDepth;
00088         }
00089         else 
00090         {
00091             // Get colour depth from display
00092             mColourDepth = GetDeviceCaps(GetDC(0), BITSPIXEL);
00093         }
00094 
00095         if (!mExternalHandle) {
00096             mWidth = width;
00097             mHeight = height;
00098             if (!fullScreen)
00099             {
00100                 if (!left && (unsigned)GetSystemMetrics(SM_CXSCREEN) > mWidth)
00101                 {
00102                     mLeft = (GetSystemMetrics(SM_CXSCREEN) / 2) - (mWidth / 2);
00103                 }
00104                 else
00105                 {
00106                     mLeft = left;
00107                 }
00108                 if (!top && (unsigned)GetSystemMetrics(SM_CYSCREEN) > mHeight)
00109                 {
00110                     mTop = (GetSystemMetrics(SM_CYSCREEN) / 2) - (mHeight / 2);
00111                 }
00112                 else
00113                 {
00114                     mTop = top;
00115                 }
00116             }
00117             else
00118             {
00119                 mTop = mLeft = 0;
00120             }
00121 
00122             // Register the window class
00123 
00124             WNDCLASS wndClass = { CS_HREDRAW | CS_VREDRAW, WndProc, 0, 4, hInst,
00125                 LoadIcon( NULL, "IDI_ICON1" ),
00126                 LoadCursor( NULL, IDC_ARROW ),
00127                 (HBRUSH)GetStockObject( BLACK_BRUSH ), NULL,
00128                 TEXT(name.c_str()) };
00129             RegisterClass( &wndClass );
00130 
00131             // Create our main window
00132             // Pass pointer to self
00133             HWND hWnd = CreateWindowEx(fullScreen?WS_EX_TOPMOST:0, TEXT(name.c_str()), TEXT(name.c_str()),
00134                 (fullScreen?WS_POPUP:WS_OVERLAPPEDWINDOW)|WS_CLIPCHILDREN|WS_CLIPSIBLINGS, left, top,
00135                 width, height, 0L, 0L, hInst, this);
00136             mHWnd = hWnd;
00137 
00138             RECT rc;
00139             GetClientRect(mHWnd,&rc);
00140             mWidth = rc.right;
00141             mHeight = rc.bottom;
00142 
00143             if (fullScreen) {
00144                 DEVMODE DevMode;
00145                 DevMode.dmSize = sizeof(DevMode);
00146                 DevMode.dmBitsPerPel = mColourDepth;
00147                 DevMode.dmPelsWidth = mWidth;
00148                 DevMode.dmPelsHeight = mHeight;
00149                 DevMode.dmDisplayFrequency = displayFrequency;
00150                 DevMode.dmFields = DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT|DM_DISPLAYFREQUENCY;
00151                 if (ChangeDisplaySettings(&DevMode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
00152                     LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettingsEx");
00153             }
00154 
00155         }
00156         else {
00157             mHWnd = mExternalHandle;
00158             RECT rc;
00159             GetClientRect(mHWnd, &rc);
00160             mWidth = rc.right;
00161             mHeight = rc.bottom;
00162             mLeft = rc.left;
00163             mTop = rc.top;
00164         }
00165         ShowWindow(mHWnd, SW_SHOWNORMAL);
00166         UpdateWindow(mHWnd);
00167         mName = name;
00168         mIsDepthBuffered = depthBuffer;
00169         mIsFullScreen = fullScreen;
00170 
00171         /*if (!vsync) {
00172             mOldSwapIntervall = wglGetSwapIntervalEXT();
00173             wglSwapIntervalEXT(0);
00174         }
00175         else
00176             mOldSwapIntervall = -1;*/
00177         HDC hdc = GetDC(mHWnd);
00178 
00179         LogManager::getSingleton().logMessage(
00180             LML_NORMAL, "Created Win32Window '%s' : %ix%i, %ibpp",
00181             mName.c_str(), mWidth, mHeight, mColourDepth );
00182 
00183         PIXELFORMATDESCRIPTOR pfd = {
00184             sizeof(PIXELFORMATDESCRIPTOR),
00185             1,
00186             PFD_DRAW_TO_WINDOW |
00187             PFD_SUPPORT_OPENGL |
00188             PFD_DOUBLEBUFFER,
00189             PFD_TYPE_RGBA,
00190             mColourDepth,
00191             0, 0, 0, 0, 0, 0,
00192             0,
00193             0,
00194             0,
00195             0, 0, 0, 0,
00196             32,                  // 32-bit z-buffer
00197             0,                   // no stencil buffer
00198             0,
00199             PFD_MAIN_PLANE,
00200             0,
00201             0, 0, 0};
00202         int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
00203         if (!iPixelFormat)
00204             Except(0, "ChoosePixelFormat failed", "Win32Window::create");
00205         if (!SetPixelFormat(hdc, iPixelFormat, &pfd))
00206             Except(0, "SetPixelFormat failed", "Win32Window::create");
00207 
00208         HGLRC glrc = wglCreateContext(hdc);
00209         if (!glrc)
00210             Except(0, "wglCreateContext", "Win32Window::create");
00211         if (!wglMakeCurrent(hdc, glrc))
00212             Except(0, "wglMakeCurrent", "Win32Window::create");
00213         
00214         mGlrc = glrc;
00215         mHDC = hdc;
00216 
00217         mReady = true;
00218     }
00219 
00220     void Win32Window::destroy(void)
00221     {
00222         if (mGlrc) {
00223             wglMakeCurrent(NULL, NULL);
00224             wglDeleteContext(mGlrc);
00225             mGlrc = NULL;
00226         }
00227         if (mHDC) {
00228             ReleaseDC(mHWnd, mHDC);
00229             mHDC = NULL;
00230         }
00231         /*if (mOldSwapIntervall >= 0)
00232             wglSwapIntervalEXT(mOldSwapIntervall);*/
00233         if (mIsFullScreen)
00234             ChangeDisplaySettings(NULL, 0);
00235         DestroyWindow(mHWnd);
00236         mActive = false;
00237     }
00238 
00239     bool Win32Window::isActive() const
00240     {
00241         return mActive;
00242     }
00243 
00244     bool Win32Window::isClosed() const
00245     {
00246         return mClosed;
00247     }
00248 
00249     void Win32Window::reposition(int left, int top)
00250     {
00251         // XXX FIXME
00252     }
00253 
00254     void Win32Window::resize(unsigned int width, unsigned int height)
00255     {
00256 
00257         mWidth = width;
00258         mHeight = height;
00259 
00260         // Notify viewports of resize
00261         ViewportList::iterator it, itend;
00262         itend = mViewportList.end();
00263         for( it = mViewportList.begin(); it != itend; ++it )
00264             (*it).second->_updateDimensions();
00265         // TODO - resize window
00266     }
00267 
00268     void Win32Window::WindowMovedOrResized()
00269     {
00270         // TODO
00271     }
00272 
00273     void Win32Window::swapBuffers(bool waitForVSync)
00274     {
00275         SwapBuffers(mHDC);
00276     }
00277 
00278     void Win32Window::outputText(int x, int y, const String& text)
00279     {
00280         //deprecated
00281     }
00282     void Win32Window::writeContentsToFile(const String& filename)
00283     {
00284         ImageCodec::ImageData imgData;
00285         imgData.width = mWidth;
00286         imgData.height = mHeight;
00287         imgData.format = PF_R8G8B8;
00288 
00289         // Allocate buffer 
00290         uchar* pBuffer = new uchar[mWidth * mHeight * 3];
00291 
00292         // Read pixels
00293         // I love GL: it does all the locking & colour conversion for us
00294         glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
00295 
00296         // Wrap buffer in a chunk
00297         DataChunk chunk(pBuffer, mWidth * mHeight * 3);
00298 
00299         // Need to flip the read data over in Y though
00300         Image img;
00301         img.loadRawData(chunk, mWidth, mHeight, PF_R8G8B8 );
00302         img.flipAroundX();
00303 
00304         DataChunk chunkFlipped(img.getData(), chunk.getSize());
00305 
00306         // Get codec 
00307         size_t pos = filename.find_last_of(".");
00308         String extension;
00309         if( pos == String::npos )
00310             Except(
00311             Exception::ERR_INVALIDPARAMS, 
00312             "Unable to determine image type for '" + filename + "' - invalid extension.",
00313             "Win32Window::writeContentsToFile" );
00314 
00315         while( pos != filename.length() - 1 )
00316             extension += filename[++pos];
00317 
00318         // Get the codec
00319         Codec * pCodec = Codec::getCodec(extension);
00320 
00321         // Write out
00322         pCodec->codeToFile(chunkFlipped, filename, &imgData);
00323 
00324         delete [] pBuffer;
00325     }
00326 
00327     // Window procedure callback
00328     // This is a static member, so applies to all windows but we store the
00329     // Win32Window instance in the window data GetWindowLog/SetWindowLog
00330     LRESULT Win32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
00331     {
00332         Win32Window* win;
00333 
00334         // look up window instance
00335         if( WM_CREATE != uMsg )
00336             win = (Win32Window*)GetWindowLong( hWnd, 0 );
00337 
00338         switch( uMsg )
00339         {
00340         case WM_ACTIVATE:
00341             if( WA_INACTIVE == LOWORD( wParam ) )
00342                 win->mActive = false;
00343             else
00344                 win->mActive = true;
00345             break;
00346 
00347         case WM_CREATE: {
00348             // Log the new window
00349             // Get CREATESTRUCT
00350             LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
00351             win = (Win32Window*)(lpcs->lpCreateParams);
00352             // Store pointer in window user data area
00353             SetWindowLong( hWnd, 0, (long)win );
00354             win->mActive = true;
00355 
00356             return 0; }
00357             break;
00358 
00359         case WM_PAINT:
00360             // If we get WM_PAINT messges, it usually means our window was
00361             // comvered up, so we need to refresh it by re-showing the contents
00362             // of the current frame.
00363             if( win->mActive && win->mReady )
00364                 win->update();
00365             break;
00366 
00367         case WM_MOVE:
00368             // Move messages need to be tracked to update the screen rects
00369             // used for blitting the backbuffer to the primary
00370             // *** This doesn't need to be used to Direct3D9 ***
00371             break;
00372 
00373         case WM_ENTERSIZEMOVE:
00374             // Previent rendering while moving / sizing
00375             win->mReady = false;
00376             break;
00377 
00378         case WM_EXITSIZEMOVE:
00379             win->WindowMovedOrResized();
00380             win->mReady = true;
00381             break;
00382 
00383         case WM_SIZE:
00384             // Check to see if we are losing or gaining our window.  Set the 
00385             // active flag to match
00386             if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
00387                 win->mActive = false;
00388             else
00389             {
00390                 win->mActive = true;
00391                 if( win->mReady )
00392                     win->WindowMovedOrResized();
00393             }
00394             break;
00395 
00396         case WM_GETMINMAXINFO:
00397             // Prevent the window from going smaller than some minimu size
00398             ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
00399             ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
00400             break;
00401 
00402         case WM_CLOSE:
00403             DestroyWindow( win->mHWnd );
00404             win->mClosed = true;
00405             return 0;
00406         }
00407 
00408         return DefWindowProc( hWnd, uMsg, wParam, lParam );
00409     }
00410 }

Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:32 2004