WPF_自定义无边框窗体

*.WindowChrome方式实现自定义窗体的拖动、大小拖拽、系统菜单、双击最大化、双击正常等功能。

效果图如下:

1.创建资源字典:NBorderWindow.xaml,代码如下:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:o="http://schemas.microsoft.com/winfx/2006/xaml/presentation/options"
                    xmlns:shell="clr-namespace:System.Windows.Shell;assembly=PresentationFramework"
                    xmlns:control="clr-namespace:MainApp.Client.UI.Controls">
    <Geometry o:Freeze="True" x:Key="WindowMinGeometry">M0,4 L10,4 L10,5 L0,5 z</Geometry>
    <Geometry o:Freeze="True" x:Key="WindowMaxGeometry">M1,1 L1,9 L9,9 L9,1 z M0,0 L10,0 L10,10 L0,10 z</Geometry>
    <Geometry o:Freeze="True" x:Key="WindowRestoreGeometry">M1,3 L1,9 L7,9 L7,3 z M3,1 L3,2 L8,2 L8,7 L9,7 L9,1 z M2,0 L10,0 L10,8 L8,8 L8,10 L0,10 L0,2 L2,2 z</Geometry>
    <Geometry o:Freeze="True" x:Key="CloseGeometry">M0.7,0 L5,4.3 L9.3,0 L10,0.7 L5.7,5 L10,9.3 L9.3,10 L5,5.7 L0.7,10 L0,9.3 L4.3,5 L0,0.7 z</Geometry>
    <Style x:Key="NBorderWindow" TargetType="{x:Type control:NBorderWindow}">
        <Setter Property="Background">
            <Setter.Value>
                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                    <GradientStop Color="#FF1B2A3C" Offset="1"/>
                    <GradientStop Color="#FF4D5F6F" Offset="0"/>
                </LinearGradientBrush>
            </Setter.Value>
        </Setter>
        <Setter Property="BorderThickness" Value="1" />
        <Setter Property="UseLayoutRounding" Value="True" />
        <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
        <Setter Property="WindowStyle" Value="None"/>
        <Setter Property="AllowsTransparency" Value="True"/>
        <Setter Property="shell:WindowChrome.WindowChrome">
            <Setter.Value>
                <shell:WindowChrome UseAeroCaptionButtons="False" ResizeBorderThickness="6"/>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="control:NBorderWindow">
                    <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                        <Border.Effect>
                            <DropShadowEffect Color="#FF1B2A3C" ShadowDepth="0" BlurRadius="5" Opacity="0.3" Direction="0"/>
                        </Border.Effect>
                        <Grid x:Name="windowGrid" Background="{TemplateBinding Background}">
                            <AdornerDecorator>
                                <ContentPresenter/>
                            </AdornerDecorator>
                            <Grid shell:WindowChrome.IsHitTestVisibleInChrome="True">
                                <StackPanel HorizontalAlignment="Right" VerticalAlignment="Top" Orientation="Horizontal">
                                    <control:PathGeometryButton x:Name="minimizedButton" Width="34" Height="30" PathGeometry="{StaticResource WindowMinGeometry}" Background="Transparent"
                                           ToolTip="最小化" BgFocus="#F76B69" Foreground="White" BorderThickness="0" Cursor="Hand"
                                           Command="SystemCommands.MinimizeWindowCommand"/>
                                    <control:PathGeometryButton x:Name="restoreButton" Visibility="Collapsed" Width="34" Height="30" PathGeometry="{StaticResource WindowRestoreGeometry}" Background="Transparent"
                                           ToolTip="还原" BgFocus="#F76B69" Foreground="White" BorderThickness="0" Cursor="Hand"
                                           Command="SystemCommands.RestoreWindowCommand"/>
                                    <control:PathGeometryButton x:Name="maximizedButton" Width="34" Height="30" PathGeometry="{StaticResource WindowMaxGeometry}" Background="Transparent"
                                           ToolTip="最大化" BgFocus="#F76B69" Foreground="White" BorderThickness="0" Cursor="Hand"
                                           Command="SystemCommands.MaximizeWindowCommand"/>
                                    <control:PathGeometryButton Width="34" Height="30" PathGeometry="{StaticResource CloseGeometry}" Background="Transparent"
                                           ToolTip="关闭" BgFocus="#F76B69" Foreground="White" BorderThickness="0" Cursor="Hand" 
                                           Command="SystemCommands.CloseWindowCommand"/>
                                </StackPanel>
                            </Grid>
                        </Grid>
                    </Border>
                    <ControlTemplate.Triggers>
                        <Trigger Property="ResizeMode" Value="NoResize">
                            <Setter TargetName="minimizedButton" Property="Visibility" Value="Hidden" />
                            <Setter TargetName="maximizedButton" Property="Visibility" Value="Hidden" />
                            <Setter TargetName="restoreButton" Property="Visibility" Value="Collapsed" />
                        </Trigger>
                        <Trigger Property="ResizeMode" Value="CanMinimize">
                            <Setter TargetName="maximizedButton" Property="Visibility" Value="Hidden" />
                            <Setter TargetName="restoreButton" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="minimizedButton" Property="Margin" Value="0,0,40,0" />
                        </Trigger>
                        <Trigger Property="WindowState" Value="Maximized">
                            <Setter TargetName="maximizedButton" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="restoreButton" Property="Visibility" Value="Visible" />
                            <Setter TargetName="windowGrid" Property="Margin" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(shell:WindowChrome.WindowChrome).ResizeBorderThickness}" />
                            <Setter TargetName="border" Property="BorderThickness" Value="0" />
                        </Trigger>
                        <Trigger Property="WindowState" Value="Normal">
                            <Setter TargetName="restoreButton" Property="Visibility" Value="Collapsed" />
                            <Setter TargetName="maximizedButton" Property="Visibility" Value="Visible" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

