From 93784cc630193952527778948563f51d9659231a Mon Sep 17 00:00:00 2001 From: Jason Ross Date: Mon, 1 Jun 2026 16:16:49 -0500 Subject: [PATCH] Fix tiny window on high-DPI displays and tray restore un-maximizing AppWindow.Resize/Move take physical pixels and the app is PerMonitorV2-aware, but RestoreWindowBounds passed the logical default/minimum sizes unscaled, so on a high-DPI display (e.g. a 200% laptop panel) the window came out at half size. That showed up when restoring from the tray, since RestoreMainWindow's SW_RESTORE un-maximizes to that size. Scale the default/minimum sizes by the window DPI via GetDpiForWindow. Also stop RestoreMainWindow from un-maximizing: it called SW_RESTORE unconditionally, collapsing a window that was hidden to the tray while maximized. Only SW_RESTORE when the window is minimized; otherwise SW_SHOW preserves state. Verified on a 200% display: the restored window is 1520x1360 (= 760x680 logical) and stays maximized across tray hide/show. Co-Authored-By: Claude Opus 4.8 --- .../MainWindow.cs | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/LibreHardwareMonitor.Windows.WinUI/MainWindow.cs b/LibreHardwareMonitor.Windows.WinUI/MainWindow.cs index 64f4240..2d57572 100644 --- a/LibreHardwareMonitor.Windows.WinUI/MainWindow.cs +++ b/LibreHardwareMonitor.Windows.WinUI/MainWindow.cs @@ -788,7 +788,10 @@ public sealed class MainWindow : Window IntPtr hwnd = WindowNative.GetWindowHandle(this); _isMainWindowHidden = false; ShowWindow(hwnd, ShowWindowShow); - ShowWindow(hwnd, ShowWindowRestore); + // Only un-minimize. The window is hidden to the tray with SW_HIDE while keeping its maximized state, so + // SW_SHOW alone brings it back as it was; an unconditional SW_RESTORE would also un-maximize it. + if (IsIconic(hwnd)) + ShowWindow(hwnd, ShowWindowRestore); Activate(); } @@ -1542,8 +1545,14 @@ public sealed class MainWindow : Window private void RestoreWindowBounds() { - int width = Math.Max(470, ViewModel.Settings.GetValue("mainForm.Width", 760)); - int height = Math.Max(640, ViewModel.Settings.GetValue("mainForm.Height", 680)); + // AppWindow.Resize takes physical pixels and the app is PerMonitorV2 DPI-aware, so the logical default/minimum + // sizes must be scaled by the window's DPI. Without this, on a high-DPI display (e.g. a 200% laptop panel) the + // window — and any SW_RESTORE from the tray, which un-maximizes to this size — came out at half size. + double scale = GetWindowScale(); + int minWidth = (int)Math.Round(470 * scale); + int minHeight = (int)Math.Round(640 * scale); + int width = Math.Max(minWidth, ViewModel.Settings.GetValue("mainForm.Width", (int)Math.Round(760 * scale))); + int height = Math.Max(minHeight, ViewModel.Settings.GetValue("mainForm.Height", (int)Math.Round(680 * scale))); _appWindow.Resize(new SizeInt32(width, height)); int x = ViewModel.Settings.GetValue("mainForm.Location.X", int.MinValue); @@ -1552,6 +1561,12 @@ public sealed class MainWindow : Window _appWindow.Move(new PointInt32(x, y)); } + private double GetWindowScale() + { + uint dpi = GetDpiForWindow(WindowNative.GetWindowHandle(this)); + return dpi == 0 ? 1.0 : dpi / 96.0; + } + private void MaximizeWindow() { if (_appWindow.Presenter is OverlappedPresenter presenter) @@ -1787,6 +1802,9 @@ public sealed class MainWindow : Window [return: MarshalAs(UnmanagedType.Bool)] private static extern bool IsIconic(IntPtr windowHandle); + [DllImport("user32.dll")] + private static extern uint GetDpiForWindow(IntPtr windowHandle); + private sealed record ParameterEditorRow(IParameter Parameter, Grid Container, CheckBox UseDefault, TextBox Value); private static void Bind(DependencyObject target, DependencyProperty property, object source, string path, BindingMode mode = BindingMode.OneWay)