Skip to content

Instantly share code, notes, and snippets.

@emoacht
Created May 20, 2022 12:15
Show Gist options
  • Save emoacht/f42a00c838157212977134927ad49f38 to your computer and use it in GitHub Desktop.
Save emoacht/f42a00c838157212977134927ad49f38 to your computer and use it in GitHub Desktop.
Move a window at the center of monitor.
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