using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Windows.Interop; namespace System.Windows.Forms { public enum SizingAction { None = 0, North = 3, South = 6, East = 2, West = 1, NorthEast = 5, NorthWest = 4, SouthEast = 8, SouthWest = 7 } internal static class NativeMethods { const int WM_SYSCOMMAND = 0x112; const int SC_SIZE = 0xF000; const int GWL_STYLE = -16; const int GWL_EXSTYLE = -20; const int WS_EX_DLGMODALFRAME = 0x0001; const int SW_MAXIMIZE = 3; const int WS_MAXIMIZEBOX = 0x10000; const int WS_MINIMIZEBOX = 0x20000; const int WM_SETICON = 0x0080; [DllImport("user32.dll", SetLastError = true)] private static extern bool MoveWindow(IntPtr hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint); [DllImport("user32.dll")] static extern int GetWindowLong(IntPtr hwnd, int index); [DllImport("user32.dll")] static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle); [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool GetCursorPos(ref Win32Point pt); [DllImport("user32.dll")] public static extern int GetDoubleClickTime(); [DllImport("user32.dll")] private extern static int GetWindowRect(IntPtr hWnd, ref RECT lpRect); [DllImport("user32.dll")] private extern static int GetClientRect(IntPtr hWnd, ref RECT lpRect); [DllImport("user32.dll")] private static extern IntPtr MonitorFromPoint(Win32Point pt, int flags); [DllImport("user32.dll", SetLastError = true)] public static extern IntPtr MonitorFromWindow(HandleRef handle, int flags); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern bool GetMonitorInfo(HandleRef hmonitor, [In][Out] MONITORINFOEX info); [DllImport("user32.dll")] public static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lprcClip, MonitorEnumDelegate lpfnEnum, IntPtr dwData); public delegate bool MonitorEnumDelegate(IntPtr hMonitor, IntPtr hdcMonitor, ref RECT lprcMonitor, IntPtr dwData); [DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); [DllImport("dwmapi.dll", PreserveSig = true)] private static extern int DwmSetWindowAttribute(IntPtr hwnd, int attr, ref int attrValue, int attrSize); [DllImport("dwmapi.dll")] private static extern int DwmExtendFrameIntoClientArea(IntPtr hWnd, ref NativeMethods.RECT pMarInset); [StructLayout(LayoutKind.Sequential)] public struct Win32Point { public Int32 X; public Int32 Y; }; [StructLayout(LayoutKind.Sequential)] public struct RECT { public int left; public int top; public int right; public int bottom; public int Width => right - left; public int Height => bottom - top; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)] public class MONITORINFOEX { internal int cbSize = SizeOf(); internal RECT rcMonitor; internal RECT rcWork; internal int dwFlags; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] internal char[] szDevice = new char[32]; private static int SizeOf() => Marshal.SizeOf(typeof(MONITORINFOEX)); } [StructLayout(LayoutKind.Sequential)] public struct MINMAXINFO { public Win32Point ptReserved; public Win32Point ptMaxSize; public Win32Point ptMaxPosition; public Win32Point ptMinTrackSize; public Win32Point ptMaxTrackSize; }; [StructLayout(LayoutKind.Sequential)] private struct WINDOWPLACEMENT { public int length; public int flags; public int showCmd; public Win32Point ptMinPosition; public Win32Point ptMaxPosition; public RECT rcNormalPosition; public RECT rcDevice; } [DllImport("user32.dll")] private static extern bool GetWindowPlacement(IntPtr hWnd, ref WINDOWPLACEMENT lpwndpl); public static bool IsWindowMaximized(IntPtr hWnd) { var wpl = new WINDOWPLACEMENT(); GetWindowPlacement(hWnd, ref wpl); return wpl.showCmd == SW_MAXIMIZE; } [DllImport("user32.dll")] private static extern IntPtr GetActiveWindow(); public static Window ActiveWindow() { IntPtr active = GetActiveWindow(); return System.Windows.Application.Current.Windows.OfType() .SingleOrDefault(window => new WindowInteropHelper(window).Handle == active); } [DllImport("Shcore.dll")] private static extern IntPtr GetDpiForMonitor([In] IntPtr hmonitor, [In] uint dpiType, [Out] out uint dpiX, [Out] out uint dpiY); public static int GetDpiForMonitor(IntPtr mon) { try { GetDpiForMonitor(mon, 0, out uint dpiX, out uint dpiY); return (int)dpiX; } catch { using (Graphics gr = Graphics.FromHwnd(IntPtr.Zero)) return (int)gr.DpiX; } } public static void MoveWindow(Form form, Rectangle rect) { IntPtr handle = new WindowInteropHelper(form.window).EnsureHandle(); // The first move puts it on the correct monitor, which triggers WM_DPICHANGED // The +1/-1 coerces WPF to update Window.Top/Left/Width/Height in the second move MoveWindow(handle, rect.Left + 1, rect.Top, rect.Width - 1, rect.Height, false); MoveWindow(handle, rect.Left, rect.Top, rect.Width, rect.Height, true); } public static Drawing.Point GetMousePosition() { var w32Mouse = new Win32Point(); GetCursorPos(ref w32Mouse); return new Drawing.Point(w32Mouse.X, w32Mouse.Y); } public static IntPtr GetCurrentMonitorFromMousePosition() { var w32Mouse = new Win32Point(); GetCursorPos(ref w32Mouse); return MonitorFromPoint(w32Mouse, 2); } public static IntPtr GetMonitorFromPoint(int x, int y) { return MonitorFromPoint(new Win32Point() { X = x, Y = y }, 2); } public static RECT WorkAreaBoundsForMointor(IntPtr hMonitor) { MONITORINFOEX info = new MONITORINFOEX(); GetMonitorInfo(new HandleRef(null, hMonitor), info); return info.rcWork; } public static Drawing.Size GetClientSizeDelta(Window window) { IntPtr handle = new WindowInteropHelper(window).EnsureHandle(); RECT rect = new RECT(); GetWindowRect(handle, ref rect); RECT clientRect = new RECT(); GetClientRect(handle, ref clientRect); return new Drawing.Size(rect.Width - clientRect.Width, rect.Height - clientRect.Height); } public static void RemoveWindowItems(Window window, bool icon, bool minimize, bool maximize) { IntPtr hwnd = new WindowInteropHelper(window).EnsureHandle(); if (!icon) { int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE); SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_DLGMODALFRAME); // this removes icon if it is set in app resources (case: the WpfDemo) SendMessage(hwnd, WM_SETICON, new IntPtr(1), IntPtr.Zero); SendMessage(hwnd, WM_SETICON, IntPtr.Zero, IntPtr.Zero); } if (!minimize || !maximize) { int currentStyle = GetWindowLong(hwnd, GWL_STYLE); if (!minimize) currentStyle &= ~WS_MINIMIZEBOX; if (!maximize) currentStyle &= ~WS_MAXIMIZEBOX; SetWindowLong(hwnd, GWL_STYLE, currentStyle); } } public static void DragSize(IntPtr handle, SizingAction sizingAction) { SendMessage(handle, WM_SYSCOMMAND, (IntPtr)(SC_SIZE + sizingAction), IntPtr.Zero); } public static bool DropShadow(IntPtr handle, bool shadow) { try { int val = 2; int ret1 = DwmSetWindowAttribute(handle, 2, ref val, 4); if (ret1 == 0) { var m = new RECT { left = 0, top = shadow ? 1 : 0, right = 0, bottom = 0 }; int ret2 = DwmExtendFrameIntoClientArea(handle, ref m); return ret2 == 0; } else { return false; } } catch { // Probably dwmapi.dll not found (incompatible OS) return false; } } } }