support fullscreen switch now
This commit is contained in:
parent
ebe3fa1e6b
commit
8ec5daeafd
|
|
@ -28,14 +28,14 @@
|
||||||
#include "Transition.h"
|
#include "Transition.h"
|
||||||
#include <windowsx.h>
|
#include <windowsx.h>
|
||||||
#include <imm.h>
|
#include <imm.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#pragma comment (lib ,"imm32.lib")
|
#pragma comment (lib ,"imm32.lib")
|
||||||
|
|
||||||
namespace easy2d
|
namespace easy2d
|
||||||
{
|
{
|
||||||
Application::Application(String const& app_name)
|
Application::Application(String const& app_name)
|
||||||
: active_(false)
|
: debug_(false)
|
||||||
, debug_(false)
|
|
||||||
, curr_scene_(nullptr)
|
, curr_scene_(nullptr)
|
||||||
, next_scene_(nullptr)
|
, next_scene_(nullptr)
|
||||||
, transition_(nullptr)
|
, transition_(nullptr)
|
||||||
|
|
@ -93,6 +93,8 @@ namespace easy2d
|
||||||
Audio::Instance()->Init(debug_)
|
Audio::Instance()->Init(debug_)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Setup();
|
||||||
|
|
||||||
// disable imm
|
// disable imm
|
||||||
::ImmAssociateContext(hwnd, nullptr);
|
::ImmAssociateContext(hwnd, nullptr);
|
||||||
|
|
||||||
|
|
@ -122,9 +124,7 @@ namespace easy2d
|
||||||
}
|
}
|
||||||
|
|
||||||
// use Application instance in message loop
|
// use Application instance in message loop
|
||||||
::SetWindowLongW(hwnd, GWLP_USERDATA, PtrToUlong(this));
|
::SetWindowLongPtr(hwnd, GWLP_USERDATA, PtrToUlong(this));
|
||||||
|
|
||||||
Setup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::Run()
|
void Application::Run()
|
||||||
|
|
@ -133,8 +133,7 @@ namespace easy2d
|
||||||
|
|
||||||
if (hwnd)
|
if (hwnd)
|
||||||
{
|
{
|
||||||
::ShowWindow(hwnd, SW_SHOWNORMAL);
|
Window::Instance()->Prepare();
|
||||||
::UpdateWindow(hwnd);
|
|
||||||
|
|
||||||
MSG msg = {};
|
MSG msg = {};
|
||||||
while (::GetMessageW(&msg, nullptr, 0, 0))
|
while (::GetMessageW(&msg, nullptr, 0, 0))
|
||||||
|
|
@ -250,8 +249,7 @@ namespace easy2d
|
||||||
rt->EndDraw()
|
rt->EndDraw()
|
||||||
);
|
);
|
||||||
|
|
||||||
if (active_)
|
::InvalidateRect(hwnd, NULL, FALSE);
|
||||||
::InvalidateRect(hwnd, NULL, FALSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
LRESULT CALLBACK Application::WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
|
||||||
|
|
@ -342,15 +340,10 @@ namespace easy2d
|
||||||
|
|
||||||
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
|
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
|
||||||
{
|
{
|
||||||
app->active_ = false;
|
|
||||||
|
|
||||||
E2D_LOG(L"Window minimized");
|
E2D_LOG(L"Window minimized");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
app->active_ = true;
|
|
||||||
::InvalidateRect(hwnd, nullptr, FALSE);
|
|
||||||
|
|
||||||
E2D_LOG(L"Window resized");
|
E2D_LOG(L"Window resized");
|
||||||
|
|
||||||
if (app->curr_scene_)
|
if (app->curr_scene_)
|
||||||
|
|
@ -360,6 +353,8 @@ namespace easy2d
|
||||||
evt.win.height = static_cast<int>(height);
|
evt.win.height = static_cast<int>(height);
|
||||||
app->curr_scene_->Dispatch(evt);
|
app->curr_scene_->Dispatch(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window::Instance()->UpdateWindowRect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -382,14 +377,17 @@ namespace easy2d
|
||||||
case WM_ACTIVATE:
|
case WM_ACTIVATE:
|
||||||
{
|
{
|
||||||
bool active = (LOWORD(wparam) != WA_INACTIVE);
|
bool active = (LOWORD(wparam) != WA_INACTIVE);
|
||||||
|
|
||||||
|
E2D_LOG(active ? L"Window activated" : L"Window deactivated");
|
||||||
|
|
||||||
|
Window::Instance()->SetActive(active);
|
||||||
|
|
||||||
if (app->curr_scene_)
|
if (app->curr_scene_)
|
||||||
{
|
{
|
||||||
Event evt(WindowEvent::FocusChanged);
|
Event evt(WindowEvent::FocusChanged);
|
||||||
evt.win.focus = active;
|
evt.win.focus = active;
|
||||||
app->curr_scene_->Dispatch(evt);
|
app->curr_scene_->Dispatch(evt);
|
||||||
}
|
}
|
||||||
|
|
||||||
E2D_LOG(active ? L"Window activated" : L"Window deactivated");
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
@ -422,14 +420,7 @@ namespace easy2d
|
||||||
|
|
||||||
case WM_CLOSE:
|
case WM_CLOSE:
|
||||||
{
|
{
|
||||||
E2D_LOG(L"Window is closing");
|
Window::Instance()->Destroy();
|
||||||
|
|
||||||
if (app->curr_scene_)
|
|
||||||
{
|
|
||||||
Event evt(WindowEvent::Closing);
|
|
||||||
app->curr_scene_->Dispatch(evt);
|
|
||||||
}
|
|
||||||
::DestroyWindow(hwnd);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
@ -438,6 +429,12 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
E2D_LOG(L"Window was destroyed");
|
E2D_LOG(L"Window was destroyed");
|
||||||
|
|
||||||
|
if (app->curr_scene_)
|
||||||
|
{
|
||||||
|
Event evt(WindowEvent::Closed);
|
||||||
|
app->curr_scene_->Dispatch(evt);
|
||||||
|
}
|
||||||
|
|
||||||
::PostQuitMessage(0);
|
::PostQuitMessage(0);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,6 @@ namespace easy2d
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool debug_;
|
bool debug_;
|
||||||
bool active_;
|
|
||||||
float time_scale_;
|
float time_scale_;
|
||||||
String app_name_;
|
String app_name_;
|
||||||
ScenePtr curr_scene_;
|
ScenePtr curr_scene_;
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ namespace easy2d
|
||||||
Resized, // 窗口大小变化
|
Resized, // 窗口大小变化
|
||||||
FocusChanged, // 获得或失去焦点
|
FocusChanged, // 获得或失去焦点
|
||||||
TitleChanged, // 标题变化
|
TitleChanged, // 标题变化
|
||||||
Closing, // 关闭窗口
|
Closed, // 窗口被关闭
|
||||||
|
|
||||||
Last
|
Last
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -38,12 +38,12 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
E2D_LOG(L"Creating device-independent resources");
|
E2D_LOG(L"Creating device-independent resources");
|
||||||
|
|
||||||
D2D1_FACTORY_OPTIONS fact_options;
|
D2D1_FACTORY_OPTIONS options;
|
||||||
fact_options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE;
|
options.debugLevel = debug ? D2D1_DEBUG_LEVEL_INFORMATION : D2D1_DEBUG_LEVEL_NONE;
|
||||||
HRESULT hr = modules::DirectX::Get().D2D1CreateFactory(
|
HRESULT hr = modules::DirectX::Get().D2D1CreateFactory(
|
||||||
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
D2D1_FACTORY_TYPE_SINGLE_THREADED,
|
||||||
__uuidof(ID2D1Factory),
|
__uuidof(ID2D1Factory),
|
||||||
&fact_options,
|
&options,
|
||||||
reinterpret_cast<void**>(&factory_)
|
reinterpret_cast<void**>(&factory_)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,13 +38,13 @@ namespace easy2d
|
||||||
E2D_LOG(L"Destroying input device");
|
E2D_LOG(L"Destroying input device");
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Input::Init(HWND hwnd, float scale_x, float scale_y, bool debug)
|
HRESULT Input::Init(HWND hwnd, float scalex, float scaley, bool debug)
|
||||||
{
|
{
|
||||||
E2D_LOG(L"Initing input device");
|
E2D_LOG(L"Initing input device");
|
||||||
|
|
||||||
hwnd_ = hwnd;
|
hwnd_ = hwnd;
|
||||||
scale_x_ = scale_x;
|
scale_x_ = scalex;
|
||||||
scale_y_ = scale_y;
|
scale_y_ = scaley;
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ namespace easy2d
|
||||||
E2D_DECLARE_SINGLETON(Input);
|
E2D_DECLARE_SINGLETON(Input);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HRESULT Init(HWND hwnd, float scale_x, float scale_y, bool debug);
|
HRESULT Init(HWND hwnd, float scalex, float scaley, bool debug);
|
||||||
|
|
||||||
// 检测键盘按键是否正被按下
|
// 检测键盘按键是否正被按下
|
||||||
bool IsDown(
|
bool IsDown(
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,14 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
#ifdef E2D_DEBUG
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
|
#else
|
||||||
|
bool enabled = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
void Out(std::wostream& stream, const wchar_t* output)
|
void Out(std::wostream& stream, const wchar_t* output)
|
||||||
{
|
{
|
||||||
stream.imbue(std::locale("chs"));
|
|
||||||
stream << output;
|
stream << output;
|
||||||
::OutputDebugStringW(output);
|
::OutputDebugStringW(output);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -31,28 +31,46 @@ namespace easy2d
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void GetContentScale(float* scale_x, float* scale_y);
|
MONITORINFOEX GetMoniterInfoEx(HWND hwnd);
|
||||||
|
|
||||||
|
void GetContentScale(float* scalex, float* scaley);
|
||||||
|
|
||||||
void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height);
|
void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height);
|
||||||
|
|
||||||
|
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name);
|
||||||
|
|
||||||
|
void RestoreResolution(WCHAR* device_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::Window()
|
Window::Window()
|
||||||
: handle(nullptr)
|
: handle_(nullptr)
|
||||||
, scale_x(1.f)
|
, width_(0)
|
||||||
, scale_y(1.f)
|
, height_(0)
|
||||||
|
, scalex_(1.f)
|
||||||
|
, scaley_(1.f)
|
||||||
|
, device_name_(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Window::~Window()
|
Window::~Window()
|
||||||
{
|
{
|
||||||
E2D_LOG(L"Destroying window");
|
E2D_LOG(L"Destroying window");
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
if (device_name_)
|
||||||
|
{
|
||||||
|
delete[] device_name_;
|
||||||
|
device_name_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT Window::Init(String title, int width, int height, LPCWSTR icon, bool fullscreen, 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 hinst = GetModuleHandleW(nullptr);
|
||||||
WNDCLASSEX wcex = { 0 };
|
WNDCLASSEX wcex = { 0 };
|
||||||
wcex.cbSize = sizeof(WNDCLASSEX);
|
wcex.cbSize = sizeof(WNDCLASSEX);
|
||||||
wcex.lpszClassName = E2D_WND_CLASS_NAME;
|
wcex.lpszClassName = E2D_WND_CLASS_NAME;
|
||||||
|
|
@ -61,52 +79,49 @@ namespace easy2d
|
||||||
wcex.hIcon = nullptr;
|
wcex.hIcon = nullptr;
|
||||||
wcex.cbClsExtra = 0;
|
wcex.cbClsExtra = 0;
|
||||||
wcex.cbWndExtra = sizeof(LONG_PTR);
|
wcex.cbWndExtra = sizeof(LONG_PTR);
|
||||||
wcex.hInstance = hinstance;
|
wcex.hInstance = hinst;
|
||||||
wcex.hbrBackground = nullptr;
|
wcex.hbrBackground = nullptr;
|
||||||
wcex.lpszMenuName = nullptr;
|
wcex.lpszMenuName = nullptr;
|
||||||
wcex.hCursor = ::LoadCursor(nullptr, IDC_ARROW);
|
wcex.hCursor = ::LoadCursorW(nullptr, IDC_ARROW);
|
||||||
|
|
||||||
if (icon)
|
if (icon)
|
||||||
{
|
{
|
||||||
wcex.hIcon = (HICON)::LoadImageW(
|
wcex.hIcon = (HICON)::LoadImageW(hinst, icon, IMAGE_ICON, 0, 0, LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
|
||||||
hinstance,
|
|
||||||
icon,
|
|
||||||
IMAGE_ICON,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
wcex.hIcon = ::LoadIconW(nullptr, IDI_APPLICATION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
::RegisterClassExW(&wcex);
|
::RegisterClassExW(&wcex);
|
||||||
|
|
||||||
|
// Get the nearest monitor to this window
|
||||||
|
HMONITOR monitor = ::MonitorFromPoint(POINT{ 0, 0 }, MONITOR_DEFAULTTOPRIMARY);
|
||||||
|
|
||||||
|
// Get the target monitor info
|
||||||
|
MONITORINFOEX monitor_info_ex;
|
||||||
|
memset(&monitor_info_ex, 0, sizeof(MONITORINFOEX));
|
||||||
|
monitor_info_ex.cbSize = sizeof(MONITORINFOEX);
|
||||||
|
::GetMonitorInfoW(monitor, &monitor_info_ex);
|
||||||
|
|
||||||
|
// Save the device name
|
||||||
|
int len = lstrlenW(monitor_info_ex.szDevice);
|
||||||
|
device_name_ = new WCHAR[len + 1];
|
||||||
|
lstrcpyW(device_name_, monitor_info_ex.szDevice);
|
||||||
|
|
||||||
|
GetContentScale(&scalex_, &scaley_);
|
||||||
|
|
||||||
int left = -1;
|
int left = -1;
|
||||||
int top = -1;
|
int top = -1;
|
||||||
|
|
||||||
HMONITOR monitor = nullptr;
|
is_fullscreen_ = fullscreen;
|
||||||
MONITORINFOEX monitor_info_ex;
|
|
||||||
|
|
||||||
// Get the nearest monitor to this window
|
if (is_fullscreen_)
|
||||||
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);
|
|
||||||
|
|
||||||
if (fullscreen)
|
|
||||||
{
|
{
|
||||||
top = monitor_info_ex.rcMonitor.top;
|
top = monitor_info_ex.rcMonitor.top;
|
||||||
left = monitor_info_ex.rcMonitor.left;
|
left = monitor_info_ex.rcMonitor.left;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -117,9 +132,9 @@ namespace easy2d
|
||||||
AdjustWindow(
|
AdjustWindow(
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
fullscreen ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE),
|
GetWindowStyle(),
|
||||||
scale_x,
|
scalex_,
|
||||||
scale_y,
|
scaley_,
|
||||||
&win_width,
|
&win_width,
|
||||||
&win_height
|
&win_height
|
||||||
);
|
);
|
||||||
|
|
@ -130,55 +145,51 @@ namespace easy2d
|
||||||
height = win_height;
|
height = win_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (width > monitor_info_ex.rcWork.right - left)
|
handle_ = ::CreateWindowExW(
|
||||||
width = monitor_info_ex.rcWork.right - left;
|
is_fullscreen_ ? WS_EX_TOPMOST : 0,
|
||||||
|
|
||||||
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(
|
|
||||||
fullscreen ? (WS_EX_TOPMOST) : 0,
|
|
||||||
E2D_WND_CLASS_NAME,
|
E2D_WND_CLASS_NAME,
|
||||||
title.c_str(),
|
title.c_str(),
|
||||||
fullscreen ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE),
|
GetWindowStyle(),
|
||||||
left,
|
left,
|
||||||
top,
|
top,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
nullptr,
|
nullptr,
|
||||||
nullptr,
|
nullptr,
|
||||||
hinstance,
|
hinst,
|
||||||
nullptr
|
nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
if (handle == nullptr)
|
if (handle_ == nullptr)
|
||||||
{
|
{
|
||||||
::UnregisterClass(E2D_WND_CLASS_NAME, hinstance);
|
::UnregisterClass(E2D_WND_CLASS_NAME, hinst);
|
||||||
return HRESULT_FROM_WIN32(GetLastError());
|
return HRESULT_FROM_WIN32(GetLastError());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
GetClientRect(handle_, &rc);
|
||||||
|
width_ = rc.right - rc.left;
|
||||||
|
height_ = rc.bottom - rc.top;
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::Prepare()
|
||||||
|
{
|
||||||
|
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||||
|
::UpdateWindow(handle_);
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
ChangeFullScreenResolution(width_, height_, device_name_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
String Window::GetTitle() const
|
String Window::GetTitle() const
|
||||||
{
|
{
|
||||||
if (handle)
|
if (handle_)
|
||||||
{
|
{
|
||||||
wchar_t title[256];
|
wchar_t title[256];
|
||||||
GetWindowTextW(handle, title, 256);
|
::GetWindowTextW(handle_, title, 256);
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
return String();
|
return String();
|
||||||
|
|
@ -186,37 +197,31 @@ namespace easy2d
|
||||||
|
|
||||||
void Window::SetTitle(String const& title)
|
void Window::SetTitle(String const& title)
|
||||||
{
|
{
|
||||||
if (handle)
|
if (handle_)
|
||||||
::SetWindowText(handle, title.c_str());
|
::SetWindowTextW(handle_, title.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
Size Window::GetSize() const
|
Size Window::GetSize() const
|
||||||
{
|
{
|
||||||
if (handle)
|
return Size{
|
||||||
{
|
static_cast<float>(width_),
|
||||||
RECT rect;
|
static_cast<float>(height_)
|
||||||
GetClientRect(handle, &rect);
|
};
|
||||||
return Size{
|
|
||||||
static_cast<float>(rect.right - rect.left),
|
|
||||||
static_cast<float>(rect.bottom - rect.top)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return Size{};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetWidth() const
|
float Window::GetWidth() const
|
||||||
{
|
{
|
||||||
return GetSize().x;
|
return static_cast<float>(width_);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetHeight() const
|
float Window::GetHeight() const
|
||||||
{
|
{
|
||||||
return GetSize().y;
|
return static_cast<float>(height_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::SetIcon(LPCWSTR icon_resource)
|
void Window::SetIcon(LPCWSTR icon_resource)
|
||||||
{
|
{
|
||||||
if (handle)
|
if (handle_)
|
||||||
{
|
{
|
||||||
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
HINSTANCE hinstance = GetModuleHandle(nullptr);
|
||||||
HICON icon = (HICON)::LoadImage(
|
HICON icon = (HICON)::LoadImage(
|
||||||
|
|
@ -228,35 +233,150 @@ namespace easy2d
|
||||||
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
|
||||||
);
|
);
|
||||||
|
|
||||||
::SendMessage(handle, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon);
|
||||||
::SendMessage(handle, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::Resize(int width, int height)
|
||||||
|
{
|
||||||
|
if (handle_ && !is_fullscreen_)
|
||||||
|
{
|
||||||
|
RECT rc = { 0, 0, int(width), int(height) };
|
||||||
|
::AdjustWindowRect(&rc, GetWindowStyle(), false);
|
||||||
|
|
||||||
|
width = rc.right - rc.left;
|
||||||
|
height = rc.bottom - rc.top;
|
||||||
|
::SetWindowPos(handle_, 0, 0, 0, width, height, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::SetFullscreen(bool fullscreen, int width, int height)
|
||||||
|
{
|
||||||
|
if (is_fullscreen_ != fullscreen || width != width_ || height != height_)
|
||||||
|
{
|
||||||
|
is_fullscreen_ = fullscreen;
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
// move window to (0, 0) before display switch
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, 0, 0, width_, height_, SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
ChangeFullScreenResolution(width, height, device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
|
||||||
|
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width, height, SWP_NOACTIVATE);
|
||||||
|
|
||||||
|
width_ = width;
|
||||||
|
height_ = height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
|
||||||
|
UINT screenw = info.rcWork.right - info.rcWork.left;
|
||||||
|
UINT screenh = info.rcWork.bottom - info.rcWork.top;
|
||||||
|
|
||||||
|
UINT win_width, win_height;
|
||||||
|
AdjustWindow(width, height, GetWindowStyle(), scalex_, scaley_, &win_width, &win_height);
|
||||||
|
|
||||||
|
int left = screenw > win_width ? ((screenw - win_width) / 2) : 0;
|
||||||
|
int top = screenh > win_height ? ((screenh - win_height) / 2) : 0;
|
||||||
|
|
||||||
|
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
|
||||||
|
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, win_width, win_height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
|
||||||
|
|
||||||
|
UpdateWindowRect();
|
||||||
|
}
|
||||||
|
|
||||||
|
::ShowWindow(handle_, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND Window::GetHandle() const
|
HWND Window::GetHandle() const
|
||||||
{
|
{
|
||||||
return handle;
|
return handle_;
|
||||||
|
}
|
||||||
|
|
||||||
|
DWORD Window::GetWindowStyle() const
|
||||||
|
{
|
||||||
|
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (WINDOW_STYLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetContentScaleX() const
|
float Window::GetContentScaleX() const
|
||||||
{
|
{
|
||||||
return scale_x;
|
return scalex_;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Window::GetContentScaleY() const
|
float Window::GetContentScaleY() const
|
||||||
{
|
{
|
||||||
return scale_y;
|
return scaley_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::UpdateWindowRect()
|
||||||
|
{
|
||||||
|
if (!handle_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
RECT rc;
|
||||||
|
::GetClientRect(handle_, &rc);
|
||||||
|
|
||||||
|
width_ = rc.right - rc.left;
|
||||||
|
height_ = rc.bottom - rc.top;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::SetActive(bool actived)
|
||||||
|
{
|
||||||
|
if (!handle_)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (is_fullscreen_)
|
||||||
|
{
|
||||||
|
if (actived)
|
||||||
|
{
|
||||||
|
ChangeFullScreenResolution(width_, height_, device_name_);
|
||||||
|
|
||||||
|
MONITORINFOEX info = GetMoniterInfoEx(handle_);
|
||||||
|
::SetWindowPos(handle_, HWND_TOPMOST, info.rcMonitor.top, info.rcMonitor.left, width_, height_, SWP_NOACTIVATE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
RestoreResolution(device_name_);
|
||||||
|
|
||||||
|
::SetWindowPos(handle_, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
|
||||||
|
::ShowWindow(handle_, SW_MINIMIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::Destroy()
|
void Window::Destroy()
|
||||||
{
|
{
|
||||||
if (handle)
|
if (handle_)
|
||||||
::DestroyWindow(handle);
|
{
|
||||||
|
::DestroyWindow(handle_);
|
||||||
|
handle_ = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
void GetContentScale(float* scale_x, float* scale_y)
|
MONITORINFOEX GetMoniterInfoEx(HWND hwnd)
|
||||||
|
{
|
||||||
|
HMONITOR monitor = ::MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||||
|
MONITORINFOEX monitor_info;
|
||||||
|
|
||||||
|
memset(&monitor_info, 0, sizeof(MONITORINFOEX));
|
||||||
|
monitor_info.cbSize = sizeof(MONITORINFOEX);
|
||||||
|
::GetMonitorInfoW(monitor, &monitor_info);
|
||||||
|
|
||||||
|
return monitor_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetContentScale(float* scalex, float* scaley)
|
||||||
{
|
{
|
||||||
const float DEFAULT_SCREEN_DPI = 96.f;
|
const float DEFAULT_SCREEN_DPI = 96.f;
|
||||||
const HDC dc = GetDC(NULL);
|
const HDC dc = GetDC(NULL);
|
||||||
|
|
@ -264,10 +384,10 @@ namespace easy2d
|
||||||
float ydpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSY));
|
float ydpi = static_cast<float>(GetDeviceCaps(dc, LOGPIXELSY));
|
||||||
ReleaseDC(NULL, dc);
|
ReleaseDC(NULL, dc);
|
||||||
|
|
||||||
if (scale_x)
|
if (scalex)
|
||||||
*scale_x = xdpi / DEFAULT_SCREEN_DPI;
|
*scalex = xdpi / DEFAULT_SCREEN_DPI;
|
||||||
if (scale_y)
|
if (scaley)
|
||||||
*scale_y = ydpi / DEFAULT_SCREEN_DPI;
|
*scaley = ydpi / DEFAULT_SCREEN_DPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height)
|
void AdjustWindow(UINT width, UINT height, DWORD style, float scalex, float scaley, UINT* win_width, UINT* win_height)
|
||||||
|
|
@ -279,19 +399,35 @@ namespace easy2d
|
||||||
*win_width = rc.right - rc.left;
|
*win_width = rc.right - rc.left;
|
||||||
*win_height = rc.bottom - rc.top;
|
*win_height = rc.bottom - rc.top;
|
||||||
|
|
||||||
HMONITOR monitor = ::MonitorFromWindow(NULL, MONITOR_DEFAULTTONEAREST);
|
MONITORINFOEX info = GetMoniterInfoEx(NULL);
|
||||||
MONITORINFO monitor_info;
|
|
||||||
::memset(&monitor_info, 0, sizeof(MONITORINFO));
|
|
||||||
monitor_info.cbSize = sizeof(MONITORINFO);
|
|
||||||
::GetMonitorInfoW(monitor, &monitor_info);
|
|
||||||
|
|
||||||
long max_width = monitor_info.rcWork.right - monitor_info.rcWork.left;
|
UINT screenw = info.rcWork.right - info.rcWork.left;
|
||||||
long max_height = monitor_info.rcWork.bottom - monitor_info.rcWork.top;
|
UINT screenh = info.rcWork.bottom - info.rcWork.top;
|
||||||
|
|
||||||
if (*win_width > static_cast<UINT>(max_width))
|
if (*win_width > screenw)
|
||||||
*win_width = max_width;
|
*win_width = screenw;
|
||||||
if (*win_height > static_cast<UINT>(max_height))
|
if (*win_height > screenh)
|
||||||
*win_height = max_height;
|
*win_height = screenh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name)
|
||||||
|
{
|
||||||
|
DEVMODE mode;
|
||||||
|
|
||||||
|
memset(&mode, 0, sizeof(mode));
|
||||||
|
mode.dmSize = sizeof(DEVMODE);
|
||||||
|
mode.dmBitsPerPel = ::GetDeviceCaps(::GetDC(0), BITSPIXEL);;
|
||||||
|
mode.dmPelsWidth = width;
|
||||||
|
mode.dmPelsHeight = height;
|
||||||
|
mode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
|
||||||
|
|
||||||
|
if (::ChangeDisplaySettingsExW(device_name, &mode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL)
|
||||||
|
logs::Errorln(L"ChangeDisplaySettings failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
void RestoreResolution(WCHAR* device_name)
|
||||||
|
{
|
||||||
|
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,16 +30,6 @@ namespace easy2d
|
||||||
E2D_DECLARE_SINGLETON(Window);
|
E2D_DECLARE_SINGLETON(Window);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
HRESULT Init(
|
|
||||||
String title,
|
|
||||||
int width,
|
|
||||||
int height,
|
|
||||||
LPCWSTR icon,
|
|
||||||
bool fullscreen,
|
|
||||||
WNDPROC proc,
|
|
||||||
bool debug
|
|
||||||
);
|
|
||||||
|
|
||||||
// »ñÈ¡±êÌâ
|
// »ñÈ¡±êÌâ
|
||||||
String GetTitle() const;
|
String GetTitle() const;
|
||||||
|
|
||||||
|
|
@ -58,12 +48,36 @@ namespace easy2d
|
||||||
// ÉèÖô°¿Úͼ±ê
|
// ÉèÖô°¿Úͼ±ê
|
||||||
void SetIcon(LPCWSTR icon_resource);
|
void SetIcon(LPCWSTR icon_resource);
|
||||||
|
|
||||||
|
// 重设窗口大小
|
||||||
|
void Resize(int width, int height);
|
||||||
|
|
||||||
|
// 设置全屏模式
|
||||||
|
void SetFullscreen(bool fullscreen, int width, int height);
|
||||||
|
|
||||||
|
HRESULT Init(
|
||||||
|
String title,
|
||||||
|
int width,
|
||||||
|
int height,
|
||||||
|
LPCWSTR icon,
|
||||||
|
bool fullscreen,
|
||||||
|
WNDPROC proc,
|
||||||
|
bool debug
|
||||||
|
);
|
||||||
|
|
||||||
|
void Prepare();
|
||||||
|
|
||||||
HWND GetHandle() const;
|
HWND GetHandle() const;
|
||||||
|
|
||||||
|
DWORD GetWindowStyle() const;
|
||||||
|
|
||||||
float GetContentScaleX() const;
|
float GetContentScaleX() const;
|
||||||
|
|
||||||
float GetContentScaleY() const;
|
float GetContentScaleY() const;
|
||||||
|
|
||||||
|
void UpdateWindowRect();
|
||||||
|
|
||||||
|
void SetActive(bool actived);
|
||||||
|
|
||||||
void Destroy();
|
void Destroy();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -72,8 +86,12 @@ namespace easy2d
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
HWND handle;
|
HWND handle_;
|
||||||
float scale_x;
|
bool is_fullscreen_;
|
||||||
float scale_y;
|
int width_;
|
||||||
|
int height_;
|
||||||
|
float scalex_;
|
||||||
|
float scaley_;
|
||||||
|
WCHAR* device_name_;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue