Created
May 20, 2022 12:15
-
-
Save emoacht/f42a00c838157212977134927ad49f38 to your computer and use it in GitHub Desktop.
Move a window at the center of monitor.
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 class WindowCenterMover | |
{ | |
#region Win32 | |
[DllImport("User32.dll")] | |
private static extern IntPtr MonitorFromWindow( | |
IntPtr hwnd, | |
MONITOR_DEFAULTTO dwFlags); | |
private enum MONITOR_DEFAULTTO : uint | |
{ | |
MONITOR_DEFAULTTONULL = 0x00000000, | |
MONITOR_DEFAULTTOPRIMARY = 0x00000001, | |
MONITOR_DEFAULTTONEAREST = 0x00000002, | |
} | |
[DllImport("User32.dll", SetLastError = true)] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool GetWindowRect( | |
IntPtr hWnd, | |
out RECT lpRect); | |
[DllImport("User32.dll")] | |
[return: MarshalAs(UnmanagedType.Bool)] | |
private static extern bool GetMonitorInfo( | |
IntPtr hMonitor, | |
ref MONITORINFO lpmi); | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] | |
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; | |
public static implicit operator Point(POINT point) => new(point.x, point.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; | |
} | |
public static implicit operator Rect(RECT rect) => new(rect.left, rect.top, rect.Width, rect.Height); | |
} | |
#endregion | |
private readonly Window _window; | |
public WindowCenterMover(Window window) | |
{ | |
_window = window ?? throw new ArgumentNullException(nameof(window)); | |
_window.Loaded += (_, _) => CenterWindow(); | |
_window.SizeChanged += (_, _) => CenterWindow(); | |
} | |
private void CenterWindow() | |
{ | |
if (_window.WindowState != WindowState.Normal) | |
return; | |
var windowHandle = new WindowInteropHelper(_window).EnsureHandle(); | |
if (windowHandle == IntPtr.Zero) | |
return; | |
if (!GetWindowRect(windowHandle, out RECT windowRect)) | |
return; | |
var monitorHandle = MonitorFromWindow(windowHandle, MONITOR_DEFAULTTO.MONITOR_DEFAULTTONULL); | |
if (monitorHandle == IntPtr.Zero) | |
return; | |
var monitorInfo = new MONITORINFO { cbSize = (uint)Marshal.SizeOf<MONITORINFO>() }; | |
if (!GetMonitorInfo(monitorHandle, ref monitorInfo)) | |
return; | |
var workRect = monitorInfo.rcWork; | |
if ((workRect.Width < windowRect.Width) || (workRect.Height < windowRect.Height)) | |
return; | |
if (!GetWindowPlacement(windowHandle, out WINDOWPLACEMENT windowPlacement)) | |
return; | |
windowPlacement.rcNormalPosition = new RECT( | |
x: (int)(workRect.left + (workRect.Width - windowRect.Width) / 2D), | |
y: (int)(workRect.top + (workRect.Height - windowRect.Height) / 2D), | |
width: windowRect.Width, | |
height: windowRect.Height); | |
SetWindowPlacement(windowHandle, ref windowPlacement); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment