diff --git a/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs b/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs index f6b0b94d44..8674e63303 100644 --- a/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs +++ b/src/modules/peek/Peek.UI/Extensions/HWNDExtensions.cs @@ -4,8 +4,10 @@ using System.Text; using Peek.UI.Native; +using Windows.Foundation; using Windows.Win32; using Windows.Win32.Foundation; +using Windows.Win32.Graphics.Gdi; namespace Peek.UI.Extensions { @@ -47,5 +49,14 @@ namespace Peek.UI.Extensions { return PInvoke.FindWindowEx(windowHandle, HWND.Null, className, null); } + + internal static Size GetMonitorSize(this HWND hwnd) + { + var monitor = PInvoke.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); + MONITORINFO info = default(MONITORINFO); + info.cbSize = 40; + PInvoke.GetMonitorInfo(monitor, ref info); + return new Size(info.rcMonitor.Size.Width, info.rcMonitor.Size.Height); + } } } diff --git a/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs b/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs index 3e7f65c408..b113003c1f 100644 --- a/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs +++ b/src/modules/peek/Peek.UI/Extensions/WindowExtensions.cs @@ -2,30 +2,18 @@ // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Runtime.InteropServices; using Microsoft.UI.Xaml; -using Windows.Foundation; using Windows.Win32; using Windows.Win32.Foundation; using Windows.Win32.Graphics.Gdi; +using Windows.Win32.UI.WindowsAndMessaging; using WinUIEx; namespace Peek.UI.Extensions { public static class WindowExtensions { - public static Size GetMonitorSize(this Window window) - { - var hwnd = new HWND(window.GetWindowHandle()); - var hwndDesktop = PInvoke.MonitorFromWindow(hwnd, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); - MONITORINFO info = default(MONITORINFO); - info.cbSize = 40; - PInvoke.GetMonitorInfo(hwndDesktop, ref info); - double monitorWidth = info.rcMonitor.left + info.rcMonitor.right; - double monitorHeight = info.rcMonitor.bottom + info.rcMonitor.top; - - return new Size(monitorWidth, monitorHeight); - } - public static double GetMonitorScale(this Window window) { var hwnd = new HWND(window.GetWindowHandle()); @@ -53,5 +41,33 @@ namespace Peek.UI.Extensions PInvoke.ShowWindow(new HWND(windowHandle), Windows.Win32.UI.WindowsAndMessaging.SHOW_WINDOW_CMD.SW_SHOW); PInvoke.AttachThreadInput(windowThreadProcessId, currentThreadId, false); } + + internal static void CenterOnMonitor(this Window window, HWND hwndDesktop, double? width = null, double? height = null) + { + var hwndToCenter = new HWND(window.GetWindowHandle()); + var monitor = PInvoke.MonitorFromWindow(hwndDesktop, MONITOR_FROM_FLAGS.MONITOR_DEFAULTTONEAREST); + MONITORINFO info = default(MONITORINFO); + info.cbSize = 40; + PInvoke.GetMonitorInfo(monitor, ref info); + var dpi = PInvoke.GetDpiForWindow(new HWND(hwndDesktop)); + PInvoke.GetWindowRect(new HWND(hwndToCenter), out RECT windowRect); + var scalingFactor = dpi / 96d; + var w = width.HasValue ? (int)(width * scalingFactor) : windowRect.right - windowRect.left; + var h = height.HasValue ? (int)(height * scalingFactor) : windowRect.bottom - windowRect.top; + var cx = (info.rcMonitor.left + info.rcMonitor.right) / 2; + var cy = (info.rcMonitor.bottom + info.rcMonitor.top) / 2; + var left = cx - (w / 2); + var top = cy - (h / 2); + SetWindowPosOrThrow(new HWND(hwndToCenter), default(HWND), left, top, w, h, SET_WINDOW_POS_FLAGS.SWP_SHOWWINDOW); + } + + private static void SetWindowPosOrThrow(HWND hWnd, HWND hWndInsertAfter, int x, int y, int cx, int cy, SET_WINDOW_POS_FLAGS uFlags) + { + bool result = PInvoke.SetWindowPos(hWnd, hWndInsertAfter, x, y, cx, cy, uFlags); + if (!result) + { + Marshal.ThrowExceptionForHR(Marshal.GetLastWin32Error()); + } + } } } diff --git a/src/modules/peek/Peek.UI/MainWindow.xaml.cs b/src/modules/peek/Peek.UI/MainWindow.xaml.cs index 0db33d20db..76ac8160fc 100644 --- a/src/modules/peek/Peek.UI/MainWindow.xaml.cs +++ b/src/modules/peek/Peek.UI/MainWindow.xaml.cs @@ -103,7 +103,9 @@ namespace Peek.UI /// PreviewSizeChangedArgs private void FilePreviewer_PreviewSizeChanged(object sender, PreviewSizeChangedArgs e) { - var monitorSize = this.GetMonitorSize(); + var foregroundWindowHandle = Windows.Win32.PInvoke.GetForegroundWindow(); + + var monitorSize = foregroundWindowHandle.GetMonitorSize(); // If no size is requested, try to fit to the monitor size. Size requestedSize = e.WindowSizeRequested ?? monitorSize; @@ -131,7 +133,7 @@ namespace Peek.UI if (!TitleBarControl.Pinned) { - this.CenterOnScreen(desiredScaledWidth, desiredScaledHeight); // re-center if not pinned + this.CenterOnMonitor(foregroundWindowHandle, desiredScaledWidth, desiredScaledHeight); // re-center if not pinned } this.Show(); diff --git a/src/modules/peek/Peek.UI/NativeMethods.txt b/src/modules/peek/Peek.UI/NativeMethods.txt index e60c0fb4ab..7cc3a51db2 100644 --- a/src/modules/peek/Peek.UI/NativeMethods.txt +++ b/src/modules/peek/Peek.UI/NativeMethods.txt @@ -11,4 +11,8 @@ GetWindowTextLength FindWindowEx SID_STopLevelBrowser GetClassName -_SVGIO \ No newline at end of file +_SVGIO +MONITORINFO +GetWindowRect +SET_WINDOW_POS_FLAGS +SetWindowPos \ No newline at end of file