WPF自定义Window窗体样式

时间:2022-03-21 00:18:38

资源文件代码:

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<!-- 最大化按钮形状 -->
<PathGeometry x:Key="pathMaximize">
<PathGeometry.Figures>
M1,1 L1 ,11 L11,11 L11,1 z M0,0 L12,0 L12,12 L0,12 z
</PathGeometry.Figures>
</PathGeometry>
<!-- 还原按钮形状 -->
<PathGeometry x:Key="pathRestore">
<PathGeometry.Figures>
M1,3 L1,11 L9,11 L9,3 z M3,1 L3,2 L10,2 L10,9 L11,9 L11,1 z M2 ,0 L12,0 L12,10 L10,10 L10,12 L0,12 L0,2 L2 ,2 z
</PathGeometry.Figures>
</PathGeometry>
<!-- 窗体模板 -->
<ControlTemplate x:Key="tmplWindowEx" TargetType="{x:Type Window}">
<Border>
<Border CornerRadius="5" Background="#0998B8" Margin="{Binding BorderMargin}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="28"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<TextBlock Text="{TemplateBinding Title}" Margin="10 0 0 0" FontFamily="微软雅黑,黑体" FontSize="12" Foreground="#fff" VerticalAlignment="Center"></TextBlock>
<!-- Border用于遮盖Title -->
<Border Margin="88 0 0 0" CornerRadius="0 5 0 0" Background="#0998B8" Width="90" HorizontalAlignment="{Binding BtnPanelHorizontalAlignment}"></Border>
<StackPanel Orientation="Horizontal" HorizontalAlignment="{Binding BtnPanelHorizontalAlignment}" Margin="98 0 5 0">
<Button x:Name="btnMinimize" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="1" Visibility="{Binding BtnMinimizeVisibility}" >
<Button.Template>
<ControlTemplate>
<Grid x:Name="grid" Background="Transparent">
<Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="M0,5 L12,5 L12,6 L0,6 z" VerticalAlignment="Center" HorizontalAlignment="Center"></Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="grid" Property="Background" Value="#0988a8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="btnMaximize" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="2" Visibility="{Binding BtnMaximizeVisibility}" >
<Button.Template>
<ControlTemplate>
<Grid x:Name="grid" Background="Transparent">
<Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="{Binding BtnMaximizePathData}" VerticalAlignment="Center" HorizontalAlignment="Center" ></Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="grid" Property="Background" Value="#0988a8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
<Button x:Name="btnClose" Width="28" Height="28" WindowChrome.IsHitTestVisibleInChrome="True" Command="{Binding DataContext.WindowBtnCommand, RelativeSource={RelativeSource AncestorType=Window}}" CommandParameter="3">
<Button.Template>
<ControlTemplate>
<Grid x:Name="grid" Background="Transparent">
<Path x:Name="path1" Width="12" Height="12" Fill="#fff" Data="M1,0 L6,5 L11,0 L12,1 L7,6 L12,11 L11,12 L6,7 L1,12 L0,11 L5,6 L0,1 z" VerticalAlignment="Center" HorizontalAlignment="Center" ></Path>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter TargetName="grid" Property="Background" Value="#0988a8"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Button.Template>
</Button>
</StackPanel>
<Border Background="#d6e7f1" CornerRadius="3 0 3 3" Grid.Row="1" Margin="3 0 3 3" >
<ContentPresenter ></ContentPresenter>
</Border>
</Grid>
</Border>
</Border>
</ControlTemplate>
<!-- 窗体样式 -->
<Style x:Key="stlWindowEx" TargetType="{x:Type Window}">
<Setter Property="Template" Value="{StaticResource tmplWindowEx}"/>
<!--在代码中设置AllowsTransparency和WindowStyle-->
<!--<Setter Property="AllowsTransparency" Value="True"></Setter>-->
<!--<Setter Property="WindowStyle" Value="None" />-->
<Setter Property="Background" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="ResizeMode" Value="NoResize" />
<Setter Property="ShowInTaskbar" Value="False" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CornerRadius="5"
CaptionHeight="28"
GlassFrameThickness="0"
UseAeroCaptionButtons="False"
NonClientFrameEdges="None">
</WindowChrome>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

