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.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;

View File

@ -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)
{}
};

View File

@ -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&)
{
}
}

View File

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

View File

@ -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<int>(client_rect.origin.x),
static_cast<int>(client_rect.origin.y),
static_cast<int>(client_rect.size.x),
static_cast<int>(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<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)
{
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<LONG>(math::Ceil(width * scale_x)),
static_cast<LONG>(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<int>(rect.right - rect.left);
height = static_cast<int>(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<float>((max_width - width) / 2),
static_cast<float>((max_height - height) / 2),
static_cast<float>(width),
static_cast<float>(height)
);
if (*win_width > static_cast<UINT>(max_width))
*win_width = max_width;
if (*win_height > static_cast<UINT>(max_height))
*win_height = max_height;
}
}
}

View File

@ -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);