| 1 | /* | 
|---|
| 2 | ----------------------------------------------------------------------------- | 
|---|
| 3 | This source file is part of OGRE | 
|---|
| 4 | (Object-oriented Graphics Rendering Engine) | 
|---|
| 5 | For the latest info, see http://www.ogre3d.org/ | 
|---|
| 6 |  | 
|---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd | 
|---|
| 8 | Also see acknowledgements in Readme.html | 
|---|
| 9 |  | 
|---|
| 10 | This program is free software; you can redistribute it and/or modify it under | 
|---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software | 
|---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later | 
|---|
| 13 | version. | 
|---|
| 14 |  | 
|---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT | 
|---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | 
|---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. | 
|---|
| 18 |  | 
|---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with | 
|---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple | 
|---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to | 
|---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. | 
|---|
| 23 |  | 
|---|
| 24 | You may alternatively use this source under the terms of a specific version of | 
|---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from | 
|---|
| 26 | Torus Knot Software Ltd. | 
|---|
| 27 | ----------------------------------------------------------------------------- | 
|---|
| 28 | */ | 
|---|
| 29 |  | 
|---|
| 30 | #include "OgreWin32Window.h" | 
|---|
| 31 | #include "OgreRoot.h" | 
|---|
| 32 | #include "OgreLogManager.h" | 
|---|
| 33 | #include "OgreRenderSystem.h" | 
|---|
| 34 | #include "OgreImageCodec.h" | 
|---|
| 35 | #include "OgreStringConverter.h" | 
|---|
| 36 | #include "OgreException.h" | 
|---|
| 37 | #include "OgreWin32GLSupport.h" | 
|---|
| 38 | #include "OgreWin32Context.h" | 
|---|
| 39 | #include "OgreWindowEventUtilities.h" | 
|---|
| 40 |  | 
|---|
| 41 | namespace Ogre { | 
|---|
| 42 |  | 
|---|
| 43 |         Win32Window::Win32Window(Win32GLSupport &glsupport): | 
|---|
| 44 |                 mGLSupport(glsupport), | 
|---|
| 45 |                 mContext(0) | 
|---|
| 46 |         { | 
|---|
| 47 |                 mIsFullScreen = false; | 
|---|
| 48 |                 mHWnd = 0; | 
|---|
| 49 |                 mGlrc = 0; | 
|---|
| 50 |                 mIsExternal = false; | 
|---|
| 51 |                 mIsExternalGLControl = false; | 
|---|
| 52 |                 mIsExternalGLContext = false; | 
|---|
| 53 |                 mSizing = false; | 
|---|
| 54 |                 mClosed = false; | 
|---|
| 55 |                 mDisplayFrequency = 0; | 
|---|
| 56 |                 mActive = false; | 
|---|
| 57 |         } | 
|---|
| 58 |  | 
|---|
| 59 |         Win32Window::~Win32Window() | 
|---|
| 60 |         { | 
|---|
| 61 |                 destroy(); | 
|---|
| 62 |         } | 
|---|
| 63 |  | 
|---|
| 64 |         void Win32Window::create(const String& name, unsigned int width, unsigned int height, | 
|---|
| 65 |                                                         bool fullScreen, const NameValuePairList *miscParams) | 
|---|
| 66 |         { | 
|---|
| 67 |                 // destroy current window, if any | 
|---|
| 68 |                 if (mHWnd) | 
|---|
| 69 |                         destroy(); | 
|---|
| 70 |  | 
|---|
| 71 | #ifdef OGRE_STATIC_LIB | 
|---|
| 72 |                 HINSTANCE hInst = GetModuleHandle( NULL ); | 
|---|
| 73 | #else | 
|---|
| 74 |                 HINSTANCE hInst = GetModuleHandle("RenderSystem_GL.dll"); | 
|---|
| 75 | #endif | 
|---|
| 76 |  | 
|---|
| 77 |                 mHWnd = 0; | 
|---|
| 78 |                 mName = name; | 
|---|
| 79 |                 mIsFullScreen = fullScreen; | 
|---|
| 80 |                 mClosed = false; | 
|---|
| 81 |  | 
|---|
| 82 |                 // load window defaults | 
|---|
| 83 |                 mLeft = mTop = -1; // centered | 
|---|
| 84 |                 mWidth = width; | 
|---|
| 85 |                 mHeight = height; | 
|---|
| 86 |                 mDisplayFrequency = 0; | 
|---|
| 87 |                 mIsDepthBuffered = true; | 
|---|
| 88 |                 mColourDepth = mIsFullScreen? 32 : GetDeviceCaps(GetDC(0), BITSPIXEL); | 
|---|
| 89 |  | 
|---|
| 90 |                 HWND parent = 0; | 
|---|
| 91 |                 String title = name; | 
|---|
| 92 |                 bool vsync = false; | 
|---|
| 93 |                 int fsaa = 0; | 
|---|
| 94 |                 String border; | 
|---|
| 95 |                 bool outerSize = false; | 
|---|
| 96 |  | 
|---|
| 97 |                 if(miscParams) | 
|---|
| 98 |                 { | 
|---|
| 99 |                         // Get variable-length params | 
|---|
| 100 |                         NameValuePairList::const_iterator opt; | 
|---|
| 101 |                         NameValuePairList::const_iterator end = miscParams->end(); | 
|---|
| 102 |  | 
|---|
| 103 |                         if ((opt = miscParams->find("title")) != end) | 
|---|
| 104 |                                 title = opt->second; | 
|---|
| 105 |  | 
|---|
| 106 |                         if ((opt = miscParams->find("left")) != end) | 
|---|
| 107 |                                 mLeft = StringConverter::parseInt(opt->second); | 
|---|
| 108 |  | 
|---|
| 109 |                         if ((opt = miscParams->find("top")) != end) | 
|---|
| 110 |                                 mTop = StringConverter::parseInt(opt->second); | 
|---|
| 111 |  | 
|---|
| 112 |                         if ((opt = miscParams->find("depthBuffer")) != end) | 
|---|
| 113 |                                 mIsDepthBuffered = StringConverter::parseBool(opt->second); | 
|---|
| 114 |  | 
|---|
| 115 |                         if ((opt = miscParams->find("vsync")) != end) | 
|---|
| 116 |                                 vsync = StringConverter::parseBool(opt->second); | 
|---|
| 117 |  | 
|---|
| 118 |                         if ((opt = miscParams->find("FSAA")) != end) | 
|---|
| 119 |                                 fsaa = StringConverter::parseUnsignedInt(opt->second); | 
|---|
| 120 |  | 
|---|
| 121 |                         if ((opt = miscParams->find("externalWindowHandle")) != end) | 
|---|
| 122 |                         { | 
|---|
| 123 |                                 mHWnd = (HWND)StringConverter::parseUnsignedInt(opt->second); | 
|---|
| 124 |                                 if (mHWnd) | 
|---|
| 125 |                                 { | 
|---|
| 126 |                                         mIsExternal = true; | 
|---|
| 127 |                                         mIsFullScreen = false; | 
|---|
| 128 |                                 } | 
|---|
| 129 |  | 
|---|
| 130 |                                 if ((opt = miscParams->find("externalGLControl")) != end) { | 
|---|
| 131 |                                   mIsExternalGLControl = StringConverter::parseBool(opt->second); | 
|---|
| 132 |                                 } | 
|---|
| 133 |                         } | 
|---|
| 134 |                         if ((opt = miscParams->find("externalGLContext")) != end) | 
|---|
| 135 |                         { | 
|---|
| 136 |                                 mGlrc = (HGLRC)StringConverter::parseUnsignedLong(opt->second); | 
|---|
| 137 |                                 if( mGlrc ) | 
|---|
| 138 |                                         mIsExternalGLContext = true; | 
|---|
| 139 |                         } | 
|---|
| 140 |  | 
|---|
| 141 |                         // window border style | 
|---|
| 142 |                         opt = miscParams->find("border"); | 
|---|
| 143 |                         if(opt != miscParams->end()) | 
|---|
| 144 |                                 border = opt->second; | 
|---|
| 145 |                         // set outer dimensions? | 
|---|
| 146 |                         opt = miscParams->find("outerDimensions"); | 
|---|
| 147 |                         if(opt != miscParams->end()) | 
|---|
| 148 |                                 outerSize = StringConverter::parseBool(opt->second); | 
|---|
| 149 |  | 
|---|
| 150 |                         // only available with fullscreen | 
|---|
| 151 |                         if ((opt = miscParams->find("displayFrequency")) != end) | 
|---|
| 152 |                                 mDisplayFrequency = StringConverter::parseUnsignedInt(opt->second); | 
|---|
| 153 |                         if ((opt = miscParams->find("colourDepth")) != end) | 
|---|
| 154 |                                 mColourDepth = StringConverter::parseUnsignedInt(opt->second); | 
|---|
| 155 |  | 
|---|
| 156 |                         // incompatible with fullscreen | 
|---|
| 157 |                         if ((opt = miscParams->find("parentWindowHandle")) != end) | 
|---|
| 158 |                                 parent = (HWND)StringConverter::parseUnsignedInt(opt->second); | 
|---|
| 159 |                 } | 
|---|
| 160 |  | 
|---|
| 161 |                 if (!mIsExternal) | 
|---|
| 162 |                 { | 
|---|
| 163 |                         DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN; | 
|---|
| 164 |                         DWORD dwStyleEx = 0; | 
|---|
| 165 |                         int outerw, outerh; | 
|---|
| 166 |  | 
|---|
| 167 |                         if (mIsFullScreen) | 
|---|
| 168 |                         { | 
|---|
| 169 |                                 dwStyle |= WS_POPUP; | 
|---|
| 170 |                                 dwStyleEx |= WS_EX_TOPMOST; | 
|---|
| 171 |                                 outerw = mWidth; | 
|---|
| 172 |                                 outerh = mHeight; | 
|---|
| 173 |                                 mLeft = mTop = 0; | 
|---|
| 174 |                         } | 
|---|
| 175 |                         else | 
|---|
| 176 |                         { | 
|---|
| 177 |                                 if (parent) | 
|---|
| 178 |                                 { | 
|---|
| 179 |                                         dwStyle |= WS_CHILD; | 
|---|
| 180 |                                 } | 
|---|
| 181 |                                 else | 
|---|
| 182 |                                 { | 
|---|
| 183 |                                         if (border == "none") | 
|---|
| 184 |                                                 dwStyle |= WS_POPUP; | 
|---|
| 185 |                                         else if (border == "fixed") | 
|---|
| 186 |                                                 dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION | | 
|---|
| 187 |                                                 WS_SYSMENU | WS_MINIMIZEBOX; | 
|---|
| 188 |                                         else | 
|---|
| 189 |                                                 dwStyle |= WS_OVERLAPPEDWINDOW; | 
|---|
| 190 |                                 } | 
|---|
| 191 |  | 
|---|
| 192 |                                 int screenw = GetSystemMetrics(SM_CXSCREEN); | 
|---|
| 193 |                                 int screenh = GetSystemMetrics(SM_CYSCREEN); | 
|---|
| 194 |  | 
|---|
| 195 |                                 if (!outerSize) | 
|---|
| 196 |                                 { | 
|---|
| 197 |                                         // calculate overall dimensions for requested client area | 
|---|
| 198 |                                         RECT rc = { 0, 0, mWidth, mHeight }; | 
|---|
| 199 |                                         AdjustWindowRect(&rc, dwStyle, false); | 
|---|
| 200 |  | 
|---|
| 201 |                                         // clamp window dimensions to screen size | 
|---|
| 202 |                                         outerw = (rc.right-rc.left < screenw)? rc.right-rc.left : screenw; | 
|---|
| 203 |                                         outerh = (rc.bottom-rc.top < screenh)? rc.bottom-rc.top : screenh; | 
|---|
| 204 |                                 } | 
|---|
| 205 |  | 
|---|
| 206 |                                 // center window if given negative coordinates | 
|---|
| 207 |                                 if (mLeft < 0) | 
|---|
| 208 |                                         mLeft = (screenw - outerw) / 2; | 
|---|
| 209 |                                 if (mTop < 0) | 
|---|
| 210 |                                         mTop = (screenh - outerh) / 2; | 
|---|
| 211 |  | 
|---|
| 212 |                                 // keep window contained in visible screen area | 
|---|
| 213 |                                 if (mLeft > screenw - outerw) | 
|---|
| 214 |                                         mLeft = screenw - outerw; | 
|---|
| 215 |                                 if (mTop > screenh - outerh) | 
|---|
| 216 |                                         mTop = screenh - outerh; | 
|---|
| 217 |                         } | 
|---|
| 218 |  | 
|---|
| 219 |                         // register class and create window | 
|---|
| 220 |                         WNDCLASS wc = { CS_OWNDC, WindowEventUtilities::_WndProc, 0, 0, hInst, | 
|---|
| 221 |                                 LoadIcon(NULL, IDI_APPLICATION), LoadCursor(NULL, IDC_ARROW), | 
|---|
| 222 |                                 (HBRUSH)GetStockObject(BLACK_BRUSH), NULL, "OgreGLWindow" }; | 
|---|
| 223 |                         RegisterClass(&wc); | 
|---|
| 224 |  | 
|---|
| 225 |                         // Pass pointer to self as WM_CREATE parameter | 
|---|
| 226 |                         mHWnd = CreateWindowEx(dwStyleEx, "OgreGLWindow", title.c_str(), | 
|---|
| 227 |                                 dwStyle, mLeft, mTop, outerw, outerh, parent, 0, hInst, this); | 
|---|
| 228 |  | 
|---|
| 229 |                         WindowEventUtilities::_addRenderWindow(this); | 
|---|
| 230 |  | 
|---|
| 231 |                         StringUtil::StrStreamType str; | 
|---|
| 232 |                         str << "Created Win32Window '" | 
|---|
| 233 |                                 << mName << "' : " << mWidth << "x" << mHeight | 
|---|
| 234 |                                 << ", " << mColourDepth << "bpp"; | 
|---|
| 235 |                         LogManager::getSingleton().logMessage(LML_NORMAL, str.str()); | 
|---|
| 236 |  | 
|---|
| 237 |                         if (mIsFullScreen) | 
|---|
| 238 |                         { | 
|---|
| 239 |                                 DEVMODE dm; | 
|---|
| 240 |                                 dm.dmSize = sizeof(DEVMODE); | 
|---|
| 241 |                                 dm.dmBitsPerPel = mColourDepth; | 
|---|
| 242 |                                 dm.dmPelsWidth = mWidth; | 
|---|
| 243 |                                 dm.dmPelsHeight = mHeight; | 
|---|
| 244 |                                 dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; | 
|---|
| 245 |                                 if (mDisplayFrequency) | 
|---|
| 246 |                                 { | 
|---|
| 247 |                                         dm.dmDisplayFrequency = mDisplayFrequency; | 
|---|
| 248 |                                         dm.dmFields |= DM_DISPLAYFREQUENCY; | 
|---|
| 249 |                                         if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 250 |                                         { | 
|---|
| 251 |                                                 LogManager::getSingleton().logMessage(LML_NORMAL, "ChangeDisplaySettings with user display frequency failed"); | 
|---|
| 252 |                                                 dm.dmFields ^= DM_DISPLAYFREQUENCY; | 
|---|
| 253 |                                         } | 
|---|
| 254 |                                 } | 
|---|
| 255 |                                 if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 256 |                                         LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed"); | 
|---|
| 257 |                         } | 
|---|
| 258 |                 } | 
|---|
| 259 |  | 
|---|
| 260 |                 HDC old_hdc = wglGetCurrentDC(); | 
|---|
| 261 |                 HGLRC old_context = wglGetCurrentContext(); | 
|---|
| 262 |  | 
|---|
| 263 |                 RECT rc; | 
|---|
| 264 |                 // top and left represent outer window position | 
|---|
| 265 |                 GetWindowRect(mHWnd, &rc); | 
|---|
| 266 |                 mTop = rc.top; | 
|---|
| 267 |                 mLeft = rc.left; | 
|---|
| 268 |                 // width and height represent drawable area only | 
|---|
| 269 |                 GetClientRect(mHWnd, &rc); | 
|---|
| 270 |                 mWidth = rc.right; | 
|---|
| 271 |                 mHeight = rc.bottom; | 
|---|
| 272 |  | 
|---|
| 273 |                 mHDC = GetDC(mHWnd); | 
|---|
| 274 |  | 
|---|
| 275 |                 if (!mIsExternalGLControl) | 
|---|
| 276 |                 { | 
|---|
| 277 |                         if (!mGLSupport.selectPixelFormat(mHDC, mColourDepth, fsaa)) | 
|---|
| 278 |                         { | 
|---|
| 279 |                                 if (fsaa == 0) | 
|---|
| 280 |                                         OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "selectPixelFormat failed", "Win32Window::create"); | 
|---|
| 281 |  | 
|---|
| 282 |                                 LogManager::getSingleton().logMessage(LML_NORMAL, "FSAA level not supported, falling back"); | 
|---|
| 283 |                                 if (!mGLSupport.selectPixelFormat(mHDC, mColourDepth, 0)) | 
|---|
| 284 |                                         OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "selectPixelFormat failed", "Win32Window::create"); | 
|---|
| 285 |                         } | 
|---|
| 286 |                 } | 
|---|
| 287 |                 if (!mIsExternalGLContext) | 
|---|
| 288 |                 { | 
|---|
| 289 |                         mGlrc = wglCreateContext(mHDC); | 
|---|
| 290 |                         if (!mGlrc) | 
|---|
| 291 |                                 OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "wglCreateContext", "Win32Window::create"); | 
|---|
| 292 |                 } | 
|---|
| 293 |                 if (!wglMakeCurrent(mHDC, mGlrc)) | 
|---|
| 294 |                         OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "wglMakeCurrent", "Win32Window::create"); | 
|---|
| 295 |  | 
|---|
| 296 |                 // Do not change vsync if the external window has the OpenGL control | 
|---|
| 297 |                 if (!mIsExternalGLControl) { | 
|---|
| 298 |                         // Don't use wglew as if this is the first window, we won't have initialised yet | 
|---|
| 299 |                         PFNWGLSWAPINTERVALEXTPROC _wglSwapIntervalEXT =  | 
|---|
| 300 |                                 (PFNWGLSWAPINTERVALEXTPROC)wglGetProcAddress("wglSwapIntervalEXT"); | 
|---|
| 301 |                         if (_wglSwapIntervalEXT) | 
|---|
| 302 |                                 _wglSwapIntervalEXT(vsync? 1 : 0); | 
|---|
| 303 |                 } | 
|---|
| 304 |  | 
|---|
| 305 |         if (old_context && old_context != mGlrc) | 
|---|
| 306 |         { | 
|---|
| 307 |             // Restore old context | 
|---|
| 308 |                     if (!wglMakeCurrent(old_hdc, old_context)) | 
|---|
| 309 |                             OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "wglMakeCurrent() failed", "Win32Window::create"); | 
|---|
| 310 |  | 
|---|
| 311 |             // Share lists with old context | 
|---|
| 312 |                     if (!wglShareLists(old_context, mGlrc)) | 
|---|
| 313 |                             OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, "wglShareLists() failed", " Win32Window::create"); | 
|---|
| 314 |         } | 
|---|
| 315 |  | 
|---|
| 316 |                 // Create RenderSystem context | 
|---|
| 317 |                 mContext = new Win32Context(mHDC, mGlrc); | 
|---|
| 318 |  | 
|---|
| 319 |                 mActive = true; | 
|---|
| 320 |         } | 
|---|
| 321 |  | 
|---|
| 322 |         void Win32Window::setFullscreen(bool fullScreen, unsigned int width, unsigned int height) | 
|---|
| 323 |         { | 
|---|
| 324 |                 if (mIsFullScreen != fullScreen || width != mWidth || height != mHeight) | 
|---|
| 325 |                 { | 
|---|
| 326 |                         mIsFullScreen = fullScreen; | 
|---|
| 327 |                         DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN; | 
|---|
| 328 |  | 
|---|
| 329 |                         if (mIsFullScreen) | 
|---|
| 330 |                         { | 
|---|
| 331 |                                 dwStyle |= WS_POPUP; | 
|---|
| 332 |  | 
|---|
| 333 |                                 DEVMODE dm; | 
|---|
| 334 |                                 dm.dmSize = sizeof(DEVMODE); | 
|---|
| 335 |                                 dm.dmBitsPerPel = mColourDepth; | 
|---|
| 336 |                                 dm.dmPelsWidth = width; | 
|---|
| 337 |                                 dm.dmPelsHeight = height; | 
|---|
| 338 |                                 dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; | 
|---|
| 339 |                                 if (mDisplayFrequency) | 
|---|
| 340 |                                 { | 
|---|
| 341 |                                         dm.dmDisplayFrequency = mDisplayFrequency; | 
|---|
| 342 |                                         dm.dmFields |= DM_DISPLAYFREQUENCY; | 
|---|
| 343 |                                         if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 344 |                                         { | 
|---|
| 345 |                                                 LogManager::getSingleton().logMessage(LML_NORMAL, "ChangeDisplaySettings with user display frequency failed"); | 
|---|
| 346 |                                                 dm.dmFields ^= DM_DISPLAYFREQUENCY; | 
|---|
| 347 |                                         } | 
|---|
| 348 |                                 } | 
|---|
| 349 |                                 else | 
|---|
| 350 |                                 { | 
|---|
| 351 |                                         // try a few | 
|---|
| 352 |                                         dm.dmDisplayFrequency = 100; | 
|---|
| 353 |                                         dm.dmFields |= DM_DISPLAYFREQUENCY; | 
|---|
| 354 |                                         if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 355 |                                         { | 
|---|
| 356 |                                                 dm.dmDisplayFrequency = 75; | 
|---|
| 357 |                                                 if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN | CDS_TEST) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 358 |                                                 { | 
|---|
| 359 |                                                         dm.dmFields ^= DM_DISPLAYFREQUENCY; | 
|---|
| 360 |                                                 } | 
|---|
| 361 |                                         } | 
|---|
| 362 |  | 
|---|
| 363 |                                 } | 
|---|
| 364 |                                 if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) | 
|---|
| 365 |                                         LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed"); | 
|---|
| 366 |  | 
|---|
| 367 |                                 SetWindowLong(mHWnd, GWL_STYLE, dwStyle); | 
|---|
| 368 |                                 SetWindowPos(mHWnd, HWND_TOPMOST, 0, 0, width, height, | 
|---|
| 369 |                                         SWP_NOACTIVATE); | 
|---|
| 370 |                                 mWidth = width; | 
|---|
| 371 |                                 mHeight = height; | 
|---|
| 372 |  | 
|---|
| 373 |  | 
|---|
| 374 |                         } | 
|---|
| 375 |                         else | 
|---|
| 376 |                         { | 
|---|
| 377 |                                 dwStyle |= WS_OVERLAPPEDWINDOW; | 
|---|
| 378 |  | 
|---|
| 379 |                                 // drop out of fullscreen | 
|---|
| 380 |                                 ChangeDisplaySettings(NULL, 0); | 
|---|
| 381 |  | 
|---|
| 382 |                                 // calculate overall dimensions for requested client area | 
|---|
| 383 |                                 RECT rc = { 0, 0, width, height }; | 
|---|
| 384 |                                 AdjustWindowRect(&rc, dwStyle, false); | 
|---|
| 385 |                                 unsigned int winWidth = rc.right - rc.left; | 
|---|
| 386 |                                 unsigned int winHeight = rc.bottom - rc.top; | 
|---|
| 387 |  | 
|---|
| 388 |                                 int screenw = GetSystemMetrics(SM_CXSCREEN); | 
|---|
| 389 |                                 int screenh = GetSystemMetrics(SM_CYSCREEN); | 
|---|
| 390 |                                 int left = (screenw - winWidth) / 2; | 
|---|
| 391 |                                 int top = (screenh - winHeight) / 2; | 
|---|
| 392 |  | 
|---|
| 393 |  | 
|---|
| 394 |                                 SetWindowLong(mHWnd, GWL_STYLE, dwStyle); | 
|---|
| 395 |                                 SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight, | 
|---|
| 396 |                                         SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE); | 
|---|
| 397 |                                 mWidth = width; | 
|---|
| 398 |                                 mHeight = height; | 
|---|
| 399 |  | 
|---|
| 400 |                         } | 
|---|
| 401 |  | 
|---|
| 402 |                 } | 
|---|
| 403 |         } | 
|---|
| 404 |  | 
|---|
| 405 |         void Win32Window::destroy(void) | 
|---|
| 406 |         { | 
|---|
| 407 |                 if (!mHWnd) | 
|---|
| 408 |                         return; | 
|---|
| 409 |  | 
|---|
| 410 |                 // Unregister and destroy OGRE GLContext | 
|---|
| 411 |                 delete mContext; | 
|---|
| 412 |  | 
|---|
| 413 |                 if (!mIsExternalGLContext && mGlrc) | 
|---|
| 414 |                 { | 
|---|
| 415 |                         wglDeleteContext(mGlrc); | 
|---|
| 416 |                         mGlrc = 0; | 
|---|
| 417 |                 } | 
|---|
| 418 |                 if (!mIsExternal) | 
|---|
| 419 |                 { | 
|---|
| 420 |                         WindowEventUtilities::_removeRenderWindow(this); | 
|---|
| 421 |  | 
|---|
| 422 |                         if (mIsFullScreen) | 
|---|
| 423 |                                 ChangeDisplaySettings(NULL, 0); | 
|---|
| 424 |                         DestroyWindow(mHWnd); | 
|---|
| 425 |                 } | 
|---|
| 426 |                 else | 
|---|
| 427 |                 { | 
|---|
| 428 |                         // just release the DC | 
|---|
| 429 |                         ReleaseDC(mHWnd, mHDC); | 
|---|
| 430 |                 } | 
|---|
| 431 |  | 
|---|
| 432 |                 mActive = false; | 
|---|
| 433 |                 mClosed = true; | 
|---|
| 434 |                 mHDC = 0; // no release thanks to CS_OWNDC wndclass style | 
|---|
| 435 |                 mHWnd = 0; | 
|---|
| 436 |         } | 
|---|
| 437 |  | 
|---|
| 438 |         bool Win32Window::isVisible() const | 
|---|
| 439 |         { | 
|---|
| 440 |                 return (mHWnd && !IsIconic(mHWnd)); | 
|---|
| 441 |         } | 
|---|
| 442 |  | 
|---|
| 443 |         bool Win32Window::isClosed() const | 
|---|
| 444 |         { | 
|---|
| 445 |                 return mClosed; | 
|---|
| 446 |         } | 
|---|
| 447 |  | 
|---|
| 448 |         void Win32Window::reposition(int left, int top) | 
|---|
| 449 |         { | 
|---|
| 450 |                 if (mHWnd && !mIsFullScreen) | 
|---|
| 451 |                 { | 
|---|
| 452 |                         SetWindowPos(mHWnd, 0, left, top, 0, 0, | 
|---|
| 453 |                                 SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); | 
|---|
| 454 |                 } | 
|---|
| 455 |         } | 
|---|
| 456 |  | 
|---|
| 457 |         void Win32Window::resize(unsigned int width, unsigned int height) | 
|---|
| 458 |         { | 
|---|
| 459 |                 if (mHWnd && !mIsFullScreen) | 
|---|
| 460 |                 { | 
|---|
| 461 |                         RECT rc = { 0, 0, width, height }; | 
|---|
| 462 |                         AdjustWindowRect(&rc, GetWindowLong(mHWnd, GWL_STYLE), false); | 
|---|
| 463 |                         width = rc.right - rc.left; | 
|---|
| 464 |                         height = rc.bottom - rc.top; | 
|---|
| 465 |                         SetWindowPos(mHWnd, 0, 0, 0, width, height, | 
|---|
| 466 |                                 SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE); | 
|---|
| 467 |                 } | 
|---|
| 468 |         } | 
|---|
| 469 |  | 
|---|
| 470 |         void Win32Window::windowMovedOrResized() | 
|---|
| 471 |         { | 
|---|
| 472 |                 if (!isVisible()) | 
|---|
| 473 |                         return; | 
|---|
| 474 |  | 
|---|
| 475 |                 RECT rc; | 
|---|
| 476 |                 // top and left represent outer window position | 
|---|
| 477 |                 GetWindowRect(mHWnd, &rc); | 
|---|
| 478 |                 mTop = rc.top; | 
|---|
| 479 |                 mLeft = rc.left; | 
|---|
| 480 |                 // width and height represent drawable area only | 
|---|
| 481 |                 GetClientRect(mHWnd, &rc); | 
|---|
| 482 |  | 
|---|
| 483 |                 if (mWidth == rc.right && mHeight == rc.bottom) | 
|---|
| 484 |                         return; | 
|---|
| 485 |  | 
|---|
| 486 |                 mWidth = rc.right; | 
|---|
| 487 |                 mHeight = rc.bottom; | 
|---|
| 488 |  | 
|---|
| 489 |                 // Notify viewports of resize | 
|---|
| 490 |                 ViewportList::iterator it, itend; | 
|---|
| 491 |                 itend = mViewportList.end(); | 
|---|
| 492 |                 for( it = mViewportList.begin(); it != itend; ++it ) | 
|---|
| 493 |                         (*it).second->_updateDimensions(); | 
|---|
| 494 |         } | 
|---|
| 495 |  | 
|---|
| 496 |         void Win32Window::swapBuffers(bool waitForVSync) | 
|---|
| 497 |         { | 
|---|
| 498 |           if (!mIsExternalGLControl) { | 
|---|
| 499 |                 SwapBuffers(mHDC); | 
|---|
| 500 |           } | 
|---|
| 501 |         } | 
|---|
| 502 |  | 
|---|
| 503 |         void Win32Window::writeContentsToFile(const String& filename) | 
|---|
| 504 |         { | 
|---|
| 505 |                 ImageCodec::ImageData *imgData = new ImageCodec::ImageData(); | 
|---|
| 506 |                 imgData->width = mWidth; | 
|---|
| 507 |                 imgData->height = mHeight; | 
|---|
| 508 |                 imgData->depth = 1; | 
|---|
| 509 |                 imgData->format = PF_BYTE_RGB; | 
|---|
| 510 |  | 
|---|
| 511 |                 // Allocate buffer  | 
|---|
| 512 |                 uchar* pBuffer = new uchar[mWidth * mHeight * 3]; | 
|---|
| 513 |  | 
|---|
| 514 |                 // Switch context if different from current one | 
|---|
| 515 |                 RenderSystem* rsys = Root::getSingleton().getRenderSystem(); | 
|---|
| 516 |                 rsys->_setViewport(this->getViewport(0)); | 
|---|
| 517 |  | 
|---|
| 518 |                 // Must change the packing to ensure no overruns! | 
|---|
| 519 |                 glPixelStorei(GL_PACK_ALIGNMENT, 1); | 
|---|
| 520 |  | 
|---|
| 521 |                 // Read pixels | 
|---|
| 522 |                 // I love GL: it does all the locking & colour conversion for us | 
|---|
| 523 |                 if (mIsFullScreen) | 
|---|
| 524 |                         glReadBuffer(GL_FRONT); | 
|---|
| 525 |                 glReadPixels(0,0, mWidth, mHeight, GL_RGB, GL_UNSIGNED_BYTE, pBuffer); | 
|---|
| 526 |  | 
|---|
| 527 |                 // restore default alignment | 
|---|
| 528 |                 glPixelStorei(GL_PACK_ALIGNMENT, 4); | 
|---|
| 529 |  | 
|---|
| 530 |                 // Wrap buffer in a memory stream | 
|---|
| 531 |                 DataStreamPtr stream(new MemoryDataStream(pBuffer, mWidth * mHeight * 3, false)); | 
|---|
| 532 |  | 
|---|
| 533 |                 // Need to flip the read data over in Y though | 
|---|
| 534 |                 Image img; | 
|---|
| 535 |                 img.loadRawData(stream, mWidth, mHeight, imgData->format ); | 
|---|
| 536 |                 img.flipAroundX(); | 
|---|
| 537 |  | 
|---|
| 538 |                 MemoryDataStreamPtr streamFlipped(new MemoryDataStream(img.getData(), stream->size(), false)); | 
|---|
| 539 |  | 
|---|
| 540 |                 // Get codec  | 
|---|
| 541 |                 size_t pos = filename.find_last_of("."); | 
|---|
| 542 |                 String extension; | 
|---|
| 543 |                 if( pos == String::npos ) | 
|---|
| 544 |                         OGRE_EXCEPT( | 
|---|
| 545 |                         Exception::ERR_INVALIDPARAMS,  | 
|---|
| 546 |                         "Unable to determine image type for '" + filename + "' - invalid extension.", | 
|---|
| 547 |                         "Win32Window::writeContentsToFile" ); | 
|---|
| 548 |  | 
|---|
| 549 |                 while( pos != filename.length() - 1 ) | 
|---|
| 550 |                         extension += filename[++pos]; | 
|---|
| 551 |  | 
|---|
| 552 |                 // Get the codec | 
|---|
| 553 |                 Codec * pCodec = Codec::getCodec(extension); | 
|---|
| 554 |  | 
|---|
| 555 |                 // Write out | 
|---|
| 556 |                 Codec::CodecDataPtr ptr(imgData); | 
|---|
| 557 |                 pCodec->codeToFile(streamFlipped, filename, ptr); | 
|---|
| 558 |  | 
|---|
| 559 |                 delete [] pBuffer; | 
|---|
| 560 |         } | 
|---|
| 561 |  | 
|---|
| 562 |         void Win32Window::getCustomAttribute( const String& name, void* pData ) | 
|---|
| 563 |         { | 
|---|
| 564 |                 if( name == "GLCONTEXT" ) { | 
|---|
| 565 |                         *static_cast<GLContext**>(pData) = mContext; | 
|---|
| 566 |                         return; | 
|---|
| 567 |                 } else if( name == "WINDOW" ) | 
|---|
| 568 |                 { | 
|---|
| 569 |                         HWND *pHwnd = (HWND*)pData; | 
|---|
| 570 |                         *pHwnd = getWindowHandle(); | 
|---|
| 571 |                         return; | 
|---|
| 572 |                 }  | 
|---|
| 573 |         } | 
|---|
| 574 |  | 
|---|
| 575 |         void Win32Window::setActive( bool state ) | 
|---|
| 576 |         { | 
|---|
| 577 |                 mActive = state; | 
|---|
| 578 |  | 
|---|
| 579 |                 if( mIsFullScreen ) | 
|---|
| 580 |                 { | 
|---|
| 581 |                         if( state == false ) | 
|---|
| 582 |                         {       //Restore Desktop | 
|---|
| 583 |                                 ChangeDisplaySettings(NULL, 0); | 
|---|
| 584 |                                 ShowWindow(mHWnd, SW_SHOWMINNOACTIVE); | 
|---|
| 585 |                         } | 
|---|
| 586 |                         else | 
|---|
| 587 |                         {       //Restore App | 
|---|
| 588 |                                 ShowWindow(mHWnd, SW_SHOWNORMAL); | 
|---|
| 589 |  | 
|---|
| 590 |                                 DEVMODE dm; | 
|---|
| 591 |                                 dm.dmSize = sizeof(DEVMODE); | 
|---|
| 592 |                                 dm.dmBitsPerPel = mColourDepth; | 
|---|
| 593 |                                 dm.dmPelsWidth = mWidth; | 
|---|
| 594 |                                 dm.dmPelsHeight = mHeight; | 
|---|
| 595 |                                 dm.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; | 
|---|
| 596 |                                 if (mDisplayFrequency) | 
|---|
| 597 |                                 { | 
|---|
| 598 |                                         dm.dmDisplayFrequency = mDisplayFrequency; | 
|---|
| 599 |                                         dm.dmFields |= DM_DISPLAYFREQUENCY; | 
|---|
| 600 |                                 } | 
|---|
| 601 |                                 ChangeDisplaySettings(&dm, CDS_FULLSCREEN); | 
|---|
| 602 |                         } | 
|---|
| 603 |                 } | 
|---|
| 604 |         } | 
|---|
| 605 | } | 
|---|