Browse Source

add client area extending api to window.

demo1
Dan Walmsley 6 years ago
parent
commit
1168dd186d
  1. 6
      src/Avalonia.Controls/Platform/IWindowImpl.cs
  2. 62
      src/Avalonia.Controls/Window.cs
  3. 6
      src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs
  4. 6
      src/Avalonia.DesignerSupport/Remote/Stubs.cs
  5. 6
      src/Avalonia.Native/WindowImpl.cs
  6. 6
      src/Avalonia.X11/X11Window.cs
  7. 77
      src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs

6
src/Avalonia.Controls/Platform/IWindowImpl.cs

@ -94,5 +94,11 @@ namespace Avalonia.Platform
/// </summary>
///
void SetMinMaxSize(Size minSize, Size maxSize);
bool ExtendClientAreaToDecorationsHint { get; set; }
Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
Thickness ExtendedMargins { get; }
}
}

62
src/Avalonia.Controls/Window.cs

@ -71,6 +71,8 @@ namespace Avalonia.Controls
{
private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>();
private bool _isExtendedIntoWindowDecorations;
/// <summary>
/// Defines the <see cref="SizeToContent"/> property.
/// </summary>
@ -87,6 +89,29 @@ namespace Avalonia.Controls
o => o.HasSystemDecorations,
(o, v) => o.HasSystemDecorations = v);
/// <summary>
/// Defines the <see cref="ExtendClientAreaToDecorationsHint"/> property.
/// </summary>
public static readonly StyledProperty<bool> ExtendClientAreaToDecorationsHintProperty =
AvaloniaProperty.Register<Window, bool>(nameof(ExtendClientAreaToDecorationsHint), false);
/// <summary>
/// Defines the <see cref="IsExtendedIntoWindowDecorations"/> property.
/// </summary>
public static readonly DirectProperty<Window, bool> IsExtendedIntoWindowDecorationsProperty =
AvaloniaProperty.RegisterDirect<Window, bool>(nameof(IsExtendedIntoWindowDecorations),
o => o.IsExtendedIntoWindowDecorations,
unsetValue: false);
/// <summary>
/// Defines the <see cref="WindowDecorationMargins"/> property.
/// </summary>
public static readonly DirectProperty<Window, Thickness> WindowDecorationMarginsProperty =
AvaloniaProperty.RegisterDirect<Window, Thickness>(nameof(WindowDecorationMargins),
o => o.WindowDecorationMargins);
/// <summary>
/// Defines the <see cref="SystemDecorations"/> property.
/// </summary>
@ -164,6 +189,9 @@ namespace Avalonia.Controls
WindowStateProperty.Changed.AddClassHandler<Window>(
(w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.WindowState = (WindowState)e.NewValue; });
ExtendClientAreaToDecorationsHintProperty.Changed.AddClassHandler<Window>(
(w, e) => { if (w.PlatformImpl != null) w.PlatformImpl.ExtendClientAreaToDecorationsHint = (bool)e.NewValue; });
MinWidthProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size((double)e.NewValue, w.MinHeight), new Size(w.MaxWidth, w.MaxHeight)));
MinHeightProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, (double)e.NewValue), new Size(w.MaxWidth, w.MaxHeight)));
MaxWidthProperty.Changed.AddClassHandler<Window>((w, e) => w.PlatformImpl?.SetMinMaxSize(new Size(w.MinWidth, w.MinHeight), new Size((double)e.NewValue, w.MaxHeight)));
@ -189,6 +217,7 @@ namespace Avalonia.Controls
impl.GotInputWhenDisabled = OnGotInputWhenDisabled;
impl.WindowStateChanged = HandleWindowStateChanged;
_maxPlatformClientSize = PlatformImpl?.MaxAutoSizeHint ?? default(Size);
impl.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged;
this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x));
PlatformImpl?.ShowTaskbarIcon(ShowInTaskbar);
@ -237,6 +266,32 @@ namespace Avalonia.Controls
}
}
/// <summary>
/// Gets or sets if the ClientArea is Extended into the Window Decorations (chrome or border).
/// </summary>
public bool ExtendClientAreaToDecorationsHint
{
get { return GetValue(ExtendClientAreaToDecorationsHintProperty); }
set { SetValue(ExtendClientAreaToDecorationsHintProperty, value); }
}
/// <summary>
/// Gets if the ClientArea is Extended into the Window Decorations.
/// </summary>
public bool IsExtendedIntoWindowDecorations
{
get => _isExtendedIntoWindowDecorations;
private set => SetAndRaise(IsExtendedIntoWindowDecorationsProperty, ref _isExtendedIntoWindowDecorations, value);
}
private Thickness _windowDecorationMargins;
public Thickness WindowDecorationMargins
{
get => _windowDecorationMargins;
private set => SetAndRaise(WindowDecorationMarginsProperty, ref _windowDecorationMargins, value);
}
/// <summary>
/// Sets the system decorations (title bar, border, etc)
/// </summary>
@ -435,6 +490,13 @@ namespace Avalonia.Controls
}
}
protected virtual void ExtendClientAreaToDecorationsChanged(bool isExtended)
{
IsExtendedIntoWindowDecorations = isExtended;
WindowDecorationMargins = PlatformImpl.ExtendedMargins;
}
/// <summary>
/// Hides the window but does not close it.
/// </summary>

6
src/Avalonia.DesignerSupport/Remote/PreviewerWindowImpl.cs

