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_APPLICATION ),
    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, mLeft, mTop,
    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
    00157         }
    00158         else {
    00159             mHWnd = mExternalHandle;
    00160             RECT rc;
    00161             GetClientRect(mHWnd, &rc);
    00162             mWidth = rc.right;
    00163             mHeight = rc.bottom;
    00164             mLeft = rc.left;
    00165             mTop = rc.top;
    00166         }
    00167         ShowWindow(mHWnd, SW_SHOWNORMAL);
    00168         UpdateWindow(mHWnd);
    00169         mName = name;
    00170         mIsDepthBuffered = depthBuffer;
    00171         mIsFullScreen = fullScreen;
    00172
    00173
    00174         HDC hdc = GetDC(mHWnd);
    00175
    00176         LogManager::getSingleton().logMessage(
    00177             LML_NORMAL, "Created Win32Window '%s' : %ix%i, %ibpp",
    00178             mName.c_str(), mWidth, mHeight, mColourDepth );
    00179
    00180
    00181         PIXELFORMATDESCRIPTOR pfd = {
    00182             sizeof(PIXELFORMATDESCRIPTOR),
    00183             1,
    00184             PFD_DRAW_TO_WINDOW |
    00185             PFD_SUPPORT_OPENGL |
    00186             PFD_DOUBLEBUFFER,
    00187             PFD_TYPE_RGBA,
    00188             mColourDepth,
    00189             0, 0, 0, 0, 0, 0,
    00190             0,
    00191             0,
    00192             0,
    00193             0, 0, 0, 0,
    00194             32,                  // 32-bit depth-buffer (will be emulated in 16-bit colour mode)
    00195             8,                   // 8-bit stencil buffer
    00196             0,
    00197             PFD_MAIN_PLANE,
    00198             0,
    00199             0, 0, 0};
    00200         int iPixelFormat = ChoosePixelFormat(hdc, &pfd);
    00201         if (!iPixelFormat)
    00202             Except(0, "ChoosePixelFormat failed", "Win32Window::create");
    00203         if (!SetPixelFormat(hdc, iPixelFormat, &pfd))
    00204             Except(0, "SetPixelFormat failed", "Win32Window::create");
    00205
    00206         HGLRC glrc = wglCreateContext(hdc);
    00207         if (!glrc)
    00208             Except(0, "wglCreateContext", "Win32Window::create");
    00209         if (!wglMakeCurrent(hdc, glrc))
    00210             Except(0, "wglMakeCurrent", "Win32Window::create");
    00211
    00212         mGlrc = glrc;
    00213         mHDC = hdc;
    00214
    00215         mOldSwapIntervall = wglGetSwapIntervalEXT();
    00216         if (vsync)
    00217             wglSwapIntervalEXT(1);
    00218         else
    00219             wglSwapIntervalEXT(0);
    00220
    00221         mReady = true;
    00222     }
    00223
    00224     void Win32Window::destroy(void)
    00225     {
    00226         wglSwapIntervalEXT(mOldSwapIntervall);
    00227         if (mGlrc) {
    00228             wglMakeCurrent(NULL, NULL);
    00229             wglDeleteContext(mGlrc);
    00230             mGlrc = NULL;
    00231         }
    00232         if (mHDC) {
    00233             ReleaseDC(mHWnd, mHDC);
    00234             mHDC = NULL;
    00235         }
    00236         if (mIsFullScreen)
    00237         {
    00238             ChangeDisplaySettings(NULL, 0);
    00239         }
    00240     DestroyWindow(mHWnd);
    00241         mActive = false;
    00242     }
    00243
    00244     bool Win32Window::isActive() const
    00245     {
    00246         return mActive;
    00247     }
    00248
    00249     bool Win32Window::isClosed() const
    00250     {
    00251         return mClosed;
    00252     }
    00253
    00254     void Win32Window::reposition(int left, int top)
    00255     {
    00256         // XXX FIXME
    00257     }
    00258
    00259     void Win32Window::resize(unsigned int width, unsigned int height)
    00260     {
    00261
    00262         mWidth = width;
    00263         mHeight = height;
    00264
    00265         // Notify viewports of resize
    00266         ViewportList::iterator it, itend;
    00267         itend = mViewportList.end();
    00268         for( it = mViewportList.begin(); it != itend; ++it )
    00269             (*it).second->_updateDimensions();
    00270         // TODO - resize window
    00271     }
    00272
    00273     void Win32Window::windowMovedOrResized()
    00274     {
    00275         RECT temprect;
    00276         ::GetClientRect(getWindowHandle(),&temprect);
    00277         resize(temprect.right-temprect.left,temprect.bottom-temprect.top);
    00278         // TODO
    00279     }
    00280
    00281     void Win32Window::swapBuffers(bool waitForVSync)
    00282     {
    00283         SwapBuffers(mHDC);
    00284     }
    00285
    00286     void Win32Window::writeContentsToFile(const String& filename)
    00287     {
    00288         ImageCodec::ImageData imgData;
    00289         imgData.width = mWidth;
    00290         imgData.height = mHeight;
    00291         imgData.format = PF_R8G8B8;
    00292
    00293         // Allocate buffer
    00294         uchar* pBuffer = new uchar[mWidth * mHeight * 3];
    00295
    00296         // Read pixels
    00297         // I love GL: it does all the locking & colour conversion for us
    00298         glReadPixels(0,0, mWidth-1, mHeight-1, GL_RGB, GL_UNSIGNED_BYTE, pBuffer);
    00299
    00300         // Wrap buffer in a chunk
    00301         DataChunk chunk(pBuffer, mWidth * mHeight * 3);
    00302
    00303         // Need to flip the read data over in Y though
    00304         Image img;
    00305         img.loadRawData(chunk, mWidth, mHeight, PF_R8G8B8 );
    00306         img.flipAroundX();
    00307
    00308         DataChunk chunkFlipped(img.getData(), chunk.getSize());
    00309
    00310         // Get codec
    00311         size_t pos = filename.find_last_of(".");
    00312         String extension;
    00313         if( pos == String::npos )
    00314             Except(
    00315             Exception::ERR_INVALIDPARAMS,
    00316             "Unable to determine image type for '" + filename + "' - invalid extension.",
    00317             "Win32Window::writeContentsToFile" );
    00318
    00319         while( pos != filename.length() - 1 )
    00320             extension += filename[++pos];
    00321
    00322         // Get the codec
    00323         Codec * pCodec = Codec::getCodec(extension);
    00324
    00325         // Write out
    00326         pCodec->codeToFile(chunkFlipped, filename, &imgData);
    00327
    00328         delete [] pBuffer;
    00329     }
    00330
    00331     // Window procedure callback
    00332     // This is a static member, so applies to all windows but we store the
    00333     // Win32Window instance in the window data GetWindowLog/SetWindowLog
    00334     LRESULT Win32Window::WndProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
    00335     {
    00336         Win32Window* win;
    00337
    00338         // look up window instance
    00339         if( WM_CREATE != uMsg )
    00340             win = (Win32Window*)GetWindowLong( hWnd, 0 );
    00341
    00342         switch( uMsg )
    00343         {
    00344         case WM_ACTIVATE:
    00345             if( WA_INACTIVE == LOWORD( wParam ) )
    00346                 win->mActive = false;
    00347             else
    00348                 win->mActive = true;
    00349             break;
    00350
    00351         case WM_CREATE: {
    00352             // Log the new window
    00353             // Get CREATESTRUCT
    00354             LPCREATESTRUCT lpcs = (LPCREATESTRUCT)lParam;
    00355             win = (Win32Window*)(lpcs->lpCreateParams);
    00356             // Store pointer in window user data area
    00357             SetWindowLong( hWnd, 0, (long)win );
    00358             win->mActive = true;
    00359
    00360             return 0; }
    00361             break;
    00362
    00363         case WM_PAINT:
    00364             // If we get WM_PAINT messges, it usually means our window was
    00365             // comvered up, so we need to refresh it by re-showing the contents
    00366             // of the current frame.
    00367             if( win->mActive && win->mReady )
    00368                 win->update();
    00369             break;
    00370
    00371         case WM_MOVE:
    00372             // Move messages need to be tracked to update the screen rects
    00373             // used for blitting the backbuffer to the primary
    00374             // *** This doesn't need to be used to Direct3D9 ***
    00375             break;
    00376
    00377         case WM_ENTERSIZEMOVE:
    00378             // Previent rendering while moving / sizing
    00379             win->mReady = false;
    00380             break;
    00381
    00382         case WM_EXITSIZEMOVE:
    00383             win->windowMovedOrResized();
    00384             win->mReady = true;
    00385             break;
    00386
    00387         case WM_SIZE:
    00388             // Check to see if we are losing or gaining our window.  Set the
    00389             // active flag to match
    00390             if( SIZE_MAXHIDE == wParam || SIZE_MINIMIZED == wParam )
    00391                 win->mActive = false;
    00392             else
    00393             {
    00394                 win->mActive = true;
    00395                 if( win->mReady )
    00396                     win->windowMovedOrResized();
    00397             }
    00398             break;
    00399
    00400         case WM_GETMINMAXINFO:
    00401             // Prevent the window from going smaller than some minimu size
    00402             ((MINMAXINFO*)lParam)->ptMinTrackSize.x = 100;
    00403             ((MINMAXINFO*)lParam)->ptMinTrackSize.y = 100;
    00404             break;
    00405
    00406         case WM_CLOSE:
    00407             DestroyWindow( win->mHWnd );
    00408             win->mClosed = true;
    00409             return 0;
    00410         }
    00411
    00412         return DefWindowProc( hWnd, uMsg, wParam, lParam );
    00413     }
    00414 }

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:51 2004