XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFEToolBox

【WPF】XFE工具箱

公开
关注 0 Fork 0 Star 0
UTF-8
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using XFEToolBox.WpfCore.Windowing;

namespace XFEToolBox.WpfCore.Controls;

public partial class WindowCaptionBar : UserControl
{
    public static readonly DependencyProperty DragHandleVisibilityProperty = DependencyProperty.Register(
        nameof(DragHandleVisibility), typeof(Visibility), typeof(WindowCaptionBar), new PropertyMetadata(Visibility.Visible));

    public static readonly DependencyProperty MinimizeButtonVisibilityProperty = DependencyProperty.Register(
        nameof(MinimizeButtonVisibility), typeof(Visibility), typeof(WindowCaptionBar), new PropertyMetadata(Visibility.Visible));

    public static readonly DependencyProperty CloseButtonVisibilityProperty = DependencyProperty.Register(
        nameof(CloseButtonVisibility), typeof(Visibility), typeof(WindowCaptionBar), new PropertyMetadata(Visibility.Visible));

    public static readonly DependencyProperty AllowMaximizeProperty = DependencyProperty.Register(
        nameof(AllowMaximize), typeof(bool), typeof(WindowCaptionBar), new PropertyMetadata(true));

    public WindowCaptionBar()
    {
        InitializeComponent();
        Loaded += (_, _) =>
        {
            if (Window.GetWindow(this) is { } window)
                WindowWorkAreaHelper.Attach(window);
        };
    }

    public Visibility DragHandleVisibility
    {
        get => (Visibility)GetValue(DragHandleVisibilityProperty);
        set => SetValue(DragHandleVisibilityProperty, value);
    }

    public Visibility MinimizeButtonVisibility
    {
        get => (Visibility)GetValue(MinimizeButtonVisibilityProperty);
        set => SetValue(MinimizeButtonVisibilityProperty, value);
    }

    public Visibility CloseButtonVisibility
    {
        get => (Visibility)GetValue(CloseButtonVisibilityProperty);
        set => SetValue(CloseButtonVisibilityProperty, value);
    }

    public bool AllowMaximize
    {
        get => (bool)GetValue(AllowMaximizeProperty);
        set => SetValue(AllowMaximizeProperty, value);
    }

    /// <summary>
    /// 提供给交互教程等外部功能的真实拖动区域,不包含最小化和关闭按钮。
    /// </summary>
    public FrameworkElement DragSurfaceElement => DragSurface;

    public event EventHandler? MinimizeRequested;
    public event EventHandler? CloseRequested;

    private void DragSurface_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton != MouseButton.Left)
            return;
        if (e.ClickCount == 2 && AllowMaximize)
        {
            var window = Window.GetWindow(this);
            if (window?.ResizeMode is ResizeMode.CanResize or ResizeMode.CanResizeWithGrip)
                window.WindowState = window.WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
            e.Handled = true;
        }
    }

    private void DragSurface_MouseMove(object sender, MouseEventArgs e)
    {
        if (e.LeftButton != MouseButtonState.Pressed || Window.GetWindow(this) is not { } window)
            return;

        if (window.WindowState == WindowState.Maximized)
        {
            var pointer = e.GetPosition(window);
            var screenPoint = window.PointToScreen(pointer);
            if (PresentationSource.FromVisual(window)?.CompositionTarget is { } compositionTarget)
                screenPoint = compositionTarget.TransformFromDevice.Transform(screenPoint);
            var horizontalRatio = window.ActualWidth <= 0 ? 0.5 : pointer.X / window.ActualWidth;
            window.WindowState = WindowState.Normal;
            window.Left = screenPoint.X - window.Width * horizontalRatio;
            window.Top = Math.Max(0, screenPoint.Y - 10);
        }

        try
        {
            window.DragMove();
        }
        catch (InvalidOperationException)
        {
            // 鼠标在窗口状态变化期间释放时,拖动自然结束。
        }
    }

    private void MinimizeImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        if (MinimizeRequested is not null)
            MinimizeRequested.Invoke(this, EventArgs.Empty);
        else if (Window.GetWindow(this) is { } window)
            window.WindowState = WindowState.Minimized;
    }

    private void CloseImage_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        e.Handled = true;
        if (CloseRequested is not null)
            CloseRequested.Invoke(this, EventArgs.Empty);
        else
            Window.GetWindow(this)?.Close();
    }
}