00001 #include "../pch.h"
00002
00003 NAMESPACE_START
00004
00005 inline void ClientResize(HWND hWnd, int width, int height){
00006 POINT diff;
00007 RECT rcClient, rcWindow;
00008 GetClientRect(hWnd, &rcClient);
00009 GetWindowRect(hWnd, &rcWindow);
00010 diff.x = (rcWindow.right - rcWindow.left) - rcClient.right;
00011 diff.y = (rcWindow.bottom - rcWindow.top) - rcClient.bottom;
00012 MoveWindow(hWnd, rcWindow.left, rcWindow.top, width+diff.x, height+diff.y, TRUE);
00013 }
00014
00015 wchar* Window::windowClassName = TEXT("REAL_WINDOW");
00016 bool Window::m_wndClassCreated = false;
00017 HINSTANCE Window::m_hInstance = 0;
00018 Window* Window::m_curWindow = 0;
00019 bool isFullscreen = false;
00020
00021 Window::Window()
00022 : renderListeners(10),
00023 windowListeners(10),
00024 deviceListeners(10)
00025 {
00026 info.parent = 0;
00027 info.state = ::stateWindowed;
00028 info.style = ::styleNormal;
00029 info.title = 0;
00030 m_rc.bottom = 0;
00031 m_rc.top = 0;
00032 m_rc.left = 0;
00033 m_rc.right = 0;
00034 m_hWnd = 0;
00035 m_image = 0;
00036 m_loadScreenUsed = false;
00037 m_mouseX = m_mouseY = 0;
00038 m_wndX = m_wndY = 0;
00039 initialized = false;
00040 }
00041
00042 Window::~Window(){
00043 uninit();
00044 }
00045
00046 bool Window::init(int x, int y, int width, int height, const wchar* title,
00047 ::STATE state, ::STYLE style,
00048 ::IWindow* parent, float alpha)
00049 {
00050 WNDCLASS wndClass;
00051
00052 if(initialized)
00053 return false;
00054
00055 inputWindow.init();
00056
00057 if(m_wndClassCreated == false){
00058 m_hInstance = GetModuleHandle(NULL);
00059 wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
00060 wndClass.lpfnWndProc = MessageHandler;
00061 wndClass.cbClsExtra = 0;
00062 wndClass.cbWndExtra = 0;
00063 wndClass.hInstance = m_hInstance;
00064 wndClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
00065 wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
00066 wndClass.hbrBackground = NULL;
00067 wndClass.lpszMenuName = NULL;
00068 wndClass.lpszClassName = windowClassName;
00069
00070 RegisterClass(&wndClass);
00071 m_wndClassCreated = true;
00072
00073 info.cursor = (::pCursor)wndClass.hCursor;
00074 }else{
00075
00076 info.cursor = (::pCursor)LoadCursor(NULL, IDC_ARROW);
00077 }
00078
00079
00080 ulong Style = m_loadScreenUsed ? 0 : WS_VISIBLE, ExStyle = 0;
00081 DEVMODE dmScreenSettings;
00082 DISPLAY_DEVICE device;
00083
00084 switch(info.state = state){
00085 case ::stateMaximized:
00086 Style |= WS_MAXIMIZE;
00087 break;
00088
00089 case ::stateMinimized:
00090 Style |= WS_MINIMIZE;
00091 break;
00092
00093 case ::stateFullscreen:
00094 if(isFullscreen == false){
00095 memset(&dmScreenSettings,0,sizeof(dmScreenSettings));
00096 dmScreenSettings.dmSize = sizeof(dmScreenSettings);
00097 dmScreenSettings.dmPelsWidth = width;
00098 dmScreenSettings.dmPelsHeight = height;
00099 dmScreenSettings.dmBitsPerPel = 32;
00100 dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
00101 memset(&device, 0, sizeof(device));
00102 device.cb = sizeof(device);
00103 for(int i=0; EnumDisplayDevices(0, i, &device, 0); i++)
00104 if(device.StateFlags & (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP|DISPLAY_DEVICE_ACTIVE))
00105 if(ChangeDisplaySettingsEx(device.DeviceName, &dmScreenSettings, 0, CDS_FULLSCREEN, 0) != DISP_CHANGE_SUCCESSFUL)
00106 LOGLN("Window::init: Fullscreen mode is not supported!");
00107 isFullscreen = true;
00108 }
00109 break;
00110
00111 case ::stateCentered:
00112 case ::stateWindowed:
00113 default:
00114 break;
00115 }
00116
00117 switch(info.style = style){
00118 case ::styleDialog:
00119 Style |= WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME;
00120 ExStyle |= WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00121 break;
00122
00123 case ::styleNoBorder:
00124 Style |= WS_POPUP;
00125 ExStyle |= WS_EX_APPWINDOW;
00126 break;
00127
00128 case ::styleTool:
00129 Style |= WS_CAPTION | WS_SYSMENU;
00130 ExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
00131 break;
00132
00133 case ::styleNormal:
00134 Style |= WS_OVERLAPPEDWINDOW;
00135 ExStyle |= WS_EX_APPWINDOW | WS_EX_WINDOWEDGE;
00136 break;
00137
00138 case ::styleInfo:
00139 Style |= WS_OVERLAPPED;
00140 ExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST | WS_EX_WINDOWEDGE;
00141 break;
00142
00143 case ::styleFullscreen:
00144 case ::styleLoadScreen:
00145 Style |= WS_POPUP;
00146 ExStyle |= WS_EX_TOOLWINDOW | WS_EX_TOPMOST;
00147 break;
00148 default:
00149 break;
00150 }
00151
00152 if(0.f<=alpha && alpha<1.f)
00153 ExStyle |= WS_EX_LAYERED;
00154
00155 RECT rcWnd;
00156 rcWnd.left = (long)x;
00157 rcWnd.top = (long)y;
00158 rcWnd.right = rcWnd.left+(long)width;
00159 rcWnd.bottom = rcWnd.top+(long)height;
00160
00161 if(state == ::stateCentered){
00162 x = (GetSystemMetrics(SM_CXSCREEN) - rcWnd.right + rcWnd.left)/2;
00163 y = (GetSystemMetrics(SM_CYSCREEN) - rcWnd.bottom + rcWnd.top)/2;
00164 }
00165
00166 if(!(m_hWnd = CreateWindowEx(
00167 ExStyle,
00168 windowClassName,
00169 title,
00170 Style,
00171 m_wndX = x,
00172 m_wndY = y,
00173 rcWnd.right - rcWnd.left,
00174 rcWnd.bottom - rcWnd.top,
00175 parent == 0 ? 0 : (HWND)parent->getWindow(),
00176 NULL,
00177 m_hInstance,
00178 NULL)))
00179 {
00180 uninit();
00181 LOGLN("Window::init: Window could not be created!");
00182 return false;
00183 }
00184
00185 ClientResize(m_hWnd, width, height);
00186
00187 if(0.f<=alpha && alpha<1.f)
00188 SetLayeredWindowAttributes(m_hWnd, 0, uchar(100.f*alpha), LWA_ALPHA);
00189
00190
00191 info.title = (wchar*)title;
00192
00193 info.parent = parent;
00194
00195
00196
00197
00198
00199 if(m_loadScreenUsed == false){
00200
00201
00202 SetFocus(m_hWnd);
00203 }
00204
00205
00206 IsOpen = true;
00207 windowList.add(this);
00208 initialized = true;
00209
00210 return true;
00211 }
00212
00213 bool Window::init(const wchar* title, ::STATE state, ::STYLE style,
00214 ::IWindow* parent, const wchar* imageFile, float alpha)
00215 {
00216 PAINTSTRUCT ps;
00217 HDC hdc;
00218
00219 ULONG_PTR gdiplusToken;
00220 Gdiplus::GdiplusStartupInput gdiplusStartupInput;
00221 Gdiplus::GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, 0);
00222 {
00223 Gdiplus::Image image(imageFile);
00224
00225 if(init(0, 0, int(image.GetWidth()), int(image.GetHeight()), title, state, style, parent, alpha) == false){
00226 LOGLN("Window::createScreen: Screen window could not be created!");
00227 uninit();
00228 return false;
00229 }
00230
00231 hdc = BeginPaint(m_hWnd, &ps);
00232 Gdiplus::Graphics graphics(hdc);
00233 graphics.DrawImage(&image, 0, 0, image.GetWidth(), image.GetHeight());
00234 EndPaint(m_hWnd, &ps);
00235 }
00236 Gdiplus::GdiplusShutdown(gdiplusToken);
00237
00238 return true;
00239 }
00240
00241 void Window::uninit(void){
00242 if(initialized){
00243
00244
00245
00246
00247 inputWindow.uninit();
00248
00249 if(m_hWnd){
00250
00251 DestroyWindow(m_hWnd);
00252 m_hWnd = 0;
00253 }
00254 if(m_image){
00255 DeleteObject(m_image);
00256 m_image = 0;
00257 }
00258
00259
00260
00261 renderListeners.clear();
00262 windowListeners.clear();
00263 deviceListeners.clear();
00264
00265 if(isFullscreen){
00266 DISPLAY_DEVICE device;
00267 memset(&device, 0, sizeof(device));
00268 device.cb = sizeof(device);
00269 for(int i=0; EnumDisplayDevices(0, i, &device, 0); i++)
00270 if(device.StateFlags & (DISPLAY_DEVICE_ATTACHED_TO_DESKTOP|DISPLAY_DEVICE_ACTIVE))
00271 ChangeDisplaySettingsEx(device.DeviceName, 0, 0, 0, 0);
00272 isFullscreen = false;
00273 }
00274
00275
00276 initialized = false;
00277 }
00278 }
00279
00280 int Window::fileDialog(wchar* out, uint outSize, const wchar* title, ::DIALOGFLAGS flags, const wchar* filter){
00281 OPENFILENAME ofn;
00282 if(out == 0 || outSize == 0)
00283 return false;
00284
00285 memset(&ofn, 0, sizeof(ofn));
00286 ofn.lStructSize = sizeof(ofn);
00287 ofn.hwndOwner = m_hWnd;
00288 ofn.lpstrFilter = filter;
00289 ofn.lpstrFile = out;
00290 ofn.nMaxFile = ulong(outSize);
00291 ofn.lpstrTitle = title;
00292 ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | (flags == ::dialogOpen ? OFN_ALLOWMULTISELECT : 0);
00293
00294 if(flags==::dialogOpen ? GetOpenFileName(&ofn) : GetSaveFileName(&ofn)){
00295 uint numFiles = 0;
00296 for(uint i=0; i<outSize-1 && (out[i]!=0 || out[i+1]!=0); i++)
00297 if(out[i] == 0) numFiles++;
00298 return numFiles==0?1:numFiles;
00299 }
00300 return 0;
00301 }
00302
00303 void* Window::getWindow(void){
00304 return m_hWnd;
00305 }
00306
00307 void* Window::getDisplay(void){
00308 return 0;
00309 }
00310
00311 ::pIWindow Window::getParent(void){
00312 return info.parent;
00313 }
00314
00315 void Window::setSize(int x, int y, int width, int height){
00316 MoveWindow(m_hWnd, x, y, width, height, TRUE);
00317 m_wndX = x;
00318 m_wndY = y;
00319 }
00320
00321 void Window::setSize(::WindowSize wndSize){
00322 setSize(wndSize.x, wndSize.y, wndSize.width, wndSize.height);
00323 }
00324
00325 ::WindowSize Window::getSize(void){
00326 ::WindowSize wndSize;
00327 GetWindowRect(m_hWnd, &m_rc);
00328 m_wndX = wndSize.x = m_rc.left;
00329 m_wndY = wndSize.y = m_rc.top;
00330 GetClientRect(m_hWnd, &m_rc);
00331 wndSize.width = m_rc.right - m_rc.left;
00332 wndSize.height = m_rc.bottom - m_rc.top;
00333 return wndSize;
00334 }
00335
00336 void Window::setState(::STATE state){
00337 int x, y;
00338 HDC hdcScreen;
00339
00340 switch(state){
00341 case ::stateMaximized:
00342 ShowWindow(m_hWnd, SW_MAXIMIZE);
00343 break;
00344 case ::stateMinimized:
00345 ShowWindow(m_hWnd, SW_MINIMIZE);
00346 break;
00347
00348
00349
00350
00351
00352
00353 case ::stateFullscreen:
00354 hdcScreen = GetDC(0);
00355 x = GetDeviceCaps(hdcScreen, HORZRES);
00356 y = GetDeviceCaps(hdcScreen, VERTRES);
00357 ReleaseDC(NULL, hdcScreen);
00358 SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP | WS_VISIBLE);
00359 SetWindowPos(m_hWnd, HWND_TOP, 0, 0, x, y, SWP_NOACTIVATE);
00360 ShowWindow(m_hWnd, SW_NORMAL);
00361 break;
00362 case ::stateCentered:
00363 hdcScreen = GetDC(0);
00364 x = GetDeviceCaps(hdcScreen, HORZRES);
00365 y = GetDeviceCaps(hdcScreen, VERTRES);
00366 ReleaseDC(m_hWnd, hdcScreen);
00367 SetWindowPos(m_hWnd, HWND_TOP, (GetSystemMetrics(SM_CXSCREEN)-x)/2, (GetSystemMetrics(SM_CYSCREEN)-y)/2, x, y, SWP_NOACTIVATE);
00368 ShowWindow(m_hWnd, SW_NORMAL);
00369 break;
00370 case ::stateWindowed:
00371 ShowWindow(m_hWnd, SW_NORMAL);
00372 break;
00373 default:
00374 return;
00375 }
00376
00377 info.state = state;
00378 UpdateWindow(m_hWnd);
00379 }
00380
00381 ::STATE Window::getState(void){
00382 return info.state;
00383 }
00384
00385 void Window::setStyle(::STYLE style){
00386 switch(style){
00387 case ::styleDialog:
00388 SetWindowLong(m_hWnd, GWL_STYLE, WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME | WS_VISIBLE);
00389 break;
00390 case ::styleNoBorder:
00391 SetWindowLong(m_hWnd, GWL_STYLE, WS_POPUP | WS_CAPTION | WS_VISIBLE);
00392 break;
00393 case ::styleTool:
00394 SetWindowLong(m_hWnd, GWL_STYLE, WS_CAPTION | WS_SYSMENU);
00395 SetWindowLong(m_hWnd, GWL_EXSTYLE, WS_EX_TOOLWINDOW | WS_EX_TOPMOST);
00396 break;
00397 case ::styleNormal:
00398 SetWindowLong(m_hWnd, GWL_STYLE, WS_OVERLAPPEDWINDOW | WS_VISIBLE);
00399 break;
00400 default:
00401 return;
00402 }
00403
00404 info.style = style;
00405 UpdateWindow(m_hWnd);
00406 }
00407
00408 ::STYLE Window::getStyle(void){
00409 return info.style;
00410 }
00411
00412 void Window::setTitle(const wchar* title){
00413 info.title = (wchar*)title;
00414 SetWindowText(m_hWnd, title);
00415 }
00416
00417 const wchar* Window::getTitle(void){
00418 return info.title;
00419 }
00420
00421 ::pCursor Window::createCursor(const wchar* file){
00422 return (::pCursor)LoadCursorFromFile(file);
00423 }
00424
00425 void Window::freeCursor(::pCursor& cur){
00426 if(cur != 0){
00427 DestroyCursor((HCURSOR)cur);
00428 cur = 0;
00429 }
00430 }
00431
00432 void Window::setCursor(::pCursor cur){
00433 if(cur == 0)
00434 return;
00435 info.cursor = cur;
00436 SetCursor((HCURSOR)cur);
00437 }
00438
00439 ::pCursor Window::getCursor(void){
00440 return info.cursor;
00441 }
00442
00443 void Window::showCursor(bool show){
00444 ShowCursor(show?TRUE:FALSE);
00445 }
00446
00447 void Window::setCursorPosition(int x, int y){
00448 POINT point;
00449 point.x = x;
00450 point.y = y;
00451 ScreenToClient(m_hWnd, &point);
00452 SetCursorPos(point.x, point.y);
00453 }
00454
00455 void Window::setCursorPosition(::CursorPosition cursorPos){
00456 setCursorPosition(cursorPos.x, cursorPos.y);
00457 }
00458
00459 ::CursorPosition Window::getCursorPosition(void){
00460 ::CursorPosition cursorPos;
00461 cursorPos.x = m_mouseX;
00462 cursorPos.y = m_mouseY;
00463 return cursorPos;
00464 }
00465
00466 void Window::addListener(::pEventRenderListener listener){
00467 if(listener != 0)
00468 renderListeners.add(listener);
00469 }
00470
00471 void Window::addListener(::pEventWindowListener listener){
00472 if(listener != 0)
00473 windowListeners.add(listener);
00474 }
00475
00476 void Window::addListener(::pEventDeviceListener listener){
00477 if(listener != 0)
00478 deviceListeners.add(listener);
00479 }
00480
00481 void Window::removeListener(::pEventRenderListener listener){
00482 renderListeners.remove(listener);
00483 }
00484
00485 void Window::removeListener(::pEventWindowListener listener){
00486 windowListeners.remove(listener);
00487 }
00488
00489 void Window::removeListener(::pEventDeviceListener listener){
00490 deviceListeners.remove(listener);
00491 }
00492
00493 ::pScreen Window::createScreen(const wchar* imageFile, float alpha){
00494 Window* screen = new Window();
00495 if(screen->init(TEXT("Loading ..."), ::stateCentered,
00496 ::styleLoadScreen, 0, imageFile, alpha) == false)
00497 {
00498 SAVEDELETE(screen);
00499 return 0;
00500 }
00501 m_loadScreenUsed = true;
00502 return (::pScreen)screen;
00503 }
00504
00505 void Window::freeScreen(::pScreen& screen){
00506 Window*& window = (Window*&)screen;
00507 if(window != 0){
00508
00509 window->uninit();
00510 SAVEDELETE(window);
00511
00512 if(m_loadScreenUsed && m_hWnd){
00513 UpdateWindow(m_hWnd);
00514 ShowWindow(m_hWnd, SW_SHOW);
00515 SetFocus(m_hWnd);
00516 m_loadScreenUsed = false;
00517 }
00518 }
00519 }
00520
00521 void Window::close(void){
00522 SendMessage(m_hWnd, WM_CLOSE, 0, 0);
00523 }
00524
00525 NAMESPACE_END