diff --git a/BrightSharp.Ui.Tests/CustomWindow.xaml b/BrightSharp.Ui.Tests/CustomWindow.xaml
index 2932427..a9b85f6 100644
--- a/BrightSharp.Ui.Tests/CustomWindow.xaml
+++ b/BrightSharp.Ui.Tests/CustomWindow.xaml
@@ -4,17 +4,17 @@
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:bs="http://schemas.brightsharp.com/developer"
- xmlns:conv="http://schemas.brightsharp.com/developer"
xmlns:local="clr-namespace:BrightSharp.Ui.Tests"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d" ResizeMode="CanResizeWithGrip"
WindowStyle="ToolWindow" Title="Brushes Explorer"
+ bs:MarkupExtensionProperties.UseMinMaxSizeBehavior="True"
Height="800" Width="600" Style="{DynamicResource BrightSharpWindowStyle}">
-
+
diff --git a/BrightSharp.Ui.Tests/MainWindow.xaml b/BrightSharp.Ui.Tests/MainWindow.xaml
index c665343..96e75ea 100644
--- a/BrightSharp.Ui.Tests/MainWindow.xaml
+++ b/BrightSharp.Ui.Tests/MainWindow.xaml
@@ -5,6 +5,7 @@
xmlns:viewModel="clr-namespace:BrightSharp.Ui.Tests"
xmlns:ex="http://schemas.brightsharp.com/developer"
xmlns:bsDiag="http://schemas.brightsharp.com/diagrams"
+ ex:MarkupExtensionProperties.UseMinMaxSizeBehavior="True"
Style="{DynamicResource BrightSharpWindowStyle}"
ResizeMode="CanResizeWithGrip"
x:Class="BrightSharp.Ui.Tests.MainWindow"
diff --git a/BrightSharp/Behaviors/WindowMinMaxSizeBehavior.cs b/BrightSharp/Behaviors/WindowMinMaxSizeBehavior.cs
new file mode 100644
index 0000000..3ff9e4d
--- /dev/null
+++ b/BrightSharp/Behaviors/WindowMinMaxSizeBehavior.cs
@@ -0,0 +1,78 @@
+using BrightSharp.Interop;
+using BrightSharp.Interop.Constants;
+using BrightSharp.Interop.Structures;
+using System;
+using System.Runtime.InteropServices;
+using System.Windows;
+using System.Windows.Interactivity;
+using System.Windows.Interop;
+
+namespace BrightSharp.Behaviors
+{
+ public class WindowMinMaxSizeBehavior : Behavior
+ {
+ private HwndSource hwndSource;
+
+ protected override void OnAttached()
+ {
+ base.OnAttached();
+
+ AssociatedObject.SourceInitialized += AssociatedObject_SourceInitialized;
+ }
+
+ private void AssociatedObject_SourceInitialized(object sender, EventArgs e)
+ {
+ IntPtr handle = (new WindowInteropHelper(AssociatedObject)).Handle;
+ hwndSource = HwndSource.FromHwnd(handle);
+ hwndSource.AddHook(WindowProc);
+ }
+
+ protected override void OnDetaching()
+ {
+ AssociatedObject.SourceInitialized -= AssociatedObject_SourceInitialized;
+ if (hwndSource != null)
+ {
+ hwndSource.RemoveHook(WindowProc);
+ hwndSource.Dispose();
+ }
+ base.OnDetaching();
+ }
+
+ private IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
+ {
+ switch (msg)
+ {
+ case 0x0024:
+ WmGetMinMaxInfo(hwnd, lParam);
+ handled = true;
+ break;
+ }
+ return (IntPtr)0;
+ }
+
+ private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam)
+ {
+ var mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
+
+ // Adjust the maximized size and position to fit the work area of the correct monitor
+ IntPtr monitor = NativeMethods.MonitorFromWindow(hwnd, (int)MonitorFromWindowFlags.MONITOR_DEFAULTTONEAREST);
+
+ if (monitor != IntPtr.Zero)
+ {
+ var monitorInfo = new MONITORINFO();
+ NativeMethods.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);
+ mmi.ptMinTrackSize.x = (int)AssociatedObject.MinWidth;
+ mmi.ptMinTrackSize.y = (int)AssociatedObject.MinHeight;
+ }
+
+ Marshal.StructureToPtr(mmi, lParam, true);
+ }
+
+ }
+}
diff --git a/BrightSharp/BrightSharp.csproj b/BrightSharp/BrightSharp.csproj
index 5a42609..7ad816c 100644
--- a/BrightSharp/BrightSharp.csproj
+++ b/BrightSharp/BrightSharp.csproj
@@ -53,6 +53,7 @@
+
@@ -68,6 +69,9 @@
+
+
+
Theme.xaml
diff --git a/BrightSharp/Extensions/MarkupExtensionProperties.cs b/BrightSharp/Extensions/MarkupExtensionProperties.cs
index 984bd30..4aed7ee 100644
--- a/BrightSharp/Extensions/MarkupExtensionProperties.cs
+++ b/BrightSharp/Extensions/MarkupExtensionProperties.cs
@@ -1,5 +1,9 @@
-using System.Windows;
+using BrightSharp.Behaviors;
+using System;
+using System.Linq;
+using System.Windows;
using System.Windows.Controls;
+using System.Windows.Interactivity;
using System.Windows.Media;
namespace BrightSharp.Extensions
@@ -120,6 +124,16 @@ namespace BrightSharp.Extensions
obj.SetValue(SpecialBrushProperty, value);
}
+ public static bool GetUseMinMaxSizeBehavior(Window obj)
+ {
+ return (bool)obj.GetValue(UseMinMaxSizeBehaviorProperty);
+ }
+
+ public static void SetUseMinMaxSizeBehavior(Window obj, bool value)
+ {
+ obj.SetValue(UseMinMaxSizeBehaviorProperty, value);
+ }
+
public static readonly DependencyProperty SpecialBrushProperty = DependencyProperty.RegisterAttached("SpecialBrush", typeof(Brush), typeof(MarkupExtensionProperties), new PropertyMetadata(null));
public static readonly DependencyProperty IsDragHelperVisibleProperty = DependencyProperty.RegisterAttached("IsDragHelperVisible", typeof(bool), typeof(MarkupExtensionProperties), new FrameworkPropertyMetadata(true));
public static readonly DependencyProperty HeaderPaddingProperty = DependencyProperty.RegisterAttached("HeaderPadding", typeof(Thickness), typeof(MarkupExtensionProperties), new PropertyMetadata(null));
@@ -134,7 +148,23 @@ namespace BrightSharp.Extensions
public static readonly DependencyProperty HeaderHorizontalAlignmentProperty = DependencyProperty.RegisterAttached("HeaderHorizontalAlignment", typeof(HorizontalAlignment), typeof(MarkupExtensionProperties), new PropertyMetadata(HorizontalAlignment.Left));
public static readonly DependencyProperty SpecialHeightProperty = DependencyProperty.RegisterAttached("SpecialHeight", typeof(double), typeof(MarkupExtensionProperties), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
public static readonly DependencyProperty SpecialWidthProperty = DependencyProperty.RegisterAttached("SpecialWidth", typeof(double), typeof(MarkupExtensionProperties), new FrameworkPropertyMetadata(0.0, FrameworkPropertyMetadataOptions.Inherits | FrameworkPropertyMetadataOptions.AffectsRender | FrameworkPropertyMetadataOptions.AffectsMeasure));
-
+ public static readonly DependencyProperty UseMinMaxSizeBehaviorProperty = DependencyProperty.RegisterAttached("UseMinMaxSizeBehavior", typeof(bool), typeof(MarkupExtensionProperties), new PropertyMetadata(false, UseMinMaxSizeBehaviorChanged));
+
+
+ private static void UseMinMaxSizeBehaviorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
+ {
+ var window = d as Window;
+ if (window == null) return;
+ if ((bool)e.NewValue)
+ {
+ Interaction.GetBehaviors(window).Add(new WindowMinMaxSizeBehavior());
+ }
+ else
+ {
+ var beh = Interaction.GetBehaviors(window).OfType().FirstOrDefault();
+ if (beh != null) Interaction.GetBehaviors(window).Remove(beh);
+ }
+ }
}
}
diff --git a/BrightSharp/Interop/Constants.cs b/BrightSharp/Interop/Constants.cs
new file mode 100644
index 0000000..d18d5fe
--- /dev/null
+++ b/BrightSharp/Interop/Constants.cs
@@ -0,0 +1,11 @@
+namespace BrightSharp.Interop
+{
+ namespace Constants
+ {
+ internal enum MonitorFromWindowFlags
+ {
+ MONITOR_DEFAULTTONEAREST = 0x00000002
+ }
+
+ }
+}
diff --git a/BrightSharp/Interop/NativeMethods.cs b/BrightSharp/Interop/NativeMethods.cs
new file mode 100644
index 0000000..2c75530
--- /dev/null
+++ b/BrightSharp/Interop/NativeMethods.cs
@@ -0,0 +1,20 @@
+using BrightSharp.Interop.Structures;
+using System;
+using System.Runtime.InteropServices;
+
+namespace BrightSharp.Interop
+{
+ internal static class NativeMethods
+ {
+ #region Monitor
+
+ [DllImport("user32.dll", SetLastError = true)]
+ internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);
+
+ [DllImport("user32.dll", SetLastError = true)]
+ internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);
+
+ #endregion
+
+ }
+}
diff --git a/BrightSharp/Interop/Structures.cs b/BrightSharp/Interop/Structures.cs
new file mode 100644
index 0000000..16a6ef2
--- /dev/null
+++ b/BrightSharp/Interop/Structures.cs
@@ -0,0 +1,130 @@
+using System;
+using System.Runtime.InteropServices;
+
+namespace BrightSharp.Interop
+{
+ namespace Structures
+ {
+
+ [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
+ internal class MONITORINFO
+ {
+ public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));
+
+ public RECT rcMonitor;
+
+ public RECT rcWork;
+
+ public int dwFlags;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ internal struct POINT
+ {
+ public int x;
+ public int y;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 0)]
+ internal struct RECT
+ {
+ public int Left;
+
+ public int Top;
+
+ public int Right;
+
+ public int Bottom;
+
+ public static readonly RECT Empty;
+
+ public int Width
+ {
+ get {
+ return Math.Abs(Right - Left);
+ } // Abs needed for BIDI OS
+ }
+
+ public int Height
+ {
+ get {
+ return Bottom - Top;
+ }
+ }
+
+ public RECT(int left, int top, int right, int bottom)
+ {
+ Left = left;
+ Top = top;
+ Right = right;
+ Bottom = bottom;
+ }
+
+ public RECT(RECT rcSrc)
+ {
+ Left = rcSrc.Left;
+ Top = rcSrc.Top;
+ Right = rcSrc.Right;
+ Bottom = rcSrc.Bottom;
+ }
+
+ public bool IsEmpty
+ {
+ get {
+ // BUGBUG : On Bidi OS (hebrew arabic) left > right
+ return Left >= Right || Top >= Bottom;
+ }
+ }
+
+ public override string ToString()
+ {
+ if (this == Empty)
+ {
+ return "RECT {Empty}";
+ }
+ return "RECT { left : " + Left + " / top : " + Top + " / right : " + Right + " / bottom : " +
+ Bottom + " }";
+ }
+
+ public override bool Equals(object obj)
+ {
+ if (!(obj is RECT))
+ {
+ return false;
+ }
+ return (this == (RECT)obj);
+ }
+
+ public override int GetHashCode()
+ {
+ return Left.GetHashCode() + Top.GetHashCode() + Right.GetHashCode() +
+ Bottom.GetHashCode();
+ }
+
+ public static bool operator ==(RECT rect1, RECT rect2)
+ {
+ return (rect1.Left == rect2.Left && rect1.Top == rect2.Top && rect1.Right == rect2.Right &&
+ rect1.Bottom == rect2.Bottom);
+ }
+
+ public static bool operator !=(RECT rect1, RECT rect2)
+ {
+ return !(rect1 == rect2);
+ }
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ internal struct MINMAXINFO
+ {
+ public POINT ptReserved;
+
+ public POINT ptMaxSize;
+
+ public POINT ptMaxPosition;
+
+ public POINT ptMinTrackSize;
+
+ public POINT ptMaxTrackSize;
+ };
+ }
+}
diff --git a/BrightSharp/Themes/Theme.xaml b/BrightSharp/Themes/Theme.xaml
index da1d3a8..11bd21d 100644
--- a/BrightSharp/Themes/Theme.xaml
+++ b/BrightSharp/Themes/Theme.xaml
@@ -5630,7 +5630,6 @@