-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseWindow.hpp
More file actions
120 lines (105 loc) · 2.62 KB
/
BaseWindow.hpp
File metadata and controls
120 lines (105 loc) · 2.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#pragma once
#include <wil/resource.h>
#include <string_view>
template<size_t N>
struct StringLiteral {
constexpr StringLiteral(const wchar_t(&str)[N]) {
std::copy_n(str, N, value);
}
wchar_t value[N];
};
template<typename T, StringLiteral className>
class BaseWindow
{
static void OnPaint(HWND) {}
protected:
wil::unique_hwnd m_hwnd;
[[nodiscard]] static auto getSelfFromHwnd(HWND const window)
{
return reinterpret_cast<T*>(GetWindowLongPtr(window, GWLP_USERDATA));
}
static void OnNCCreate(HWND hwnd, CREATESTRUCT* lparam)
{
}
static void OnSize(HWND hwnd, WPARAM wparam, UINT width, UINT height)
{
}
static void OnDpiChanged(HWND, WORD dpiX, WORD dpiY, RECT* suggestPosition)
{
}
static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
{
switch (msg)
{
//Methods that have default (no-op) implementation
case WM_DPICHANGED:
OnDpiChanged(hwnd, LOWORD(wparam), HIWORD(wparam), reinterpret_cast<RECT*>(lparam));
break;
case WM_NCCREATE:
OnNCCreate(hwnd, reinterpret_cast<CREATESTRUCT*>(lparam));
break;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
//Methods that must be implemented by derived class
case WM_PAINT:
T::OnPaint(hwnd);
return 0;
case WM_SIZE:
T::OnSize(hwnd, wparam, LOWORD(lparam), HIWORD(lparam));
return 0;
default:
break;
}
return DefWindowProcW(hwnd, msg, wparam, lparam);
}
public:
BaseWindow(std::wstring_view windowName, DWORD exStyle = 0, DWORD style = WS_OVERLAPPEDWINDOW, int x = CW_USEDEFAULT, int y = CW_USEDEFAULT, int cx = CW_USEDEFAULT, int cy = CW_USEDEFAULT)
{
static auto windowClass = [] {
WNDCLASS wc
{
.style = CS_HREDRAW | CS_VREDRAW,
.lpfnWndProc = WndProc,
.cbWndExtra = sizeof(void*),
.lpszClassName = className.value,
};
RegisterClass(&wc);
return wc;
}();
auto const hwnd = CreateWindowExW(
exStyle,
className.value,
windowName.data(),
style,
x,
y,
cx,
cy,
nullptr,
nullptr,
nullptr,
static_cast<T*>(this)
);
SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(static_cast<T*>(this)));
ShowWindow(hwnd, SW_SHOW);
m_hwnd.reset(hwnd);
}
RECT ClientRect() const
{
RECT clientRect;
THROW_IF_WIN32_BOOL_FALSE(GetClientRect(m_hwnd.get(), &clientRect));
return clientRect;
}
UINT GetDpi() const
{
return GetDpiForWindow(m_hwnd.get());
}
auto SetPosition(int x, int y, int cx, int cy, UINT flags) const
{
auto const result = SetWindowPos(m_hwnd.get(), HWND_TOP, x, y, cx, cy, flags);
InvalidateRect(m_hwnd.get(), nullptr, true);
UpdateWindow(m_hwnd.get());
return result;
}
};