diff --git a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml index 0017ee09b5..a782dbec23 100644 --- a/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml +++ b/samples/ControlCatalog/Pages/WindowCustomizationsPage.xaml @@ -7,7 +7,8 @@ Header="Window Customizations" x:Class="ControlCatalog.Pages.WindowCustomizationsPage" x:DataType="viewModels:MainWindowViewModel" - x:CompileBindings="True"> + x:CompileBindings="True" + DataContext="{Binding $parent[Window].DataContext}"> 0) @@ -862,6 +839,37 @@ namespace Avalonia.Win32 return IntPtr.Zero; } + case WindowsMessage.WM_WINDOWPOSCHANGING: + { + var pos = (WINDOWPOS*)lParam; + var style = GetStyle(); + var flags = (SetWindowPosFlags)pos->flags; + + // A window without a caption (i.e. None and BorderOnly decorations) maximizes to the whole screen + // by default. Adjust that to the screen's working area instead. + if (!style.HasAllFlags(WindowStyles.WS_CAPTION | WindowStyles.WS_THICKFRAME) && + style.HasAllFlags(WindowStyles.WS_MAXIMIZE) && + !_isFullScreenActive && + !flags.HasAllFlags(SetWindowPosFlags.SWP_NOMOVE | SetWindowPosFlags.SWP_NOSIZE)) + { + // Prefer ScreenFromRect as it contains the new position. + // If the window was minimized, ScreenFromHwnd won't return the correct monitor at this point. + var screen = Screen.ScreenFromRect(new PixelRect(pos->x, pos->y, pos->cx, pos->cy)) + ?? Screen.ScreenFromHwnd(Hwnd, MONITOR.MONITOR_DEFAULTTONEAREST); + + if (screen is not null) + { + var maximizedRect = GetCaptionlessMaximizedRect(style, screen.WorkingArea); + pos->x = maximizedRect.X; + pos->y = maximizedRect.Y; + pos->cx = maximizedRect.Width; + pos->cy = maximizedRect.Height; + return IntPtr.Zero; + } + } + break; + } + case WindowsMessage.WM_DISPLAYCHANGE: { Screen?.OnChanged(); @@ -996,6 +1004,38 @@ namespace Avalonia.Win32 return DefWindowProc(hWnd, msg, wParam, lParam); } + + /// + /// Gets the expected maximized rect for a window without a caption. + /// + private PixelRect GetCaptionlessMaximizedRect(WindowStyles style, PixelRect workingArea) + { + var x = workingArea.X; + var y = workingArea.Y; + var cx = workingArea.Width; + var cy = workingArea.Height; + + var adjuster = CreateWindowRectAdjuster(); + var borderThickness = new RECT(); + + var adjustedStyle = style & ~WindowStyles.WS_CAPTION; + + if (style.HasAllFlags(WindowStyles.WS_BORDER)) + adjustedStyle |= WindowStyles.WS_BORDER; + + if (style.HasAllFlags(WindowStyles.WS_CAPTION)) + adjustedStyle |= WindowStyles.WS_THICKFRAME; + + adjuster.Adjust(ref borderThickness, adjustedStyle, 0); + + x += borderThickness.left; + y += borderThickness.top; + cx += -borderThickness.left + borderThickness.right; + cy += -borderThickness.top + borderThickness.bottom; + + return new PixelRect(x, y, cx, cy); + } + internal bool IsOurWindow(IntPtr hwnd) { if (hwnd == IntPtr.Zero)