#include "WindowWin.h" #define L_WIN32 #include #include "log/NLog.h" namespace LifeCore { LRESULT __stdcall WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam); WindowWin::WindowWin() { bFullscreen = false; bActive = true; bModeSwitching = false; bCursorVisible = true; bAltEnterLocked = false; width = 256; height = 256; g_hInst = GetModuleHandle(NULL); g_hwnd = NULL; //memset(&g_wndClass,0,sizeof(WNDCLASSEX)); WNDCLASSEX g_wndClass = { NULL }; g_wndClass.cbSize = sizeof(WNDCLASSEX); g_wndClass.cbClsExtra = NULL; g_wndClass.cbWndExtra = NULL; g_wndClass.hbrBackground = (HBRUSH)GetStockObject(1); g_wndClass.hCursor = (HCURSOR)LoadCursor(NULL, IDC_ARROW); g_wndClass.hIcon = LoadIcon(g_hInst, IDI_APPLICATION); g_wndClass.hIconSm = LoadIcon(g_hInst, IDI_APPLICATION); g_wndClass.hInstance = g_hInst; g_wndClass.lpfnWndProc = WndProc; g_wndClass.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; g_wndClass.lpszMenuName = NULL; g_wndClass.lpszClassName = _text("Onotole"); if(!RegisterClassEx(&g_wndClass)) { MessageBox(g_hwnd, _text("Can not create window class! We all gonna die!!"), _text("OH SHIT!"), MB_OK); } //calculate window size RECT NewWindowSize; NewWindowSize.top = 30; NewWindowSize.left = 300; NewWindowSize.bottom = NewWindowSize.top + height; NewWindowSize.right = NewWindowSize.left + width; AdjustWindowRect(&NewWindowSize, WS_OVERLAPPEDWINDOW, false); /*WS_MINIMIZEBOX WS_MAXIMIZEBOX*/ if(!(g_hwnd = CreateWindowEx(NULL, _text("Onotole"), _text("LifeEngine render window"), WS_THICKFRAME, NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, NULL, NULL, g_hInst, NULL))) { MessageBox(g_hwnd, _text("Can not create window! We all gonna die!!"), _text("HOLY SHIT!"), MB_OK); } ShowWindow(g_hwnd, SW_SHOWNORMAL); SetForegroundWindow(g_hwnd); SetFocus(g_hwnd); ZeroMemory(&mode, sizeof(DEVMODE)); mode.dmSize = sizeof(DEVMODE); EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &mode); WindowWin* ptr = this; long val = (long)ptr; SetWindowLongPtr(g_hwnd, GWLP_USERDATA, val); fsMode.width = 640; fsMode.height = 480; fsMode.refreshRate = 60; fsMode.bpp = 4; CenterWindow(); } bool WindowWin::IsKeyPressed(KeyCodes::Key key) { return false; } void WindowWin::Update() { #ifdef L_WIN32 MSG msg = { 0 }; while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) { switch(msg.message) { case WM_QUIT: { Event_Quit.Invoke(); //exit(0); } break; } TranslateMessage(&msg); DispatchMessage(&msg); } #endif } void WindowWin::SetCaption(const String& val) { caption = val; SetWindowText(g_hwnd, caption.c_str()); } void WindowWin::SetFullScreen(bool state) { bFullscreen = state; } bool WindowWin::IsFullScreen() { return bFullscreen; } WindowWin::~WindowWin(void) { ChangeDisplaySettings(&mode, 0); } void WindowWin::OnActivate() { bActive = true; Event_Activate.Invoke(this); } void WindowWin::OnDeactivate() { bActive = false; Event_Deactivate.Invoke(this); } void WindowWin::OnResize() { if(!IsFullScreen() || !bModeSwitching) { RECT r; ::GetClientRect(g_hwnd, &r); width = r.right - r.left; height = r.bottom - r.top; } Event_Resize.Invoke(this); } bool WindowWin::IsActive() { return bActive; } bool WindowWin::IsModeSwitching() { return bModeSwitching; } void WindowWin::SetCursorVisible(bool state) { bCursorVisible = state; } bool WindowWin::IsCursorVisible() { return bCursorVisible; } bool WindowWin::SwitchMode(bool fullscreen) { bFullscreen = fullscreen; if(bFullscreen) { bModeSwitching = true; DEVMODE fmode; ZeroMemory(&fmode, sizeof(DEVMODE)); fmode.dmSize = sizeof(DEVMODE); fmode.dmPelsWidth = fsMode.width; fmode.dmPelsHeight = fsMode.height; fmode.dmBitsPerPel = mode.dmBitsPerPel; fmode.dmDisplayFrequency = fsMode.refreshRate; fmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; //if(ChangeDisplaySettings(&fmode,0)!= DISP_CHANGE_SUCCESSFUL) // return false; SetWindowLong(g_hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW | WS_EX_TOPMOST); SetWindowLong(g_hwnd, GWL_STYLE, WS_POPUP); SetWindowPos(g_hwnd, HWND_TOPMOST, 0, 0, fsMode.width, fsMode.height, SWP_SHOWWINDOW | SWP_FRAMECHANGED); bModeSwitching = false; } else { //if(ChangeDisplaySettings(&mode_window,0)!= DISP_CHANGE_SUCCESSFUL) // return false; SetWindowLong(g_hwnd, GWL_EXSTYLE, WS_EX_APPWINDOW); SetWindowLong(g_hwnd, GWL_STYLE, WS_OVERLAPPEDWINDOW); SetSize(width, height); CenterWindow(); } Event_SwitchFullscreen.Invoke(this); return true; } void WindowWin::CenterWindow() { int mx = GetSystemMetrics(SM_CXSCREEN); int my = GetSystemMetrics(SM_CYSCREEN); int nx = (mx - width) / 2; int ny = (my - height) / 2; SetWindowPos(g_hwnd, NULL, nx, ny, -1, -1, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); } void WindowWin::SetFullscreenMode(LifeCore::DisplayMode mode) { fsMode = mode; } void WindowWin::SetSize(int w, int h) { if(!IsFullScreen()) { width = w; height = h; RECT NewWindowSize; NewWindowSize.top = 50; NewWindowSize.left = 50; NewWindowSize.bottom = NewWindowSize.top + h; NewWindowSize.right = NewWindowSize.left + w; AdjustWindowRect(&NewWindowSize, WS_OVERLAPPEDWINDOW, false); SetWindowPos(g_hwnd, HWND_TOP, NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, SWP_SHOWWINDOW | SWP_FRAMECHANGED); //::MoveWindow(g_hwnd,NewWindowSize.left, NewWindowSize.top, NewWindowSize.right - NewWindowSize.left, NewWindowSize.bottom - NewWindowSize.top, true); CenterWindow(); } } KeyCodes::Key WindowWin::ConvertKeyCode(unsigned long key_code) { switch(key_code) { case VK_ESCAPE: return KeyCodes::KEY_ESCAPE; case VK_F1: return KeyCodes::KEY_F1; case VK_F2: return KeyCodes::KEY_F2; case VK_F3: return KeyCodes::KEY_F3; case VK_F4: return KeyCodes::KEY_F4; case VK_F5: return KeyCodes::KEY_F5; case VK_F6: return KeyCodes::KEY_F6; case VK_F7: return KeyCodes::KEY_F7; case VK_F8: return KeyCodes::KEY_F8; case VK_F9: return KeyCodes::KEY_F9; case VK_F10: return KeyCodes::KEY_F10; case VK_F11: return KeyCodes::KEY_F11; case VK_F12: return KeyCodes::KEY_F12; case VK_SNAPSHOT: return KeyCodes::KEY_PRINT_SCREEN; case VK_SCROLL: return KeyCodes::KEY_SCROLL_LOCK; case VK_PAUSE: return KeyCodes::KEY_PAUSE; case VK_OEM_3: return KeyCodes::KEY_TILDE; case 0x30: return KeyCodes::KEY_1; case 0x31: return KeyCodes::KEY_2; case 0x32: return KeyCodes::KEY_3; case 0x33: return KeyCodes::KEY_4; case 0x34: return KeyCodes::KEY_5; case 0x35: return KeyCodes::KEY_6; case 0x36: return KeyCodes::KEY_7; case 0x37: return KeyCodes::KEY_8; case 0x38: return KeyCodes::KEY_9; case 0x39: return KeyCodes::KEY_0; case 0xBD: return KeyCodes::KEY_MINUS; case 0xBB: return KeyCodes::KEY_EQUAL; case VK_BACK: return KeyCodes::KEY_BACKSPACE; case VK_TAB: return KeyCodes::KEY_TAB; case VK_CAPITAL: return KeyCodes::KEY_CAPS_LOCK; case VK_SHIFT: return KeyCodes::KEY_SHIFT; case VK_CONTROL: return KeyCodes::KEY_CONTROL; case VK_LWIN: return KeyCodes::KEY_META_LEFT; case VK_RWIN: return KeyCodes::KEY_META_RIGHT; case VK_MENU: return KeyCodes::KEY_ALT; case VK_SPACE: return KeyCodes::KEY_SPACE; case VK_APPS: return KeyCodes::KEY_MENU; case VK_RETURN: return KeyCodes::KEY_ENTER; case 0x41: return KeyCodes::KEY_A; case 0x42: return KeyCodes::KEY_B; case 0x43: return KeyCodes::KEY_C; case 0x44: return KeyCodes::KEY_D; case 0x45: return KeyCodes::KEY_E; case 0x46: return KeyCodes::KEY_F; case 0x47: return KeyCodes::KEY_G; case 0x48: return KeyCodes::KEY_H; case 0x49: return KeyCodes::KEY_I; case 0x4A: return KeyCodes::KEY_J; case 0x4B: return KeyCodes::KEY_K; case 0x4C: return KeyCodes::KEY_L; case 0x4D: return KeyCodes::KEY_M; case 0x4E: return KeyCodes::KEY_N; case 0x4F: return KeyCodes::KEY_O; case 0x50: return KeyCodes::KEY_P; case 0x51: return KeyCodes::KEY_Q; case 0x52: return KeyCodes::KEY_R; case 0x53: return KeyCodes::KEY_S; case 0x54: return KeyCodes::KEY_T; case 0x55: return KeyCodes::KEY_U; case 0x56: return KeyCodes::KEY_V; case 0x57: return KeyCodes::KEY_W; case 0x58: return KeyCodes::KEY_X; case 0x59: return KeyCodes::KEY_Y; case 0x5A: return KeyCodes::KEY_Z; case VK_OEM_4: return KeyCodes::KEY_BRACKET_LEFT; case VK_OEM_6: return KeyCodes::KEY_BRACKET_RIGHT; case VK_OEM_5: return KeyCodes::KEY_BACKSLASH; case VK_OEM_1: return KeyCodes::KEY_SEMICOLON; case VK_OEM_7: return KeyCodes::KEY_APOSTROPHE; case 0xBC: return KeyCodes::KEY_COMMA; case 0xBE: return KeyCodes::KEY_DOT; case VK_OEM_2: return KeyCodes::KEY_SLASH; case VK_INSERT: return KeyCodes::KEY_INSERT; case VK_DELETE: return KeyCodes::KEY_DELETE; case VK_HOME: return KeyCodes::KEY_HOME; case VK_END: return KeyCodes::KEY_END; case VK_PRIOR: return KeyCodes::KEY_PAGE_UP; case VK_NEXT: return KeyCodes::KEY_PAGE_DOWN; case VK_UP: return KeyCodes::KEY_UP; case VK_LEFT: return KeyCodes::KEY_LEFT; case VK_DOWN: return KeyCodes::KEY_DOWN; case VK_RIGHT: return KeyCodes::KEY_RIGHT; case VK_NUMLOCK: return KeyCodes::KEY_NUM_LOCK; case VK_ADD: return KeyCodes::KEY_NUM_ADD; case VK_SUBTRACT: return KeyCodes::KEY_NUM_SUBTRACT; case VK_MULTIPLY: return KeyCodes::KEY_NUM_MULTIPLY; case VK_DIVIDE: return KeyCodes::KEY_NUM_DIVIDE; case VK_NUMPAD0: return KeyCodes::KEY_NUM_0; case VK_NUMPAD1: return KeyCodes::KEY_NUM_1; case VK_NUMPAD2: return KeyCodes::KEY_NUM_2; case VK_NUMPAD3: return KeyCodes::KEY_NUM_3; case VK_NUMPAD4: return KeyCodes::KEY_NUM_4; case VK_NUMPAD5: return KeyCodes::KEY_NUM_5; case VK_CLEAR: return KeyCodes::KEY_NUM_SPECIAL; case VK_NUMPAD6: return KeyCodes::KEY_NUM_6; case VK_NUMPAD7: return KeyCodes::KEY_NUM_7; case VK_NUMPAD8: return KeyCodes::KEY_NUM_8; case VK_NUMPAD9: return KeyCodes::KEY_NUM_9; case VK_DECIMAL: return KeyCodes::KEY_NUM_DECIMAL; default: return KeyCodes::UNKNOWN_KEY; } } LRESULT __stdcall WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) { switch(message) { case WM_SIZE: { //не ресайзим девайс если окно свёрнуто if(wparam != SIZE_MINIMIZED) { long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; wnd->OnResize(); } } } break; case WM_SETCURSOR: { static bool hiddencursor = false; WORD ht = LOWORD(lparam); long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; if(wnd->IsCursorVisible()) { ShowCursor(true); } else { if(HTCLIENT == ht && !hiddencursor) { hiddencursor = true; ShowCursor(false); } else if(HTCLIENT != ht && hiddencursor) { hiddencursor = false; ShowCursor(true); } } } } break; case WM_ACTIVATEAPP: { //if(wparam == TRUE) long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; if(wparam!= 0) { wnd->OnActivate(); } else { wnd->OnDeactivate(); } } } break; case WM_ACTIVATE: //Catch Alt + Tab { switch(wparam) { case WA_ACTIVE: { long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; wnd->OnActivate(); } } break; case WA_INACTIVE: { long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; wnd->OnDeactivate(); } } break; } } break; case WM_DESTROY: PostQuitMessage(0); DestroyWindow(hwnd); break; case WM_SYSKEYDOWN: switch(wparam) { case VK_RETURN: { if(GetKeyState(VK_MENU)) //Alt + Enter { long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; if(!wnd->IsAltEnterLocked()) { wnd->SetAltEnterLocked(true); wnd->SwitchMode(!wnd->IsFullScreen()); } } } } break; } break; case WM_SYSKEYUP: { switch(wparam) { case VK_RETURN: { long val = GetWindowLongPtr(hwnd, GWLP_USERDATA); if(val) { WindowWin* wnd = (WindowWin*)val; wnd->SetAltEnterLocked(false); } } break; } } break; case WM_KEYDOWN: switch(wparam) { case VK_ESCAPE: //PostQuitMessage(0); exit(0); break; } } return DefWindowProc(hwnd, message, wparam, lparam); } }