Created
December 5, 2022 23:36
-
-
Save emoacht/bb085f26429439152f55135eca02a6d9 to your computer and use it in GitHub Desktop.
Moves a specified Window to the center of a monitor where the cursor locates.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Runtime.InteropServices; | |
using System.Windows; | |
using System.Windows.Interop; | |
public static class WindowHelper | |
{ | |
/// <summary> | |
/// Moves a specified Window to the center of a monitor where the cursor locates. | |
/// </summary> | |
/// <param name="window">Window to be moved</param> | |
/// <returns> | |
/// This should be called before Loaded event such as ArrangeOverride method. | |
/// </returns> | |
public static bool MoveToCenter(Window window) | |
{ | |
if (window.WindowStartupLocation != WindowStartupLocation.CenterScreen) | |
return false; | |
if (window.IsLoaded) | |
return false; | |
return MoveToCenterBase(window); | |
} | |
public static bool MoveToCenterBase(Window window) | |
{ | |
if (!GetCursorPos(out POINT cursorPoint)) | |
return false; | |
var monitorHandle = MonitorFromPoint( | |
cursorPoint, | |
MONITOR_DEFAULTTO.MONITOR_DEFAULTTONULL); | |
if (monitorHandle == IntPtr.Zero) | |
return false; | |
var monitorInfo = new MONITORINFO() { cbSize = (uint)Marshal.SizeOf<MONITORINFO>() }; | |
if (!GetMonitorInfo( | |
monitorHandle, | |
ref monitorInfo)) | |
{ | |
return false; | |
} | |
var windowHandle = new WindowInteropHelper(window).EnsureHandle(); | |
if (windowHandle == IntPtr.Zero) | |
return false; | |
if (!GetWindowPlacement( | |
windowHandle, | |
out WINDOWPLACEMENT windowPlacement)) | |
{ | |
return false; | |
} | |
int left = monitorInfo.rcWork.left + Math.Max(0, (int)((monitorInfo.rcWork.Width - windowPlacement.rcNormalPosition.Width) / 2D)); | |
int top = monitorInfo.rcWork.top + Math.Max(0, (int)((monitorInfo.rcWork.Height - windowPlacement.rcNormalPosition.Height) / 2D)); | |
windowPlacement.rcNormalPosition = new RECT(left, top, width: windowPlacement.rcNormalPosition.Width, height: windowPlacement.rcNormalPosition.Height); | |
return SetWindowPlacement( | |
windowHandle, | |
ref windowPlacement); | |
} | |
#region Win32 | |
[DllImport("User32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool GetCursorPos( | |
out POINT lpPoint); | |
[DllImport("User32.dll")] | |
private static extern IntPtr MonitorFromPoint( | |
POINT pt, | |
MONITOR_DEFAULTTO dwFlags); | |
private enum MONITOR_DEFAULTTO : uint | |
{ | |
MONITOR_DEFAULTTONULL = 0x00000000, | |
MONITOR_DEFAULTTOPRIMARY = 0x00000001, | |
MONITOR_DEFAULTTONEAREST = 0x00000002, | |
} | |
[DllImport("User32.dll")] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool GetMonitorInfo( | |
IntPtr hMonitor, | |
ref MONITORINFO lpmi); | |
[StructLayout(LayoutKind.Sequential)] | |
private struct MONITORINFO | |
{ | |
public uint cbSize; | |
public RECT rcMonitor; | |
public RECT rcWork; | |
public uint dwFlags; | |
} | |
[DllImport("User32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool GetWindowPlacement( | |
IntPtr hWnd, | |
out WINDOWPLACEMENT lpwndpl); | |
[DllImport("User32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool SetWindowPlacement( | |
IntPtr hWnd, | |
[In] ref WINDOWPLACEMENT lpwndpl); | |
[StructLayout(LayoutKind.Sequential)] | |
private struct WINDOWPLACEMENT | |
{ | |
public uint length; | |
public uint flags; | |
public uint showCmd; | |
public POINT ptMinPosition; | |
public POINT ptMaxPosition; | |
public RECT rcNormalPosition; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
private struct POINT | |
{ | |
public int x; | |
public int y; | |
} | |
[StructLayout(LayoutKind.Sequential)] | |
private struct RECT | |
{ | |
public int left; | |
public int top; | |
public int right; | |
public int bottom; | |
public int Width => right - left; | |
public int Height => bottom - top; | |
public RECT(int x, int y, int width, int height) | |
{ | |
left = x; | |
top = y; | |
right = x + width; | |
bottom = y + height; | |
} | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment