2024-07-13 22:55:36 -03:00
|
|
|
#include "xna/xna-dx.hpp"
|
2024-03-18 15:41:46 -03:00
|
|
|
|
|
|
|
namespace xna {
|
|
|
|
GameWindow::GameWindow() {
|
2024-07-30 15:29:58 -03:00
|
|
|
impl = unew<PlatformImplementation>(this);
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
impl->_hInstance = GetModuleHandle(NULL);
|
|
|
|
impl->_windowIcon = LoadIcon(NULL, IDI_APPLICATION);
|
|
|
|
impl->_windowCursor = LoadCursor(NULL, IDC_ARROW);
|
|
|
|
impl->_windowStyle = static_cast<int>(GameWindowMode::Windowed);
|
|
|
|
impl->_windowCenterX = impl->_windowWidth / 2.0F;
|
2024-07-30 15:29:58 -03:00
|
|
|
impl->_windowCenterY = impl->_windowHeight / 2.0F;
|
|
|
|
impl->_windowWidth = GameWindow::DefaultClientWidth;
|
|
|
|
impl->_windowHeight = GameWindow::DefaultClientHeight;
|
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
void GameWindow::PlatformImplementation::Position(int width, int height, bool update) {
|
2024-03-30 14:25:08 -03:00
|
|
|
_windowPosX = width;
|
|
|
|
_windowPosY = height;
|
|
|
|
setCenter();
|
|
|
|
|
|
|
|
if(update) Update();
|
|
|
|
}
|
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
void GameWindow::PlatformImplementation::Size(int width, int height, bool update) {
|
2024-03-18 15:41:46 -03:00
|
|
|
_windowWidth = width;
|
|
|
|
_windowHeight = height;
|
|
|
|
setPosition();
|
2024-03-21 16:01:47 -03:00
|
|
|
setCenter();
|
2024-03-30 14:25:08 -03:00
|
|
|
|
|
|
|
if(update) Update();
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
|
|
|
|
2024-07-30 15:29:58 -03:00
|
|
|
void GameWindow::Title(String const& value) {
|
|
|
|
title = value;
|
2024-05-24 12:31:24 -03:00
|
|
|
impl->_windowTitle = title;
|
2024-03-21 16:01:47 -03:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
bool GameWindow::PlatformImplementation::Create() {
|
2024-03-18 15:41:46 -03:00
|
|
|
WNDCLASSEX wndClass{};
|
|
|
|
wndClass.cbSize = sizeof(WNDCLASSEX);
|
|
|
|
wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
|
|
|
|
wndClass.lpfnWndProc = WinProc;
|
|
|
|
wndClass.cbClsExtra = 0;
|
|
|
|
wndClass.cbWndExtra = 0;
|
|
|
|
wndClass.hInstance = _hInstance;
|
|
|
|
wndClass.hIcon = _windowIcon;
|
|
|
|
wndClass.hCursor = _windowCursor;
|
|
|
|
wndClass.hbrBackground = (HBRUSH)CreateSolidBrush(_windowColor);
|
|
|
|
wndClass.lpszMenuName = NULL;
|
|
|
|
wndClass.lpszClassName = "XnaGameWindow";
|
|
|
|
wndClass.hIconSm = _windowIcon;
|
|
|
|
|
|
|
|
if (!RegisterClassEx(&wndClass))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
_windowHandle = CreateWindowEx(
|
|
|
|
NULL,
|
|
|
|
"XnaGameWindow",
|
|
|
|
_windowTitle.c_str(),
|
|
|
|
_windowStyle,
|
|
|
|
_windowPosX, _windowPosY,
|
|
|
|
_windowWidth, _windowHeight,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
_hInstance,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
if (_windowStyle == static_cast<int>(GameWindowMode::Windowed)) {
|
|
|
|
RECT winRect = { 0, 0, _windowWidth, _windowHeight };
|
|
|
|
|
|
|
|
AdjustWindowRectEx(&winRect,
|
|
|
|
GetWindowStyle(_windowHandle),
|
|
|
|
GetMenu(_windowHandle) != NULL,
|
|
|
|
GetWindowExStyle(_windowHandle));
|
|
|
|
|
|
|
|
_windowPosX = GetSystemMetrics(SM_CXSCREEN) / 2 - (winRect.right - winRect.left) / 2;
|
|
|
|
_windowPosY = GetSystemMetrics(SM_CYSCREEN) / 2 - (winRect.bottom - winRect.top) / 2;
|
|
|
|
|
|
|
|
MoveWindow(
|
|
|
|
_windowHandle,
|
|
|
|
_windowPosX,
|
|
|
|
_windowPosY,
|
|
|
|
winRect.right - winRect.left,
|
|
|
|
winRect.bottom - winRect.top,
|
|
|
|
TRUE);
|
|
|
|
|
2024-07-31 16:30:47 -03:00
|
|
|
if (!_windowHandle)
|
|
|
|
return false;
|
2024-03-21 16:01:47 -03:00
|
|
|
}
|
|
|
|
|
2024-07-30 15:29:58 -03:00
|
|
|
|
|
|
|
//
|
|
|
|
// GameWindow
|
|
|
|
//
|
|
|
|
|
2024-07-31 16:30:47 -03:00
|
|
|
const auto handle = reinterpret_cast<intptr_t>(_windowHandle);
|
|
|
|
|
|
|
|
gameWindow->handle = handle;
|
2024-07-30 15:29:58 -03:00
|
|
|
gameWindow->title = _windowTitle;
|
|
|
|
gameWindow->clientBounds = { _windowPosX, _windowPosY, _windowWidth, _windowHeight };
|
|
|
|
gameWindow->currentOrientation = DisplayOrientation::Default;
|
|
|
|
|
|
|
|
auto screens = Screen::AllScreens();
|
|
|
|
|
|
|
|
if (screens.size() == 1)
|
|
|
|
gameWindow->screenDeviceName = screens[0]->DeviceName();
|
|
|
|
else {
|
|
|
|
for (size_t i = 0; i < screens.size(); ++i) {
|
|
|
|
const auto& screen = screens[i];
|
|
|
|
|
|
|
|
if (screen->Primary())
|
|
|
|
gameWindow->screenDeviceName = screen->DeviceName();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-03-21 16:01:47 -03:00
|
|
|
return true;
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
bool GameWindow::PlatformImplementation::Update() {
|
2024-03-30 14:25:08 -03:00
|
|
|
if (_windowStyle == static_cast<int>(GameWindowMode::Windowed)) {
|
|
|
|
RECT winRect = { 0, 0, _windowWidth, _windowHeight };
|
|
|
|
|
|
|
|
AdjustWindowRectEx(&winRect,
|
|
|
|
GetWindowStyle(_windowHandle),
|
|
|
|
GetMenu(_windowHandle) != NULL,
|
|
|
|
GetWindowExStyle(_windowHandle));
|
|
|
|
|
|
|
|
_windowPosX = GetSystemMetrics(SM_CXSCREEN) / 2 - (winRect.right - winRect.left) / 2;
|
|
|
|
_windowPosY = GetSystemMetrics(SM_CYSCREEN) / 2 - (winRect.bottom - winRect.top) / 2;
|
|
|
|
|
|
|
|
MoveWindow(
|
|
|
|
_windowHandle,
|
|
|
|
_windowPosX,
|
|
|
|
_windowPosY,
|
|
|
|
winRect.right - winRect.left,
|
|
|
|
winRect.bottom - winRect.top,
|
|
|
|
TRUE);
|
|
|
|
|
|
|
|
return _windowHandle ? true : false;
|
|
|
|
}
|
|
|
|
|
2024-07-30 15:29:58 -03:00
|
|
|
gameWindow->clientBounds = { _windowPosX, _windowPosY, _windowWidth, _windowHeight };
|
2024-03-18 15:41:46 -03:00
|
|
|
|
2024-07-30 15:29:58 -03:00
|
|
|
return true;
|
|
|
|
}
|
2024-05-24 12:31:24 -03:00
|
|
|
|
2024-07-30 15:29:58 -03:00
|
|
|
bool GameWindow::IsWindowMinimized() const {
|
|
|
|
return IsIconic(impl->_windowHandle);
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
|
|
|
|
2024-05-24 12:31:24 -03:00
|
|
|
LRESULT GameWindow::PlatformImplementation::WinProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
2024-03-18 15:41:46 -03:00
|
|
|
{
|
|
|
|
switch (msg) {
|
|
|
|
case WM_DESTROY:
|
|
|
|
PostQuitMessage(0);
|
|
|
|
return 0;
|
2024-04-16 16:13:36 -03:00
|
|
|
case WM_ACTIVATE:
|
|
|
|
case WM_ACTIVATEAPP:
|
2024-05-24 12:31:24 -03:00
|
|
|
if(Keyboard::impl) Keyboard::impl->ProcessMessage(msg, wParam, lParam);
|
|
|
|
if(Mouse::impl) Mouse::impl->ProcessMessage(msg, wParam, lParam);
|
2024-04-16 16:13:36 -03:00
|
|
|
break;
|
|
|
|
case WM_SYSKEYDOWN:
|
2024-05-21 17:24:43 -03:00
|
|
|
if (!(wParam == VK_RETURN && (lParam & 0x60000000) == 0x20000000)) {
|
2024-05-24 12:31:24 -03:00
|
|
|
if (Keyboard::impl) Keyboard::impl->ProcessMessage(msg, wParam, lParam);
|
2024-04-16 16:13:36 -03:00
|
|
|
}
|
|
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
|
|
case WM_KEYUP:
|
|
|
|
case WM_SYSKEYUP:
|
2024-05-24 12:31:24 -03:00
|
|
|
if (Keyboard::impl) Keyboard::impl->ProcessMessage(msg, wParam, lParam);
|
2024-04-16 16:13:36 -03:00
|
|
|
break;
|
2024-04-16 19:27:05 -03:00
|
|
|
|
|
|
|
case WM_INPUT:
|
|
|
|
case WM_MOUSEMOVE:
|
|
|
|
case WM_LBUTTONDOWN:
|
|
|
|
case WM_LBUTTONUP:
|
|
|
|
case WM_RBUTTONDOWN:
|
|
|
|
case WM_RBUTTONUP:
|
|
|
|
case WM_MBUTTONDOWN:
|
|
|
|
case WM_MBUTTONUP:
|
|
|
|
case WM_MOUSEWHEEL:
|
|
|
|
case WM_XBUTTONDOWN:
|
|
|
|
case WM_XBUTTONUP:
|
|
|
|
case WM_MOUSEHOVER:
|
2024-05-24 12:31:24 -03:00
|
|
|
if (Mouse::impl) Mouse::impl->ProcessMessage(msg, wParam, lParam);
|
2024-04-16 19:27:05 -03:00
|
|
|
break;
|
2024-04-24 10:11:53 -03:00
|
|
|
case WM_KILLFOCUS:
|
2024-05-24 12:31:24 -03:00
|
|
|
if (GamePad::impl) GamePad::impl->Suspend();
|
2024-04-24 10:11:53 -03:00
|
|
|
break;
|
|
|
|
case WM_SETFOCUS:
|
2024-05-24 12:31:24 -03:00
|
|
|
if (GamePad::impl) GamePad::impl->Resume();
|
2024-04-24 10:11:53 -03:00
|
|
|
break;
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|
|
|
|
return DefWindowProc(hWnd, msg, wParam, lParam);
|
|
|
|
}
|
2024-07-30 09:26:27 -03:00
|
|
|
|
|
|
|
uptr<Screen> GameWindow::ScreenFromAdapter(GraphicsAdapter const& adapter) {
|
|
|
|
auto screens = Screen::AllScreens();
|
|
|
|
|
|
|
|
for (size_t i = 0; i < screens.size(); ++i) {
|
|
|
|
auto& screen = screens[i];
|
|
|
|
|
|
|
|
if (screen->DeviceName() == adapter.DeviceName())
|
|
|
|
return std::move(screen);
|
2024-07-31 16:30:47 -03:00
|
|
|
}
|
2024-07-30 09:26:27 -03:00
|
|
|
|
|
|
|
return nullptr;
|
|
|
|
}
|
2024-07-30 09:41:31 -03:00
|
|
|
|
|
|
|
uptr<Screen> GameWindow::ScreenFromHandle(intptr_t windowHandle) {
|
2024-07-31 16:30:47 -03:00
|
|
|
const auto handle = reinterpret_cast<HWND>(windowHandle);
|
|
|
|
auto hMonitor = MonitorFromWindow(handle, MONITOR_DEFAULTTOPRIMARY);
|
2024-07-30 09:41:31 -03:00
|
|
|
|
|
|
|
if (!hMonitor)
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
MONITORINFOEX monitorInfo{};
|
|
|
|
monitorInfo.cbSize = sizeof(MONITORINFOEX);
|
|
|
|
GetMonitorInfo(hMonitor, &monitorInfo);
|
|
|
|
|
|
|
|
const auto hmonitor = reinterpret_cast<intptr_t>(hMonitor);
|
|
|
|
const auto primary = monitorInfo.dwFlags == MONITORINFOF_PRIMARY;
|
|
|
|
|
|
|
|
Rectangle bounds;
|
|
|
|
bounds.X = monitorInfo.rcMonitor.left;
|
|
|
|
bounds.Y = monitorInfo.rcMonitor.top;
|
|
|
|
bounds.Width = monitorInfo.rcMonitor.right - monitorInfo.rcMonitor.left;
|
|
|
|
bounds.Height = monitorInfo.rcMonitor.bottom - monitorInfo.rcMonitor.top;
|
|
|
|
|
|
|
|
Rectangle workingArea;
|
|
|
|
workingArea.X = monitorInfo.rcWork.left;
|
|
|
|
workingArea.Y = monitorInfo.rcWork.top;
|
|
|
|
workingArea.Width = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
|
|
|
|
workingArea.Height = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
|
|
|
|
|
|
|
|
const auto deviceName = String(monitorInfo.szDevice);
|
|
|
|
|
|
|
|
auto screen = unew<Screen>(
|
|
|
|
hmonitor,
|
|
|
|
primary,
|
|
|
|
bounds,
|
|
|
|
workingArea,
|
|
|
|
deviceName
|
|
|
|
);
|
|
|
|
|
|
|
|
return screen;
|
|
|
|
}
|
2024-07-30 15:29:58 -03:00
|
|
|
|
|
|
|
String GameWindow::ScreenDeviceName() const {
|
2024-07-31 17:07:06 -03:00
|
|
|
const auto screen = ScreenFromHandle(handle);
|
|
|
|
return screen->DeviceName();
|
2024-07-30 15:29:58 -03:00
|
|
|
}
|
2024-03-18 15:41:46 -03:00
|
|
|
}
|