]> gitweb.ps.run Git - autorec/blob - src/win.h
Icons
[autorec] / src / win.h
1 #pragma comment(linker, "\"/manifestdependency:type='win32' \\r
2 name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \\r
3 processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")\r
4 \r
5 #include <windows.h>\r
6 #include <CommCtrl.h>\r
7 \r
8 #include "../res/resource.h"\r
9 \r
10 #include "layout.h"\r
11 \r
12 #include <functional>\r
13 #include <unordered_map>\r
14 #include <string>\r
15 \r
16 \r
17 namespace win\r
18 {\r
19   struct Window;\r
20   struct Hwnd\r
21   {\r
22     HWND hwnd;\r
23     lay_id lId;\r
24     Window *window;\r
25 \r
26     Hwnd() {}\r
27     Hwnd(Window *window, LPCSTR className, LPCSTR windowName, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave);\r
28 \r
29     void setStyle(DWORD style)\r
30     {\r
31       SetWindowLongPtrA(hwnd, GWL_STYLE, style);\r
32     }\r
33     DWORD getStyle()\r
34     {\r
35       return GetWindowLongPtrA(hwnd, GWL_STYLE);\r
36     }\r
37     void addStyle(DWORD style)\r
38     {\r
39       SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() | style);\r
40     }\r
41     void removeStyle(DWORD style)\r
42     {\r
43       SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() & (~style));\r
44     }\r
45   };\r
46   struct Window : Hwnd\r
47   {\r
48   private:\r
49 \r
50     static LRESULT CALLBACK\r
51     WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
52     {\r
53       Window *window = (Window*)GetWindowLongPtrA(hwnd, 0);\r
54       if (window == nullptr)\r
55         return DefWindowProc(hwnd, msg, wParam, lParam);\r
56 \r
57       bool defaultHandler = false;\r
58 \r
59       switch (msg) {\r
60         case WM_CLOSE:\r
61           DestroyWindow(hwnd);\r
62           break;\r
63         case WM_DESTROY:\r
64           lay_destroy_context(&window->ctx);\r
65           PostQuitMessage(0);\r
66           break;\r
67         case WM_SIZE:\r
68           if (wParam != SIZE_MINIMIZED) {\r
69             lay_set_size_xy(&window->ctx, window->lId, LOWORD(lParam), HIWORD(lParam));\r
70             lay_run_context(&window->ctx);\r
71 \r
72             //RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);\r
73           }\r
74           break;\r
75         case WM_NOTIFY:\r
76           break;\r
77         case WM_CTLCOLORSTATIC:\r
78           return (LONG_PTR)GetStockObject(WHITE_BRUSH);\r
79         default:\r
80           defaultHandler = true;\r
81           break;\r
82       }\r
83       \r
84       for (auto handler : window->handlers[msg])\r
85         handler(hwnd, msg, wParam, lParam);\r
86 \r
87       if (defaultHandler)\r
88         return DefWindowProc(hwnd, msg, wParam, lParam);\r
89       else\r
90         return 0;\r
91     }\r
92   public:\r
93     lay_context ctx;\r
94     std::unordered_map<UINT,\r
95       std::vector<\r
96         std::function<void(HWND, UINT, WPARAM, LPARAM)>>> handlers;\r
97 \r
98     Window(std::string title, std::string className, HINSTANCE hInstance)\r
99     {\r
100       WNDCLASSEXA wc;\r
101       wc.cbSize = sizeof(WNDCLASSEX);\r
102       wc.style = 0;\r
103       wc.lpfnWndProc = WndProc;\r
104       wc.cbClsExtra = 0;\r
105       wc.cbWndExtra = sizeof(Window*);\r
106       wc.hInstance = hInstance;\r
107       wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_WHITE));\r
108       wc.hCursor = LoadCursor(hInstance, IDC_ARROW);\r
109       wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
110       wc.lpszMenuName = nullptr;\r
111       wc.lpszClassName = className.c_str();\r
112       wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_WHITE));\r
113       RegisterClassExA(&wc);\r
114 \r
115       lay_init_context(&ctx);\r
116       lId = lay_item(&ctx);\r
117       lay_set_contain(&ctx, lId, LAY_COLUMN);\r
118 \r
119       hwnd = CreateWindowA(className.c_str(),\r
120                           title.c_str(),\r
121                           WS_OVERLAPPEDWINDOW,\r
122                           CW_USEDEFAULT,\r
123                           CW_USEDEFAULT,\r
124                           CW_USEDEFAULT,\r
125                           CW_USEDEFAULT,\r
126                           nullptr,\r
127                           nullptr,\r
128                           hInstance,\r
129                           nullptr);\r
130 \r
131       SetWindowLongPtrA(hwnd, 0, (LONG_PTR)this);\r
132     }\r
133     bool update()\r
134     {\r
135       MSG msg;\r
136       if (GetMessage(&msg, nullptr, 0, 0) > 0) {\r
137         TranslateMessage(&msg);\r
138         DispatchMessage(&msg);\r
139         return true;\r
140       }\r
141       return false;\r
142     }\r
143     void show()\r
144     {\r
145       ShowWindow(hwnd, true);\r
146     }\r
147     void setDefaultFont()\r
148     {\r
149       EnumChildWindows(\r
150         hwnd,\r
151         [](HWND hwnd, LPARAM lParam) -> BOOL {\r
152           HFONT guiFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);\r
153           SendMessage(hwnd, WM_SETFONT, (WPARAM)guiFont, MAKELPARAM(TRUE, 0));\r
154           return TRUE;\r
155         },\r
156         0);\r
157     }\r
158   };\r
159 \r
160   struct Button : Hwnd\r
161   {\r
162     Button(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
163       : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave)\r
164     {\r
165       window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
166         if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED)\r
167           for (auto handler : this->onClickHandlers)\r
168             handler();\r
169       });\r
170     }\r
171 \r
172     void onClick(std::function<void()> cb)\r
173     {\r
174       onClickHandlers.push_back(cb);\r
175     }\r
176   private:\r
177     std::vector<std::function<void()>> onClickHandlers;\r
178   };\r
179   \r
180   struct CheckBox : Hwnd\r
181   {\r
182     CheckBox(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
183       : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave)\r
184     {\r
185       addStyle(BS_CHECKBOX);\r
186       window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
187         if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED)\r
188           SendMessageA(this->hwnd, BM_SETCHECK, SendMessageA(this->hwnd, BM_GETCHECK, 0, 0) ? BST_UNCHECKED : BST_CHECKED, 0);\r
189       });\r
190     }\r
191   };\r
192 \r
193   struct ListBox : Hwnd\r
194   {\r
195     ListBox(Window *window, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
196       : Hwnd(window, WC_LISTBOXA, "", parent, w, h, contain, behave)\r
197     {\r
198       addStyle(WS_BORDER);\r
199       //addStyle(WS_VSCROLL);\r
200     }\r
201 \r
202     void addString(std::string str)\r
203     {\r
204       SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)str.c_str());\r
205     }\r
206 \r
207     int getSelectedIndex()\r
208     {\r
209       return SendMessage(hwnd, LB_GETCURSEL, 0, 0);\r
210     }\r
211 \r
212     int findString(std::string str)\r
213     {\r
214       return SendMessageA(hwnd, LB_FINDSTRINGEXACT, -1, (LPARAM)str.c_str());\r
215     }\r
216 \r
217     std::string getText(int index)\r
218     {\r
219       int len = SendMessageA(hwnd, LB_GETTEXTLEN, index, 0);\r
220       std::string result(len, 0);\r
221       SendMessage(hwnd, LB_GETTEXT, index, (LPARAM)result.data());\r
222       return result;\r
223     }\r
224 \r
225     void clear()\r
226     {\r
227       SendMessageA(hwnd, LB_RESETCONTENT, 0, 0);\r
228     }\r
229 \r
230     void remove(int index)\r
231     {\r
232       SendMessageA(hwnd, LB_DELETESTRING, index, 0);\r
233     }\r
234   };\r
235 \r
236   lay_id createLayId(lay_context *ctx, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
237   {\r
238     lay_id lId = lay_item(ctx);\r
239     lay_insert(ctx, parent, lId);\r
240     lay_set_size_xy(ctx, lId, w, h);\r
241     lay_set_contain(ctx, lId, contain);\r
242     lay_set_behave(ctx, lId, behave);\r
243     return lId;\r
244   }\r
245 }\r
246 \r
247 \r
248 \r
249 \r
250 win::Hwnd::Hwnd(Window *window, LPCSTR className, LPCSTR windowName, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
251 {\r
252   this->window = window;\r
253   \r
254   lId = createLayId(&window->ctx, parent, w, h, contain, behave);\r
255   \r
256   hwnd = CreateWindowExA(0,\r
257                           className,\r
258                           windowName,\r
259                           WS_VISIBLE | WS_CHILD,\r
260                           0,\r
261                           0,\r
262                           0,\r
263                           0,\r
264                           window->hwnd,\r
265                           nullptr,\r
266                           nullptr,\r
267                           nullptr);\r
268 \r
269   window->handlers[WM_SIZE].push_back([this](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
270     lay_vec4 rect = lay_get_rect(&this->window->ctx, this->lId);\r
271     SetWindowPos(this->hwnd, HWND_TOP,\r
272       rect[0],\r
273       rect[1],\r
274       rect[2],\r
275       rect[3],\r
276       SWP_NOZORDER\r
277     );\r
278   });\r
279 }