自定义窗体封装WindowEx类代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Resources;
using System.Windows.Shapes; namespace SunCreate.Common.Controls
{
/// <summary>
/// 窗体封装
/// </summary>
public class WindowEx : Window, INotifyPropertyChanged
{
public event EventHandler<WindowExFixEventArgs> FixEvent; private ResourceDictionary _resource; private ICommand _WindowBtnCommand;
/// <summary>
/// 窗体按钮命令
/// </summary>
public ICommand WindowBtnCommand
{
get
{
return _WindowBtnCommand;
}
set
{
_WindowBtnCommand = value;
OnPropertyChanged("WindowBtnCommand");
}
} private Thickness _BorderMargin = new Thickness(, , , );
public Thickness BorderMargin
{
get
{
return _BorderMargin;
}
set
{
_BorderMargin = value;
OnPropertyChanged("BorderMargin");
}
} private HorizontalAlignment _BtnPanelHorizontalAlignment = HorizontalAlignment.Right;
/// <summary>
/// 窗体按钮的Panel位置
/// </summary>
public HorizontalAlignment BtnPanelHorizontalAlignment
{
get
{
return _BtnPanelHorizontalAlignment;
}
set
{
_BtnPanelHorizontalAlignment = value;
OnPropertyChanged("BtnPanelHorizontalAlignment");
}
} private Visibility _BtnMinimizeVisibility = Visibility.Visible;
/// <summary>
/// 窗体最小化按钮的显示状态
/// </summary>
public Visibility BtnMinimizeVisibility
{
get
{
return _BtnMinimizeVisibility;
}
set
{
_BtnMinimizeVisibility = value;
OnPropertyChanged("BtnMinimizeVisibility");
}
} private Visibility _BtnMaximizeVisibility = Visibility.Visible;
/// <summary>
/// 窗体最大化按钮的显示状态
/// </summary>
public Visibility BtnMaximizeVisibility
{
get
{
return _BtnMaximizeVisibility;
}
set
{
_BtnMaximizeVisibility = value;
OnPropertyChanged("BtnMaximizeVisibility");
}
} private Geometry _BtnMaximizePathData;
/// <summary>
/// 窗体最大化按钮的样式
/// </summary>
public Geometry BtnMaximizePathData
{
get
{
return _BtnMaximizePathData;
}
set
{
_BtnMaximizePathData = value;
OnPropertyChanged("BtnMaximizePathData");
}
} private Visibility _TitleVisibility = Visibility.Visible;
/// <summary>
/// 是否显示标题
/// </summary>
public Visibility TitleVisibility
{
get
{
return _TitleVisibility;
}
set
{
_TitleVisibility = value;
OnPropertyChanged("TitleVisibility");
}
} private WindowExTheme _Theme = WindowExTheme.Default;
/// <summary>
/// 窗体主题
/// </summary>
public WindowExTheme Theme
{
get
{
return _Theme;
}
set
{
_Theme = value;
OnPropertyChanged("Theme");
}
} /// <summary>
/// 窗体 构造函数
/// </summary>
public WindowEx()
{
this.Loaded += WindowEx_Loaded;
this.DataContext = this; #region 窗体样式设置
//this.AllowsTransparency = true; //AllowsTransparency会导致视频播放不显示
this.WindowStyle = WindowStyle.None;
#endregion #region 窗体按钮事件
WindowBtnCommand windowBtnCommand = new WindowBtnCommand();
windowBtnCommand.DoAction = (parameter) =>
{
if (parameter == ) //最小化
{
MinimizedSet();
this.WindowState = WindowState.Minimized;
}
if (parameter == ) //窗口还原、最大化
{
if (this.WindowState == WindowState.Normal)
{
MaximizedSet();
this.WindowState = WindowState.Maximized;
}
else if (this.WindowState == WindowState.Maximized)
{
RestoredSet();
this.WindowState = WindowState.Normal;
}
else if (this.WindowState == WindowState.Minimized)
{
RestoredSet();
this.WindowState = WindowState.Normal;
}
}
if (parameter == ) //关闭窗口
{
this.Close();
}
if (parameter == ) //固定窗口
{
if (FixEvent != null)
{
WindowExFixEventArgs args = new WindowExFixEventArgs(this.Content);
FixEvent(this, args);
}
}
};
this.WindowBtnCommand = windowBtnCommand;
this.StateChanged += (s, e) =>
{
if (this.WindowState == WindowState.Maximized)
{
MaximizedSet();
}
if (this.WindowState == WindowState.Normal)
{
RestoredSet();
}
if (this.WindowState == WindowState.Minimized)
{
MinimizedSet();
}
};
#endregion } /// <summary>
/// 窗体Loaded
/// </summary>
private void WindowEx_Loaded(object sender, RoutedEventArgs e)
{
#region 窗体样式设置
Uri uri = null;
switch (Theme)
{
case WindowExTheme.Default:
uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/WindowExResource.xaml", UriKind.Relative);
break;
case WindowExTheme.MessageBox:
uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/MessageBoxExResource.xaml", UriKind.Relative);
break;
case WindowExTheme.TabContainer:
uri = new Uri("/SunCreate.Common.Controls;Component/WindowEx/TabContainerResource.xaml", UriKind.Relative);
break;
}
_resource = new ResourceDictionary();
_resource.Source = uri;
this.Style = _resource["stlWindowEx"] as Style;
if (this.WindowState == WindowState.Maximized)
{
this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry;
}
else
{
this.BtnMaximizePathData = _resource["pathMaximize"] as PathGeometry;
}
#endregion #region 最大化设置
if (this.WindowState == WindowState.Maximized)
{
this.BorderMargin = CalculateWinMargin(true);
}
#endregion } #region 最小化设置
private void MinimizedSet()
{
this.BorderMargin = new Thickness(, , , );
BtnPanelHorizontalAlignment = HorizontalAlignment.Left;
BtnMinimizeVisibility = Visibility.Collapsed;
if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Collapsed; //最小化时隐藏Content
if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Visible;
this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry;
}
#endregion #region 还原设置
private void RestoredSet()
{
this.BorderMargin = new Thickness(, , , );
BtnPanelHorizontalAlignment = HorizontalAlignment.Right;
BtnMinimizeVisibility = Visibility.Visible;
if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Visible; //最大化或还原时显示Content
this.BtnMaximizePathData = _resource["pathMaximize"] as PathGeometry;
if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Collapsed;
}
#endregion #region 最大化设置
private void MaximizedSet()
{
this.BorderMargin = CalculateWinMargin(false);
BtnPanelHorizontalAlignment = HorizontalAlignment.Right;
BtnMinimizeVisibility = Visibility.Visible;
if (this.Content != null) (this.Content as FrameworkElement).Visibility = Visibility.Visible; //最大化或还原时显示Content
this.BtnMaximizePathData = _resource["pathRestore"] as PathGeometry;
if (this.Theme == WindowExTheme.TabContainer) TitleVisibility = Visibility.Collapsed;
}
#endregion #region 计算窗体Margin大小
/// <summary>
/// 计算窗体Margin大小
/// </summary>
private Thickness CalculateWinMargin(bool firstLoad = false)
{
double taskBarHeight = SystemParameters.PrimaryScreenHeight - SystemParameters.WorkArea.Height;
double taskBarWidth = SystemParameters.PrimaryScreenWidth - SystemParameters.WorkArea.Width;
if (this.Theme == WindowExTheme.TabContainer || firstLoad)
{
if (taskBarWidth > )
{
return new Thickness(, , taskBarWidth + , );
}
if (taskBarHeight > )
{
return new Thickness(, , , taskBarHeight + );
}
return new Thickness(, , , );
}
else
{
if (taskBarWidth > )
{
return new Thickness(, , taskBarWidth, );
}
if (taskBarHeight > )
{
return new Thickness(, , , taskBarHeight);
}
return new Thickness(, , , );
}
}
#endregion #region 实现INotifyPropertyChanged接口
public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
#endregion }
}

窗体最小化、最大化、关闭按钮的命令WindowBtnCommand:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input; namespace SunCreate.Common.Controls
{
public class WindowBtnCommand : ICommand
{
public Action<int> DoAction { get; set; } public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
} public bool CanExecute(object parameter)
{
return true;
} public void Execute(object parameter)
{
if (DoAction != null)
{
DoAction(Convert.ToInt32(parameter));
}
}
}
}

使用WindowEx类的示例代码:

<ui:WindowEx x:Class="SunCreate.Common.Controls.Demo.MyWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ui="clr-namespace:SunCreate.Common.Controls;assembly=SunCreate.Common.Controls"
Title="视频播放视频播放ABCDEFG" Height="300" Width="500" WindowStartupLocation="CenterScreen"
BtnMinimizeVisibility="Visible" BtnMaximizeVisibility="Visible" >
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/SunCreate.Common.Controls;Component/Themes/ScrollViewer.xaml"/>
<ResourceDictionary Source="/SunCreate.Common.Controls;Component/Themes/ControlsResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Window.Resources>
<Grid>
<StackPanel>
<Border Margin="10">
<Button Height="30" Width="80" Content="测试" Style="{StaticResource stlTxtBtn}" HorizontalAlignment="Left" Click="Button_Click" />
</Border>
<Border Margin="10">
<TextBlock Text="测试内容ABC"></TextBlock>
</Border>
</StackPanel>
</Grid>
</ui:WindowEx>

效果图:

WPF自定义Window窗体样式

窗体最小化效果图:

WPF自定义Window窗体样式