using System; using System.Runtime.InteropServices; using System.Windows; using System.Windows.Interop; namespace ClientApp.MagicCode { /// /// Fixes the issue with Windows of Style covering the taskbar /// public class WindowResizer { #region Private Members /// /// The window to handle the resizing for /// private Window mWindow; #endregion #region Dll Imports [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] static extern bool GetCursorPos(out POINT lpPoint); [DllImport("user32.dll")] static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); [DllImport("user32.dll", SetLastError = true)] static extern IntPtr MonitorFromPoint(POINT pt, MonitorOptions dwFlags); #endregion #region Constructor /// /// Default constructor /// /// The window to monitor and correctly maximize /// The callback for the host to adjust the maximum available size if needed public WindowResizer(Window window) { mWindow = window; // Listen out for source initialized to setup mWindow.SourceInitialized += Window_SourceInitialized; } #endregion #region Initialize /// /// Initialize and hook into the windows message pump /// /// /// private void Window_SourceInitialized(object sender, System.EventArgs e) { // Get the handle of this window var handle = (new WindowInteropHelper(mWindow)).Handle; var handleSource = HwndSource.FromHwnd(handle); // If not found, end if (handleSource == null) return; // Hook into it's Windows messages handleSource.AddHook(WindowProc); } #endregion #region Windows Proc /// /// Listens out for all windows messages for this window /// /// /// /// /// /// /// private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { // Handle the GetMinMaxInfo of the Window case 0x0024:/* WM_GETMINMAXINFO */ WmGetMinMaxInfo(hwnd, lParam); handled = true; break; } return (IntPtr)0; } #endregion /// /// Get the min/max window size for this window /// Correctly accounting for the taskbar size and position /// /// /// private void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam) { POINT lMousePosition; GetCursorPos(out lMousePosition); IntPtr lPrimaryScreen = MonitorFromPoint(new POINT(0, 0), MonitorOptions.MONITOR_DEFAULTTOPRIMARY); MONITORINFO lPrimaryScreenInfo = new MONITORINFO(); if (GetMonitorInfo(lPrimaryScreen, lPrimaryScreenInfo) == false) { return; } IntPtr lCurrentScreen = MonitorFromPoint(lMousePosition, MonitorOptions.MONITOR_DEFAULTTONEAREST); MINMAXINFO lMmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); if (lPrimaryScreen.Equals(lCurrentScreen) == true) { lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcWork.Left; lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcWork.Top; lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcWork.Right - lPrimaryScreenInfo.rcWork.Left; lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcWork.Bottom - lPrimaryScreenInfo.rcWork.Top; } else { lMmi.ptMaxPosition.X = lPrimaryScreenInfo.rcMonitor.Left; lMmi.ptMaxPosition.Y = lPrimaryScreenInfo.rcMonitor.Top; lMmi.ptMaxSize.X = lPrimaryScreenInfo.rcMonitor.Right - lPrimaryScreenInfo.rcMonitor.Left; lMmi.ptMaxSize.Y = lPrimaryScreenInfo.rcMonitor.Bottom - lPrimaryScreenInfo.rcMonitor.Top; } // Now we have the max size, allow the host to tweak as needed Marshal.StructureToPtr(lMmi, lParam, true); } } #region Dll Helper Structures enum MonitorOptions : uint { MONITOR_DEFAULTTONULL = 0x00000000, MONITOR_DEFAULTTOPRIMARY = 0x00000001, MONITOR_DEFAULTTONEAREST = 0x00000002 } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO { public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); public Rectangle rcMonitor = new Rectangle(); public Rectangle rcWork = new Rectangle(); public int dwFlags = 0; } [StructLayout(LayoutKind.Sequential)] public struct Rectangle { public int Left, Top, Right, Bottom; public Rectangle(int left, int top, int right, int bottom) { this.Left = left; this.Top = top; this.Right = right; this.Bottom = bottom; } } [StructLayout(LayoutKind.Sequential)] public struct MINMAXINFO { public POINT ptReserved; public POINT ptMaxSize; public POINT ptMaxPosition; public POINT ptMinTrackSize; public POINT ptMaxTrackSize; }; [StructLayout(LayoutKind.Sequential)] public struct POINT { /// /// x coordinate of point. /// public int X; /// /// y coordinate of point. /// public int Y; /// /// Construct a point of coordinates (x,y). /// public POINT(int x, int y) { this.X = x; this.Y = y; } } #endregion }