From ebe3fa1e6be5bfab0405bd241fb62266d0d11d88 Mon Sep 17 00:00:00 2001 From: Nomango <569629550@qq.com> Date: Fri, 25 Jan 2019 01:45:03 +0800 Subject: [PATCH] support fullscreen --- src/core/Application.cpp | 7 +- src/core/Application.h | 14 ++-- src/core/Scene.cpp | 11 --- src/core/Scene.h | 6 -- src/core/window.cpp | 156 +++++++++++++++++++++++++-------------- src/core/window.h | 8 +- 6 files changed, 111 insertions(+), 91 deletions(-) diff --git a/src/core/Application.cpp b/src/core/Application.cpp index 46ed86ec..eff32f19 100644 --- a/src/core/Application.cpp +++ b/src/core/Application.cpp @@ -64,6 +64,7 @@ namespace easy2d options.width, options.height, options.icon, + options.fullscreen, Application::WndProc, debug_ ) @@ -264,14 +265,8 @@ namespace easy2d { case WM_PAINT: { - PAINTSTRUCT ps; - ::BeginPaint(hwnd, &ps); - app->Update(); app->Render(hwnd); - - ::EndPaint(hwnd, &ps); - return 0; } break; diff --git a/src/core/Application.h b/src/core/Application.h index 8481941b..77d85e86 100644 --- a/src/core/Application.h +++ b/src/core/Application.h @@ -30,12 +30,13 @@ namespace easy2d { struct Options { - String title; // 标题 - int width; // 宽度 - int height; // 高度 - LPCWSTR icon; // 图标 - bool vsync; // 垂直同步 - bool debug; // 调试模式 + String title; // 标题 + int width; // 宽度 + int height; // 高度 + LPCWSTR icon; // 图标 + bool vsync; // 垂直同步 + bool fullscreen; // 全屏模式 + bool debug; // 调试模式 Options() : title(L"Easy2D Game") @@ -43,6 +44,7 @@ namespace easy2d , height(480) , icon(nullptr) , vsync(true) + , fullscreen(false) , debug(false) {} }; diff --git a/src/core/Scene.cpp b/src/core/Scene.cpp index 443fbb38..42d95675 100644 --- a/src/core/Scene.cpp +++ b/src/core/Scene.cpp @@ -26,9 +26,6 @@ namespace easy2d { Scene::Scene() { - //AddListener(WindowEvent::Activate, Closure(this, &Scene::OnActivate)); - //AddListener(WindowEvent::Deavtivate, Closure(this, &Scene::OnDeactivate)); - scene_ = this; } @@ -46,12 +43,4 @@ namespace easy2d E2D_LOG(L"Scene exited"); } - void Scene::OnDeactivate(Event const&) - { - } - - void Scene::OnActivate(Event const&) - { - } - } diff --git a/src/core/Scene.h b/src/core/Scene.h index 7b0aa784..7416bfb8 100644 --- a/src/core/Scene.h +++ b/src/core/Scene.h @@ -37,11 +37,5 @@ namespace easy2d // 退出场景 virtual void OnExit(); - - // 窗口获得焦点 - virtual void OnActivate(Event const&); - - // 窗口失去焦点 - virtual void OnDeactivate(Event const&); }; } diff --git a/src/core/window.cpp b/src/core/window.cpp index 3f1a20f8..9d0c9bd0 100644 --- a/src/core/window.cpp +++ b/src/core/window.cpp @@ -23,8 +23,9 @@ #include "logs.h" #include "../math/scalar.hpp" -#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME -#define REGISTER_CLASS L"Easy2DApp" +#define WINDOW_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX +#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP +#define E2D_WND_CLASS_NAME L"Easy2DAppWnd" namespace easy2d { @@ -32,7 +33,7 @@ namespace easy2d { void GetContentScale(float* scale_x, float* scale_y); - Rect LocateWindow(int width, int height, float scale_x, float scale_y); + void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height); } Window::Window() @@ -47,14 +48,14 @@ namespace easy2d E2D_LOG(L"Destroying window"); } - HRESULT Window::Init(String title, int width, int height, LPCWSTR icon, WNDPROC proc, bool debug) + HRESULT Window::Init(String title, int width, int height, LPCWSTR icon, bool fullscreen, WNDPROC proc, bool debug) { E2D_LOG(L"Creating window"); - + HINSTANCE hinstance = GetModuleHandle(nullptr); WNDCLASSEX wcex = { 0 }; wcex.cbSize = sizeof(WNDCLASSEX); - wcex.lpszClassName = REGISTER_CLASS; + wcex.lpszClassName = E2D_WND_CLASS_NAME; wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */; wcex.lpfnWndProc = proc; wcex.hIcon = nullptr; @@ -67,7 +68,7 @@ namespace easy2d if (icon) { - wcex.hIcon = (HICON)::LoadImage( + wcex.hIcon = (HICON)::LoadImageW( hinstance, icon, IMAGE_ICON, @@ -78,23 +79,86 @@ namespace easy2d } else { - wcex.hIcon = ::LoadIcon(nullptr, IDI_APPLICATION); + wcex.hIcon = ::LoadIconW(nullptr, IDI_APPLICATION); } - ::RegisterClassEx(&wcex); + ::RegisterClassExW(&wcex); + + int left = -1; + int top = -1; + + HMONITOR monitor = nullptr; + MONITORINFOEX monitor_info_ex; + + // Get the nearest monitor to this window + POINT anchor; + anchor.x = left; + anchor.y = top; + monitor = MonitorFromPoint(anchor, MONITOR_DEFAULTTOPRIMARY); + + // Get the target monitor info + memset(&monitor_info_ex, 0, sizeof(MONITORINFOEX)); + monitor_info_ex.cbSize = sizeof(MONITORINFOEX); + GetMonitorInfoW(monitor, &monitor_info_ex); GetContentScale(&scale_x, &scale_y); - Rect client_rect = LocateWindow(width, height, scale_x, scale_y); + if (fullscreen) + { + top = monitor_info_ex.rcMonitor.top; + left = monitor_info_ex.rcMonitor.left; + } + else + { + UINT screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left; + UINT screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top; + + UINT win_width, win_height; + AdjustWindow( + width, + height, + fullscreen ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE), + scale_x, + scale_y, + &win_width, + &win_height + ); + + left = monitor_info_ex.rcWork.left + (screenw - win_width) / 2; + top = monitor_info_ex.rcWork.top + (screenh - win_height) / 2; + width = win_width; + height = win_height; + } + + if (width > monitor_info_ex.rcWork.right - left) + width = monitor_info_ex.rcWork.right - left; + + if (height > monitor_info_ex.rcWork.bottom - top) + height = monitor_info_ex.rcWork.bottom - top; + + if (fullscreen) + { + DEVMODE mode; + memset(&mode, 0, sizeof(mode)); + mode.dmSize = sizeof(DEVMODE); + mode.dmBitsPerPel = fullscreen ? 32 : (::GetDeviceCaps(GetDC(0), BITSPIXEL)); + mode.dmPelsWidth = width; + mode.dmPelsHeight = height; + mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; + + if (DISP_CHANGE_SUCCESSFUL != ::ChangeDisplaySettingsExW(monitor_info_ex.szDevice, &mode, NULL, CDS_FULLSCREEN, NULL)) + logs::Errorln(L"ChangeDisplaySettings failed"); + } + handle = ::CreateWindowExW( - NULL, - REGISTER_CLASS, + fullscreen ? (WS_EX_TOPMOST) : 0, + E2D_WND_CLASS_NAME, title.c_str(), - WINDOW_STYLE, - static_cast(client_rect.origin.x), - static_cast(client_rect.origin.y), - static_cast(client_rect.size.x), - static_cast(client_rect.size.y), + fullscreen ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE), + left, + top, + width, + height, nullptr, nullptr, hinstance, @@ -103,7 +167,7 @@ namespace easy2d if (handle == nullptr) { - ::UnregisterClass(REGISTER_CLASS, hinstance); + ::UnregisterClass(E2D_WND_CLASS_NAME, hinstance); return HRESULT_FROM_WIN32(GetLastError()); } return S_OK; @@ -150,22 +214,6 @@ namespace easy2d return GetSize().y; } - void Window::SetSize(int width, int height) - { - if (handle) - { - Rect rect = LocateWindow(width, height, scale_x, scale_y); - ::MoveWindow( - handle, - static_cast(rect.origin.x), - static_cast(rect.origin.y), - static_cast(rect.size.x), - static_cast(rect.size.y), - TRUE - ); - } - } - void Window::SetIcon(LPCWSTR icon_resource) { if (handle) @@ -222,34 +270,28 @@ namespace easy2d *scale_y = ydpi / DEFAULT_SCREEN_DPI; } - Rect LocateWindow(int width, int height, float scale_x, float scale_y) + void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height) { - int max_width = ::GetSystemMetrics(SM_CXSCREEN); - int max_height = ::GetSystemMetrics(SM_CYSCREEN); - RECT rect = - { - 0, - 0, - static_cast(math::Ceil(width * scale_x)), - static_cast(math::Ceil(height * scale_y)) - }; + RECT rc; + ::SetRect(&rc, 0, 0, (int)math::Ceil(width * scalex), (int)math::Ceil(height * scaley)); + ::AdjustWindowRect(&rc, style, false); - ::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); - width = static_cast(rect.right - rect.left); - height = static_cast(rect.bottom - rect.top); + *win_width = rc.right - rc.left; + *win_height = rc.bottom - rc.top; - if (max_width < width || max_height < height) - logs::Warningln(L"The window is larger than screen!"); + HMONITOR monitor = ::MonitorFromWindow(NULL, MONITOR_DEFAULTTONEAREST); + MONITORINFO monitor_info; + ::memset(&monitor_info, 0, sizeof(MONITORINFO)); + monitor_info.cbSize = sizeof(MONITORINFO); + ::GetMonitorInfoW(monitor, &monitor_info); - width = std::min(width, max_width); - height = std::min(height, max_height); + long max_width = monitor_info.rcWork.right - monitor_info.rcWork.left; + long max_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top; - return Rect( - static_cast((max_width - width) / 2), - static_cast((max_height - height) / 2), - static_cast(width), - static_cast(height) - ); + if (*win_width > static_cast(max_width)) + *win_width = max_width; + if (*win_height > static_cast(max_height)) + *win_height = max_height; } } } diff --git a/src/core/window.h b/src/core/window.h index f35762e8..876ed2d7 100644 --- a/src/core/window.h +++ b/src/core/window.h @@ -35,6 +35,7 @@ namespace easy2d int width, int height, LPCWSTR icon, + bool fullscreen, WNDPROC proc, bool debug ); @@ -42,9 +43,6 @@ namespace easy2d // 获取标题 String GetTitle() const; - // 设置标题 - void SetTitle(String const& title); - // 获取窗口大小 Size GetSize() const; @@ -54,8 +52,8 @@ namespace easy2d // 获取窗口高度 float GetHeight() const; - // 重设窗口大小 - void SetSize(int width, int height); + // 设置标题 + void SetTitle(String const& title); // 设置窗口图标 void SetIcon(LPCWSTR icon_resource);