00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00018
00034
00035 #include <fs/rap/fsWinApp.h>
00036
00037
00038 #if defined(FS_HAS_FSASSERT)
00039 # include <fs/sys/fsAssert.h>
00040 #else
00041 # include <cassert>
00042 # if !defined(FS_ASSERT)
00043 # define FS_ASSERT(exp) assert(exp)
00044 # endif
00045 # if !defined(FS_ASSERT_MSG)
00046 # define FS_ASSERT_MSG(exp, msg) assert(exp && msg)
00047 # endif
00048 # if !defined(FS_VERIFY)
00049 # define FS_VERIFY(exp) \
00050 { bool bExp = !!(exp); assert(bExp && #exp); bExp; }
00051 # endif
00052 # if !defined(FS_VERIFY_MSG)
00053 # define FS_VERIFY_MSG(exp, msg) \
00054 { bool bExp = !!(exp); assert(bExp && #exp && msg); bExp; }
00055 # endif
00056 # if !defined(FS_STATIC_ASSERT)
00057 # define FS_STATIC_ASSERT(exp) { char error[(exp) ? 1 : 0]; error; }
00058 # endif
00059 #endif
00060 #if !defined(FS_VERIFY_RETURN)
00061 # define FS_VERIFY_RETURN(exp) \
00062 if(!(exp)) { FS_ASSERT_MSG(0, #exp "<return>"); return; }
00063 #endif
00064 #if !defined(FS_VERIFY_RETURN_VAL)
00065 # define FS_VERIFY_RETURN_VAL(exp, ret) \
00066 if(!(exp)) { FS_ASSERT_MSG(0, #exp "<returns:>" #ret); return (ret); }
00067 #endif
00068
00069
00070 #include <vector>
00071 #include <windows.h>
00072
00073
00074 #if defined(FS_HAS_FSMEMMGR)
00075 # include <fs/sys/fsMemMgr.h>
00076 #endif
00077
00078 using namespace fs::rap;
00079
00080 namespace fs { namespace rap {
00081
00082 WinApp_t & WinAppInst()
00083 {
00084 static WinApp_t Inst;
00085 return Inst;
00086 }
00087
00088 }}
00089
00090
00091
00092 namespace {
00093
00094 WinApp_t::InitCfg_t g_Cfg;
00095 const char *g_pszCmdLine = 0;
00096 HWND g_hWnd = 0;
00097 int g_nMouseX = 0, g_nMouseY = 0;
00098 typedef std::vector<WinApp_t::EvRcvr_i *> TEvRcvrs;
00099 TEvRcvrs g_EvRcvrs;
00100 bool g_bIgnSysEvs = true;
00101
00102 template <typename T>
00103 void Send(T &Event)
00104 {
00105 for(size_t i = 0; i < g_EvRcvrs.size(); ++i)
00106 g_EvRcvrs[i]->OnEvent(Event, WinAppInst());
00107 }
00108
00109 LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
00110 {
00111 if(g_bIgnSysEvs)
00112 return ::DefWindowProc(hWnd, msg, wParam, lParam);
00113
00114 switch(msg)
00115 {
00116 case WM_MOUSEMOVE:
00117 {
00118 g_nMouseX = LOWORD(lParam);
00119 g_nMouseY = HIWORD(lParam);
00120 const WinApp_t::MouseEv_t MouseEv(g_nMouseX, g_nMouseY);
00121
00122 Send(MouseEv);
00123
00124 break;
00125 }
00126 case WM_PAINT:
00127 {
00128 const WinApp_t::DrawEv_t DrawEv;
00129 Send(DrawEv);
00130
00131
00132 ::ValidateRect(hWnd, 0);
00133
00134 break;
00135 }
00136 case WM_KEYDOWN:
00137 {
00138 const WinApp_t::KeyEv_t KeyEv
00139 (static_cast<int>(wParam), true, g_nMouseX, g_nMouseY);
00140
00141 Send(KeyEv);
00142
00143 break;
00144 }
00145 case WM_KEYUP:
00146 {
00147 const WinApp_t::KeyEv_t KeyEv
00148 (static_cast<int>(wParam), false, g_nMouseX, g_nMouseY);
00149
00150 Send(KeyEv);
00151
00152 break;
00153 }
00154 case WM_LBUTTONDOWN:
00155 {
00156 const WinApp_t::KeyEv_t KeyEv
00157 (WinApp_t::KeyEv_t::KEY_LMBTN, true, g_nMouseX, g_nMouseY);
00158
00159 Send(KeyEv);
00160
00161 break;
00162 }
00163 case WM_LBUTTONUP:
00164 {
00165 const WinApp_t::KeyEv_t KeyEv
00166 (WinApp_t::KeyEv_t::KEY_LMBTN, false, g_nMouseX, g_nMouseY);
00167
00168 Send(KeyEv);
00169
00170 break;
00171 }
00172 case WM_SYSCHAR:
00173 {
00174 if(wParam == VK_RETURN)
00175 {
00176 WinAppInst().Fscrn(!g_Cfg.m_bFscrn);
00177 }
00178 break;
00179 }
00180 case WM_SIZE:
00181 {
00182 if(!g_Cfg.m_bFscrn)
00183 {
00184 g_Cfg.m_nClW = LOWORD(lParam);
00185 g_Cfg.m_nClH = HIWORD(lParam);
00186 }
00187
00188 const WinApp_t::SizeEv_t SizeEv(LOWORD(lParam), HIWORD(lParam));
00189
00190 Send(SizeEv);
00191
00192 break;
00193 }
00194 case WM_CLOSE:
00195 {
00196 WinAppInst().Quit();
00197
00198 break;
00199 }
00200
00201 default:
00202 return ::DefWindowProc(hWnd, msg, wParam, lParam);
00203 };
00204
00205 return 0;
00206 }
00207
00208 void GetWinStyles(const WinApp_t::InitCfg_t &Cfg, DWORD &dwStyle, DWORD
00209 &dwExStyle)
00210 {
00211 if(Cfg.m_bFscrn)
00212 {
00213 dwStyle = WS_POPUP;
00214 dwExStyle = WS_EX_APPWINDOW;
00215 }
00216 else
00217 {
00218 dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
00219
00220 if(!Cfg.m_bSzbl)
00221 {
00222 dwStyle &= ~WS_MAXIMIZEBOX;
00223 dwStyle &= ~WS_SIZEBOX;
00224 }
00225
00226 dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00227 }
00228 }
00229
00231 void GetDeskSize(int &nDeskW, int &nDeskH)
00232 {
00233 const HWND hWnd = ::GetDesktopWindow();
00234 FS_ASSERT(hWnd);
00235
00236 RECT rc;
00237 ::GetWindowRect(hWnd, &rc);
00238
00239 nDeskW = rc.right - rc.left;
00240 nDeskH = rc.bottom - rc.top;
00241 }
00242
00243 void CalcClientRect(const WinApp_t::InitCfg_t &Cfg, RECT &rcCl)
00244 {
00245
00246 if(Cfg.m_bFscrn)
00247 {
00248 rcCl.left = 0;
00249 rcCl.top = 0;
00250
00251
00252 if(Cfg.m_nFscrnW > 0 && Cfg.m_nFscrnH)
00253 {
00254 rcCl.right = Cfg.m_nFscrnW;
00255 rcCl.bottom = Cfg.m_nFscrnH;
00256 }
00257
00258 else
00259 {
00260 int nDeskW, nDeskH;
00261 GetDeskSize(nDeskW, nDeskH);
00262
00263 rcCl.right = nDeskW;
00264 rcCl.bottom = nDeskH;
00265 }
00266 }
00267
00268 else
00269 {
00270 int nDeskW, nDeskH;
00271 GetDeskSize(nDeskW, nDeskH);
00272
00273 rcCl.left = nDeskW / 2 - Cfg.m_nClW / 2;
00274 rcCl.top = nDeskH / 2 - Cfg.m_nClH / 2;
00275 rcCl.right = rcCl.left + Cfg.m_nClW;
00276 rcCl.bottom = rcCl.top + Cfg.m_nClH;
00277 }
00278 }
00279
00280 void CalcWinRect(const WinApp_t::InitCfg_t &Cfg, RECT &rcWin)
00281 {
00282
00283 DWORD dwStyle, dwExStyle;
00284 GetWinStyles(Cfg, dwStyle, dwExStyle);
00285
00286
00287 CalcClientRect(Cfg, rcWin);
00288
00289
00290 ::AdjustWindowRectEx(&rcWin, dwStyle, FALSE, dwExStyle);
00291 }
00292
00293 HWND CreateWin(const WinApp_t::InitCfg_t &Cfg)
00294 {
00295
00296
00297
00298 DWORD dwStyle, dwExStyle;
00299 GetWinStyles(Cfg, dwStyle, dwExStyle);
00300
00301
00302 RECT rcWin;
00303 CalcWinRect(Cfg, rcWin);
00304
00305
00306
00307 const HINSTANCE hInst = ::GetModuleHandle(0);
00308 FS_ASSERT(hInst);
00309
00310 WNDCLASS wc;
00311
00312 wc.style = CS_HREDRAW | CS_VREDRAW;
00313 wc.lpfnWndProc = (WNDPROC)WndProc;
00314 wc.cbClsExtra = 0;
00315 wc.cbWndExtra = 0;
00316 wc.hInstance = hInst;
00317 wc.hIcon = 0;
00318 wc.hCursor = 0;
00319 wc.hbrBackground = Cfg.m_bClrBgr?(HBRUSH)::GetStockObject(BLACK_BRUSH):0;
00320 wc.lpszMenuName = 0;
00321 wc.lpszClassName = TEXT("FS_RAP_WINAPP");
00322
00323 if(!::RegisterClass(&wc))
00324 {
00325 FS_ASSERT_MSG(0, "Could not register application window class!");
00326 return false;
00327 }
00328
00329
00330
00331 HWND hWnd = ::CreateWindowEx(
00332 dwExStyle,
00333 TEXT("FS_RAP_WINAPP"),
00334 TEXT("FS_RAP_WINAPP"),
00335 dwStyle,
00336 rcWin.left,
00337 rcWin.top,
00338 rcWin.right - rcWin.left,
00339 rcWin.bottom - rcWin.top,
00340 0,
00341 0,
00342 hInst,
00343 0
00344 );
00345
00346 if(!hWnd)
00347 {
00348 FS_ASSERT_MSG(g_hWnd, "Could not create application window!");
00349 return false;
00350 }
00351
00352
00353
00354 return hWnd;
00355 }
00356
00357 }
00358
00359
00360
00361 int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR pszCmdLine, int)
00362 {
00363 g_pszCmdLine = pszCmdLine;
00364 FS_ASSERT(g_pszCmdLine);
00365
00366
00367
00368
00369 if(!WinAppInit(WinAppInst(), g_Cfg))
00370 return 0;
00371
00372
00373 g_hWnd = CreateWin(g_Cfg);
00374 if(!g_hWnd)
00375 return 0;
00376
00377
00378
00379
00380 WinAppInst().SetTitle(g_Cfg.m_pszTitle);
00381
00382
00383 const WinApp_t::InitEv_t InitEv;
00384 Send(InitEv);
00385
00386
00387 RECT rcCl;
00388 ::GetClientRect(g_hWnd, &rcCl);
00389 const WinApp_t::SizeEv_t SizeEv
00390 (rcCl.right - rcCl.left, rcCl.bottom - rcCl.top);
00391 Send(SizeEv);
00392
00393
00394 ::ShowWindow(g_hWnd, SW_SHOW);
00395
00396 g_bIgnSysEvs = false;
00397
00398
00399
00400 if(g_Cfg.m_bRtm)
00401 {
00402 for(;;)
00403 {
00404 MSG msg;
00405
00406 while(::PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
00407 {
00408 if(msg.message == WM_QUIT)
00409 return static_cast<int>(msg.wParam);
00410
00411 ::TranslateMessage(&msg);
00412 ::DispatchMessage(&msg);
00413 }
00414
00415
00416 const WinApp_t::RunEv_t RunEv;
00417 Send(RunEv);
00418 }
00419 }
00420 else
00421 {
00422 MSG msg;
00423 while(::GetMessage(&msg, 0, 0, 0))
00424 {
00425 ::TranslateMessage(&msg);
00426 ::DispatchMessage(&msg);
00427 }
00428
00429
00430 return static_cast<int>(msg.wParam);
00431 }
00432 }
00433
00434
00435
00436 bool WinApp_t::IsValid() const
00437 {
00438 return g_hWnd ? true : false;
00439 }
00440
00441 const char * WinApp_t::GetCmdLine() const
00442 {
00443 FS_ASSERT(g_pszCmdLine);
00444
00445 return g_pszCmdLine;
00446 }
00447
00448 void WinApp_t::SetTitle(const char *pszTitle)
00449 {
00450 FS_VERIFY_RETURN(IsValid());
00451 FS_VERIFY_RETURN(pszTitle);
00452 FS_ASSERT(g_hWnd);
00453
00454 ::SetWindowTextA(g_hWnd, pszTitle);
00455 }
00456
00457 void WinApp_t::Redraw()
00458 {
00459 FS_VERIFY_RETURN(IsValid());
00460
00461
00462 FS_ASSERT(g_hWnd);
00463 ::InvalidateRect(g_hWnd, 0, true);
00464 }
00465
00466 void WinApp_t::Fscrn(bool bOn)
00467 {
00468 FS_VERIFY_RETURN(IsValid());
00469
00470
00471 g_Cfg.m_bFscrn = bOn;
00472
00473
00474
00475
00476 DWORD dwStyle, dwExStyle;
00477 GetWinStyles(g_Cfg, dwStyle, dwExStyle);
00478
00479
00480 RECT rcWin;
00481 CalcWinRect(g_Cfg, rcWin);
00482
00483
00484
00485 FS_ASSERT(g_hWnd);
00486
00487
00488 FS_VERIFY(::SetWindowLongPtr(g_hWnd, GWL_STYLE, dwStyle));
00489 FS_VERIFY(::SetWindowLongPtr(g_hWnd, GWL_EXSTYLE, dwExStyle));
00490
00491
00492 FS_VERIFY(::SetWindowPos(
00493 g_hWnd,
00494 0,
00495 rcWin.left, rcWin.top,
00496 rcWin.right - rcWin.left, rcWin.bottom - rcWin.top,
00497 SWP_SHOWWINDOW
00498 ));
00499
00500
00501 if(!g_Cfg.m_bFscrn)
00502 {
00503 const HWND hDeskWnd = ::GetDesktopWindow();
00504 FS_ASSERT(hDeskWnd);
00505 ::RedrawWindow(
00506 hDeskWnd, 0, 0,
00507 RDW_FRAME | RDW_INVALIDATE | RDW_UPDATENOW | RDW_ALLCHILDREN
00508 );
00509 }
00510 }
00511
00512 void WinApp_t::Quit()
00513 {
00514 FS_VERIFY_RETURN(IsValid());
00515
00516 const WinApp_t::QuitEv_t QuitEv;
00517 Send(QuitEv);
00518
00519 ::PostQuitMessage(0);
00520 }
00521
00522 void * WinApp_t::GetWinHdle() const
00523 {
00524 FS_VERIFY_RETURN_VAL(IsValid(), 0);
00525 FS_ASSERT(g_hWnd);
00526
00527 return g_hWnd;
00528 }
00529
00530 void WinApp_t::RegEvRcvr(EvRcvr_i *pEvRcvr)
00531 {
00532 FS_VERIFY_RETURN(pEvRcvr);
00533
00534 g_EvRcvrs.push_back(pEvRcvr);
00535 }
00536