@ -84,6 +84,12 @@ namespace Avalonia.DesignerSupport.Remote
public IScreenImpl Screen { get; } = new ScreenStub();
public Action GotInputWhenDisabled { get; set; }
public bool ExtendClientAreaToDecorationsHint { get; set; }
public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
public Thickness ExtendedMargins { get; } = new Thickness();
public void Activate()
{

6
src/Avalonia.DesignerSupport/Remote/Stubs.cs

@ -39,6 +39,12 @@ namespace Avalonia.DesignerSupport.Remote
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
public bool ExtendClientAreaToDecorationsHint { get; set; }
public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
public Thickness ExtendedMargins { get; } = new Thickness();
public WindowStub(IWindowImpl parent = null)
{
if (parent != null)

6
src/Avalonia.Native/WindowImpl.cs

@ -98,6 +98,12 @@ namespace Avalonia.Native
public Action<WindowState> WindowStateChanged { get; set; }
public bool ExtendClientAreaToDecorationsHint { get; set; }
public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
public Thickness ExtendedMargins { get; } = new Thickness();
public void ShowTaskbarIcon(bool value)
{
// NO OP On OSX

6
src/Avalonia.X11/X11Window.cs

@ -311,6 +311,12 @@ namespace Avalonia.X11
set => _transparencyHelper.TransparencyLevelChanged = value;
}
public bool ExtendClientAreaToDecorationsHint { get; set; }
public Action<bool> ExtendClientAreaToDecorationsChanged { get; set; }
public Thickness ExtendedMargins { get; } = new Thickness();
public Action Closed { get; set; }
public Action<PixelPoint> PositionChanged { get; set; }

77
src/Windows/Avalonia.Win32/WindowImpl.WndProc.cs

@ -14,11 +14,6 @@ namespace Avalonia.Win32
{
public partial class WindowImpl
{
private int LEFTEXTENDWIDTH = 4;
private int RIGHTEXTENDWIDTH = 4;
private int BOTTOMEXTENDWIDTH = 4;
private int TOPEXTENDWIDTH = 100;
// Hit test the frame for resizing and moving.
HitTestValues HitTestNCA(IntPtr hWnd, IntPtr wParam, IntPtr lParam)
{
@ -32,28 +27,40 @@ namespace Avalonia.Win32
RECT rcFrame = new RECT();
AdjustWindowRectEx(ref rcFrame, (uint)(WindowStyles.WS_OVERLAPPEDWINDOW & ~WindowStyles.WS_CAPTION), false, 0);
RECT border_thickness = new RECT();
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
// Determine if the hit test is for resizing. Default middle (1,1).
ushort uRow = 1;
ushort uCol = 1;
bool fOnResizeBorder = false;
// Determine if the point is at the top or bottom of the window.
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + TOPEXTENDWIDTH)
if (ptMouse.Y >= rcWindow.top && ptMouse.Y < rcWindow.top + border_thickness.top)
{
fOnResizeBorder = (ptMouse.Y < (rcWindow.top - rcFrame.top));
uRow = 0;
}
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - BOTTOMEXTENDWIDTH)
else if (ptMouse.Y < rcWindow.bottom && ptMouse.Y >= rcWindow.bottom - border_thickness.bottom)
{
uRow = 2;
}
// Determine if the point is at the left or right of the window.
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + LEFTEXTENDWIDTH)
if (ptMouse.X >= rcWindow.left && ptMouse.X < rcWindow.left + border_thickness.left)
{
uCol = 0; // left side
}
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - RIGHTEXTENDWIDTH)
else if (ptMouse.X < rcWindow.right && ptMouse.X >= rcWindow.right - border_thickness.right)
{
uCol = 2; // right side
}
@ -66,8 +73,6 @@ namespace Avalonia.Win32
new []{ HitTestValues.HTBOTTOMLEFT, HitTestValues.HTBOTTOM, HitTestValues.HTBOTTOMRIGHT },
};
System.Diagnostics.Debug.WriteLine(hitTests[uRow][uCol]);
return hitTests[uRow][uCol];
}
@ -84,35 +89,37 @@ namespace Avalonia.Win32
{
case WindowsMessage.WM_ACTIVATE:
{
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
if (!_isClientAreaExtended)
{
if (GetStyle().HasFlag(WindowStyles.WS_THICKFRAME))
{
AdjustWindowRectEx(ref border_thickness, (uint)(GetStyle()), false, 0);
border_thickness.left *= -1;
border_thickness.top *= -1;
}
else if (GetStyle().HasFlag(WindowStyles.WS_BORDER))
{
border_thickness = new RECT { bottom = 1, left = 1, right = 1, top = 1 };
}
LEFTEXTENDWIDTH = border_thickness.left;
RIGHTEXTENDWIDTH = border_thickness.right;
BOTTOMEXTENDWIDTH = border_thickness.bottom;
TOPEXTENDWIDTH = border_thickness.top;
// Extend the frame into the client area.
margins.cxLeftWidth = border_thickness.left;
margins.cxRightWidth = border_thickness.right;
margins.cyBottomHeight = border_thickness.bottom;
margins.cyTopHeight = border_thickness.top;
// Extend the frame into the client area.
margins.cxLeftWidth = border_thickness.left;
margins.cxRightWidth = border_thickness.right;
margins.cyBottomHeight = border_thickness.bottom;
margins.cyTopHeight = border_thickness.top;
var hr = DwmExtendFrameIntoClientArea(hWnd, ref margins);
var hr = DwmExtendFrameIntoClientArea(hWnd, ref margins);
//if (hr < 0)
{
// Handle the error.
}
//if (hr < 0)
{
// Handle the error.
}
_isClientAreaExtended = true;
_extendedMargins = new Thickness(margins.cxLeftWidth / Scaling, margins.cyTopHeight / Scaling, margins.cxRightWidth / Scaling, margins.cyBottomHeight / Scaling);
ExtendClientAreaToDecorationsChanged?.Invoke(true);
}
lRet = IntPtr.Zero;
callDwp = true;
break;

Loading…
Cancel
Save