support fullscreen

This commit is contained in:
Nomango 2019-01-25 01:45:03 +08:00 committed by Nomango
parent 59ac54063e
commit ebe3fa1e6b
6 changed files with 111 additions and 91 deletions

View File

@ -64,6 +64,7 @@ namespace easy2d
options.width, options.width,
options.height, options.height,
options.icon, options.icon,
options.fullscreen,
Application::WndProc, Application::WndProc,
debug_ debug_
) )
@ -264,14 +265,8 @@ namespace easy2d
{ {
case WM_PAINT: case WM_PAINT:
{ {
PAINTSTRUCT ps;
::BeginPaint(hwnd, &ps);
app->Update(); app->Update();
app->Render(hwnd); app->Render(hwnd);
::EndPaint(hwnd, &ps);
return 0; return 0;
} }
break; break;

View File

@ -35,6 +35,7 @@ namespace easy2d
int height; // 高度 int height; // 高度
LPCWSTR icon; // 图标 LPCWSTR icon; // 图标
bool vsync; // 垂直同步 bool vsync; // 垂直同步
bool fullscreen; // 全屏模式
bool debug; // 调试模式 bool debug; // 调试模式
Options() Options()
@ -43,6 +44,7 @@ namespace easy2d
, height(480) , height(480)
, icon(nullptr) , icon(nullptr)
, vsync(true) , vsync(true)
, fullscreen(false)
, debug(false) , debug(false)
{} {}
}; };

View File

@ -26,9 +26,6 @@ namespace easy2d
{ {
Scene::Scene() Scene::Scene()
{ {
//AddListener(WindowEvent::Activate, Closure(this, &Scene::OnActivate));
//AddListener(WindowEvent::Deavtivate, Closure(this, &Scene::OnDeactivate));
scene_ = this; scene_ = this;
} }
@ -46,12 +43,4 @@ namespace easy2d
E2D_LOG(L"Scene exited"); E2D_LOG(L"Scene exited");
} }
void Scene::OnDeactivate(Event const&)
{
}
void Scene::OnActivate(Event const&)
{
}
} }

View File

@ -37,11 +37,5 @@ namespace easy2d
// 退出场景 // 退出场景
virtual void OnExit(); virtual void OnExit();
// 窗口获得焦点
virtual void OnActivate(Event const&);
// 窗口失去焦点
virtual void OnDeactivate(Event const&);
}; };
} }

View File

