X-Git-Url: https://gitweb.ps.run/autorec/blobdiff_plain/8d2244aefe172b5b1e15a32ad23991945d128f3a..81f259240d157ddcb0cb692826855d7505f4a22f:/src/win.h diff --git a/src/win.h b/src/win.h index 65f2595..0a734c9 100644 --- a/src/win.h +++ b/src/win.h @@ -1,329 +1,298 @@ -#pragma comment(linker, "\"/manifestdependency:type='win32' \ -name='Microsoft.Windows.Common-Controls' version='6.0.0.0' \ -processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"") - #include #include +#include "../res/resource.h" + #include "layout.h" #include -#include +#include #include -using std::string; -namespace win { -struct Length -{ - int pixel; - float percent; -}; -struct Size +namespace win { - Length x, y, w, h; - int getX(HWND hwnd) - { - RECT rect; - GetClientRect(hwnd, &rect); - return x.percent * (rect.right - rect.left) + x.pixel; - } - int getY(HWND hwnd) + struct Window; + struct Hwnd { - RECT rect; - GetClientRect(hwnd, &rect); - return y.percent * (rect.bottom - rect.top) + y.pixel; - } - int getW(HWND hwnd) - { - RECT rect; - GetClientRect(hwnd, &rect); - return w.percent * (rect.right - rect.left) + w.pixel; - } - int getH(HWND hwnd, int _w, int _h) - { - RECT rect; - GetWindowRect(hwnd, &rect); - return h.percent * (rect.bottom - rect.top) + h.pixel; - } -}; + HWND hwnd; + lay_id lId; + Window *window; -namespace _ { -using CallbackFn = std::function; -std::map> handlers; -std::map lIds; + Hwnd() {} + Hwnd(Window *window, LPCSTR className, LPCSTR windowName, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave); -NOTIFYICONDATA niData = { 0 }; - -lay_context ctx; -lay_id root; - -LRESULT CALLBACK -WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) -{ - switch (msg) { - case WM_CLOSE: - DestroyWindow(hwnd); - break; - case WM_DESTROY: - Shell_NotifyIconA(NIM_DELETE, &niData); - lay_destroy_context(&ctx); - PostQuitMessage(0); - break; - case WM_SIZE: - if (wParam == SIZE_MINIMIZED) { - ShowWindow(hwnd, false); - SetForegroundWindow(hwnd); - SetActiveWindow(hwnd); - } - else { - lay_set_size_xy(&_::ctx, _::root, LOWORD(lParam), HIWORD(lParam)); - lay_run_context(&_::ctx); - - for (auto &lId : lIds) { - lay_vec4 rect = lay_get_rect(&_::ctx, lId.second); - SetWindowPos(lId.first, HWND_TOP, - rect[0], - rect[1], - rect[2], - rect[3], - SWP_NOZORDER - ); - } - RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); + void setStyle(DWORD style) + { + SetWindowLongPtrA(hwnd, GWL_STYLE, style); + } + DWORD getStyle() + { + return GetWindowLongPtrA(hwnd, GWL_STYLE); + } + void addStyle(DWORD style) + { + SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() | style); + } + void removeStyle(DWORD style) + { + SetWindowLongPtrA(hwnd, GWL_STYLE, getStyle() & (~style)); + } + void setActive(bool active) + { + EnableWindow(hwnd, active); + } + }; + struct Window : Hwnd + { + private: + + static LRESULT CALLBACK + WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) + { + Window *window = (Window*)GetWindowLongPtrA(hwnd, 0); + if (window == nullptr) + return DefWindowProc(hwnd, msg, wParam, lParam); + + bool defaultHandler = false; + + switch (msg) { + case WM_CLOSE: + DestroyWindow(hwnd); + break; + case WM_DESTROY: + lay_destroy_context(&window->ctx); + PostQuitMessage(0); + break; + case WM_SIZE: + if (wParam != SIZE_MINIMIZED) { + lay_set_size_xy(&window->ctx, window->lId, LOWORD(lParam), HIWORD(lParam)); + lay_run_context(&window->ctx); + + //RedrawWindow(hwnd, 0, 0, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); + } + break; + case WM_NOTIFY: + break; + case WM_CTLCOLORSTATIC: + return (LONG_PTR)GetStockObject(WHITE_BRUSH); + default: + defaultHandler = true; + break; } - break; - case WM_COMMAND: - if (handlers.find((HWND)lParam) != handlers.end()) { - auto handler = handlers[(HWND)lParam]; - if (handler.find(HIWORD(wParam)) != handler.end()) { - auto cb = handler[HIWORD(wParam)]; - cb(); - } + + for (auto handler : window->handlers[msg]) + handler(hwnd, msg, wParam, lParam); + + if (defaultHandler) + return DefWindowProc(hwnd, msg, wParam, lParam); + else + return 0; + } + public: + lay_context ctx; + std::unordered_map>> handlers; + + struct Timer { + bool active = true; + std::function f; + }; + std::vector timers; + + Window(std::string title, std::string className, HINSTANCE hInstance) + { + WNDCLASSEXA wc; + wc.cbSize = sizeof(WNDCLASSEX); + wc.style = 0; + wc.lpfnWndProc = WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(Window*); + wc.hInstance = hInstance; + wc.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_WHITE)); + wc.hCursor = LoadCursor(hInstance, IDC_ARROW); + wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); + wc.lpszMenuName = nullptr; + wc.lpszClassName = className.c_str(); + wc.hIconSm = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_ICON_WHITE)); + RegisterClassExA(&wc); + + lay_init_context(&ctx); + lId = lay_item(&ctx); + lay_set_contain(&ctx, lId, LAY_COLUMN); + + hwnd = CreateWindowA(className.c_str(), + title.c_str(), + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + hInstance, + nullptr); + + SetWindowLongPtrA(hwnd, 0, (LONG_PTR)this); + } + bool update() + { + MSG msg; + if (GetMessage(&msg, nullptr, 0, 0) > 0) { + TranslateMessage(&msg); + DispatchMessage(&msg); + return true; } - break; - case WM_NOTIFY: - break; - case WM_APP + 1: - if (LOWORD(lParam) == NIN_SELECT) - ShowWindow(hwnd, true); - break; - case WM_CTLCOLORSTATIC: - return (LONG)GetStockObject(WHITE_BRUSH); - case WM_GETMINMAXINFO: { - MINMAXINFO *mmInfo = (MINMAXINFO*)lParam; - mmInfo->ptMinTrackSize.x = 400; - mmInfo->ptMinTrackSize.y = 200; - break; + return false; } - default: - return DefWindowProc(hwnd, msg, wParam, lParam); - } - return 0; -} -} - -void -ShowNotificationIcon(HINSTANCE hInstance, HWND hwnd) -{ - _::niData.cbSize = sizeof(_::niData); - _::niData.uID = 12345; - _::niData.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP; - _::niData.hIcon = LoadIconA(nullptr, IDI_WINLOGO); - _::niData.hWnd = hwnd; - _::niData.uCallbackMessage = WM_APP+1; - _::niData.uVersion = NOTIFYICON_VERSION_4; - - Shell_NotifyIconA(NIM_ADD, &_::niData); - Shell_NotifyIconA(NIM_SETVERSION, &_::niData); -} + void show() + { + ShowWindow(hwnd, true); + } + void setDefaultFont() + { + EnumChildWindows( + hwnd, + [](HWND hwnd, LPARAM lParam) -> BOOL { + HFONT guiFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); + SendMessage(hwnd, WM_SETFONT, (WPARAM)guiFont, MAKELPARAM(TRUE, 0)); + return TRUE; + }, + 0); + } + void setTimer(UINT interval, std::function cb) + { + SetTimer(this->hwnd, timers.size() + 1000, interval, [](HWND hwnd, UINT uMsg, UINT_PTR uIdEvent, DWORD dwTime) { + Window *window = (Window*)GetWindowLongPtrA(hwnd, 0); + if (window == nullptr) + return; + + window->timers[uIdEvent-1000].f(); + }); + Timer t; + t.f = cb; + timers.push_back(t); + } + }; -void -Callback(HWND hwnd, WORD ev, std::function cb) -{ - _::handlers[hwnd][ev] = cb; -} + struct Button : Hwnd + { + Button(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) + : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave) + { + window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED) + for (auto handler : this->onClickHandlers) + handler(); + }); + } -HWND -Window(string title, string className, HINSTANCE hInstance) -{ - WNDCLASSEX wc; - wc.cbSize = sizeof(WNDCLASSEX); - wc.style = 0; - wc.lpfnWndProc = _::WndProc; - wc.cbClsExtra = 0; - wc.cbWndExtra = 0; - wc.hInstance = hInstance; - wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION); - wc.hCursor = LoadCursor(nullptr, IDC_ARROW); - wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); - wc.lpszMenuName = nullptr; - wc.lpszClassName = className.c_str(); - wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION); - RegisterClassEx(&wc); - - lay_init_context(&_::ctx); - _::root = lay_item(&_::ctx); - lay_set_contain(&_::ctx, _::root, LAY_COLUMN); - lay_set_margins_ltrb(&_::ctx, _::root, 5, 5, 5, 5); - - return CreateWindowA(className.c_str(), - title.c_str(), - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - hInstance, - nullptr); -} + void onClick(std::function cb) + { + onClickHandlers.push_back(cb); + } + private: + std::vector> onClickHandlers; + }; + + struct CheckBox : Hwnd + { + CheckBox(Window *window, std::string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) + : Hwnd(window, WC_BUTTONA, title.c_str(), parent, w, h, contain, behave) + { + addStyle(BS_CHECKBOX); + window->handlers[WM_COMMAND].push_back([&](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + if ((HWND)lParam == this->hwnd && HIWORD(wParam) == BN_CLICKED) + SendMessageA(this->hwnd, BM_SETCHECK, SendMessageA(this->hwnd, BM_GETCHECK, 0, 0) ? BST_UNCHECKED : BST_CHECKED, 0); + }); + } + }; -bool -UpdateWindow(HWND hwnd) -{ - MSG msg; - if (GetMessage(&msg, nullptr, 0, 0) > 0) { - TranslateMessage(&msg); - DispatchMessage(&msg); - return true; - } - return false; -} + struct ListBox : Hwnd + { + ListBox(Window *window, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) + : Hwnd(window, WC_LISTBOXA, "", parent, w, h, contain, behave) + { + addStyle(WS_BORDER); + //addStyle(WS_VSCROLL); + } -void -ShowWindow(HWND hwnd) -{ - ShowWindow(hwnd, true); - - EnumChildWindows( - hwnd, - [](HWND hwnd, LPARAM lParam) -> BOOL { - HFONT guiFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT); - SendMessage(hwnd, WM_SETFONT, (WPARAM)guiFont, MAKELPARAM(TRUE, 0)); - return TRUE; - }, - 0); -} + void addString(std::string str) + { + SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)str.c_str()); + } -HWND -Button(HWND hwnd, string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) -{ - lay_id lId = lay_item(&_::ctx); - lay_insert(&_::ctx, parent, lId); - lay_set_size_xy(&_::ctx, lId, w, h); - lay_set_contain(&_::ctx, lId, contain); - lay_set_behave(&_::ctx, lId, behave); - - HWND result = CreateWindowExA(0, - WC_BUTTONA, - title.c_str(), - WS_VISIBLE | WS_CHILD, - 0, 0, 0, 0, - hwnd, - nullptr, - nullptr, - nullptr); - _::lIds[result] = lId; - return result; -} + int getSelectedIndex() + { + return SendMessage(hwnd, LB_GETCURSEL, 0, 0); + } -HWND -ListBox(HWND hwnd, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) -{ - lay_id lId = lay_item(&_::ctx); - lay_insert(&_::ctx, parent, lId); - lay_set_size_xy(&_::ctx, lId, w, h); - lay_set_contain(&_::ctx, lId, contain); - lay_set_behave(&_::ctx, lId, behave); - - HWND result = CreateWindowExA(0, - WC_LISTBOXA, - "", - WS_VISIBLE | WS_CHILD | WS_BORDER | WS_VSCROLL, - 0, 0, 0, 0, - hwnd, - nullptr, - nullptr, - nullptr); - _::lIds[result] = lId; - return result; -} + int findString(std::string str) + { + return SendMessageA(hwnd, LB_FINDSTRINGEXACT, -1, (LPARAM)str.c_str()); + } -void -ListAddString(HWND hwnd, string str) -{ - SendMessage(hwnd, LB_ADDSTRING, 0, (LPARAM)str.c_str()); -} + std::string getText(int index) + { + int len = SendMessageA(hwnd, LB_GETTEXTLEN, index, 0); + std::string result(len, 0); + SendMessage(hwnd, LB_GETTEXT, index, (LPARAM)result.data()); + return result; + } -int -ListGetSelectedIndex(HWND hwnd) -{ - int sel = SendMessage(hwnd, LB_GETCURSEL, 0, 0); - return sel; -} + void clear() + { + SendMessageA(hwnd, LB_RESETCONTENT, 0, 0); + } -int ListFindString(HWND hwnd, string str) -{ - return SendMessageA(hwnd, LB_FINDSTRINGEXACT, -1, (LPARAM)str.c_str()); -} + void remove(int index) + { + SendMessageA(hwnd, LB_DELETESTRING, index, 0); + } + }; -string -ListGetText(HWND hwnd, int index) -{ - char buffer[1024]; - SendMessage(hwnd, LB_GETTEXT, index, (LPARAM)buffer); - return string(buffer); + lay_id createLayId(lay_context *ctx, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) + { + lay_id lId = lay_item(ctx); + lay_insert(ctx, parent, lId); + lay_set_size_xy(ctx, lId, w, h); + lay_set_contain(ctx, lId, contain); + lay_set_behave(ctx, lId, behave); + return lId; + } } -void -ListClear(HWND hwnd) -{ - SendMessageA(hwnd, LB_RESETCONTENT, 0, 0); -} -void ListRemove(HWND hwnd, int index) -{ - SendMessageA(hwnd, LB_DELETESTRING, index, 0); -} -HWND -CheckBox(HWND hwnd, string title, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) -{ - lay_id lId = lay_item(&_::ctx); - lay_insert(&_::ctx, parent, lId); - lay_set_size_xy(&_::ctx, lId, w, h); - lay_set_contain(&_::ctx, lId, contain); - lay_set_behave(&_::ctx, lId, behave); - - HWND result = CreateWindowExA(0, - WC_BUTTONA, - title.c_str(), - WS_VISIBLE | WS_CHILD | BS_CHECKBOX, - 0, 0, 0, 0, - hwnd, - nullptr, - nullptr, - nullptr); - _::lIds[result] = lId; - return result; -} -void SetStyle(HWND hwnd, DWORD style) +win::Hwnd::Hwnd(Window *window, LPCSTR className, LPCSTR windowName, lay_id parent, lay_scalar w, lay_scalar h, uint32_t contain, uint32_t behave) { - SetWindowLongPtrA(hwnd, GWL_STYLE, style); -} -DWORD GetStyle(HWND hwnd) -{ - return GetWindowLongPtrA(hwnd, GWL_STYLE); -} -void AddStyle(HWND hwnd, DWORD style) -{ - SetWindowLongPtrA(hwnd, GWL_STYLE, GetStyle(hwnd) | style); -} -void RemoveStyle(HWND hwnd, DWORD style) -{ - SetWindowLongPtrA(hwnd, GWL_STYLE, GetStyle(hwnd) & (~style)); -} + this->window = window; + + lId = createLayId(&window->ctx, parent, w, h, contain, behave); + + hwnd = CreateWindowExA(0, + className, + windowName, + WS_VISIBLE | WS_CHILD, + 0, + 0, + 0, + 0, + window->hwnd, + nullptr, + nullptr, + nullptr); + + window->handlers[WM_SIZE].push_back([this](HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { + lay_vec4 rect = lay_get_rect(&this->window->ctx, this->lId); + SetWindowPos(this->hwnd, HWND_TOP, + rect[0], + rect[1], + rect[2], + rect[3], + SWP_NOZORDER + ); + }); } \ No newline at end of file