• Main Page
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/window/src/Window.cpp

Go to the documentation of this file.
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);                                 // Grab An Instance For Our Window
00059                 wndClass.style         = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;    // Redraw On Size, And Own DC For Window.
00060                 wndClass.lpfnWndProc   = MessageHandler;                                                // WndProc Handles Messages
00061                 wndClass.cbClsExtra    = 0;                                                                             // No Extra Window Data
00062                 wndClass.cbWndExtra    = 0;                                                                             // No Extra Window Data
00063                 wndClass.hInstance     = m_hInstance;                                                   // Set The Instance
00064                 wndClass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);                   // Load The Default Icon
00065                 wndClass.hCursor       = LoadCursor(NULL, IDC_ARROW);                   // Load The Arrow Pointer
00066                 wndClass.hbrBackground = NULL;
00067                 wndClass.lpszMenuName  = NULL;
00068                 wndClass.lpszClassName = windowClassName;
00069 
00070                 RegisterClass(&wndClass);
00071                 m_wndClassCreated = true;
00072                 // remember current cursor
00073                 info.cursor = (::pCursor)wndClass.hCursor;
00074         }else{
00075                 // remember current cursor
00076                 info.cursor = (::pCursor)LoadCursor(NULL, IDC_ARROW);
00077         }
00078 
00079         // Set Window Style
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)); // Makes Sure Memory's Cleared
00096                                 dmScreenSettings.dmSize = sizeof(dmScreenSettings);   // Size Of The Devmode Structure
00097                                 dmScreenSettings.dmPelsWidth  = width;                // Selected Screen Width
00098                                 dmScreenSettings.dmPelsHeight = height;               // Selected Screen Height
00099                                 dmScreenSettings.dmBitsPerPel = 32;                   // Selected Bits Per Pixel
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,          // classname
00169                         title,                    // window title
00170                         Style,                    // window style
00171                         m_wndX = x,               // x
00172                         m_wndY = y,               // y
00173                         rcWnd.right - rcWnd.left, // width
00174                         rcWnd.bottom - rcWnd.top, // height
00175                         parent == 0 ? 0 : (HWND)parent->getWindow(), // parent handle
00176                         NULL,                     // menu handle
00177                         m_hInstance,              // app instance
00178                         NULL)))                   // User Data
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         // remember title
00191         info.title = (wchar*)title;
00192         // remember parrent window
00193         info.parent = parent;
00194 
00195         // if a load screen is
00196         // used, do not show the
00197         // window until the load
00198         // screen is deleted
00199         if(m_loadScreenUsed == false){
00200                 //UpdateWindow(m_hWnd);
00201                 //ShowWindow(m_hWnd, SW_SHOW);
00202                 SetFocus(m_hWnd);
00203         }
00204 
00205         // successfully initialized
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                 // uninitialize input window
00244                 // Note that the input window is
00245                 // only uninitialized if no other
00246                 // window is using it.
00247                 inputWindow.uninit();
00248 
00249                 if(m_hWnd){
00250                         // destroy the window
00251                         DestroyWindow(m_hWnd);
00252                         m_hWnd = 0;
00253                 }
00254                 if(m_image){
00255                         DeleteObject(m_image);
00256                         m_image = 0;
00257                 }
00258                 // IsOpen = false; windowList.remove(this) is called automaticaly
00259                 // in the window msg callback
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                 // no longer initialized
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); // SEE NOTE BELOW
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                 //case ::stateHidden:
00348                 //      ShowWindow(m_hWnd, SW_HIDE);
00349                 //      break;
00350                 //case ::stateShown:
00351                 //      ShowWindow(m_hWnd, SW_SHOW);
00352                 //      break;
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                 // delete load screen
00509                 window->uninit();
00510                 SAVEDELETE(window);
00511                 // show this window
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

Generated on Fri Jun 18 2010 17:48:40 for Cannonball by  doxygen 1.7.0