@ -23,8 +23,9 @@
#include "logs.h" #include "logs.h"
#include "../math/scalar.hpp" #include "../math/scalar.hpp"
#define WINDOW_STYLE WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX & ~WS_THICKFRAME #define WINDOW_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
#define REGISTER_CLASS L"Easy2DApp" #define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
#define E2D_WND_CLASS_NAME L"Easy2DAppWnd"
namespace easy2d namespace easy2d
{ {
@ -32,7 +33,7 @@ namespace easy2d
{ {
void GetContentScale(float* scale_x, float* scale_y); 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() Window::Window()
@ -47,14 +48,14 @@ namespace easy2d
E2D_LOG(L"Destroying window"); 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"); E2D_LOG(L"Creating window");
HINSTANCE hinstance = GetModuleHandle(nullptr); HINSTANCE hinstance = GetModuleHandle(nullptr);
WNDCLASSEX wcex = { 0 }; WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX); wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = REGISTER_CLASS; wcex.lpszClassName = E2D_WND_CLASS_NAME;
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */; wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
wcex.lpfnWndProc = proc; wcex.lpfnWndProc = proc;
wcex.hIcon = nullptr; wcex.hIcon = nullptr;
@ -67,7 +68,7 @@ namespace easy2d
if (icon) if (icon)
{ {
wcex.hIcon = (HICON)::LoadImage( wcex.hIcon = (HICON)::LoadImageW(
hinstance, hinstance,
icon, icon,
IMAGE_ICON, IMAGE_ICON,
@ -78,23 +79,86 @@ namespace easy2d
} }
else 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); 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( handle = ::CreateWindowExW(
NULL, fullscreen ? (WS_EX_TOPMOST) : 0,
REGISTER_CLASS, E2D_WND_CLASS_NAME,
title.c_str(), title.c_str(),
WINDOW_STYLE, fullscreen ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE),
static_cast<int>(client_rect.origin.x), left,
static_cast<int>(client_rect.origin.y), top,
static_cast<int>(client_rect.size.x), width,
static_cast<int>(client_rect.size.y), height,
nullptr, nullptr,
nullptr, nullptr,
hinstance, hinstance,
@ -103,7 +167,7 @@ namespace easy2d
if (handle == nullptr) if (handle == nullptr)
{ {
::UnregisterClass(REGISTER_CLASS, hinstance); ::UnregisterClass(E2D_WND_CLASS_NAME, hinstance);
return HRESULT_FROM_WIN32(GetLastError()); return HRESULT_FROM_WIN32(GetLastError());
} }
return S_OK; return S_OK;
@ -150,22 +214,6 @@ namespace easy2d
return GetSize().y; 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<int>(rect.origin.x),
static_cast<int>(rect.origin.y),
static_cast<int>(rect.size.x),
static_cast<int>(rect.size.y),
TRUE
);
}
}
void Window::SetIcon(LPCWSTR icon_resource) void Window::SetIcon(LPCWSTR icon_resource)
{ {
if (handle) if (handle)
@ -222,34 +270,28 @@ namespace easy2d
*scale_y = ydpi / DEFAULT_SCREEN_DPI; *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); RECT rc;
int max_height = ::GetSystemMetrics(SM_CYSCREEN); ::SetRect(&rc, 0, 0, (int)math::Ceil(width * scalex), (int)math::Ceil(height * scaley));
RECT rect = ::AdjustWindowRect(&rc, style, false);
{
0,
0,
static_cast<LONG>(math::Ceil(width * scale_x)),
static_cast<LONG>(math::Ceil(height * scale_y))
};
::AdjustWindowRectEx(&rect, WINDOW_STYLE, FALSE, NULL); *win_width = rc.right - rc.left;
width = static_cast<int>(rect.right - rect.left); *win_height = rc.bottom - rc.top;
height = static_cast<int>(rect.bottom - rect.top);
if (max_width < width || max_height < height) HMONITOR monitor = ::MonitorFromWindow(NULL, MONITOR_DEFAULTTONEAREST);
logs::Warningln(L"The window is larger than screen!"); MONITORINFO monitor_info;
::memset(&monitor_info, 0, sizeof(MONITORINFO));
monitor_info.cbSize = sizeof(MONITORINFO);
::GetMonitorInfoW(monitor, &monitor_info);
width = std::min(width, max_width); long max_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
height = std::min(height, max_height); long max_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
return Rect( if (*win_width > static_cast<UINT>(max_width))
static_cast<float>((max_width - width) / 2), *win_width = max_width;
static_cast<float>((max_height - height) / 2), if (*win_height > static_cast<UINT>(max_height))
static_cast<float>(width), *win_height = max_height;
static_cast<float>(height)
);
} }
} }
} }

View File

@ -35,6 +35,7 @@ namespace easy2d
int width, int width,
int height, int height,
LPCWSTR icon, LPCWSTR icon,
bool fullscreen,
WNDPROC proc, WNDPROC proc,
bool debug bool debug
); );
@ -42,9 +43,6 @@ namespace easy2d
// 获取标题 // 获取标题
String GetTitle() const; String GetTitle() const;
// 设置标题
void SetTitle(String const& title);
// 获取窗口大小 // 获取窗口大小
Size GetSize() const; Size GetSize() const;
@ -54,8 +52,8 @@ namespace easy2d
// 获取窗口高度 // 获取窗口高度
float GetHeight() const; float GetHeight() const;
// 重设窗口大小 // ÉèÖñêÌâ
void SetSize(int width, int height); void SetTitle(String const& title);
// 设置窗口图标 // 设置窗口图标
void SetIcon(LPCWSTR icon_resource); void SetIcon(LPCWSTR icon_resource);