Skip to content

Commit

Permalink
Fix #874: Allow resizing to a width greater than the window width
Browse files Browse the repository at this point in the history
  • Loading branch information
h1srf committed Jan 9, 2014
1 parent 11e5918 commit 9609132
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 26 deletions.
58 changes: 37 additions & 21 deletions MahApps.Metro/Behaviours/BorderlessWindowBehavior.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ namespace MahApps.Metro.Behaviours
{
public class BorderlessWindowBehavior : Behavior<Window>
{
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) =>
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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)
{
Expand Down
13 changes: 10 additions & 3 deletions MahApps.Metro/Native/MONITORINFO.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
}
7 changes: 5 additions & 2 deletions MahApps.Metro/Native/UnsafeNativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/// <devdoc>http://msdn.microsoft.com/en-us/library/windows/desktop/ms633545(v=vs.85).aspx</devdoc>
[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);

/// <devdoc>http://msdn.microsoft.com/en-us/library/windows/desktop/ms647486%28v=vs.85%29.aspx</devdoc>
[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);
Expand All @@ -64,7 +67,7 @@ internal static class UnsafeNativeMethods

/// <devdoc>http://msdn.microsoft.com/en-us/library/windows/desktop/ms648390(v=vs.85).aspx</devdoc>
[DllImport("user32")]
internal static extern bool GetCursorPos([Out] out Win32Point pt);
internal static extern bool GetCursorPos([Out] out POINT pt);

/// <devdoc>http://msdn.microsoft.com/en-us/library/windows/desktop/ms646258(v=vs.85).aspx</devdoc>
[DllImport("user32", CharSet = CharSet.Auto, ExactSpelling = true)]
Expand Down

0 comments on commit 9609132

Please sign in to comment.