Magic_Game/src/kiwano/platform/Window.cpp

646 lines
16 KiB
C++
Raw Normal View History

2019-08-14 21:52:49 +08:00
// Copyright (c) 2016-2018 Kiwano - Nomango
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
2019-11-13 14:33:15 +08:00
#include <kiwano/platform/Window.h>
2019-10-11 21:55:29 +08:00
#include <kiwano/platform/Application.h>
2020-01-16 18:33:42 +08:00
#include <kiwano/core/event/MouseEvent.h>
#include <kiwano/core/event/KeyEvent.h>
#include <kiwano/core/event/WindowEvent.h>
#include <kiwano/core/Logger.h>
#include <imm.h> // ImmAssociateContext
#pragma comment(lib, "imm32.lib")
2019-08-14 21:52:49 +08:00
2019-08-20 23:51:12 +08:00
#define WINDOW_FIXED_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
#define WINDOW_RESIZABLE_STYLE WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX | WS_SIZEBOX | WS_MAXIMIZEBOX
2019-08-14 21:52:49 +08:00
#define WINDOW_FULLSCREEN_STYLE WS_CLIPCHILDREN | WS_POPUP
#define KGE_WND_CLASS_NAME L"KiwanoAppWnd"
namespace kiwano
{
namespace
{
MONITORINFOEX GetMoniterInfoEx(HWND hwnd);
2019-10-12 11:26:41 +08:00
void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_width, uint32_t* win_height);
2019-08-14 21:52:49 +08:00
2019-09-29 22:23:13 +08:00
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name);
2019-08-14 21:52:49 +08:00
void RestoreResolution(WCHAR* device_name);
}
2019-10-12 11:26:41 +08:00
WindowConfig::WindowConfig(String const& title, uint32_t width, uint32_t height, uint32_t icon, bool resizable, bool fullscreen)
2019-08-23 13:00:43 +08:00
: title(title)
, width(width)
, height(height)
, icon(icon)
, resizable(resizable)
, fullscreen(fullscreen)
{
}
2019-08-14 21:52:49 +08:00
Window::Window()
: handle_(nullptr)
, width_(0)
, height_(0)
, device_name_(nullptr)
, is_fullscreen_(false)
2019-08-20 23:51:12 +08:00
, resizable_(false)
2019-08-21 16:33:41 +08:00
, mouse_cursor_(CursorType::Arrow)
2019-08-14 21:52:49 +08:00
{
}
Window::~Window()
{
}
2020-01-16 18:33:42 +08:00
void Window::Init(WindowConfig const& config)
2019-08-14 21:52:49 +08:00
{
HINSTANCE hinst = GetModuleHandleW(nullptr);
WNDCLASSEX wcex = { 0 };
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.lpszClassName = KGE_WND_CLASS_NAME;
wcex.style = CS_HREDRAW | CS_VREDRAW /* | CS_DBLCLKS */;
2020-01-16 18:33:42 +08:00
wcex.lpfnWndProc = Window::WndProc;
2019-08-14 21:52:49 +08:00
wcex.hIcon = nullptr;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = sizeof(LONG_PTR);
wcex.hInstance = hinst;
2020-01-16 18:33:42 +08:00
wcex.hbrBackground = (HBRUSH)(::GetStockObject(BLACK_BRUSH));
2019-08-14 21:52:49 +08:00
wcex.lpszMenuName = nullptr;
2019-08-20 23:51:12 +08:00
wcex.hCursor = ::LoadCursorW(hinst, IDC_ARROW);
2019-08-14 21:52:49 +08:00
2019-08-23 13:00:43 +08:00
if (config.icon)
2019-08-14 21:52:49 +08:00
{
2019-08-23 13:00:43 +08:00
wcex.hIcon = (HICON)::LoadImageW(hinst, MAKEINTRESOURCE(config.icon), IMAGE_ICON, 0, 0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE);
2019-08-14 21:52:49 +08:00
}
::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
2019-09-29 22:23:13 +08:00
int len = lstrlenW(monitor_info_ex.szDevice);
2019-10-12 11:26:41 +08:00
device_name_ = new wchar_t[len + 1];
2019-08-14 21:52:49 +08:00
lstrcpyW(device_name_, monitor_info_ex.szDevice);
2019-10-12 11:26:41 +08:00
uint32_t width = config.width;
uint32_t height = config.height;
2019-09-29 22:23:13 +08:00
int left = -1;
int top = -1;
2019-08-14 21:52:49 +08:00
2019-08-23 13:00:43 +08:00
resizable_ = config.resizable;
is_fullscreen_ = config.fullscreen;
2019-08-14 21:52:49 +08:00
if (is_fullscreen_)
{
top = monitor_info_ex.rcMonitor.top;
left = monitor_info_ex.rcMonitor.left;
2019-10-12 11:26:41 +08:00
if (width > static_cast<uint32_t>(monitor_info_ex.rcWork.right - left))
width = static_cast<uint32_t>(monitor_info_ex.rcWork.right - left);
2019-08-14 21:52:49 +08:00
2019-10-12 11:26:41 +08:00
if (height > static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top))
height = static_cast<uint32_t>(monitor_info_ex.rcWork.bottom - top);
2019-08-14 21:52:49 +08:00
}
else
{
2019-10-12 11:26:41 +08:00
uint32_t screenw = monitor_info_ex.rcWork.right - monitor_info_ex.rcWork.left;
uint32_t screenh = monitor_info_ex.rcWork.bottom - monitor_info_ex.rcWork.top;
2019-08-14 21:52:49 +08:00
2019-10-12 11:26:41 +08:00
uint32_t win_width, win_height;
2019-12-31 10:37:29 +08:00
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
2019-08-14 21:52:49 +08:00
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;
}
handle_ = ::CreateWindowExW(
is_fullscreen_ ? WS_EX_TOPMOST : 0,
KGE_WND_CLASS_NAME,
2019-08-23 13:00:43 +08:00
config.title.c_str(),
2019-08-14 21:52:49 +08:00
GetWindowStyle(),
left,
top,
width,
height,
nullptr,
nullptr,
hinst,
nullptr
);
if (handle_ == nullptr)
{
::UnregisterClass(KGE_WND_CLASS_NAME, hinst);
2019-12-30 14:24:29 +08:00
win32::ThrowIfFailed(HRESULT_FROM_WIN32(GetLastError()));
2020-01-16 18:33:42 +08:00
return;
2019-08-14 21:52:49 +08:00
}
2020-01-16 18:33:42 +08:00
width_ = width;
height_ = height;
// disable imm
::ImmAssociateContext(handle_, nullptr);
// use Application instance in message loop
::SetWindowLongPtr(handle_, GWLP_USERDATA, LONG_PTR(this));
2019-08-14 21:52:49 +08:00
::ShowWindow(handle_, SW_SHOWNORMAL);
::UpdateWindow(handle_);
if (is_fullscreen_)
{
ChangeFullScreenResolution(width_, height_, device_name_);
}
}
2020-01-16 18:33:42 +08:00
EventPtr Window::PollEvent()
2019-10-12 08:54:10 +08:00
{
2020-01-16 18:33:42 +08:00
MSG msg;
while (::PeekMessageW(&msg, nullptr, 0, 0, PM_REMOVE))
2019-10-12 08:54:10 +08:00
{
::TranslateMessage(&msg);
::DispatchMessageW(&msg);
}
2020-01-16 18:33:42 +08:00
EventPtr evt;
if (!event_queue_.empty())
{
evt = event_queue_.front();
event_queue_.pop();
}
return evt;
2019-10-12 08:54:10 +08:00
}
2019-08-14 21:52:49 +08:00
String Window::GetTitle() const
{
if (handle_)
{
2019-09-29 22:23:13 +08:00
wchar_t title[256];
2019-08-14 21:52:49 +08:00
::GetWindowTextW(handle_, title, 256);
return title;
}
return String();
}
void Window::SetTitle(String const& title)
{
if (handle_)
::SetWindowTextW(handle_, title.c_str());
}
Size Window::GetSize() const
{
return Size{
2019-09-29 22:23:13 +08:00
static_cast<float>(width_),
static_cast<float>(height_)
2019-08-14 21:52:49 +08:00
};
}
2019-09-29 22:23:13 +08:00
float Window::GetWidth() const
2019-08-14 21:52:49 +08:00
{
2019-09-29 22:23:13 +08:00
return static_cast<float>(width_);
2019-08-14 21:52:49 +08:00
}
2019-09-29 22:23:13 +08:00
float Window::GetHeight() const
2019-08-14 21:52:49 +08:00
{
2019-09-29 22:23:13 +08:00
return static_cast<float>(height_);
2019-08-14 21:52:49 +08:00
}
2019-10-12 11:26:41 +08:00
void Window::SetIcon(uint32_t icon_resource)
2019-08-14 21:52:49 +08:00
{
if (handle_)
{
HINSTANCE hinstance = GetModuleHandle(nullptr);
2019-08-21 16:33:41 +08:00
HICON icon = (HICON)::LoadImageW(
2019-08-14 21:52:49 +08:00
hinstance,
2019-08-19 09:28:59 +08:00
MAKEINTRESOURCE(icon_resource),
2019-08-14 21:52:49 +08:00
IMAGE_ICON,
0,
0,
LR_DEFAULTCOLOR | LR_CREATEDIBSECTION | LR_DEFAULTSIZE
);
::SendMessage(handle_, WM_SETICON, ICON_BIG, (LPARAM)icon);
::SendMessage(handle_, WM_SETICON, ICON_SMALL, (LPARAM)icon);
}
}
2019-09-29 22:23:13 +08:00
void Window::Resize(int width, int height)
2019-08-14 21:52:49 +08:00
{
if (handle_ && !is_fullscreen_)
{
2019-09-29 22:23:13 +08:00
RECT rc = { 0, 0, int(width), int(height) };
2019-08-14 21:52:49 +08:00
::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);
}
}
2019-09-29 22:23:13 +08:00
void Window::SetFullscreen(bool fullscreen, int width, int height)
2019-08-14 21:52:49 +08:00
{
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_);
2019-10-12 11:26:41 +08:00
uint32_t screenw = info.rcWork.right - info.rcWork.left;
uint32_t screenh = info.rcWork.bottom - info.rcWork.top;
2019-08-14 21:52:49 +08:00
2019-10-12 11:26:41 +08:00
uint32_t win_width, win_height;
2019-08-14 21:52:49 +08:00
AdjustWindow(width, height, GetWindowStyle(), &win_width, &win_height);
2019-09-29 22:23:13 +08:00
int left = screenw > win_width ? ((screenw - win_width) / 2) : 0;
int top = screenh > win_height ? ((screenh - win_height) / 2) : 0;
2019-08-14 21:52:49 +08:00
::SetWindowLongPtr(handle_, GWL_STYLE, GetWindowStyle());
::SetWindowPos(handle_, HWND_NOTOPMOST, left, top, win_width, win_height, SWP_DRAWFRAME | SWP_FRAMECHANGED);
2020-01-16 18:33:42 +08:00
// Update window rect
RECT rc;
::GetClientRect(handle_, &rc);
width_ = static_cast<uint32_t>(rc.right - rc.left);
height_ = static_cast<uint32_t>(rc.bottom - rc.top);
2019-08-14 21:52:49 +08:00
}
::ShowWindow(handle_, SW_SHOWNORMAL);
}
}
2019-08-21 16:33:41 +08:00
void Window::SetCursor(CursorType cursor)
2019-08-14 21:52:49 +08:00
{
2019-08-20 23:51:12 +08:00
mouse_cursor_ = cursor;
2019-08-14 21:52:49 +08:00
}
2020-01-16 18:33:42 +08:00
WindowHandle Window::GetHandle() const
2019-08-14 21:52:49 +08:00
{
return handle_;
}
2020-01-16 18:33:42 +08:00
bool Window::ShouldClose()
2019-08-14 21:52:49 +08:00
{
2020-01-16 18:33:42 +08:00
return handle_ == nullptr;
2019-08-14 21:52:49 +08:00
}
2020-01-16 18:33:42 +08:00
void Window::PushEvent(EventPtr evt)
2019-08-14 21:52:49 +08:00
{
2020-01-16 18:33:42 +08:00
event_queue_.push(evt);
}
void Window::Destroy()
{
if (is_fullscreen_)
RestoreResolution(device_name_);
if (device_name_)
{
delete[] device_name_;
device_name_ = nullptr;
}
2019-08-14 21:52:49 +08:00
2020-01-16 18:33:42 +08:00
if (handle_)
{
::DestroyWindow(handle_);
handle_ = nullptr;
}
}
2019-08-14 21:52:49 +08:00
2020-01-16 18:33:42 +08:00
#if defined(KGE_WIN32)
DWORD Window::GetWindowStyle() const
{
return is_fullscreen_ ? (WINDOW_FULLSCREEN_STYLE) : (resizable_ ? (WINDOW_RESIZABLE_STYLE) : (WINDOW_FIXED_STYLE));
2019-08-14 21:52:49 +08:00
}
2019-08-20 23:51:12 +08:00
void Window::UpdateCursor()
{
LPTSTR win32_cursor = IDC_ARROW;
switch (mouse_cursor_)
{
2019-08-21 16:33:41 +08:00
case CursorType::Arrow: win32_cursor = IDC_ARROW; break;
case CursorType::TextInput: win32_cursor = IDC_IBEAM; break;
case CursorType::SizeAll: win32_cursor = IDC_SIZEALL; break;
case CursorType::SizeWE: win32_cursor = IDC_SIZEWE; break;
case CursorType::SizeNS: win32_cursor = IDC_SIZENS; break;
case CursorType::SizeNESW: win32_cursor = IDC_SIZENESW; break;
case CursorType::SizeNWSE: win32_cursor = IDC_SIZENWSE; break;
case CursorType::Hand: win32_cursor = IDC_HAND; break;
2019-08-20 23:51:12 +08:00
}
::SetCursor(::LoadCursorW(nullptr, win32_cursor));
}
2019-08-14 21:52:49 +08:00
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);
}
}
}
2020-01-16 18:33:42 +08:00
LRESULT CALLBACK Window::WndProc(HWND hwnd, UINT32 msg, WPARAM wparam, LPARAM lparam)
2019-12-17 20:47:55 +08:00
{
2020-01-16 18:33:42 +08:00
Window* window = reinterpret_cast<Window*>(static_cast<LONG_PTR>(::GetWindowLongPtrW(hwnd, GWLP_USERDATA)));
if (window == nullptr)
{
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
}
2019-12-17 20:47:55 +08:00
2020-01-16 18:33:42 +08:00
switch (msg)
2019-12-17 20:47:55 +08:00
{
2020-01-16 18:33:42 +08:00
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
{
KeyDownEventPtr evt = new KeyDownEvent;
evt->code = static_cast<int>(wparam);
window->PushEvent(evt);
2019-12-17 20:47:55 +08:00
}
2020-01-16 18:33:42 +08:00
break;
2019-12-17 20:47:55 +08:00
2020-01-16 18:33:42 +08:00
case WM_KEYUP:
case WM_SYSKEYUP:
2019-12-17 20:47:55 +08:00
{
2020-01-16 18:33:42 +08:00
KeyUpEventPtr evt = new KeyUpEvent;
evt->code = static_cast<int>(wparam);
window->PushEvent(evt);
2019-12-17 20:47:55 +08:00
}
2020-01-16 18:33:42 +08:00
break;
case WM_CHAR:
{
KeyCharEventPtr evt = new KeyCharEvent;
evt->value = static_cast<char>(wparam);
window->PushEvent(evt);
}
break;
case WM_LBUTTONDOWN: case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN: case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN: case WM_MBUTTONDBLCLK:
{
MouseDownEventPtr evt = new MouseDownEvent;
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
if (msg == WM_LBUTTONDOWN || msg == WM_LBUTTONDBLCLK) { evt->button = MouseButton::Left; }
else if (msg == WM_RBUTTONDOWN || msg == WM_RBUTTONDBLCLK) { evt->button = MouseButton::Right; }
else if (msg == WM_MBUTTONDOWN || msg == WM_MBUTTONDBLCLK) { evt->button = MouseButton::Middle; }
window->PushEvent(evt);
}
break;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
{
MouseUpEventPtr evt = new MouseUpEvent;
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
if (msg == WM_LBUTTONUP) { evt->button = MouseButton::Left; }
else if (msg == WM_RBUTTONUP) { evt->button = MouseButton::Right; }
else if (msg == WM_MBUTTONUP) { evt->button = MouseButton::Middle; }
window->PushEvent(evt);
}
break;
case WM_MOUSEMOVE:
{
MouseMoveEventPtr evt = new MouseMoveEvent;
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
window->PushEvent(evt);
}
break;
case WM_MOUSEWHEEL:
{
MouseWheelEventPtr evt = new MouseWheelEvent;
evt->pos = Point(((float)(int)(short)LOWORD(lparam)), ((float)(int)(short)HIWORD(lparam)));
evt->wheel = GET_WHEEL_DELTA_WPARAM(wparam) / (float)WHEEL_DELTA;
window->PushEvent(evt);
}
break;
case WM_SIZE:
{
if (SIZE_MAXHIDE == wparam || SIZE_MINIMIZED == wparam)
{
KGE_SYS_LOG(L"Window minimized");
}
else
{
// KGE_SYS_LOG(L"Window resized");
window->width_ = ((uint32_t)(short)LOWORD(lparam));
window->height_ = ((uint32_t)(short)HIWORD(lparam));
WindowResizedEventPtr evt = new WindowResizedEvent;
evt->width = window->width_;
evt->height = window->height_;
window->PushEvent(evt);
}
}
break;
case WM_MOVE:
{
int x = ((int)(short)LOWORD(lparam));
int y = ((int)(short)HIWORD(lparam));
WindowMovedEventPtr evt = new WindowMovedEvent;
evt->x = x;
evt->y = y;
window->PushEvent(evt);
}
break;
case WM_ACTIVATE:
{
bool active = (LOWORD(wparam) != WA_INACTIVE);
window->SetActive(active);
WindowFocusChangedEventPtr evt = new WindowFocusChangedEvent;
evt->focus = active;
window->PushEvent(evt);
}
break;
case WM_SETTEXT:
{
KGE_SYS_LOG(L"Window title changed");
WindowTitleChangedEventPtr evt = new WindowTitleChangedEvent;
evt->title.assign(reinterpret_cast<const wchar_t*>(lparam));
window->PushEvent(evt);
}
break;
case WM_SETICON:
{
KGE_SYS_LOG(L"Window icon changed");
}
break;
case WM_DISPLAYCHANGE:
{
KGE_SYS_LOG(L"The display resolution has changed");
::InvalidateRect(hwnd, nullptr, FALSE);
}
break;
case WM_SETCURSOR:
{
window->UpdateCursor();
}
break;
case WM_CLOSE:
{
KGE_SYS_LOG(L"Window is closing");
WindowClosedEventPtr evt = new WindowClosedEvent;
window->PushEvent(evt);
window->Destroy();
}
break;
case WM_DESTROY:
{
KGE_SYS_LOG(L"Window was destroyed");
::PostQuitMessage(0);
return 0;
}
break;
}
return ::DefWindowProcW(hwnd, msg, wparam, lparam);
2019-12-17 20:47:55 +08:00
}
2019-08-14 21:52:49 +08:00
namespace
{
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;
}
2019-10-12 11:26:41 +08:00
void AdjustWindow(uint32_t width, uint32_t height, DWORD style, uint32_t* win_width, uint32_t* win_height)
2019-08-14 21:52:49 +08:00
{
RECT rc;
2019-09-29 22:23:13 +08:00
::SetRect(&rc, 0, 0, (int)width, (int)height);
2019-08-14 21:52:49 +08:00
::AdjustWindowRect(&rc, style, false);
*win_width = rc.right - rc.left;
*win_height = rc.bottom - rc.top;
MONITORINFOEX info = GetMoniterInfoEx(NULL);
2019-10-12 11:26:41 +08:00
uint32_t screenw = info.rcWork.right - info.rcWork.left;
uint32_t screenh = info.rcWork.bottom - info.rcWork.top;
2019-08-14 21:52:49 +08:00
if (*win_width > screenw)
*win_width = screenw;
if (*win_height > screenh)
*win_height = screenh;
}
2019-09-29 22:23:13 +08:00
void ChangeFullScreenResolution(int width, int height, WCHAR* device_name)
2019-08-14 21:52:49 +08:00
{
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)
2019-12-17 20:47:55 +08:00
KGE_ERROR(L"ChangeDisplaySettings failed");
2019-08-14 21:52:49 +08:00
}
void RestoreResolution(WCHAR* device_name)
{
::ChangeDisplaySettingsExW(device_name, NULL, NULL, 0, NULL);
}
}
2019-08-23 13:00:43 +08:00
2020-01-16 18:33:42 +08:00
#endif
2019-08-14 21:52:49 +08:00
}