#include "ASW_Window_W32.h" const unsigned int WindowW32::m_uintWndProcMsg = 1337; const unsigned int WindowW32::m_uintWndProcCmdOpen = WindowW32::m_uintWndProcMsg + 1; const unsigned int WindowW32::m_uintWndProcCmdClose = WindowW32::m_uintWndProcMsg + 2; WindowW32:: WindowW32(HINSTANCE p_hndInstance, const char * p_ptrClassName, const bool p_blnSupportOpenGL) : m_hndWindow(NULL), m_hndContextDevice(NULL), m_hndContextRender(NULL), m_ptrClassName(NULL), m_blnSupportOpenGL(p_blnSupportOpenGL), m_hndInstance(p_hndInstance), m_blnRegistered(false), m_blnFocus(false) { ASW_ASSERT(p_ptrClassName != NULL, "Class name must not be NULL"); #ifndef ASW_OPENGL ASW_ASSERT(p_blnSupportOpenGL == false, "Not compiled with OpenGL support"); #endif m_ptrClassName = UTIL::Strdup(p_ptrClassName); } WindowW32:: ~WindowW32() { Destroy(); delete [] m_ptrClassName; } bool WindowW32:: Create(const ASW::Window::Settings & p_stuSettings) { Destroy(); // // Register the window class // WNDCLASS stuWindowClass; stuWindowClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; stuWindowClass.lpfnWndProc = WindowW32::WndProc; stuWindowClass.cbClsExtra = 0; stuWindowClass.cbWndExtra = 0; stuWindowClass.hInstance = m_hndInstance; stuWindowClass.hIcon = LoadIcon(NULL, IDI_WINLOGO); stuWindowClass.hCursor = LoadCursor(NULL, IDC_ARROW); stuWindowClass.hbrBackground = NULL; stuWindowClass.lpszMenuName = NULL; stuWindowClass.lpszClassName = m_ptrClassName; CALL_WIN32(RegisterClass(&stuWindowClass), !=, 0); m_blnRegistered = true; // // Get current screen settings // DEVMODE dmScreenSettings; CALL_WIN32(EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &dmScreenSettings), ==, TRUE); unsigned char uchrBitsPerPixel = ( p_stuSettings.m_uchrBitsPerPixel == 0 ) ? (unsigned char)(dmScreenSettings.dmBitsPerPel) : p_stuSettings.m_uchrBitsPerPixel; unsigned int uintFrequency = ( p_stuSettings.m_uintFrequency == 0 ) ? dmScreenSettings.dmDisplayFrequency : p_stuSettings.m_uintFrequency; // // Set window parameters // DWORD dwdStyle = WS_OVERLAPPEDWINDOW; DWORD dwdExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; int intPositionX = p_stuSettings.m_intX; int intPositionY = p_stuSettings.m_intY; if ( p_stuSettings.m_blnFullScreen ) { // // Try To Set Selected Mode And Get Results. NOTE: CDS_FULLSCREEN Gets Rid Of Start Bar. // dmScreenSettings.dmPelsWidth = p_stuSettings.m_uintWidth; dmScreenSettings.dmPelsHeight = p_stuSettings.m_uintHeight; dmScreenSettings.dmBitsPerPel = uchrBitsPerPixel; dmScreenSettings.dmDisplayFrequency = uintFrequency; dmScreenSettings.dmFields = (DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYFREQUENCY); if ( ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL ) { Destroy(); return false; } intPositionX = intPositionY = 0; dwdExStyle = WS_EX_APPWINDOW; dwdStyle = WS_POPUP; } RECT stuWindowRect; stuWindowRect.top = stuWindowRect.left = 0; stuWindowRect.right = (long)(p_stuSettings.m_uintWidth); stuWindowRect.bottom = (long)(p_stuSettings.m_uintHeight); AdjustWindowRectEx(&stuWindowRect, dwdStyle, FALSE, dwdExStyle); intPositionX += stuWindowRect.left; intPositionY += stuWindowRect.top; // // Create The Window // m_hndWindow = CreateWindowEx(dwdExStyle, m_ptrClassName, p_stuSettings.m_ptrCaption, dwdStyle | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, intPositionX, intPositionY, (stuWindowRect.right - stuWindowRect.left), (stuWindowRect.bottom - stuWindowRect.top), NULL, NULL, m_hndInstance, NULL); if ( m_hndWindow == NULL ) { Destroy(); if ( p_stuSettings.m_blnFullScreen && ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL ) ASW_THROW("Could not reset the display mode to default after failed window creation"); return false; } SetWindowLongPtr(m_hndWindow, GWL_USERDATA, (long)(this)); // // Get a device display context // m_hndContextDevice = GetDC(m_hndWindow); if ( m_hndContextDevice == NULL ) { Destroy(); if ( p_stuSettings.m_blnFullScreen && ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL ) ASW_THROW("Could not reset the display mode to default after failed window creation"); return false; } // // Set pixel format parameters // PIXELFORMATDESCRIPTOR stuPixelFormatDesc; memset(&stuPixelFormatDesc, 0, sizeof(PIXELFORMATDESCRIPTOR)); stuPixelFormatDesc.nSize = sizeof(PIXELFORMATDESCRIPTOR); stuPixelFormatDesc.nVersion = 1; stuPixelFormatDesc.dwFlags = (PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER); stuPixelFormatDesc.iPixelType = PFD_TYPE_RGBA; stuPixelFormatDesc.cColorBits = uchrBitsPerPixel; stuPixelFormatDesc.cDepthBits = p_stuSettings.m_uchrDepthBits; stuPixelFormatDesc.cStencilBits = p_stuSettings.m_uchrStencilBits; stuPixelFormatDesc.iLayerType = PFD_MAIN_PLANE; if ( m_blnSupportOpenGL ) stuPixelFormatDesc.dwFlags |= PFD_SUPPORT_OPENGL; // // Get/set the pixel format // DWORD dwdPixelFormat = ChoosePixelFormat(m_hndContextDevice, &stuPixelFormatDesc); if ( dwdPixelFormat == 0 || SetPixelFormat(m_hndContextDevice, dwdPixelFormat, &stuPixelFormatDesc) == 0 ) { Destroy(); if ( p_stuSettings.m_blnFullScreen && ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL ) ASW_THROW("Could not reset the display mode to default after failed window creation"); return false; } #ifdef ASW_OPENGL // // Create and set the rendering context // if ( m_blnSupportOpenGL ) { m_hndContextRender = wglCreateContext(m_hndContextDevice); if ( m_hndContextRender == NULL || wglMakeCurrent(m_hndContextDevice, m_hndContextRender) == 0 ) { Destroy(); if ( p_stuSettings.m_blnFullScreen && ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL ) ASW_THROW("Could not reset the display mode to default after failed window creation"); return false; } } #endif delete [] m_stuSettings.m_ptrCaption; m_stuSettings = p_stuSettings; m_stuSettings.m_uchrBitsPerPixel = uchrBitsPerPixel; m_stuSettings.m_uintFrequency = uintFrequency; m_stuSettings.m_intX = intPositionX; m_stuSettings.m_intY = intPositionY; m_stuSettings.m_ptrCaption = ( p_stuSettings.m_ptrCaption ) ? UTIL::Strdup(p_stuSettings.m_ptrCaption) : NULL; return true; } void WindowW32:: Destroy() { if ( m_stuSettings.m_blnFullScreen ) ChangeDisplaySettings(NULL, 0); #ifdef ASW_OPENGL if ( m_blnSupportOpenGL && m_hndContextRender != NULL ) { CALL_WIN32(wglMakeCurrent(NULL, NULL), ==, TRUE); CALL_WIN32(wglDeleteContext(m_hndContextRender), ==, TRUE); m_hndContextRender = NULL; } #endif if ( m_hndContextDevice != NULL ) { CALL_WIN32(ReleaseDC(m_hndWindow, m_hndContextDevice), ==, 1); m_hndContextDevice = NULL; } if ( m_hndWindow != NULL ) { CALL_WIN32(DestroyWindow(m_hndWindow), !=, 0); m_hndWindow = NULL; } if ( m_ptrClassName != NULL && m_blnRegistered ) { CALL_WIN32(UnregisterClass(m_ptrClassName, m_hndInstance), ==, TRUE); m_blnRegistered = true; } } bool WindowW32:: Focus() { return m_blnFocus; } bool WindowW32:: ProcessEvents() { MSG stuMsg; bool blnActive = true; while ( PeekMessage(&stuMsg, NULL, 0, 0, PM_REMOVE) ) { if ( stuMsg.message != WM_QUIT ) { TranslateMessage(&stuMsg); DispatchMessage(&stuMsg); } else blnActive = false; } return blnActive; } void WindowW32:: Refresh(const int p_intShowCommand) { ShowWindow(m_hndWindow, p_intShowCommand); SetForegroundWindow(m_hndWindow); SetFocus(m_hndWindow); UpdateWindow(m_hndWindow); } bool WindowW32:: NotificationIcon(const char * p_ptrIconFile) { NOTIFYICONDATA stuData; memset(&stuData, 0, sizeof(NOTIFYICONDATA)); stuData.cbSize = sizeof(NOTIFYICONDATA); stuData.hWnd = m_hndWindow; stuData.uID = 0; bool blnReturn; if ( p_ptrIconFile ) { stuData.uFlags = NIF_ICON | NIF_TIP | NIF_MESSAGE; stuData.uCallbackMessage = WindowW32::m_uintWndProcMsg; strcpy(stuData.szTip, m_stuSettings.m_ptrCaption); stuData.hIcon = (HICON)(LoadImage(NULL, p_ptrIconFile, IMAGE_ICON, 0, 0, LR_LOADFROMFILE)); if ( stuData.hIcon == NULL ) return false; blnReturn = ( Shell_NotifyIcon(NIM_ADD, &stuData) == TRUE ); DestroyIcon(stuData.hIcon); } else blnReturn = ( Shell_NotifyIcon(NIM_DELETE, &stuData) == TRUE ); return blnReturn; } LRESULT CALLBACK WindowW32:: WndProc(HWND p_hndWindow, UINT p_uintMsg, WPARAM p_wParam, LPARAM p_lParam) { HMENU hndMenu; POINT stuClickPoint; WindowW32 * ptrWindow; switch ( p_uintMsg ) { case WM_CLOSE: PostQuitMessage(0); return 0; case WM_SIZE: ptrWindow = (WindowW32 *)(GetWindowLongPtr(p_hndWindow, GWL_USERDATA)); if ( ptrWindow != NULL ) { ptrWindow->m_stuSettings.m_uintWidth = LOWORD(p_lParam); ptrWindow->m_stuSettings.m_uintHeight = HIWORD(p_lParam); } break; case WM_SETFOCUS: ptrWindow = (WindowW32 *)(GetWindowLongPtr(p_hndWindow, GWL_USERDATA)); if ( ptrWindow != NULL ) ptrWindow->m_blnFocus = true; break; case WM_KILLFOCUS: ptrWindow = (WindowW32 *)(GetWindowLongPtr(p_hndWindow, GWL_USERDATA)); if ( ptrWindow != NULL ) ptrWindow->m_blnFocus = false; break; case WindowW32::m_uintWndProcMsg: switch( LOWORD(p_lParam) ) { case WM_LBUTTONDBLCLK: ShowWindow(p_hndWindow, SW_NORMAL); return TRUE; case WM_RBUTTONDOWN: GetCursorPos(&stuClickPoint); //place the window/menu there if needed hndMenu = CreatePopupMenu(); InsertMenu(hndMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WindowW32::m_uintWndProcCmdOpen, "&Open Server"); InsertMenu(hndMenu, 0xFFFFFFFF, MF_BYPOSITION | MF_STRING, WindowW32::m_uintWndProcCmdClose, "&Close Server"); //workaround for microsoft bug, to hide menu w/o selecting //SetForegroundWindow(hWnd); TrackPopupMenu(hndMenu, TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_BOTTOMALIGN, stuClickPoint.x, stuClickPoint.y, 0, p_hndWindow, NULL); //SendMessage(hWnd,WM_NULL,0,0); //MessageBox(NULL,"TEST rightclick","Testing ...",MB_OK); return TRUE; } break; case WM_COMMAND: switch ( LOWORD(p_wParam) ) { case WindowW32::m_uintWndProcCmdOpen: ShowWindow(p_hndWindow, SW_NORMAL); break; case WindowW32::m_uintWndProcCmdClose: ptrWindow = (WindowW32 *)(GetWindowLongPtr(p_hndWindow, GWL_USERDATA)); ptrWindow->NotificationIcon(NULL); DestroyWindow(p_hndWindow); break; } break; default: break; } return DefWindowProc(p_hndWindow, p_uintMsg, p_wParam, p_lParam); }