[idd] helper/config: implement window positioning, fonts, and high DPI support

This commit is contained in:
Quantum
2025-09-15 21:34:23 -04:00
committed by Geoffrey McRae
parent e123e02e15
commit 4585362f54
6 changed files with 128 additions and 3 deletions

View File

@@ -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<HWND>({ *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;
}

View File

@@ -3,6 +3,8 @@
#include "CStaticWidget.h"
#include <functional>
#include <memory>
#include <wrl.h>
#include "UIHelpers.h"
class CConfigWindow : public CWindow
{
@@ -11,10 +13,15 @@ class CConfigWindow : public CWindow
std::unique_ptr<CStaticWidget> m_version;
std::function<void()> m_onDestroy;
double m_scale;
Microsoft::WRL::Wrappers::HandleT<FontTraits> 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();

View File

@@ -14,5 +14,5 @@ public:
void destroy();
HWND hwnd() { return m_hwnd; }
operator HWND() { return m_hwnd; }
operator HWND() const { return m_hwnd; }
};

View File

@@ -192,6 +192,7 @@ copy /Y "$(ProjectDir)VERSION" "$(SolutionDir)$(Platform)\$(Configuration)\LGIdd
<ClInclude Include="CPipeClient.h" />
<ClInclude Include="CStaticWidget.h" />
<ClInclude Include="CWidget.h" />
<ClInclude Include="UIHelpers.h" />
<ClInclude Include="CWindow.h" />
</ItemGroup>
<ItemGroup>

View File

@@ -29,6 +29,16 @@
<ClCompile Include="CNotifyWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="$(SolutionDir)LGCommon\*.cpp" />
<ClCompile Include="CConfigWindow.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CStaticWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CWidget.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<CLInclude Include="$(SolutionDir)LGCommon\*.h" />
@@ -43,6 +53,20 @@
<ClInclude Include="CNotifyWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<CLInclude Include="$(SolutionDir)LGCommon\*.h" />
<CLInclude Include="$(SolutionDir)LGCommon\*.h" />
<ClInclude Include="CConfigWindow.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CStaticWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CWidget.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UIHelpers.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />

View File

@@ -0,0 +1,49 @@
#pragma once
#include <windows.h>
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));
}
};