diff --git a/MahApps.Metro/Behaviours/BorderlessWindowBehavior.cs b/MahApps.Metro/Behaviours/BorderlessWindowBehavior.cs index 2c11dd319e..35ccd73561 100644 --- a/MahApps.Metro/Behaviours/BorderlessWindowBehavior.cs +++ b/MahApps.Metro/Behaviours/BorderlessWindowBehavior.cs @@ -17,6 +17,8 @@ namespace MahApps.Metro.Behaviours { public class BorderlessWindowBehavior : Behavior { + private bool _isMaximize; + public static readonly DependencyProperty ResizeWithGripProperty = DependencyProperty.Register("ResizeWithGrip", typeof(bool), typeof(BorderlessWindowBehavior), new PropertyMetadata(true)); public static readonly DependencyProperty AutoSizeToContentProperty = DependencyProperty.Register("AutoSizeToContent", typeof(bool), typeof(BorderlessWindowBehavior), new PropertyMetadata(false)); public static readonly DependencyProperty EnableDWMDropShadowProperty = DependencyProperty.Register("EnableDWMDropShadow", typeof(bool), typeof(BorderlessWindowBehavior), new PropertyMetadata(false, new PropertyChangedCallback((obj, args) => @@ -79,32 +81,45 @@ private static IntPtr SetClassLong(IntPtr hWnd, int nIndex, IntPtr dwNewLong) return new IntPtr(UnsafeNativeMethods.SetClassLongPtr32(hWnd, nIndex, unchecked((uint)dwNewLong.ToInt32()))); } + /*Taken from http://stackoverflow.com/questions/20941443/properly-maximizing-wpf-window-with-windowstyle-none */ private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) { - var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); + POINT mousePosition; + UnsafeNativeMethods.GetCursorPos(out mousePosition); - // Adjust the maximized size and position to fit the work area of the correct monitor - IntPtr monitor = UnsafeNativeMethods.MonitorFromWindow(hwnd, Constants.MONITOR_DEFAULTTONEAREST); + IntPtr primaryScreen = UnsafeNativeMethods.MonitorFromPoint(new POINT(0, 0), MONITORINFO.MonitorOptions.MONITOR_DEFAULTTOPRIMARY); + MONITORINFO primaryScreenInfo = new MONITORINFO(); + if (UnsafeNativeMethods.GetMonitorInfo(primaryScreen, primaryScreenInfo) == false) + { + return; + } - if (monitor != IntPtr.Zero) + IntPtr currentScreen = UnsafeNativeMethods.MonitorFromPoint(mousePosition, MONITORINFO.MonitorOptions.MONITOR_DEFAULTTONEAREST); + + MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO)); + if (primaryScreen.Equals(currentScreen)) { - var monitorInfo = new MONITORINFO(); - UnsafeNativeMethods.GetMonitorInfo(monitor, monitorInfo); - RECT rcWorkArea = monitorInfo.rcWork; - RECT rcMonitorArea = monitorInfo.rcMonitor; - mmi.ptMaxPosition.X = Math.Abs(rcWorkArea.left - rcMonitorArea.left); - mmi.ptMaxPosition.Y = Math.Abs(rcWorkArea.top - rcMonitorArea.top); - mmi.ptMaxSize.X = Math.Abs(rcWorkArea.right - rcWorkArea.left); - mmi.ptMaxSize.Y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); - - bool ignoreTaskBar = AssociatedObject as MetroWindow != null && (((MetroWindow)this.AssociatedObject).IgnoreTaskbarOnMaximize || ((MetroWindow)this.AssociatedObject).UseNoneWindowStyle); - - if (!ignoreTaskBar) - { - mmi.ptMaxTrackSize.X = mmi.ptMaxSize.X; - mmi.ptMaxTrackSize.Y = mmi.ptMaxSize.Y; - mmi = AdjustWorkingAreaForAutoHide(monitor, mmi); - } + mmi.ptMaxPosition.X = primaryScreenInfo.rcWork.left; + mmi.ptMaxPosition.Y = primaryScreenInfo.rcWork.top; + mmi.ptMaxSize.X = primaryScreenInfo.rcWork.right - primaryScreenInfo.rcWork.left; + mmi.ptMaxSize.Y = primaryScreenInfo.rcWork.bottom - primaryScreenInfo.rcWork.top; + } + else + { + mmi.ptMaxPosition.X = primaryScreenInfo.rcMonitor.left; + mmi.ptMaxPosition.Y = primaryScreenInfo.rcMonitor.top; + mmi.ptMaxSize.X = primaryScreenInfo.rcMonitor.right - primaryScreenInfo.rcMonitor.left; + mmi.ptMaxSize.Y = primaryScreenInfo.rcMonitor.bottom - primaryScreenInfo.rcMonitor.top; + } + bool ignoreTaskBar = AssociatedObject as MetroWindow != null && (((MetroWindow)this.AssociatedObject).IgnoreTaskbarOnMaximize || ((MetroWindow)this.AssociatedObject).UseNoneWindowStyle); + + //Only do this on maximize and when mouse X position is not greater than the primary screen width + if (!(mousePosition.X >= (int)SystemParameters.PrimaryScreenWidth) && !ignoreTaskBar && primaryScreen.Equals(currentScreen) && _isMaximize) + { + mmi.ptMaxTrackSize.X = mmi.ptMaxSize.X; + mmi.ptMaxTrackSize.Y = mmi.ptMaxSize.Y; + mmi = AdjustWorkingAreaForAutoHide(primaryScreen, mmi); + _isMaximize = false; } Marshal.StructureToPtr(mmi, lParam, true); @@ -221,6 +236,7 @@ private void HandleMaximize() { if (AssociatedObject.WindowState == WindowState.Maximized) { + _isMaximize = true; IntPtr monitor = UnsafeNativeMethods.MonitorFromWindow(_mHWND, Constants.MONITOR_DEFAULTTONEAREST); if (monitor != IntPtr.Zero) { diff --git a/MahApps.Metro/Native/MONITORINFO.cs b/MahApps.Metro/Native/MONITORINFO.cs index dd5f78cfab..c663937a83 100644 --- a/MahApps.Metro/Native/MONITORINFO.cs +++ b/MahApps.Metro/Native/MONITORINFO.cs @@ -4,10 +4,17 @@ namespace MahApps.Metro.Native { [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO - { + { public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); - public RECT rcMonitor = new RECT(); - public RECT rcWork = new RECT(); + public RECT rcMonitor = new RECT(); + public RECT rcWork = new RECT(); public int dwFlags = 0; + + public enum MonitorOptions : uint + { + MONITOR_DEFAULTTONULL = 0x00000000, + MONITOR_DEFAULTTOPRIMARY = 0x00000001, + MONITOR_DEFAULTTONEAREST = 0x00000002 + } } } \ No newline at end of file diff --git a/MahApps.Metro/Native/UnsafeNativeMethods.cs b/MahApps.Metro/Native/UnsafeNativeMethods.cs index 2f3bf587c0..0f59d040b4 100644 --- a/MahApps.Metro/Native/UnsafeNativeMethods.cs +++ b/MahApps.Metro/Native/UnsafeNativeMethods.cs @@ -37,11 +37,14 @@ internal static class UnsafeNativeMethods [DllImport("user32")] internal static extern IntPtr MonitorFromWindow([In] IntPtr handle, [In] int flags); + [DllImport("user32.dll", SetLastError = true)] + internal static extern IntPtr MonitorFromPoint(POINT pt, MONITORINFO.MonitorOptions dwFlags); + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx [DllImport("user32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); - + /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms647486%28v=vs.85%29.aspx [DllImport("user32", CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "LoadStringW", SetLastError = true, CallingConvention = CallingConvention.Winapi)] internal static extern int LoadString([In] [Optional] IntPtr hInstance, [In] uint uID, [Out] StringBuilder lpBuffer, [In] int nBufferMax); @@ -64,7 +67,7 @@ internal static class UnsafeNativeMethods /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms648390(v=vs.85).aspx [DllImport("user32")] - internal static extern bool GetCursorPos([Out] out Win32Point pt); + internal static extern bool GetCursorPos([Out] out POINT pt); /// http://msdn.microsoft.com/en-us/library/windows/desktop/ms646258(v=vs.85).aspx [DllImport("user32", CharSet = CharSet.Auto, ExactSpelling = true)]