2.这里使用了自定义Button封装控件,需创建一个UserControl,修改基类为Button,相关代码如下:

 /// <summary>
    /// 按钮:根据路径绘制
    /// </summary>
    public partial class PathGeometryButton : Button
    {
        public PathGeometryButton()
        {
            InitializeComponent();
        }

        #region PathGeometryProperty
        /// <summary>
        ///路径
        /// </summary>
        public Geometry PathGeometry
        {
            get
            {
                return (Geometry)GetValue(PathGeometryProperty);
            }
            set
            {
                SetValue(PathGeometryProperty, value);
            }
        }
        public static readonly DependencyProperty PathGeometryProperty =
          DependencyProperty.RegisterAttached("PathGeometry", typeof(Geometry), typeof(PathGeometryButton), new PropertyMetadata(default(Geometry)));
        #endregion

        #region BgFocus
        public Brush BgFocus
        {
            get
            {
                return (Brush)GetValue(BgFocusProperty);
            }
            set
            {
                SetValue(BgFocusProperty, value);
            }
        }

        public static readonly DependencyProperty BgFocusProperty =
       DependencyProperty.RegisterAttached("BgFocus", typeof(Brush), typeof(PathGeometryButton), new PropertyMetadata(default(Brush)));
        #endregion

        #region CornerRadiusProperty
        /// <summary>
        /// 边框圆角
        /// </summary>
        public CornerRadius CornerRadius
        {
            get
            {
                return (CornerRadius)GetValue(CornerRadiusProperty);
            }
            set
            {
                SetValue(CornerRadiusProperty, value);
            }
        }

        public static readonly DependencyProperty CornerRadiusProperty =
          DependencyProperty.RegisterAttached("CornerRadius", typeof(CornerRadius), typeof(PathGeometryButton), new PropertyMetadata(default(CornerRadius)));
        #endregion
    }
<Button x:Class="MainApp.Client.UI.Controls.PathGeometryButton"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MainApp.Client.UI.Controls"
             mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" FocusVisualStyle="{x:Null}">
    <Button.Template>
        <ControlTemplate TargetType="Button">
            <Border Name="bg" Background="{TemplateBinding Background}" CornerRadius="{Binding Path=CornerRadius,RelativeSource={RelativeSource TemplatedParent}}" 
                    BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}">
                <Path x:Name="p" Width="10" Height="10" Data="{Binding Path=PathGeometry,RelativeSource={RelativeSource TemplatedParent}}"  Fill="{TemplateBinding Foreground}" SnapsToDevicePixels="True" Stretch="Uniform"/>
            </Border>
            <ControlTemplate.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter TargetName="bg" Property="Background" Value="{Binding Path=BgFocus,RelativeSource={RelativeSource TemplatedParent},FallbackValue=Transparent,TargetNullValue=Transparent}"/>
                    <Setter Property="Fill" Value="White" TargetName="p"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </Button.Template>
</Button>

3.创建一个NBorderWindow类,继承至Window,相关代码如下:

 /// <summary>
    /// 无边框窗体
    /// </summary>
    public class NBorderWindow : Window
    {
        #region Constructor
        static NBorderWindow()
        {
            StyleProperty.OverrideMetadata(typeof(NBorderWindow), new FrameworkPropertyMetadata(NBorderWindow.GetResource<Style>(nameof(NBorderWindow))));
        }
        public NBorderWindow()
        {
            this.Loaded += NBorderWindow_Loaded;
        } 
        #endregion

        #region NBorderWindow_Loaded
        private void NBorderWindow_Loaded(object sender, RoutedEventArgs e)
        {
            CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand,
           (s, ex) => WindowState = WindowState.Minimized));
            CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand,
                (s, ex) => WindowState = WindowState.Maximized));
            CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand,
                (s, ex) => WindowState = WindowState.Normal));
            CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, (s, ex) =>
            {
                if (this.CloseCommand != null)
                {
                    this.CloseCommand.Execute(null);
                }
                else
                {
                    Close();
                }
            }));
        }
        #endregion

        #region GetResource
        /// <summary>
        ///获取资源
        /// </summary>
        public static T GetResource<T>(string key)
        {
            if (Application.Current.TryFindResource(key) is T resource)
            {
                return resource;
            }
            return default(T);
        } 
        #endregion

        #region CloseCommand
        public ICommand CloseCommand
        {
            get
            {
                return (ICommand)GetValue(CloseCommandProperty);
            }
            set
            {
                SetValue(CloseCommandProperty, value);
            }
        }
        public static readonly DependencyProperty CloseCommandProperty =
                DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(NBorderWindow),
                    new FrameworkPropertyMetadata((ICommand)null)); 
        #endregion
    }

4.在App.xaml中绑定所创建的资源字典,如下:

    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="Resources/Styles/NBorderWindow.xaml"/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>

5.关于WindowChrome相关属性,可查阅WindowChrome 类 (System.Windows.Shell) | Microsoft Learn

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxy644492473

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值