diff --git a/idd/LGIddHelper/CConfigWindow.cpp b/idd/LGIddHelper/CConfigWindow.cpp index 9f9256b6..8e20331c 100644 --- a/idd/LGIddHelper/CConfigWindow.cpp +++ b/idd/LGIddHelper/CConfigWindow.cpp @@ -11,28 +11,65 @@ bool CConfigWindow::registerClass() WNDCLASSEX wx = {}; populateWindowClass(wx); wx.hIconSm = wx.hIcon = LoadIcon(hInstance, IDI_APPLICATION); + wx.hbrBackground = (HBRUSH)(COLOR_3DFACE + 1); wx.lpszClassName = L"LookingGlassIddConfig"; s_atom = RegisterClassEx(&wx); return s_atom; } -CConfigWindow::CConfigWindow() +CConfigWindow::CConfigWindow() : m_scale(1) { if (!CreateWindowEx(0, MAKEINTATOM(s_atom), L"Looking Glass IDD Configuration", - WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 300, 200, + WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, CW_USEDEFAULT, CW_USEDEFAULT, 500, 400, NULL, NULL, hInstance, this)) { DEBUG_ERROR_HR(GetLastError(), "Failed to create window"); } + m_scale = GetDpiForWindow(m_hwnd) / 96.0; m_version.reset(new CStaticWidget(L"Looking Glass IDD " LG_VERSION_STR, WS_CHILD | WS_VISIBLE | SS_CENTERIMAGE, m_hwnd)); + updateFont(); +} + +void CConfigWindow::updateFont() +{ + NONCLIENTMETRICS ncmMetrics = { sizeof(NONCLIENTMETRICS) }; + UINT dpi = GetDpiForWindow(m_hwnd); + if (!SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof ncmMetrics, &ncmMetrics, 0, dpi)) + { + DEBUG_ERROR_HR(GetLastError(), "SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS)"); + return; + } + + m_font.Attach(CreateFontIndirect(&ncmMetrics.lfMessageFont)); + if (!m_font.IsValid()) + { + DEBUG_ERROR_HR(GetLastError(), "CreateFontIndirect(lfMessageFont)"); + return; + } + + for (HWND child : std::initializer_list({ *m_version })) + SendMessage(child, WM_SETFONT, (WPARAM)m_font.Get(), 1); } LRESULT CConfigWindow::handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { + case WM_SIZE: + return onResize(LOWORD(lParam), HIWORD(lParam)); + case WM_DPICHANGED: + { + LPRECT lpBox = (LPRECT)lParam; + m_scale = LOWORD(wParam) / 96.0; + updateFont(); + SetWindowPos(m_hwnd, NULL, lpBox->left, lpBox->top, lpBox->right - lpBox->left, + lpBox->bottom - lpBox->top, SWP_NOZORDER | SWP_NOACTIVATE); + onResize(lpBox->right - lpBox->left, lpBox->bottom - lpBox->top); + RedrawWindow(m_hwnd, NULL, NULL, RDW_ERASE | RDW_INVALIDATE | RDW_ALLCHILDREN); + return 0; + } default: return CWindow::handleMessage(uMsg, wParam, lParam); } @@ -49,3 +86,10 @@ LRESULT CConfigWindow::onFinal() m_onDestroy(); return CWindow::onFinal(); } + +LRESULT CConfigWindow::onResize(DWORD width, DWORD height) +{ + WidgetPositioner pos(m_scale, width, height); + pos.pinTopLeftRight(*m_version, 12, 12, 12, 20); + return 0; +} diff --git a/idd/LGIddHelper/CConfigWindow.h b/idd/LGIddHelper/CConfigWindow.h index 9665599c..b25cdb2b 100644 --- a/idd/LGIddHelper/CConfigWindow.h +++ b/idd/LGIddHelper/CConfigWindow.h @@ -3,6 +3,8 @@ #include "CStaticWidget.h" #include #include +#include +#include "UIHelpers.h" class CConfigWindow : public CWindow { @@ -11,10 +13,15 @@ class CConfigWindow : public CWindow std::unique_ptr m_version; std::function m_onDestroy; + double m_scale; + Microsoft::WRL::Wrappers::HandleT m_font; + + void updateFont(); virtual LRESULT handleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) override; virtual LRESULT onCreate() override; virtual LRESULT onFinal() override; + LRESULT onResize(DWORD width, DWORD height); public: CConfigWindow(); diff --git a/idd/LGIddHelper/CWidget.h b/idd/LGIddHelper/CWidget.h index 28beed43..a50f5905 100644 --- a/idd/LGIddHelper/CWidget.h +++ b/idd/LGIddHelper/CWidget.h @@ -14,5 +14,5 @@ public: void destroy(); HWND hwnd() { return m_hwnd; } - operator HWND() { return m_hwnd; } + operator HWND() const { return m_hwnd; } }; diff --git a/idd/LGIddHelper/LGIddHelper.vcxproj b/idd/LGIddHelper/LGIddHelper.vcxproj index e90ea9ee..998c8f73 100644 --- a/idd/LGIddHelper/LGIddHelper.vcxproj +++ b/idd/LGIddHelper/LGIddHelper.vcxproj @@ -192,6 +192,7 @@ copy /Y "$(ProjectDir)VERSION" "$(SolutionDir)$(Platform)\$(Configuration)\LGIdd + diff --git a/idd/LGIddHelper/LGIddHelper.vcxproj.filters b/idd/LGIddHelper/LGIddHelper.vcxproj.filters index bebc45bc..b39d6583 100644 --- a/idd/LGIddHelper/LGIddHelper.vcxproj.filters +++ b/idd/LGIddHelper/LGIddHelper.vcxproj.filters @@ -29,6 +29,16 @@ Source Files + + + Source Files + + + Source Files + + + Source Files + @@ -43,6 +53,20 @@ Header Files + + + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/idd/LGIddHelper/UIHelpers.h b/idd/LGIddHelper/UIHelpers.h new file mode 100644 index 00000000..548be834 --- /dev/null +++ b/idd/LGIddHelper/UIHelpers.h @@ -0,0 +1,49 @@ +#pragma once +#include + +struct FontTraits +{ + typedef HFONT Type; + inline static bool Close(Type h) { return DeleteObject(h); } + inline static Type GetInvalidValue() { return nullptr; } +}; + +class WidgetPositioner +{ + HDWP hdwp; + double m_scale; + DWORD width, height; + inline int scale(int value) { return (int)round(value * m_scale); } + +public: + WidgetPositioner(double scale, DWORD width, DWORD height) : + m_scale(scale), width(width), height(height), + hdwp(BeginDeferWindowPos(10)) {} + + ~WidgetPositioner() { EndDeferWindowPos(hdwp); } + + void move(HWND child, int x, int y, int cx, int cy) + { + hdwp = DeferWindowPos(hdwp, child, nullptr, x, y, cx, cy, SWP_NOACTIVATE | SWP_NOZORDER); + } + + void pinTopLeft(HWND child, int x, int y, int cx, int cy) + { + move(child, scale(x), scale(y), scale(cx), scale(cy)); + } + + void pinTopRight(HWND child, int x, int y, int cx, int cy) + { + move(child, scale(x), scale(y), width - scale(cx), scale(cy)); + } + + void pinTopLeftRight(HWND child, int x, int y, int rx, int cy) + { + move(child, scale(x), scale(y), width - scale(rx + x), scale(cy)); + } + + void pinLeftTopBottom(HWND child, int x, int y, int cx, int by) + { + move(child, scale(x), scale(y), cx, height - scale(y + by)); + } +};