VUI/Source/Platform/Windows/Window.cppm
2025-05-29 13:21:19 +02:00

160 lines
No EOL
4.2 KiB
C++

module;
#include <Windows.h>
#include <windowsx.h>
#include <stdexcept>
export module VUI:PlatformWindow;
import :Window;
import :Ref;
namespace VUI::Windowing {
const char *CLASS_NAME = "VUI";
bool s_windowInit = false;
struct Win32Window : Window {
Win32Window();
~Win32Window() override;
void pullEvents() override;
void close() override;
void resize(uint32_t width, uint32_t height) override;
void updateTitle(const std::string &title) override;
static LRESULT CALLBACK WindowProc(HWND, UINT uMsg, WPARAM, LPARAM);
protected:
void createWindow() override;
void handleEvent(HWND, UINT message, WPARAM, LPARAM);
private:
HWND m_Window{nullptr};
HINSTANCE m_Instance{nullptr};
friend Window;
};
export Ref<Window> CreateWindowRef() { return Ref<Window>(new Win32Window()); }
Win32Window::Win32Window() : Window() { m_Instance = GetModuleHandle(nullptr); }
Win32Window::~Win32Window() { DestroyWindow(m_Window); }
void Win32Window::pullEvents() {
MSG msg;
while (PeekMessage(&msg, m_Window, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
void Win32Window::close() {
CloseWindow(m_Window);
m_IsOpen = false;
}
void Win32Window::resize(uint32_t width, uint32_t height) {
m_Specification.width = width;
m_Specification.height = height;
SetWindowPos(m_Window, nullptr, static_cast<int>(m_WindowPosition.x),
static_cast<int>(m_WindowPosition.y),
static_cast<int>(m_Specification.width),
static_cast<int>(m_Specification.height), 0);
}
void Win32Window::updateTitle(const std::string &title) {
m_Specification.title = title;
SetWindowText(m_Window, title.c_str());
}
LRESULT CALLBACK Win32Window::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam,
LPARAM lParam) {
if (uMsg == WM_CREATE) {
auto *pCreate = reinterpret_cast<CREATESTRUCT *>(lParam);
SetWindowLongPtr(hwnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR>(
static_cast<Win32Window *>(pCreate->lpCreateParams)));
return TRUE;
}
auto impl =
reinterpret_cast<Win32Window *>(GetWindowLongPtr(hwnd, GWLP_USERDATA));
if (impl != nullptr) {
impl->handleEvent(hwnd, uMsg, wParam, lParam);
return DefWindowProcA(hwnd, uMsg, wParam, lParam);
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
void registerClass(HINSTANCE hInstance) {
WNDCLASS wc = {};
wc.lpfnWndProc = Win32Window::WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
}
void Win32Window::createWindow() {
if (!s_windowInit) {
registerClass(m_Instance);
s_windowInit = true;
}
m_Window = CreateWindowEx(0, CLASS_NAME, m_Specification.title.c_str(),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, nullptr, nullptr,
m_Instance, this);
m_IsOpen = m_Window != nullptr;
if (m_Window == nullptr) {
throw std::runtime_error("Failed to create window.");
}
resize(m_Specification.width, m_Specification.height);
ShowWindow(m_Window, SW_NORMAL);
}
void Win32Window::handleEvent(HWND, UINT message, WPARAM wParam,
LPARAM lParam) {
switch (message) {
case WM_MOVE: {
m_WindowPosition.x = LOWORD(lParam);
m_WindowPosition.y = HIWORD(lParam);
break;
}
case WM_SIZE: {
m_Specification.width = LOWORD(lParam);
m_Specification.height = HIWORD(lParam);
break;
}
case WM_KEYDOWN:
case WM_KEYUP: {
uint32_t scancode = (HIWORD(lParam) & (KF_EXTENDED | 0xff));
if (scancode == 0)
scancode = MapVirtualKeyW(static_cast<UINT>(wParam), MAPVK_VK_TO_VSC);
switch (scancode) {
case 0x54: scancode = 0x137; break;
case 0x146: scancode = 0x45; break;
case 0x136: scancode = 0x36; break;
default: break;
}
UpdateKey(scancode, message == WM_KEYDOWN);
break;
}
case WM_MOUSEMOVE: {
// TODO: Handle MouseMove
Point rect(static_cast<float>(GET_X_LPARAM(lParam)),
static_cast<float>(GET_Y_LPARAM(lParam)));
break;
}
case WM_CLOSE: {
this->m_IsOpen = false;
break;
}
case WM_DESTROY: PostQuitMessage(0);
default: break;
}
}
} // namespace VUI::Windows