Platform_Win32_OS.cpp
Go to the documentation of this file.00001 //*** Platform_Win32_OS *** 00002 00003 #include "Platform_Win32_OS.h" 00004 00005 #include "Platform_Win32_Input.h" 00006 #include "Platform_Win32_Input_KeyboardDevice.h" 00007 #include "Platform_Screen.h" 00008 #include "Platform_3D.h" 00009 00010 #define WIN32_LEAN_AND_MEAN 00011 #define VC_EXTRALEAN 00012 #include <crtdbg.h> 00013 #include <stdlib.h> 00014 #include <stdio.h> 00015 00016 //*** Constructor *** 00017 00018 Platform_Win32_OS::Platform_Win32_OS(HINSTANCE hInstance, const char* commandLine): 00019 hInstance_(hInstance_), 00020 applicationName_(0), 00021 executablePath_(0), 00022 commandLine_(0), 00023 windowHandle_(0), 00024 applicationHasFocus_(false), 00025 cursor_(0), 00026 exitRequested_(false) 00027 { 00028 Platform::RegisterEventListener(this); 00029 00030 // Store a copy of the command line 00031 if (commandLine) 00032 { 00033 commandLine_=strdup(commandLine); 00034 } 00035 00036 // Retrieve the path of our executable 00037 char path[MAX_PATH + 1]; 00038 GetModuleFileName(0, path, MAX_PATH ); 00039 char* end=strrchr(path,'\\'); 00040 if (!end) 00041 { 00042 strcpy(path,""); 00043 } 00044 else 00045 { 00046 *end='\0'; 00047 } 00048 executablePath_=strdup(path); 00049 00050 // Setup the main application window 00051 RegisterWindowClass(hInstance,"Pixie"); 00052 windowHandle_=CreateWindowInstance(hInstance,"Pixie","Pixie Game Engine"); 00053 00054 // Store "this" pointer with window, so we can get back to the Platform_Win32_OS instance 00055 #pragma warning (push) 00056 #pragma warning( disable: 4244) 00057 SetWindowLongPtr(windowHandle_, GWLP_USERDATA, (LONG_PTR)this); 00058 #pragma warning (pop) 00059 00060 // Load a default Arrow cursor 00061 cursor_=LoadCursor(0,IDC_ARROW); 00062 00063 } 00064 00065 00066 //*** Destructor *** 00067 00068 Platform_Win32_OS::~Platform_Win32_OS() 00069 { 00070 Platform::UnregisterEventListener(this); 00071 00072 // Release the executable path 00073 if (executablePath_) 00074 { 00075 free(executablePath_); 00076 } 00077 00078 // Release command line data 00079 if (commandLine_) 00080 { 00081 free(commandLine_); 00082 } 00083 00084 // Release application name 00085 if (applicationName_) 00086 { 00087 free(applicationName_); 00088 } 00089 } 00090 00091 00092 //*** OsYield *** 00093 00094 void Platform_Win32_OS::OsYield() 00095 { 00096 Platform::SendEvent_OsYield(); 00097 if (applicationHasFocus_) 00098 { 00099 Sleep(0); // Yield timeslice 00100 } 00101 else 00102 { 00103 Sleep(16); // Pause for a bit... we're not in a rush here 00104 } 00105 00106 ProcessMessages(); // Windows message handling 00107 } 00108 00109 00110 //*** SetApplicationName *** 00111 00112 void Platform_Win32_OS::SetApplicationName(const char* applicationName) 00113 { 00114 if (applicationName) 00115 { 00116 SetWindowText(windowHandle_,applicationName); 00117 } 00118 else 00119 { 00120 SetWindowText(windowHandle_,"Pixie Game Engine"); 00121 } 00122 } 00123 00124 00125 //*** GetCommandLineString *** 00126 00127 const char* Platform_Win32_OS::GetCommandLineString() 00128 { 00129 return commandLine_; 00130 } 00131 00132 00133 //*** GetExecutablePath *** 00134 00135 const char* Platform_Win32_OS::GetExecutablePath() 00136 { 00137 return executablePath_; 00138 } 00139 00140 00141 //*** HasFocus *** 00142 00143 bool Platform_Win32_OS::HasFocus() 00144 { 00145 return applicationHasFocus_; 00146 } 00147 00148 00149 //*** GetWindowHandle *** 00150 00151 HWND Platform_Win32_OS::GetWindowHandle() 00152 { 00153 return windowHandle_; 00154 } 00155 00156 00157 //*** RegisterWindowClass *** 00158 00159 bool Platform_Win32_OS::RegisterWindowClass(HINSTANCE instance, const char* className) 00160 { 00161 WNDCLASS wc; 00162 wc.style = CS_GLOBALCLASS|CS_BYTEALIGNCLIENT; 00163 wc.lpfnWndProc = (WNDPROC) WindowProcedure_Static; 00164 wc.cbClsExtra = 0; 00165 wc.cbWndExtra = 0; 00166 wc.hInstance = instance; 00167 wc.hCursor = LoadCursor(0, IDC_ARROW); 00168 wc.hIcon = 0; 00169 wc.hbrBackground= (HBRUSH)GetStockObject(BLACK_BRUSH); 00170 wc.lpszMenuName = 0; 00171 wc.lpszClassName= className; 00172 00173 if(!RegisterClass(&wc)) 00174 { 00175 MessageBox(0, "Failed to register window class.", "Error", MB_OK|MB_ICONSTOP); 00176 return false; 00177 } 00178 00179 return true; 00180 } 00181 00182 00183 //*** CreateWindowInstance *** 00184 00185 HWND Platform_Win32_OS::CreateWindowInstance(HINSTANCE instance, const char* className, const char* title) 00186 { 00187 DWORD style; 00188 style=WS_OVERLAPPEDWINDOW; 00189 HWND hWnd=CreateWindow(className,title,style,0,0,320,200,(HWND)0, (HMENU)0, instance, 0); 00190 return hWnd; 00191 } 00192 00193 00194 //*** ProcessMessages *** 00195 00196 void Platform_Win32_OS::ProcessMessages() 00197 { 00198 // Store the flag for whether the application has focus 00199 // or not, so we can call notify Platform_Screen after 00200 // the message pump 00201 bool previousFocus=applicationHasFocus_; 00202 00203 // Standard windows message pump 00204 MSG msg; 00205 while (PeekMessage(&msg, 0, 0,0, PM_REMOVE)) 00206 { 00207 TranslateMessage(&msg); 00208 DispatchMessage(&msg); 00209 } 00210 00211 // We need to handle OnGainFocus and OnLoseFocus in Platform_Screen, but 00212 // not inside the message pump, or D3D will throw a fit (don't know why) 00213 if (previousFocus!=applicationHasFocus_) 00214 { 00215 if (applicationHasFocus_) 00216 { 00217 Platform::SendEvent_CustomEvent("OnGainFocus"); 00218 } 00219 else 00220 { 00221 Platform::SendEvent_CustomEvent("OnLoseFocus"); 00222 } 00223 } 00224 } 00225 00226 00227 //*** WindowProcedure_Static *** 00228 00229 LRESULT CALLBACK Platform_Win32_OS::WindowProcedure_Static(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00230 { 00231 #pragma warning (push) 00232 #pragma warning( disable: 4312) 00233 Platform_Win32_OS* this_=reinterpret_cast<Platform_Win32_OS*>(GetWindowLongPtr(window, GWLP_USERDATA)); 00234 #pragma warning (pop) 00235 00236 if (this_) 00237 { 00238 return this_->WindowProcedure(window,message,wParam,lParam); 00239 } 00240 00241 return DefWindowProc(window,message,wParam,lParam); 00242 } 00243 00244 00245 //*** WindowProcedure *** 00246 00247 LRESULT Platform_Win32_OS::WindowProcedure(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00248 { 00249 static WPARAM storedKeydown; 00250 00251 // SetCursor(cursor_); 00252 00253 switch(message) 00254 { 00255 case WM_CHAR: 00256 { 00257 if (applicationHasFocus_) 00258 { 00259 int params[2]; 00260 params[0]=(int)wParam; 00261 params[1]=(int)storedKeydown; 00262 Platform::SendEvent_CustomEvent("OnWmChar",params); 00263 } 00264 return 0; 00265 } break; 00266 00267 00268 case WM_KEYDOWN: 00269 { 00270 if (applicationHasFocus_) 00271 { 00272 storedKeydown=(int)wParam; 00273 } 00274 return 0; 00275 } break; 00276 00277 case WM_KEYUP: 00278 { 00279 int param=(int)wParam; 00280 Platform::SendEvent_CustomEvent("OnWmKeyUp",¶m); 00281 00282 return 0; 00283 } break; 00284 00285 00286 case WM_SETCURSOR: 00287 { 00288 SetCursor(cursor_); 00289 return 0; 00290 } break; 00291 00292 case WM_SIZE: 00293 { 00294 return WmSize(window,message,wParam,lParam); 00295 } break; 00296 00297 case WM_SYSCOMMAND: 00298 { 00299 return WmSysCommand(window,message,wParam,lParam); 00300 } break; 00301 00302 case WM_ACTIVATEAPP: 00303 { 00304 return WmActivateApp(window,message,wParam,lParam); 00305 } break; 00306 00307 00308 case WM_CLOSE: 00309 { 00310 return WmClose(window,message,wParam,lParam); 00311 } break; 00312 00313 } 00314 00315 return DefWindowProc(window, message, wParam, lParam); 00316 } 00317 00318 00319 //*** WmSize *** 00320 00321 LRESULT Platform_Win32_OS::WmSize(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00322 { 00323 if (applicationHasFocus_) 00324 { 00325 if (wParam!=SIZE_MAXHIDE && wParam!=SIZE_MAXSHOW && wParam!=SIZE_MINIMIZED) 00326 { 00327 int params[2]; 00328 params[0]=LOWORD(lParam); 00329 params[1]=HIWORD(lParam); 00330 Platform::SendEvent_CustomEvent("OnWmSize",params); 00331 } 00332 else if (wParam==SIZE_MINIMIZED) 00333 { 00334 Platform::SendEvent_CustomEvent("OnMinimize"); 00335 } 00336 } 00337 00338 return DefWindowProc(window, message, wParam, lParam); 00339 } 00340 00341 00342 //*** WmSysCommand *** 00343 00344 LRESULT Platform_Win32_OS::WmSysCommand(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00345 { 00346 00347 if (wParam==SC_RESTORE) 00348 { 00349 Platform::SendEvent_CustomEvent("OnRestore"); 00350 } 00351 00352 return DefWindowProc(window, message, wParam, lParam); 00353 } 00354 00355 00356 //*** WmActivateApp *** 00357 00358 LRESULT Platform_Win32_OS::WmActivateApp(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00359 { 00360 if(wParam) 00361 { 00362 if (!applicationHasFocus_) 00363 { 00364 applicationHasFocus_=true; 00365 } 00366 } 00367 else 00368 { 00369 if (applicationHasFocus_) 00370 { 00371 applicationHasFocus_=false; 00372 } 00373 } 00374 00375 return 0; 00376 } 00377 00378 00379 //*** WmClose *** 00380 00381 LRESULT Platform_Win32_OS::WmClose(HWND window, UINT message, WPARAM wParam, LPARAM lParam) 00382 { 00383 exitRequested_=true; 00384 return 0; 00385 } 00386 00387 00388 //*** ExitRequested *** 00389 00390 bool Platform_Win32_OS::ExitRequested() 00391 { 00392 return exitRequested_; 00393 } 00394 00395 00396 //*** DisplayAssertMessage *** 00397 00398 void Platform_Win32_OS::DisplayAssertMessage(const char* expression, const char* message, const char* file, int line) 00399 { 00400 if (Platform::GetPlatform_Screen()) 00401 { 00402 Platform::GetPlatform_Screen()->SetFullscreen(false); 00403 } 00404 if (Platform::GetPlatform_3D()) 00405 { 00406 Platform::GetPlatform_3D()->SetFullscreen(false); 00407 } 00408 char buf[4096]; 00409 _snprintf(buf,4095,"ASSERTION FAILED!\n\n%s\n\nExpression: %s\nFile: %s\nLine: %d\n",message,expression,file,line); 00410 OutputDebugString("******************************************\n"); 00411 OutputDebugString(buf); 00412 OutputDebugString("******************************************\n"); 00413 int result=MessageBox(0,buf,"Pixie Assert",MB_ICONWARNING | MB_ABORTRETRYIGNORE); 00414 switch (result) 00415 { 00416 case IDABORT: 00417 { 00418 // Turn off memory leak reports 00419 #ifndef NDEBUG 00420 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag 00421 flag ^= _CRTDBG_LEAK_CHECK_DF; // Turn off leak-checking bit 00422 _CrtSetDbgFlag(flag); // Set flag to the new value 00423 #endif 00424 _exit(3); // Exit application immediately, without calling crt's _atexit 00425 } break; 00426 case IDRETRY: 00427 { 00428 _asm{int 0x03}; // Break to editor 00429 } break; 00430 case IGNORE: 00431 { 00432 return; // Continue execution 00433 } break; 00434 } 00435 } 00436 00437 00438 //*** OutputDebugText *** 00439 00440 void Platform_Win32_OS::OutputDebugText(const char * formatstr, ...) 00441 { 00442 va_list arglist; 00443 char str[4096]; 00444 00445 va_start(arglist, formatstr); 00446 _vsnprintf(str, 4095, formatstr, arglist); 00447 va_end(arglist); 00448 00449 OutputDebugString(str); 00450 } 00451 00452 00453 //*** ReportFatalError *** 00454 00455 void Platform_Win32_OS::ReportFatalError(const char* message, const char* file, int line) 00456 { 00457 if (Platform::GetPlatform_Screen()) 00458 { 00459 Platform::GetPlatform_Screen()->SetFullscreen(false); 00460 } 00461 if (Platform::GetPlatform_3D()) 00462 { 00463 Platform::GetPlatform_3D()->SetFullscreen(false); 00464 } 00465 00466 INT mbtype=MB_OK; 00467 if (IsDebuggerPresent()) 00468 { 00469 mbtype=MB_OKCANCEL; 00470 } 00471 00472 char buf[4096]; 00473 _snprintf(buf,4095,"FATAL ERROR!\n\n%s\n\nIt is not possible to recover from this error. The program will now terminate.\n\nFile: %s\nLine: %d\n",message,file,line); 00474 OutputDebugString("******************************************\n"); 00475 OutputDebugString(buf); 00476 OutputDebugString("******************************************\n"); 00477 int result=MessageBox(0,buf,"Pixie Fatal Error",MB_ICONSTOP | mbtype); 00478 switch (result) 00479 { 00480 case IDOK: 00481 { 00482 // Turn off memory leak reports 00483 #ifndef NDEBUG 00484 int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG); // Get current flag 00485 flag ^= _CRTDBG_LEAK_CHECK_DF; // Turn off leak-checking bit 00486 _CrtSetDbgFlag(flag); // Set flag to the new value 00487 #endif 00488 _exit(3); // Exit application immediately, without calling crt's _atexit 00489 } break; 00490 00491 case IDCANCEL: 00492 { 00493 _asm{int 0x03}; // Break to editor 00494 } break; 00495 } 00496 } 00497 00498 00499 //*** OnCustomEvent *** 00500 00501 void Platform_Win32_OS::OnCustomEvent(const char* eventId, void* userData) 00502 { 00503 if (stricmp(eventId,"SetCursor")==0) 00504 { 00505 cursor_=(HCURSOR)userData;; 00506 return; 00507 } 00508 } 00509
Reproduction/republishing of any material on this site without permission is strictly prohibited.
