From f4a0c6fd4fa64589336df45667d9b18e4b4e79ea Mon Sep 17 00:00:00 2001 From: NaBian <836904362@qq.com> Date: Tue, 12 May 2020 23:59:46 +0800 Subject: [PATCH] fixed #325 --- .../Themes/Styles/Window.xaml | 1 - .../Controls/Window/GlowWindow.cs | 4 +- .../Controls/Window/Window.cs | 96 +++++++++++++++---- .../Themes/Styles/Window.xaml | 1 - .../Tools/Helper/WindowHelper.cs | 8 +- .../Tools/Interop/InteropMethods.cs | 7 +- .../Tools/Interop/InteropValues.cs | 25 ++++- 7 files changed, 112 insertions(+), 30 deletions(-) diff --git a/src/Net_40/HandyControl_Net_40/Themes/Styles/Window.xaml b/src/Net_40/HandyControl_Net_40/Themes/Styles/Window.xaml index a9e520ac..dc062c39 100644 --- a/src/Net_40/HandyControl_Net_40/Themes/Styles/Window.xaml +++ b/src/Net_40/HandyControl_Net_40/Themes/Styles/Window.xaml @@ -129,7 +129,6 @@ - diff --git a/src/Shared/HandyControl_Shared/Controls/Window/GlowWindow.cs b/src/Shared/HandyControl_Shared/Controls/Window/GlowWindow.cs index 490b9b67..4e31362b 100644 --- a/src/Shared/HandyControl_Shared/Controls/Window/GlowWindow.cs +++ b/src/Shared/HandyControl_Shared/Controls/Window/GlowWindow.cs @@ -75,7 +75,7 @@ namespace HandyControl.Controls } } - protected virtual IntPtr HwndSourceHook(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) + private IntPtr HwndSourceHook(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { if (msg <= InteropValues.WM_WINDOWPOSCHANGED) { @@ -167,7 +167,7 @@ namespace HandyControl.Controls protected override void OnSourceInitialized(EventArgs e) { - var hwndSource = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle); + var hwndSource = this.GetHwndSource(); if (hwndSource != null) { hwndSource.AddHook(HwndSourceHook); diff --git a/src/Shared/HandyControl_Shared/Controls/Window/Window.cs b/src/Shared/HandyControl_Shared/Controls/Window/Window.cs index 932e79c8..a406243c 100644 --- a/src/Shared/HandyControl_Shared/Controls/Window/Window.cs +++ b/src/Shared/HandyControl_Shared/Controls/Window/Window.cs @@ -1,10 +1,13 @@ using System; +using System.Runtime.InteropServices; using System.Windows; using System.Windows.Data; using System.Windows.Input; using System.Windows.Media; using HandyControl.Data; +using HandyControl.Tools; using HandyControl.Tools.Extension; +using HandyControl.Tools.Interop; #if netle40 using Microsoft.Windows.Shell; #else @@ -80,6 +83,8 @@ namespace HandyControl.Controls private Thickness _actualBorderThickness; + private readonly Thickness _commonPadding; + private bool _showNonClientArea = true; private double _tempNonClientAreaHeight; @@ -114,45 +119,96 @@ namespace HandyControl.Controls }; #endif BindingOperations.SetBinding(chrome, WindowChrome.CaptionHeightProperty, - new Binding(NonClientAreaHeightProperty.Name) {Source = this}); + new Binding(NonClientAreaHeightProperty.Name) { Source = this }); WindowChrome.SetWindowChrome(this, chrome); + _commonPadding = Padding; - Loaded += (s, e) => OnLoaded(e); + Loaded += (s, e) => OnLoaded(e); } + private void WmGetMinMaxInfo(IntPtr hwnd, IntPtr lParam) + { + var mmi = (InteropValues.MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(InteropValues.MINMAXINFO)); + var monitor = InteropMethods.MonitorFromWindow(hwnd, InteropValues.MONITOR_DEFAULTTONEAREST); + + if (monitor != IntPtr.Zero && mmi != null) + { + InteropValues.APPBARDATA appBarData = default; + var autoHide = InteropMethods.SHAppBarMessage(4, ref appBarData) != 0; + if (autoHide) + { + var monitorInfo = default(InteropValues.MONITORINFO); + monitorInfo.cbSize = (uint)Marshal.SizeOf(typeof(InteropValues.MONITORINFO)); + InteropMethods.GetMonitorInfo(monitor, ref monitorInfo); + var rcWorkArea = monitorInfo.rcWork; + var 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 - 1); + } + } + + Marshal.StructureToPtr(mmi, lParam, true); + } + + protected override void OnSourceInitialized(EventArgs e) + { + this.GetHwndSource()?.AddHook(HwndSourceHook); + base.OnSourceInitialized(e); + } + + private IntPtr HwndSourceHook(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam, ref bool handled) + { + switch (msg) + { + case InteropValues.WM_WINDOWPOSCHANGED: + Padding = WindowState == WindowState.Maximized ? WindowHelper.WindowMaximizedPadding : _commonPadding; + break; + case InteropValues.WM_GETMINMAXINFO: + WmGetMinMaxInfo(hwnd, lparam); + Padding = WindowState == WindowState.Maximized ? WindowHelper.WindowMaximizedPadding : _commonPadding; + handled = true; + break; + } + + return IntPtr.Zero; + } + + public Brush CloseButtonBackground { - get => (Brush) GetValue(CloseButtonBackgroundProperty); + get => (Brush)GetValue(CloseButtonBackgroundProperty); set => SetValue(CloseButtonBackgroundProperty, value); } public Brush CloseButtonForeground { - get => (Brush) GetValue(CloseButtonForegroundProperty); + get => (Brush)GetValue(CloseButtonForegroundProperty); set => SetValue(CloseButtonForegroundProperty, value); } public Brush OtherButtonBackground { - get => (Brush) GetValue(OtherButtonBackgroundProperty); + get => (Brush)GetValue(OtherButtonBackgroundProperty); set => SetValue(OtherButtonBackgroundProperty, value); } public Brush OtherButtonForeground { - get => (Brush) GetValue(OtherButtonForegroundProperty); + get => (Brush)GetValue(OtherButtonForegroundProperty); set => SetValue(OtherButtonForegroundProperty, value); } public double NonClientAreaHeight { - get => (double) GetValue(NonClientAreaHeightProperty); + get => (double)GetValue(NonClientAreaHeightProperty); set => SetValue(NonClientAreaHeightProperty, value); } public bool IsFullScreen { - get => (bool) GetValue(IsFullScreenProperty); + get => (bool)GetValue(IsFullScreenProperty); set => SetValue(IsFullScreenProperty, value); } @@ -164,56 +220,56 @@ namespace HandyControl.Controls public Brush CloseButtonHoverBackground { - get => (Brush) GetValue(CloseButtonHoverBackgroundProperty); + get => (Brush)GetValue(CloseButtonHoverBackgroundProperty); set => SetValue(CloseButtonHoverBackgroundProperty, value); } public Brush CloseButtonHoverForeground { - get => (Brush) GetValue(CloseButtonHoverForegroundProperty); + get => (Brush)GetValue(CloseButtonHoverForegroundProperty); set => SetValue(CloseButtonHoverForegroundProperty, value); } public Brush OtherButtonHoverBackground { - get => (Brush) GetValue(OtherButtonHoverBackgroundProperty); + get => (Brush)GetValue(OtherButtonHoverBackgroundProperty); set => SetValue(OtherButtonHoverBackgroundProperty, value); } public Brush OtherButtonHoverForeground { - get => (Brush) GetValue(OtherButtonHoverForegroundProperty); + get => (Brush)GetValue(OtherButtonHoverForegroundProperty); set => SetValue(OtherButtonHoverForegroundProperty, value); } public Brush NonClientAreaBackground { - get => (Brush) GetValue(NonClientAreaBackgroundProperty); + get => (Brush)GetValue(NonClientAreaBackgroundProperty); set => SetValue(NonClientAreaBackgroundProperty, value); } public Brush NonClientAreaForeground { - get => (Brush) GetValue(NonClientAreaForegroundProperty); + get => (Brush)GetValue(NonClientAreaForegroundProperty); set => SetValue(NonClientAreaForegroundProperty, value); } public bool ShowNonClientArea { - get => (bool) GetValue(ShowNonClientAreaProperty); + get => (bool)GetValue(ShowNonClientAreaProperty); set => SetValue(ShowNonClientAreaProperty, value); } public bool ShowTitle { - get => (bool) GetValue(ShowTitleProperty); + get => (bool)GetValue(ShowTitleProperty); set => SetValue(ShowTitleProperty, value); } private static void OnShowNonClientAreaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - var ctl = (Window) d; - ctl.SwitchShowNonClientArea((bool) e.NewValue); + var ctl = (Window)d; + ctl.SwitchShowNonClientArea((bool)e.NewValue); } private void SwitchShowNonClientArea(bool showNonClientArea) @@ -248,8 +304,8 @@ namespace HandyControl.Controls private static void OnIsFullScreenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { - var ctl = (Window) d; - ctl.SwitchIsFullScreen((bool) e.NewValue); + var ctl = (Window)d; + ctl.SwitchIsFullScreen((bool)e.NewValue); } private void SwitchIsFullScreen(bool isFullScreen) diff --git a/src/Shared/HandyControl_Shared/Themes/Styles/Window.xaml b/src/Shared/HandyControl_Shared/Themes/Styles/Window.xaml index c48c486c..84acaf28 100644 --- a/src/Shared/HandyControl_Shared/Themes/Styles/Window.xaml +++ b/src/Shared/HandyControl_Shared/Themes/Styles/Window.xaml @@ -128,7 +128,6 @@ - diff --git a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs index 23f73766..ae465d22 100644 --- a/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs +++ b/src/Shared/HandyControl_Shared/Tools/Helper/WindowHelper.cs @@ -132,15 +132,17 @@ namespace HandyControl.Tools { get { + InteropValues.APPBARDATA appBarData = default; + var autoHide = InteropMethods.SHAppBarMessage(4, ref appBarData) != 0; #if netle40 - return WindowResizeBorderThickness; + return WindowResizeBorderThickness.Add(new Thickness(autoHide ? -8 : 0)); #elif Core var hdc = InteropMethods.GetDC(IntPtr.Zero); var scale = InteropMethods.GetDeviceCaps(hdc, InteropValues.DESKTOPVERTRES) / (float)InteropMethods.GetDeviceCaps(hdc, InteropValues.VERTRES); InteropMethods.ReleaseDC(IntPtr.Zero, hdc); - return WindowResizeBorderThickness.Add(new Thickness(4 * scale)); + return WindowResizeBorderThickness.Add(new Thickness((autoHide ? - 4 : 4) * scale)); #else - return WindowResizeBorderThickness.Add(new Thickness(4)); + return WindowResizeBorderThickness.Add(new Thickness(autoHide ? - 4 : 4)); #endif } } diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs b/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs index fa6b8d37..fde76808 100644 --- a/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs +++ b/src/Shared/HandyControl_Shared/Tools/Interop/InteropMethods.cs @@ -17,7 +17,7 @@ namespace HandyControl.Tools.Interop { #region common - public const int E_FAIL = unchecked((int)0x80004005); + internal const int E_FAIL = unchecked((int)0x80004005); internal static readonly IntPtr HRGN_NONE = new IntPtr(-1); @@ -461,7 +461,10 @@ namespace HandyControl.Tools.Interop [ReflectionPermission(SecurityAction.Assert, Unrestricted = true), SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode)] - public static void PtrToStructure(IntPtr lparam, object data) => Marshal.PtrToStructure(lparam, data); + internal static void PtrToStructure(IntPtr lparam, object data) => Marshal.PtrToStructure(lparam, data); + + [DllImport(InteropValues.ExternDll.Shell32, CallingConvention = CallingConvention.StdCall)] + internal static extern uint SHAppBarMessage(int dwMessage, ref InteropValues.APPBARDATA pData); #endregion diff --git a/src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs b/src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs index dfc65f65..955fc062 100644 --- a/src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs +++ b/src/Shared/HandyControl_Shared/Tools/Interop/InteropValues.cs @@ -48,6 +48,7 @@ namespace HandyControl.Tools.Interop NIIF_ERROR = 0x00000003, WM_ACTIVATE = 0x0006, WM_QUIT = 0x0012, + WM_GETMINMAXINFO = 0x0024, WM_WINDOWPOSCHANGING = 0x0046, WM_WINDOWPOSCHANGED = 0x0047, WM_SETICON = 0x0080, @@ -85,7 +86,8 @@ namespace HandyControl.Tools.Interop SC_MINIMIZE = 0xF020, SC_MAXIMIZE = 0xF030, SC_RESTORE = 0xF120, - SRCCOPY = 0x00CC0020; + SRCCOPY = 0x00CC0020, + MONITOR_DEFAULTTONEAREST = 0x00000002; [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] internal class NOTIFYICONDATA @@ -933,5 +935,26 @@ namespace HandyControl.Tools.Interop return length; } } + + [StructLayout(LayoutKind.Sequential)] + internal class MINMAXINFO + { + public POINT ptReserved; + public POINT ptMaxSize; + public POINT ptMaxPosition; + public POINT ptMinTrackSize; + public POINT ptMaxTrackSize; + } + + [StructLayout(LayoutKind.Sequential)] + internal struct APPBARDATA + { + public int cbSize; + public IntPtr hWnd; + public uint uCallbackMessage; + public uint uEdge; + public RECT rc; + public int lParam; + } } } \ No newline at end of file