1#include "Win32/Win32.hpp"
9#include <unordered_map>
16 static const std::unordered_map<WPARAM, KeyCode> keyMap = {
55 {VK_ESCAPE, KeyCode::Escape},
56 {VK_LEFT, KeyCode::Left},
57 {VK_RIGHT, KeyCode::Right},
59 {VK_DOWN, KeyCode::Down},
60 {VK_SPACE, KeyCode::Space},
61 {VK_RETURN, KeyCode::Enter},
62 {VK_BACK, KeyCode::Backspace},
63 {VK_TAB, KeyCode::Tab},
64 {VK_LSHIFT, KeyCode::LShift},
65 {VK_RSHIFT, KeyCode::RShift},
66 {VK_LCONTROL, KeyCode::LCtrl},
67 {VK_RCONTROL, KeyCode::RCtrl},
68 {VK_LMENU, KeyCode::LAlt},
69 {VK_RMENU, KeyCode::RAlt}
73 const auto it = keyMap.find(key);
74 return it != keyMap.end() ? it->second : KeyCode::Count;
77LRESULT CALLBACK cae::Win32::WindowProc(
const HWND hwnd,
const UINT msg,
const WPARAM wParam,
const LPARAM lParam)
79 Win32 *self =
nullptr;
81 if (msg == WM_NCCREATE)
83 const auto *cs =
reinterpret_cast<CREATESTRUCTW *
>(lParam);
84 self =
static_cast<Win32 *
>(cs->lpCreateParams);
85 SetWindowLongPtrW(hwnd, GWLP_USERDATA,
reinterpret_cast<LONG_PTR
>(self));
89 self =
reinterpret_cast<Win32 *
>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
92 return DefWindowProcW(hwnd, msg, wParam, lParam);
99 self->m_frameBufferResized =
true;
100 self->m_frameBufferSize = {.width = LOWORD(lParam), .height = HIWORD(lParam)};
101 e.type = WindowEventType::Resize;
102 e.resize = {.w = LOWORD(lParam), .h = HIWORD(lParam)};
103 self->m_eventQueue.push(e);
108 e.type = WindowEventType::Close;
109 self->m_eventQueue.push(e);
114 e.type = WindowEventType::KeyDown;
115 e.key.key = mapWinKey(wParam);
116 self->m_eventQueue.push(e);
121 e.type = WindowEventType::KeyUp;
122 e.key.key = mapWinKey(wParam);
123 self->m_eventQueue.push(e);
129 return DefWindowProcW(hwnd, msg, wParam, lParam);
132bool cae::Win32::create(
const std::string &name,
const WindowSize size)
134 m_hInstance = GetModuleHandleW(
nullptr);
135 m_frameBufferSize = size;
136 m_shouldClose =
false;
137 m_frameBufferResized =
false;
139 const int len = MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1,
nullptr, 0);
143 MultiByteToWideChar(CP_UTF8, 0, name.c_str(), -1, m_title.data(), len);
145 if (!m_title.empty() && m_title.back() == L
'\0')
150 static bool classRegistered =
false;
151 if (!classRegistered)
154 wc.lpfnWndProc = WindowProc;
155 wc.hInstance = m_hInstance;
157 wc.hCursor = LoadCursorW(
nullptr, IDC_ARROW);
158 wc.hIcon = LoadIconW(
nullptr, IDI_APPLICATION);
159 wc.hbrBackground =
reinterpret_cast<HBRUSH
>(COLOR_WINDOW + 1);
161 if (RegisterClassW(&wc) == 0
U)
166 classRegistered =
true;
168 m_hwnd = CreateWindowExW(0,
WINDOW_CLASS_NAME, L
"", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, size.width,
169 size.height,
nullptr,
nullptr, m_hInstance,
this);
171 if (m_hwnd ==
nullptr)
176 SetWindowTextW(m_hwnd, m_title.c_str());
178 ShowWindow(m_hwnd, SW_SHOW);
179 UpdateWindow(m_hwnd);
183void cae::Win32::close()
185 if (m_hwnd !=
nullptr)
187 DestroyWindow(m_hwnd);
198 GetClientRect(m_hwnd, &rect);
199 return {.width =
static_cast<uint16_t
>(rect.right - rect.left),
200 .height =
static_cast<uint16_t
>(rect.bottom - rect.top)};
203void cae::Win32::setIcon(
const std::string &path)
const
209 for (
size_t i = 0; std::cmp_less(i, image.width * image.height); ++i)
211 std::swap(image.pixels[(i * 4) + 0], image.pixels[(i * 4) + 2]);
215 iconInfo.fIcon = TRUE;
218 bi.bV5Size =
sizeof(BITMAPV5HEADER);
219 bi.bV5Width = image.width;
220 bi.bV5Height = -
static_cast<LONG
>(image.height);
223 bi.bV5Compression = BI_BITFIELDS;
224 bi.bV5RedMask = 0x00FF0000;
225 bi.bV5GreenMask = 0x0000FF00;
226 bi.bV5BlueMask = 0x000000FF;
227 bi.bV5AlphaMask = 0xFF000000;
229 void *pBits =
nullptr;
230 const HDC hdc = GetDC(
nullptr);
231 const HBITMAP hBitmap =
232 CreateDIBSection(hdc,
reinterpret_cast<BITMAPINFO *
>(&bi), DIB_RGB_COLORS, &pBits,
nullptr, 0);
233 ReleaseDC(
nullptr, hdc);
235 if (hBitmap ==
nullptr)
241 std::memcpy(pBits, image.pixels,
static_cast<size_t>(image.width * image.height * 4));
243 iconInfo.hbmColor = hBitmap;
244 iconInfo.hbmMask = CreateBitmap(image.width, image.height, 1, 1,
nullptr);
246 HICON hIcon = CreateIconIndirect(&iconInfo);
248 DeleteObject(hBitmap);
249 DeleteObject(iconInfo.hbmMask);
251 if (hIcon ==
nullptr)
257 SendMessageW(m_hwnd, WM_SETICON, ICON_BIG,
reinterpret_cast<LPARAM
>(hIcon));
258 SendMessageW(m_hwnd, WM_SETICON, ICON_SMALL,
reinterpret_cast<LPARAM
>(hIcon));
260 catch (
const std::exception &e)
266void cae::Win32::pollEvents()
269 while (PeekMessage(&msg,
nullptr, 0, 0, PM_REMOVE))
271 if (msg.message == WM_QUIT)
273 m_shouldClose =
true;
275 TranslateMessage(&msg);
276 DispatchMessage(&msg);
280bool cae::Win32::pollEvent(WindowEvent &event)
283 while (PeekMessage(&msg,
nullptr, 0, 0, PM_REMOVE))
285 TranslateMessage(&msg);
286 DispatchMessage(&msg);
289 if (!m_eventQueue.empty())
291 event = m_eventQueue.front();
This file contains image struct.
This file contains the Logger class.
static void log(const std::string &message, const LogLevel &logLevel)
Log a message with a specific log level.
Struct for native window handle.
constexpr wchar_t WINDOW_CLASS_NAME[]