834 lines
19 KiB
C++
834 lines
19 KiB
C++
#include "ehs/io/Window_W32.h"
|
|
#include "ehs/io/hid/Keyboard.h"
|
|
#include "ehs/io/hid/Mouse.h"
|
|
#include "ehs/system/Thread.h"
|
|
|
|
#include <hidusage.h>
|
|
|
|
namespace ehs
|
|
{
|
|
Array<Window*> Window::windows;
|
|
|
|
LRESULT Window::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
Window* win = nullptr;
|
|
for (UInt_64 i = 0; i < windows.Size(); ++i)
|
|
{
|
|
if (hWnd == windows[i]->hdl)
|
|
win = windows[i];
|
|
}
|
|
|
|
if (uMsg == WM_DESTROY)
|
|
{
|
|
PostQuitMessage(0);
|
|
return 0;
|
|
}
|
|
|
|
if (!win)
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
|
|
if (uMsg == WM_CLOSE)
|
|
{
|
|
for (UInt_64 i = 0; i < windows.Size(); ++i)
|
|
{
|
|
if (windows[i]->hdl != hWnd)
|
|
continue;
|
|
|
|
if (windows.Size() > 1)
|
|
windows.Swap(i, windows.Size() - 1);
|
|
|
|
windows.Pop();
|
|
|
|
break;
|
|
}
|
|
|
|
DestroyWindow(hWnd);
|
|
win->hdl = nullptr;
|
|
win->Close();
|
|
|
|
return 0;
|
|
|
|
//return DefWindowProcW(hWnd, WM_QUIT, 0, lParam);
|
|
}
|
|
else if (uMsg == WM_SIZE)
|
|
{
|
|
Vec2<UInt_16> newSize;
|
|
newSize[0] = static_cast<UInt_16>(lParam);
|
|
newSize[1] = static_cast<UInt_16>(lParam >> 16);
|
|
|
|
win->OnResized(newSize);
|
|
}
|
|
else if (uMsg == WM_HIDE)
|
|
{
|
|
ShowWindow(hWnd, SW_HIDE);
|
|
}
|
|
else if (uMsg == WM_SHOW)
|
|
{
|
|
ShowWindow(hWnd, SW_SHOW);
|
|
}
|
|
else if (uMsg == WM_HIDE_CURSOR)
|
|
{
|
|
while (::ShowCursor(false) >= 0);
|
|
}
|
|
else if (uMsg == WM_SHOW_CURSOR)
|
|
{
|
|
while (::ShowCursor(true) < 0);
|
|
}
|
|
else if (uMsg == WM_PAINT)
|
|
{
|
|
PAINTSTRUCT ps;
|
|
HDC hdc = BeginPaint(hWnd, &ps);
|
|
|
|
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW));
|
|
|
|
EndPaint(hWnd, &ps);
|
|
}
|
|
else if (win->HasFocus() && uMsg == WM_INPUT)
|
|
{
|
|
UINT dwSize = 0;
|
|
|
|
GetRawInputData((HRAWINPUT)lParam, RID_INPUT, nullptr, &dwSize, sizeof(RAWINPUTHEADER));
|
|
|
|
if (dwSize)
|
|
{
|
|
Byte* data = new Byte[dwSize];
|
|
|
|
if (GetRawInputData((HRAWINPUT)lParam, RID_INPUT, data, &dwSize, sizeof(RAWINPUTHEADER)) != dwSize)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Getting raw input returned incorrect size.");
|
|
delete[] data;
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
RAWINPUT* raw = (RAWINPUT*)data;
|
|
|
|
if (raw->header.dwType == RIM_TYPEKEYBOARD)
|
|
{
|
|
Keyboard* keyboard = (Keyboard*)win->ih.GetDevice((UInt_64)raw->header.hDevice);
|
|
if (!keyboard)
|
|
{
|
|
UInt_32 bufferSize;
|
|
GetRawInputDeviceInfoW(raw->header.hDevice, RIDI_DEVICENAME, nullptr, &bufferSize);
|
|
|
|
Char_16* deviceName = new Char_16[bufferSize];
|
|
|
|
if (GetRawInputDeviceInfoW(raw->header.hDevice, RIDI_DEVICENAME, deviceName, &bufferSize) < 0)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve device name.");
|
|
return 0;
|
|
}
|
|
|
|
keyboard = new Keyboard(UTF::To_8(deviceName, (UInt_64)bufferSize), (UInt_64)raw->header.hDevice);
|
|
win->ih.AddDevice(keyboard);
|
|
}
|
|
|
|
const Button button = Keyboard::TranslateScanCode(raw->data.keyboard.MakeCode);
|
|
|
|
if (raw->data.keyboard.Message == WM_KEYDOWN || raw->data.keyboard.Message == WM_SYSKEYDOWN)
|
|
keyboard->ButtonDown(button);
|
|
else if (raw->data.keyboard.Message == WM_KEYUP || raw->data.keyboard.Message == WM_SYSKEYUP)
|
|
keyboard->ButtonUp(button);
|
|
}
|
|
else if (raw->header.dwType == RIM_TYPEMOUSE)
|
|
{
|
|
Mouse* mouse = (Mouse*)win->ih.GetDevice((UInt_64)raw->header.hDevice);
|
|
if (!mouse)
|
|
{
|
|
UInt_32 bufferSize;
|
|
GetRawInputDeviceInfoW(raw->header.hDevice, RIDI_DEVICENAME, nullptr, &bufferSize);
|
|
|
|
Char_16* deviceName = new Char_16[bufferSize];
|
|
|
|
if (GetRawInputDeviceInfoW(raw->header.hDevice, RIDI_DEVICENAME, deviceName, &bufferSize) < 0)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve device name.");
|
|
return 0;
|
|
}
|
|
|
|
mouse = new Mouse(UTF::To_8(deviceName, (UInt_64)bufferSize), (UInt_64)raw->header.hDevice);
|
|
win->ih.AddDevice(mouse);
|
|
}
|
|
|
|
mouse->SetDelta({raw->data.mouse.lLastX, raw->data.mouse.lLastY});
|
|
|
|
UInt_16 code = raw->data.mouse.usButtonFlags;
|
|
|
|
if (code == RI_MOUSE_LEFT_BUTTON_DOWN)
|
|
mouse->ButtonDown(Mouse::LMB);
|
|
else if (code == RI_MOUSE_LEFT_BUTTON_UP)
|
|
mouse->ButtonUp(Mouse::LMB);
|
|
else if (code == RI_MOUSE_RIGHT_BUTTON_DOWN)
|
|
mouse->ButtonDown(Mouse::RMB);
|
|
else if (code == RI_MOUSE_RIGHT_BUTTON_UP)
|
|
mouse->ButtonUp(Mouse::RMB);
|
|
else if (code == RI_MOUSE_MIDDLE_BUTTON_DOWN)
|
|
mouse->ButtonDown(Mouse::MMB);
|
|
else if (code == RI_MOUSE_MIDDLE_BUTTON_UP)
|
|
mouse->ButtonUp(Mouse::MMB);
|
|
else if (code == RI_MOUSE_BUTTON_4_DOWN)
|
|
mouse->ButtonDown(Mouse::Four);
|
|
else if (code == RI_MOUSE_BUTTON_4_UP)
|
|
mouse->ButtonUp(Mouse::Four);
|
|
else if (code == RI_MOUSE_BUTTON_5_DOWN)
|
|
mouse->ButtonDown(Mouse::Five);
|
|
else if (code == RI_MOUSE_BUTTON_5_UP)
|
|
mouse->ButtonUp(Mouse::Five);
|
|
else if (code == RI_MOUSE_WHEEL)
|
|
{
|
|
if (raw->data.mouse.usButtonData < 0)
|
|
mouse->ButtonDown(Mouse::ScrollDown);
|
|
else if (raw->data.mouse.usButtonData > 0)
|
|
mouse->ButtonDown(Mouse::ScrollUp);
|
|
}
|
|
else if (code == RI_MOUSE_HWHEEL)
|
|
{
|
|
if (raw->data.mouse.usButtonData < 0)
|
|
mouse->ButtonDown(Mouse::ScrollLeft);
|
|
else if (raw->data.mouse.usButtonData > 0)
|
|
mouse->ButtonDown(Mouse::ScrollRight);
|
|
}
|
|
}
|
|
|
|
delete[] data;
|
|
}
|
|
}
|
|
else if (uMsg == WM_KILLFOCUS)
|
|
{
|
|
win->focused = false;
|
|
|
|
if (!win->cursorVisible)
|
|
{
|
|
win->SendMsg(WM_SHOW_CURSOR, 0, 0);
|
|
}
|
|
|
|
if (win->cursorConstrained)
|
|
{
|
|
if (!ClipCursor(nullptr))
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to free cursor after losing focus with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
}
|
|
|
|
win->ih.ResetAllStates();
|
|
}
|
|
else if (uMsg == WM_SETFOCUS)
|
|
{
|
|
win->focused = true;
|
|
|
|
if (!win->cursorVisible)
|
|
win->SendMsg(WM_HIDE_CURSOR, 0, 0);
|
|
|
|
if (win->cursorConstrained)
|
|
{
|
|
RECT client = {};
|
|
|
|
if (!GetClientRect(win->GetHdl(), &client))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve client scale with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
POINT pos = {};
|
|
|
|
if (!ClientToScreen(win->GetHdl(), &pos))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve client's absolute position with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
client.left = pos.x;
|
|
client.top = pos.y;
|
|
|
|
POINT scale = {client.right, client.bottom};
|
|
|
|
if (!ClientToScreen(win->GetHdl(), &scale))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 2, "Failed to retrieve client's absolute scale with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
client.right = scale.x;
|
|
client.bottom = scale.y;
|
|
|
|
if (!ClipCursor(&client))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 3, "Failed to confine cursor with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
}
|
|
}
|
|
else if (uMsg == WM_MOUSEMOVE)
|
|
{
|
|
win->cursorPos.x = ((SInt_16*)&lParam)[0];
|
|
win->cursorPos.y = ((SInt_16*)&lParam)[1];
|
|
}
|
|
|
|
return DefWindowProcW(hWnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
Window::~Window()
|
|
{
|
|
if (!created)
|
|
return;
|
|
|
|
SendMsg(WM_CLOSE, 0, 0);
|
|
}
|
|
|
|
Window::Window()
|
|
: owner(0), instance(nullptr), hdl(nullptr)
|
|
{
|
|
}
|
|
|
|
Window::Window(const Window& win)
|
|
: BaseWindow(win), owner(0), instance(nullptr), hdl(nullptr)
|
|
{
|
|
}
|
|
|
|
Window& Window::operator=(const Window& win)
|
|
{
|
|
if (&win == this)
|
|
return *this;
|
|
|
|
BaseWindow::operator=(win);
|
|
|
|
owner = 0;
|
|
created = false;
|
|
focused = false;
|
|
instance = nullptr;
|
|
hdl = nullptr;
|
|
|
|
return* this;
|
|
}
|
|
|
|
bool Window::Poll()
|
|
{
|
|
ih.Poll();
|
|
|
|
MSG msg = {};
|
|
|
|
while (PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE))
|
|
{
|
|
if (GetMessageW(&msg, nullptr, 0, 0))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessageW(&msg);
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
BaseWindow::Poll();
|
|
|
|
return true;
|
|
}
|
|
|
|
void Window::Create_32(const Str_32& title, const Vec2_s32& pos, const Vec2_u32 scale)
|
|
{
|
|
Create_16(UTF::To_16(title), pos, scale);
|
|
}
|
|
|
|
void Window::Create_16(const Str_16& title, const Vec2_s32& pos, const Vec2_u32 scale)
|
|
{
|
|
if (created)
|
|
return;
|
|
|
|
owner = Thread::GetCurrentId();
|
|
|
|
instance = GetModuleHandleW(nullptr);
|
|
|
|
WNDCLASSEXW wcex = {};
|
|
wcex.cbSize = sizeof(wcex);
|
|
wcex.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
|
|
wcex.lpfnWndProc = &Window::WndProc;
|
|
wcex.cbClsExtra = 0;
|
|
wcex.cbWndExtra = 0;
|
|
wcex.hInstance = instance;
|
|
wcex.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
|
|
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
|
wcex.hIconSm = LoadIcon(nullptr, IDI_WINLOGO);
|
|
wcex.hbrBackground = nullptr;
|
|
wcex.lpszMenuName = nullptr;
|
|
wcex.lpszClassName = title;
|
|
|
|
if (!RegisterClassExW(&wcex))
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to register window.");
|
|
|
|
hdl = CreateWindowExW(
|
|
0,
|
|
title,
|
|
title,
|
|
WS_OVERLAPPEDWINDOW,
|
|
pos.x, pos.y, scale.x, scale.y,
|
|
nullptr, nullptr,
|
|
instance,
|
|
nullptr
|
|
);
|
|
|
|
if (!hdl)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to create window.");
|
|
return;
|
|
}
|
|
|
|
RECT tmp = {
|
|
0,
|
|
0,
|
|
static_cast<LONG>(scale.x),
|
|
static_cast<LONG>(scale.y)
|
|
};
|
|
|
|
AdjustWindowRectEx(&tmp, WS_OVERLAPPEDWINDOW, false, 0);
|
|
|
|
SetWindowPos(hdl, nullptr, 0, 0, tmp.right - tmp.left, tmp.bottom - tmp.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
|
|
RAWINPUTDEVICE rid[2];
|
|
|
|
rid[0].usUsagePage = HID_USAGE_PAGE_GENERIC;
|
|
rid[0].usUsage = HID_USAGE_GENERIC_MOUSE;
|
|
rid[0].dwFlags = 0;
|
|
rid[0].hwndTarget = hdl;
|
|
|
|
rid[1].usUsagePage = HID_USAGE_PAGE_GENERIC;
|
|
rid[1].usUsage = HID_USAGE_GENERIC_KEYBOARD;
|
|
rid[1].dwFlags = 0;
|
|
rid[1].hwndTarget = hdl;
|
|
|
|
if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == false)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 2, "Failed to register raw input devices.");
|
|
|
|
return;
|
|
}
|
|
|
|
windows.Push(this);
|
|
|
|
created = true;
|
|
|
|
OnCreated();
|
|
}
|
|
|
|
void Window::Create_8(const Str_8& title, const Vec2_s32& pos, const Vec2_u32 scale)
|
|
{
|
|
Create_16(UTF::To_16(title), pos, scale);
|
|
}
|
|
|
|
void Window::Use(HWND windowHdl)
|
|
{
|
|
hdl = windowHdl;
|
|
}
|
|
|
|
void Window::Close()
|
|
{
|
|
if (hdl)
|
|
SendMsg(WM_CLOSE, 0, 0);
|
|
|
|
created = false;
|
|
}
|
|
|
|
void Window::Show()
|
|
{
|
|
SendMsg(WM_SHOW, 0, 0);
|
|
}
|
|
|
|
void Window::Hide()
|
|
{
|
|
SendMsg(WM_HIDE, 0, 0);
|
|
}
|
|
|
|
void Window::SetTitle_32(const Str_32& title)
|
|
{
|
|
if (!SetWindowTextW(hdl, UTF::To_16(title)))
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to set window title with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
}
|
|
|
|
Str_32 Window::GetTitle_32() const
|
|
{
|
|
int size = GetWindowTextLengthW(hdl);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
Char_16* buffer = new Char_16[size];
|
|
|
|
size = GetWindowTextW(hdl, buffer, size);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
return UTF::To_32(buffer, Str_16::Len(buffer));
|
|
}
|
|
|
|
void Window::SetTitle_16(const Str_16& title)
|
|
{
|
|
if (!SetWindowTextW(hdl, title))
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to set window title with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
}
|
|
|
|
Str_16 Window::GetTitle_16() const
|
|
{
|
|
int size = GetWindowTextLengthW(hdl);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
Char_16* buffer = new Char_16[size];
|
|
|
|
size = GetWindowTextW(hdl, buffer, size);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
return {buffer};
|
|
}
|
|
|
|
void Window::SetTitle_8(const Str_8& title)
|
|
{
|
|
if (!SetWindowTextW(hdl, UTF::To_16(title)))
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to set window title with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
}
|
|
|
|
Str_8 Window::GetTitle_8() const
|
|
{
|
|
int size = GetWindowTextLengthW(hdl);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
Char_16* buffer = new Char_16[size];
|
|
|
|
size = GetWindowTextW(hdl, buffer, size);
|
|
if (!size)
|
|
{
|
|
DWORD err = GetLastError();
|
|
if (err)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve the window's title length with error #" + Str_8::FromNum(err) + ".");
|
|
|
|
return {};
|
|
}
|
|
}
|
|
|
|
return UTF::To_8(buffer, Str_16::Len(buffer));
|
|
}
|
|
|
|
void Window::SetIcon(const Str_8& filePath)
|
|
{
|
|
Handle icon = LoadImageW(nullptr, UTF::To_16(filePath), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE);
|
|
if (!icon)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to load icon at file path, \"" + filePath + "\" with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
|
|
SendMsg(WM_SETICON, ICON_SMALL, (LPARAM)icon);
|
|
SendMsg(WM_SETICON, ICON_BIG, (LPARAM)icon);
|
|
}
|
|
|
|
HWND Window::GetHdl() const
|
|
{
|
|
return hdl;
|
|
}
|
|
|
|
HWND Window::GetAvailableHdl()
|
|
{
|
|
for (UInt_64 i = 0; i < windows.Size(); ++i)
|
|
if (windows[i])
|
|
return windows[i]->hdl;
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
HINSTANCE Window::GetInst() const
|
|
{
|
|
return instance;
|
|
}
|
|
|
|
void Window::ToggleEnabled(bool toggle)
|
|
{
|
|
if (!created)
|
|
return;
|
|
|
|
EnableWindow(hdl, toggle);
|
|
}
|
|
|
|
bool Window::IsEnabled()
|
|
{
|
|
if (!created)
|
|
return false;
|
|
|
|
return IsWindowEnabled(hdl);
|
|
}
|
|
|
|
void Window::SetPos(const Vec2_s32& newPos)
|
|
{
|
|
if (!created)
|
|
return;
|
|
|
|
SetWindowPos(hdl, nullptr, newPos.x, newPos.y, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
Vec2_s32 Window::GetPos() const
|
|
{
|
|
if (!created)
|
|
return {};
|
|
|
|
RECT tmp = {};
|
|
GetWindowRect(hdl, &tmp);
|
|
|
|
return {(Int_32)tmp.left, (Int_32)tmp.top};
|
|
}
|
|
|
|
void Window::OnResized(const Vec2<UInt_32>& newSize)
|
|
{
|
|
}
|
|
|
|
void Window::SetScale(const Vec2_u32& newScale)
|
|
{
|
|
if (!created)
|
|
return;
|
|
|
|
RECT rect = {
|
|
0,
|
|
0,
|
|
static_cast<LONG>(newScale[0]),
|
|
static_cast<LONG>(newScale[1])
|
|
};
|
|
|
|
DWORD exStyle = (DWORD)GetWindowLongPtr(hdl, GWL_EXSTYLE);
|
|
DWORD style = (DWORD)GetWindowLongPtr(hdl, GWL_STYLE);
|
|
|
|
AdjustWindowRectEx(&rect, style, false, exStyle);
|
|
|
|
SetWindowPos(hdl, nullptr, 0, 0, rect.right - rect.left, rect.bottom - rect.top, SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE);
|
|
}
|
|
|
|
Vec2_u32 Window::GetScale() const
|
|
{
|
|
if (!created)
|
|
return {};
|
|
|
|
RECT tmp = {};
|
|
GetClientRect(hdl, &tmp);
|
|
|
|
return {(UInt_32)(tmp.right - tmp.left), (UInt_32)(tmp.bottom - tmp.top)};
|
|
}
|
|
|
|
void Window::ShowCursor(bool toggle)
|
|
{
|
|
SendMsg(toggle ? WM_SHOW_CURSOR : WM_HIDE_CURSOR, 0, 0);
|
|
|
|
cursorVisible = toggle;
|
|
}
|
|
|
|
void Window::ConstrainCursor(const bool toggle)
|
|
{
|
|
if (toggle)
|
|
{
|
|
RECT client = {};
|
|
|
|
if (!GetClientRect(GetHdl(), &client))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to retrieve client scale with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
|
|
POINT pos = {};
|
|
|
|
if (!ClientToScreen(GetHdl(), &pos))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to retrieve client's absolute position with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
|
|
client.left = pos.x;
|
|
client.top = pos.y;
|
|
|
|
POINT scale = {client.right, client.bottom};
|
|
|
|
if (!ClientToScreen(GetHdl(), &scale))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 2, "Failed to retrieve client's absolute scale with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
|
|
client.right = scale.x;
|
|
client.bottom = scale.y;
|
|
|
|
if (!ClipCursor(&client))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 3, "Failed to confine cursor with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ClipCursor(nullptr);
|
|
}
|
|
|
|
cursorConstrained = toggle;
|
|
}
|
|
|
|
Serializer<UInt_64> Window::GetClipboard()
|
|
{
|
|
if (!OpenClipboard(hdl))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to open Clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return {};
|
|
}
|
|
|
|
HANDLE hData = GetClipboardData(CF_TEXT);
|
|
if (!hData)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to get clipboard handle with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
if (!CloseClipboard())
|
|
EHS_LOG_INT(LogType::ERR, 4, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return {};
|
|
}
|
|
|
|
Char_8* text = (Char_8 *)GlobalLock(hData);
|
|
if (!text)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 2, "Failed to get clipboard data with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return {};
|
|
}
|
|
|
|
Serializer<UInt_64> data(Endianness::LE, (Byte *)text, Str_8::Len(text));
|
|
|
|
if (!GlobalUnlock(hData))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 3, "Failed to free clipboard data with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return data;
|
|
}
|
|
|
|
if (!CloseClipboard())
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 4, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return data;
|
|
}
|
|
|
|
EHS_LOG_SUCCESS();
|
|
|
|
return data;
|
|
}
|
|
|
|
void Window::SetClipboard(Serializer<UInt_64> data)
|
|
{
|
|
if (!OpenClipboard(hdl))
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 0, "Failed to open Clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
return;
|
|
}
|
|
|
|
if (!EmptyClipboard())
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 1, "Failed to empty clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
if (!CloseClipboard())
|
|
EHS_LOG_INT(LogType::ERR, 6, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return;
|
|
}
|
|
|
|
HGLOBAL hGlob = GlobalAlloc(GMEM_MOVEABLE, data.Size());
|
|
if (!hGlob)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 2, "Failed to allocate clipboard data with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
if (!CloseClipboard())
|
|
EHS_LOG_INT(LogType::ERR, 6, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return;
|
|
}
|
|
|
|
Byte* result = (Byte *)GlobalLock(hGlob);
|
|
if (!result)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 3, "Failed to lock data with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
GlobalFree(hGlob);
|
|
|
|
if (!CloseClipboard())
|
|
EHS_LOG_INT(LogType::ERR, 6, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return;
|
|
}
|
|
|
|
Util::Copy(result, &data[0], data.Size());
|
|
|
|
GlobalUnlock(hGlob);
|
|
|
|
HANDLE hData = SetClipboardData(CF_TEXT, hGlob);
|
|
if (!hData)
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 5, "Failed to get clipboard handle with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
GlobalFree(hGlob);
|
|
|
|
if (!CloseClipboard())
|
|
EHS_LOG_INT(LogType::ERR, 6, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return;
|
|
}
|
|
|
|
if (!CloseClipboard())
|
|
{
|
|
EHS_LOG_INT(LogType::ERR, 6, "Failed to close clipboard with error #" + Str_8::FromNum(GetLastError()) + ".");
|
|
|
|
return;
|
|
}
|
|
|
|
EHS_LOG_SUCCESS();
|
|
}
|
|
|
|
void Window::SetCursorImg(CursorImg img)
|
|
{
|
|
}
|
|
|
|
void Window::SendMsg(const UINT msg, const WPARAM wParam, const LPARAM lParam)
|
|
{
|
|
if (!hdl)
|
|
return;
|
|
|
|
if (Thread::GetCurrentId() == owner)
|
|
PostMessageW(hdl, msg, wParam, lParam);
|
|
else
|
|
SendMessageW(hdl, msg, wParam, lParam);
|
|
}
|
|
} |