#include <windows.h>\r
#include <CommCtrl.h>\r
\r
+#include "../res/resource.h"\r
+\r
#include "layout.h"\r
\r
#include <functional>\r
-#include <map>\r
+#include <unordered_map>\r
#include <string>\r
\r
-using std::string;\r
-\r
-namespace win {\r
-namespace _ {\r
-using CallbackFn = std::function<void()>;\r
-std::map<HWND, std::map<WORD, CallbackFn>> handlers;\r
-std::map<HWND, lay_id> lIds;\r
-\r
-NOTIFYICONDATA niData = { 0 };\r
-void\r
-ShowNotificationIcon()\r
-{\r
- Shell_NotifyIconA(NIM_ADD, &_::niData);\r
- Shell_NotifyIconA(NIM_SETVERSION, &_::niData);\r
-}\r
-\r
-void\r
-HideNotificationIcon()\r
-{\r
- Shell_NotifyIconA(NIM_DELETE, &_::niData);\r
-}\r
\r
-lay_context ctx;\r
-lay_id root;\r
-\r
-LRESULT CALLBACK\r
-WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
+namespace win\r
{\r
- switch (msg) {\r
- case WM_CLOSE:\r
- DestroyWindow(hwnd);\r
- break;\r
- case WM_DESTROY:\r
- Shell_NotifyIconA(NIM_DELETE, &niData);\r
- lay_destroy_context(&ctx);\r
- PostQuitMessage(0);\r
- break;\r
- case WM_SIZE:\r
- if (wParam == SIZE_MINIMIZED) {\r
- ShowNotificationIcon();\r
- ShowWindow(hwnd, false);\r
- }\r
- else {\r
- lay_set_size_xy(&_::ctx, _::root, LOWORD(lParam), HIWORD(lParam));\r
- lay_run_context(&_::ctx);\r
-\r
- for (auto &lId : lIds) {\r
- lay_vec4 rect = lay_get_rect(&_::ctx, lId.second);\r
- SetWindowPos(lId.first, HWND_TOP,\r
- rect[0],\r
- rect[1],\r
- rect[2],\r
- rect[3],\r
- SWP_NOZORDER\r
- );\r
- }\r
- RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);\r
- }\r
- break;\r
- case WM_COMMAND:\r
- if (handlers.find((HWND)lParam) != handlers.end()) {\r
- auto handler = handlers[(HWND)lParam];\r
- if (handler.find(HIWORD(wParam)) != handler.end()) {\r
- auto cb = handler[HIWORD(wParam)];\r
- cb();\r
+ struct Window;\r
+ struct Hwnd\r
+ {\r
+ HWND hwnd;\r
+ lay_id lId;\r
+ Window *window;\r
+\r
+ Hwnd() {}\r
+ Hwnd(Window *window, LPCSTR className, LPCSTR windowName, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave);\r
+\r
+ void setStyle(DWORD style)\r
+ {\r
+ SetWindowLongPtrA(hwnd, GWL_STYLE, style);\r
+ }\r
+ DWORD getStyle()\r
+ {\r
+ return GetWindowLongPtrA(hwnd, GWL_STYLE);\r
+ }\r
+ void addStyle(DWORD style)\r
+ {\r
+ SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() | style);\r
+ }\r
+ void removeStyle(DWORD style)\r
+ {\r
+ SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() & (~style));\r
+ }\r
+ };\r
+ struct Window : Hwnd\r
+ {\r
+ private:\r
+ NOTIFYICONDATAA niData = { 0 };\r
+\r
+ static LRESULT CALLBACK\r
+ WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)\r
+ {\r
+ Window *window = (Window*)GetWindowLongPtrA(hwnd, 0);\r
+ if (window == nullptr)\r
+ return DefWindowProc(hwnd, msg, wParam, lParam);\r
+\r
+ bool defaultHandler = false;\r
+\r
+ switch (msg) {\r
+ case WM_CLOSE:\r
+ DestroyWindow(hwnd);\r
+ break;\r
+ case WM_DESTROY:\r
+ Shell_NotifyIconA(NIM_DELETE, &window->niData);\r
+ lay_destroy_context(&window->ctx);\r
+ PostQuitMessage(0);\r
+ break;\r
+ case WM_SIZE:\r
+ if (wParam == SIZE_MINIMIZED) {\r
+ //TODO: auslagen\r
+ //ShowNotificationIcon();\r
+ ShowWindow(hwnd, false);\r
+ }\r
+ else {\r
+ lay_set_size_xy(&window->ctx, window->lId, LOWORD(lParam), HIWORD(lParam));\r
+ lay_run_context(&window->ctx);\r
+\r
+ //RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN);\r
+ }\r
+ break;\r
+ case WM_NOTIFY:\r
+ break;\r
+ case WM_APP + 1:\r
+ if (LOWORD(lParam) == NIN_SELECT) {\r
+ //TODO: auslagern\r
+ //HideNotificationIcon();\r
+ ShowWindow(hwnd, true);\r
+ SetForegroundWindow(hwnd);\r
+ SetActiveWindow(hwnd);\r
+ }\r
+ break;\r
+ case WM_CTLCOLORSTATIC:\r
+ return (LONG)GetStockObject(WHITE_BRUSH);\r
+ case WM_GETMINMAXINFO: {\r
+ MINMAXINFO *mmInfo = (MINMAXINFO*)lParam;\r
+ mmInfo->ptMinTrackSize.x = 400;\r
+ mmInfo->ptMinTrackSize.y = 200;\r
+ break;\r
}\r
+ default:\r
+ defaultHandler = true;\r
+ break;\r
}\r
- break;\r
- case WM_NOTIFY:\r
- break;\r
- case WM_APP + 1:\r
- if (LOWORD(lParam) == NIN_SELECT) {\r
- HideNotificationIcon();\r
- ShowWindow(hwnd, true);\r
- SetForegroundWindow(hwnd);\r
- SetActiveWindow(hwnd);\r
+ \r
+ for (auto handler : window->handlers[msg])\r
+ handler(hwnd, msg, wParam, lParam);\r
+\r
+ if (defaultHandler)\r
+ return DefWindowProc(hwnd, msg, wParam, lParam);\r
+ else\r
+ return 0;\r
+ }\r
+ public:\r
+ lay_context ctx;\r
+ std::unordered_map<UINT,\r
+ std::vector<\r
+ std::function<void(HWND, UINT, WPARAM, LPARAM)>>> handlers;\r
+\r
+ Window(std::string title, std::string className, HINSTANCE hInstance)\r
+ {\r
+ WNDCLASSEXA wc;\r
+ wc.cbSize = sizeof(WNDCLASSEX);\r
+ wc.style = 0;\r
+ wc.lpfnWndProc = WndProc;\r
+ wc.cbClsExtra = 0;\r
+ wc.cbWndExtra = sizeof(Window*);\r
+ wc.hInstance = hInstance;\r
+ wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);\r
+ wc.hCursor = LoadCursor(nullptr, IDC_ARROW);\r
+ wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
+ wc.lpszMenuName = nullptr;\r
+ wc.lpszClassName = className.c_str();\r
+ wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);\r
+ RegisterClassExA(&wc);\r
+\r
+ lay_init_context(&ctx);\r
+ lId = lay_item(&ctx);\r
+ lay_set_contain(&ctx, lId, LAY_COLUMN);\r
+\r
+ hwnd = CreateWindowA(className.c_str(),\r
+ title.c_str(),\r
+ WS_OVERLAPPEDWINDOW,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ CW_USEDEFAULT,\r
+ nullptr,\r
+ nullptr,\r
+ hInstance,\r
+ nullptr);\r
+\r
+ SetWindowLongPtrA(hwnd, 0, (LONG_PTR)this);\r
+ \r
+ \r
+ niData.cbSize = sizeof(niData);\r
+ niData.uID = 12345;\r
+ niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;\r
+ niData.hIcon = LoadIconA(hInstance, MAKEINTRESOURCEA(IDI_MY_ICON));\r
+ niData.hWnd = hwnd;\r
+ niData.uCallbackMessage = WM_APP+1;\r
+ niData.uVersion = NOTIFYICON_VERSION_4;\r
+ }\r
+ bool update()\r
+ {\r
+ MSG msg;\r
+ if (GetMessage(&msg, nullptr, 0, 0) > 0) {\r
+ TranslateMessage(&msg);\r
+ DispatchMessage(&msg);\r
+ return true;\r
}\r
- break;\r
- case WM_CTLCOLORSTATIC:\r
- return (LONG)GetStockObject(WHITE_BRUSH);\r
- case WM_GETMINMAXINFO: {\r
- MINMAXINFO *mmInfo = (MINMAXINFO*)lParam;\r
- mmInfo->ptMinTrackSize.x = 400;\r
- mmInfo->ptMinTrackSize.y = 200;\r
- break;\r
+ return false;\r
+ }\r
+ void show()\r
+ {\r
+ ShowWindow(hwnd, true);\r
+\r
+ EnumChildWindows(\r
+ hwnd,\r
+ [](HWND hwnd, LPARAM lParam) -> BOOL {\r
+ HFONT guiFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);\r
+ SendMessage(hwnd, WM_SETFONT, (WPARAM)guiFont, MAKELPARAM(TRUE, 0));\r
+ return TRUE;\r
+ },\r
+ 0);\r
+ }\r
+ };\r
+\r
+ struct Button : Hwnd\r
+ {\r
+ Button(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
+ : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave)\r
+ {\r
+ window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
+ if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED)\r
+ for (auto handler : this->onClickHandlers)\r
+ handler();\r
+ });\r
}\r
- default:\r
- return DefWindowProc(hwnd, msg, wParam, lParam);\r
- }\r
- return 0;\r
-}\r
-}\r
-\r
-\r
-void\r
-Callback(HWND hwnd, WORD ev, std::function<void()> cb)\r
-{\r
- _::handlers[hwnd][ev] = cb;\r
-}\r
-\r
-HWND\r
-Window(string title, string className, HINSTANCE hInstance)\r
-{\r
- WNDCLASSEX wc;\r
- wc.cbSize = sizeof(WNDCLASSEX);\r
- wc.style = 0;\r
- wc.lpfnWndProc = _::WndProc;\r
- wc.cbClsExtra = 0;\r
- wc.cbWndExtra = 0;\r
- wc.hInstance = hInstance;\r
- wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);\r
- wc.hCursor = LoadCursor(nullptr, IDC_ARROW);\r
- wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);\r
- wc.lpszMenuName = nullptr;\r
- wc.lpszClassName = className.c_str();\r
- wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);\r
- RegisterClassEx(&wc);\r
-\r
- lay_init_context(&_::ctx);\r
- _::root = lay_item(&_::ctx);\r
- lay_set_contain(&_::ctx, _::root, LAY_COLUMN);\r
-\r
- HWND result = CreateWindowA(className.c_str(),\r
- title.c_str(),\r
- WS_OVERLAPPEDWINDOW,\r
- CW_USEDEFAULT,\r
- CW_USEDEFAULT,\r
- CW_USEDEFAULT,\r
- CW_USEDEFAULT,\r
- nullptr,\r
- nullptr,\r
- hInstance,\r
- nullptr);\r
- \r
- _::niData.cbSize = sizeof(_::niData);\r
- _::niData.uID = 12345;\r
- _::niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;\r
- _::niData.hIcon = LoadIconA(nullptr, IDI_WINLOGO);\r
- _::niData.hWnd = result;\r
- _::niData.uCallbackMessage = WM_APP+1;\r
- _::niData.uVersion = NOTIFYICON_VERSION_4;\r
-\r
- return result;\r
-}\r
-\r
-bool\r
-UpdateWindow(HWND hwnd)\r
-{\r
- MSG msg;\r
- if (GetMessage(&msg, nullptr, 0, 0) > 0) {\r
- TranslateMessage(&msg);\r
- DispatchMessage(&msg);\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-void\r
-ShowWindow(HWND hwnd)\r
-{\r
- ShowWindow(hwnd, true);\r
-\r
- EnumChildWindows(\r
- hwnd,\r
- [](HWND hwnd, LPARAM lParam) -> BOOL {\r
- HFONT guiFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);\r
- SendMessage(hwnd, WM_SETFONT, (WPARAM)guiFont, MAKELPARAM(TRUE, 0));\r
- return TRUE;\r
- },\r
- 0);\r
-}\r
\r
-HWND\r
-Button(HWND hwnd, string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
-{\r
- lay_id lId = lay_item(&_::ctx);\r
- lay_insert(&_::ctx, parent, lId);\r
- lay_set_size_xy(&_::ctx, lId, w, h);\r
- lay_set_contain(&_::ctx, lId, contain);\r
- lay_set_behave(&_::ctx, lId, behave);\r
-\r
- HWND result = CreateWindowExA(0,\r
- WC_BUTTONA,\r
- title.c_str(),\r
- WS_VISIBLE | WS_CHILD,\r
- 0, 0, 0, 0,\r
- hwnd,\r
- nullptr,\r
- nullptr,\r
- nullptr);\r
- _::lIds[result] = lId;\r
- return result;\r
-}\r
+ void onClick(std::function<void()> cb)\r
+ {\r
+ onClickHandlers.push_back(cb);\r
+ }\r
+ private:\r
+ std::vector<std::function<void()>> onClickHandlers;\r
+ };\r
+ \r
+ struct CheckBox : Hwnd\r
+ {\r
+ CheckBox(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
+ : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave)\r
+ {\r
+ addStyle(BS_CHECKBOX);\r
+ window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
+ if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED)\r
+ SendMessageA(this->hwnd, BM_SETCHECK, SendMessageA(this->hwnd, BM_GETCHECK, 0, 0) ? BST_UNCHECKED : BST_CHECKED, 0);\r
+ });\r
+ }\r
+ };\r
+\r
+ struct ListBox : Hwnd\r
+ {\r
+ ListBox(Window *window, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
+ : Hwnd(window, WC_LISTBOXA, "", parent, w, h, contain, behave)\r
+ {\r
+ addStyle(WS_BORDER);\r
+ //addStyle(WS_VSCROLL);\r
+ }\r
\r
-HWND\r
-ListBox(HWND hwnd, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
-{\r
- lay_id lId = lay_item(&_::ctx);\r
- lay_insert(&_::ctx, parent, lId);\r
- lay_set_size_xy(&_::ctx, lId, w, h);\r
- lay_set_contain(&_::ctx, lId, contain);\r
- lay_set_behave(&_::ctx, lId, behave);\r
-\r
- HWND result = CreateWindowExA(0,\r
- WC_LISTBOXA,\r
- "",\r
- WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL,\r
- 0, 0, 0, 0,\r
- hwnd,\r
- nullptr,\r
- nullptr,\r
- nullptr);\r
- _::lIds[result] = lId;\r
- return result;\r
-}\r
+ void addString(std::string str)\r
+ {\r
+ SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)str.c_str());\r
+ }\r
\r
-void\r
-ListAddString(HWND hwnd, string str)\r
-{\r
- SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)str.c_str());\r
-}\r
+ int getSelectedIndex()\r
+ {\r
+ return SendMessage(hwnd, LB_GETCURSEL, 0, 0);\r
+ }\r
\r
-int\r
-ListGetSelectedIndex(HWND hwnd)\r
-{\r
- int sel = SendMessage(hwnd, LB_GETCURSEL, 0, 0);\r
- return sel;\r
-}\r
+ int findString(std::string str)\r
+ {\r
+ return SendMessageA(hwnd, LB_FINDSTRINGEXACT, -1, (LPARAM)str.c_str());\r
+ }\r
\r
-int ListFindString(HWND hwnd, string str)\r
-{\r
- return SendMessageA(hwnd, LB_FINDSTRINGEXACT, -1, (LPARAM)str.c_str());\r
-}\r
+ std::string getText(int index)\r
+ {\r
+ int len = SendMessageA(hwnd, LB_GETTEXTLEN, index, 0);\r
+ std::string result(len, 0);\r
+ SendMessage(hwnd, LB_GETTEXT, index, (LPARAM)result.data());\r
+ return result;\r
+ }\r
\r
-string\r
-ListGetText(HWND hwnd, int index)\r
-{\r
- char buffer[1024];\r
- SendMessage(hwnd, LB_GETTEXT, index, (LPARAM)buffer);\r
- return string(buffer);\r
-}\r
+ void clear()\r
+ {\r
+ SendMessageA(hwnd, LB_RESETCONTENT, 0, 0);\r
+ }\r
\r
-void\r
-ListClear(HWND hwnd)\r
-{\r
- SendMessageA(hwnd, LB_RESETCONTENT, 0, 0);\r
+ void remove(int index)\r
+ {\r
+ SendMessageA(hwnd, LB_DELETESTRING, index, 0);\r
+ }\r
+ };\r
+\r
+ lay_id createLayId(lay_context *ctx, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
+ {\r
+ lay_id lId = lay_item(ctx);\r
+ lay_insert(ctx, parent, lId);\r
+ lay_set_size_xy(ctx, lId, w, h);\r
+ lay_set_contain(ctx, lId, contain);\r
+ lay_set_behave(ctx, lId, behave);\r
+ return lId;\r
+ }\r
}\r
\r
-void ListRemove(HWND hwnd, int index)\r
-{\r
- SendMessageA(hwnd, LB_DELETESTRING, index, 0);\r
-}\r
\r
-HWND\r
-ListView(HWND hwnd, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
-{\r
- lay_id lId = lay_item(&_::ctx);\r
- lay_insert(&_::ctx, parent, lId);\r
- lay_set_size_xy(&_::ctx, lId, w, h);\r
- lay_set_contain(&_::ctx, lId, contain);\r
- lay_set_behave(&_::ctx, lId, behave);\r
-\r
- HWND result = CreateWindowExA(0,\r
- WC_LISTVIEWA,\r
- "",\r
- WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL,\r
- 0, 0, 0, 0,\r
- hwnd,\r
- nullptr,\r
- nullptr,\r
- nullptr);\r
- _::lIds[result] = lId;\r
- return result;\r
-}\r
\r
-HWND\r
-CheckBox(HWND hwnd, string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave)\r
-{\r
- lay_id lId = lay_item(&_::ctx);\r
- lay_insert(&_::ctx, parent, lId);\r
- lay_set_size_xy(&_::ctx, lId, w, h);\r
- lay_set_contain(&_::ctx, lId, contain);\r
- lay_set_behave(&_::ctx, lId, behave);\r
-\r
- HWND result = CreateWindowExA(0,\r
- WC_BUTTONA,\r
- title.c_str(),\r
- WS_VISIBLE | WS_CHILD | BS_CHECKBOX,\r
- 0, 0, 0, 0,\r
- hwnd,\r
- nullptr,\r
- nullptr,\r
- nullptr);\r
- _::lIds[result] = lId;\r
- return result;\r
-}\r
\r
-void SetStyle(HWND hwnd, DWORD style)\r
+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
{\r
- SetWindowLongPtrA(hwnd, GWL_STYLE, style);\r
-}\r
-DWORD GetStyle(HWND hwnd)\r
-{\r
- return GetWindowLongPtrA(hwnd, GWL_STYLE);\r
-}\r
-void AddStyle(HWND hwnd, DWORD style)\r
-{\r
- SetWindowLongPtrA(hwnd, GWL_STYLE, GetStyle(hwnd) | style);\r
-}\r
-void RemoveStyle(HWND hwnd, DWORD style)\r
-{\r
- SetWindowLongPtrA(hwnd, GWL_STYLE, GetStyle(hwnd) & (~style));\r
-}\r
+ this->window = window;\r
+ \r
+ lId = createLayId(&window->ctx, parent, w, h, contain, behave);\r
+ \r
+ hwnd = CreateWindowExA(0,\r
+ className,\r
+ windowName,\r
+ WS_VISIBLE | WS_CHILD,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ window->hwnd,\r
+ nullptr,\r
+ nullptr,\r
+ nullptr);\r
+\r
+ window->handlers[WM_SIZE].push_back([this](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {\r
+ lay_vec4 rect = lay_get_rect(&this->window->ctx, this->lId);\r
+ SetWindowPos(this->hwnd, HWND_TOP,\r
+ rect[0],\r
+ rect[1],\r
+ rect[2],\r
+ rect[3],\r
+ SWP_NOZORDER\r
+ );\r
+ });\r
}
\ No newline at end of file