160 lines
No EOL
4.2 KiB
C++
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
|