00001 #include "MercuryDisplay.h"
00002 #include "Win32Window.h"
00003 #include <windows.h>
00004 #include "MercuryLog.h"
00005 #include "MercuryINI.h"
00006 #include "crash/crashDefines.h"
00007 #include "MercuryInputWin32.h"
00008
00009 bool active = false;
00010 bool W32W_KEYS[256];
00011
00012
00013 int g_iWindowX, g_iWindowY;
00014
00015 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
00016
00017 Win32Window::Win32Window()
00018 :MercuryWindow(0, 0, false)
00019 {
00020 m_extendedStyle = (DWORD)NULL;
00021 m_style = (DWORD)NULL;
00022 m_fullscreen = false;
00023 m_hRC = NULL;
00024 m_hDC = NULL;
00025 m_hWnd = NULL;
00026 m_hInstance = NULL;
00027 active = false;
00028 memset(W32W_KEYS, false, 256);
00029
00030
00031
00032 }
00033
00034 Win32Window::~Win32Window()
00035 {
00036 ShowCursor(true);
00037 DestroyWindowAndRender();
00038 }
00039
00040 bool Win32Window::Update(const float dTime)
00041 {
00042 RECT t;
00043 GetWindowRect( (HWND)m_hWnd, &t );
00044 g_iWindowX = t.left; g_iWindowY = t.top;
00045
00046 while (PeekMessage(&m_message, NULL, 0, 0, PM_REMOVE))
00047 {
00048
00049 if (m_message.message == WM_QUIT)
00050 return false;
00051 else
00052 {
00053 TranslateMessage(&m_message);
00054 DispatchMessage(&m_message);
00055 }
00056 }
00057 return true;
00058 }
00059
00060 bool Win32Window::MakeWindow(const char* title, int width, int height, int bits, bool fullscreen)
00061 {
00062 m_bits = bits;
00063 m_width = width;
00064 m_height = height;
00065 m_fullscreen = fullscreen;
00066 SetTitle(title);
00067
00068
00069 m_rect.left = (long)0;
00070 m_rect.top = (long)0;
00071 m_rect.right = (long)m_width;
00072 m_rect.bottom = (long)m_height;
00073
00074 m_fullscreen = fullscreen;
00075
00076 m_hInstance = GetModuleHandle(NULL);
00077 m_win.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00078 m_win.lpfnWndProc = (WNDPROC)WndProc;
00079 m_win.cbClsExtra = 0;
00080 m_win.cbWndExtra = 0;
00081 m_win.hInstance = m_hInstance;
00082 m_win.hIcon = LoadIcon(NULL, IDI_WINLOGO);
00083 m_win.hCursor = LoadCursor(NULL, IDC_ARROW);
00084 m_win.hbrBackground = NULL;
00085 m_win.lpszMenuName = NULL;
00086 m_win.lpszClassName = GetTitle();
00087
00088 if (!RegisterClass(&m_win))
00089 {
00090 LOG.Warn(ssprintf("Failed To Register Window Class %s", GetTitle()));
00091 return false;
00092 }
00093
00094 if (m_fullscreen)
00095 {
00096 DEVMODE dmScreenSettings;
00097 memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
00098 dmScreenSettings.dmSize = sizeof(dmScreenSettings);
00099 dmScreenSettings.dmPelsWidth = width;
00100 dmScreenSettings.dmPelsHeight = height;
00101 dmScreenSettings.dmBitsPerPel = bits;
00102 dmScreenSettings.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
00103
00104 if (ChangeDisplaySettings(&dmScreenSettings,CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
00105 m_fullscreen = false;
00106 }
00107
00108 if (m_fullscreen)
00109 {
00110 m_extendedStyle = WS_EX_APPWINDOW;
00111 m_style = WS_POPUP;
00112 ShowCursor(false);
00113 }
00114 else
00115 {
00116 m_extendedStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00117 m_style = WS_OVERLAPPEDWINDOW;
00118 }
00119
00120 AdjustWindowRectEx(&m_rect, m_style, false, m_extendedStyle);
00121
00122 m_hWnd = (void*)CreateWindowEx(m_extendedStyle,
00123 GetTitle(),
00124 title,
00125 m_style |
00126 WS_CLIPSIBLINGS |
00127 WS_CLIPCHILDREN,
00128 0, 0,
00129 m_rect.right-m_rect.left,
00130 m_rect.bottom-m_rect.top,
00131 NULL,
00132 NULL,
00133 m_hInstance,
00134 NULL);
00135
00136 if (!m_hWnd)
00137 {
00138 LOG.Warn("Window Creation Error.");
00139 DestroyWindowAndRender();
00140 return false;
00141 }
00142
00143 ShowWindow((HWND)m_hWnd,SW_SHOW);
00144 SetForegroundWindow((HWND)m_hWnd);
00145 SetFocus((HWND)m_hWnd);
00146
00147 return true;
00148 }
00149
00150 bool Win32Window::MakeRender(const char* title, int width, int height, int bits, bool fullscreen, RendererType rt)
00151 {
00152 m_brt = rt;
00153
00154 MakeWindow( title, width, height, bits, fullscreen );
00155 if ( rt == RT_OGL )
00156 {
00157 if (!RestoreDevice())
00158 return false;
00159
00160 if (!(m_hRC=wglCreateContext(m_hDC)))
00161 {
00162 LOG.Warn("GL Rendering failed.");
00163 DestroyWindowAndRender();
00164 return false;
00165 }
00166
00167 return MakeRenderCurrent();
00168 }
00169
00170 if( rt == RT_D3D )
00171 {
00172 if( !RestoreDevice())
00173 {
00174 return false;
00175 }
00176
00177 return true;
00178 }
00179
00180 if( rt == RT_SW )
00181 {
00182 if( !RestoreDevice() )
00183 return false;
00184 m_compatDC = CreateCompatibleDC( m_hDC );
00185 m_hbm = CreateCompatibleBitmap( m_hDC, width, height );
00186 SelectObject( m_compatDC, m_hbm );
00187 m_BackBuffer = new unsigned char[width * height * bits / 8];
00188 return true;
00189 }
00190
00191 return false;
00192 }
00193
00194 bool Win32Window::MakeRenderCurrent()
00195 {
00196 if(!wglMakeCurrent(m_hDC,m_hRC))
00197 {
00198 LOG.Warn("Rendering Context failed.");
00199 DestroyWindowAndRender();
00200 return false;
00201 }
00202 return true;
00203 }
00204
00205 #ifndef WM_MOUSEWHEEL
00206 # define WM_MOUSEWHEEL (WM_MOUSELAST + 1)
00207 #endif
00208
00209 LRESULT CALLBACK WndProc( HWND hWnd,
00210 UINT uMsg,
00211 WPARAM wParam,
00212 LPARAM lParam)
00213 {
00214
00215 switch (uMsg)
00216 {
00217 case WM_MOUSEWHEEL:
00218
00219
00220 case WM_ACTIVATE:
00221 if (!HIWORD(wParam))
00222 active = true;
00223 else
00224 active = false;
00225 return 0;
00226 break;
00227 case WM_SYSCOMMAND:
00228 switch (wParam)
00229 {
00230 case SC_SCREENSAVE:
00231 case SC_MONITORPOWER:
00232 return 0;
00233 }
00234 break;
00235 case WM_CLOSE:
00236 PostQuitMessage(0);
00237 return 0;
00238 case WM_KEYDOWN:
00239 W32W_KEYS[wParam] = true;
00240
00241
00242 if( lParam & 0x40000000 )
00243 DeviceKeyboardW32::TickRepeat( wParam );
00244 return 0;
00245 case WM_KEYUP:
00246 W32W_KEYS[wParam] = false;
00247 return 0;
00248 case WM_SIZE:
00249 DISPLAY->Resize(LOWORD(lParam),HIWORD(lParam));
00250 return 0;
00251 }
00252
00253 return DefWindowProc(hWnd,uMsg,wParam,lParam);
00254 }
00255
00256 bool Win32Window::RestoreDevice()
00257 {
00258 static PIXELFORMATDESCRIPTOR pfd =
00259 {
00260 sizeof(PIXELFORMATDESCRIPTOR),
00261 1,
00262 PFD_DRAW_TO_WINDOW |
00263 PFD_SUPPORT_OPENGL |
00264 PFD_DOUBLEBUFFER,
00265 PFD_TYPE_RGBA,
00266 m_bits,
00267 0, 0, 0, 0, 0, 0,
00268 0,
00269 0,
00270 0,
00271 0, 0, 0, 0,
00272 16,
00273 8,
00274 0,
00275 PFD_MAIN_PLANE,
00276 0,
00277 0, 0, 0
00278 };
00279
00280 if (!(m_hDC = GetDC((HWND)m_hWnd)))
00281 {
00282 LOG.Warn("Create A GL Device failed.");
00283 DestroyWindowAndRender();
00284 return false;
00285 }
00286
00287 if (!(m_pixelFormat = ChoosePixelFormat(m_hDC,&pfd)))
00288 {
00289 LOG.Warn("PixelFormat failed.");
00290 DestroyWindowAndRender();
00291 return false;
00292 }
00293
00294 if(!SetPixelFormat(m_hDC, m_pixelFormat, &pfd))
00295 {
00296 LOG.Warn("Set PixelFormat failed.");
00297 DestroyWindowAndRender();
00298 return false;
00299 }
00300
00301 return MakeRenderCurrent();
00302 }
00303
00304 void Win32Window::DestroyWindow()
00305 {
00306 if (m_fullscreen)
00307 {
00308 ChangeDisplaySettings(NULL,0);
00309 ShowCursor(true);
00310 }
00311
00312 if (m_hDC && !ReleaseDC((HWND)m_hWnd,m_hDC))
00313 {
00314 LOG.Log("Release Device Context Failed.");
00315 m_hDC = NULL;
00316 }
00317
00318 if (m_hWnd && !::DestroyWindow((HWND)m_hWnd))
00319 {
00320 LOG.Log("Could Not Release hWnd.");
00321 m_hWnd = NULL;
00322 }
00323
00324 if (!UnregisterClass(GetTitle(),m_hInstance))
00325 {
00326 LOG.Log(ssprintf("Could Not Unregister Class %s", GetTitle()));
00327 m_hInstance = NULL;
00328 }
00329 }
00330
00331 void Win32Window::DestroyWindowAndRender()
00332 {
00333 if (m_hRC)
00334 {
00335 if (!wglMakeCurrent(NULL,NULL))
00336 LOG.Log("Release Of DC And RC Failed.");
00337
00338 if (!wglDeleteContext(m_hRC))
00339 LOG.Log("Destroy m_hRC failed");
00340
00341 m_hRC = NULL;
00342 }
00343
00344 DestroyWindow();
00345 }
00346
00347 bool Win32Window::HasFocus()
00348 {
00349 return ( GetForegroundWindow() == this->m_hWnd );
00350 }
00351
00352 void Win32Window::SwapBuffersInternal()
00353 {
00354 if( m_brt == RT_SW )
00355 {
00356 SetBitmapBits( m_hbm,m_width*m_height*m_bits/8,m_BackBuffer );
00357 BitBlt( m_hDC,0,0,m_width,m_height,m_compatDC ,0,0,SRCCOPY );
00358 UpdateWindow( (HWND)m_hWnd );
00359 return;
00360 }
00361
00362 ::SwapBuffers(m_hDC);
00363 }
00364
00365 unsigned char * Win32Window::GetBackDirectBuffer()
00366 {
00367 if( m_brt == RT_SW )
00368 return m_BackBuffer;
00369 else
00370 return NULL;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405