【WPF】自定义Windows窗口样式
作者:互联网
文章目录
前言
WPF中的很多控件都可以直接修改其样式,但对于Window控件,无法通过简单的style来修改其样式,本文提供了一个实现任意风格window的方法。
一、程序文件结构
为了实现任意风格的Window,就需要重写Window的默认模板,首先是创建Window的派生类,并创建自定义style,重写DefaultStyleKey属性将样式和Window派生类结合到一起。这里创建了一个WPF应用程序来实现,文件结构如下。
二、具体实现
本文实现了两种自定义窗口,普通窗口PageWindow和对话框窗口DialogWindow。
1.资源文件generic.xaml代码
创建一个Themes文件夹,添加资源文件generic.xaml,因为微软对此进行了硬编码,必须建立这样的文件夹和文件,才能将自定义控件和默认样式协同工作。
代码如下(示例):
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:customWindow="clr-namespace:CustomSystemWindow.CustomWindow">
<DataTemplate x:Key="RestoreWhite">
<Grid UseLayoutRounding="True">
<Path Data="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"
Width="12" Height="12" UseLayoutRounding="True"
VerticalAlignment="Center" HorizontalAlignment="Center" Fill="White" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="CloseWhite">
<Grid UseLayoutRounding="True">
<Path 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"
Width="12" Height="12" UseLayoutRounding="True"
VerticalAlignment="Center" HorizontalAlignment="Center" Fill="White" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="MaximizeWhite">
<Grid>
<Path Data="M1,1 L1 ,11 L11,11 L11,1 z M0,0 L12,0 L12,12 L0,12 z"
Width="12" Height="12" UseLayoutRounding="True"
VerticalAlignment="Center" HorizontalAlignment="Center" Fill="White" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="MinimizeWhite">
<Grid>
<Path Data="M0,5 L12,5 L12,6 L0,6 z"
Width="12" Height="12" UseLayoutRounding="True"
VerticalAlignment="Center" HorizontalAlignment="Center" Fill="White" />
</Grid>
</DataTemplate>
<Style x:Key="TitleBarButtonFocusVisual">
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate>
<Rectangle Margin="2" SnapsToDevicePixels="True" Stroke="Transparent"
StrokeDashArray="1 2" StrokeThickness="1" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TitleBarButtonStyle"
TargetType="{x:Type Button}">
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="#15181C" />
<Setter Property="Width" Value="36" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid x:Name="LayoutRoot"
Background="Transparent">
<Border x:Name="ButtonBackground"
BorderBrush="Gray" BorderThickness="1"
Opacity="0" Height="30" Width="30"/>
<Border x:Name="ButtonBorder"
SnapsToDevicePixels="true">
<ContentPresenter
x:Name="TitleBarButtonContentPresenter" Focusable="False"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" RecognizesAccessKey="True"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Opacity" Value="1" TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.6"
TargetName="ButtonBackground" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter TargetName="TitleBarButtonContentPresenter" Property="Opacity" Value=".5" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type customWindow:CustomWindow}">
<Setter Property="Foreground"
Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
<Setter Property="Background" Value="#FFF1F1F1" />
<Setter Property="BorderBrush" Value="#15181C" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="ResizeMode" Value="CanResizeWithGrip" />
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="TextOptions.TextFormattingMode" Value="Display" />
<Setter Property="WindowStyle" Value="SingleBorderWindow" />
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CornerRadius="0" GlassFrameThickness="1"
UseAeroCaptionButtons="False" NonClientFrameEdges="None" />
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type customWindow:CustomWindow}">
<Border x:Name="WindowBorder">
<Grid Background="#FF15181C">
<Border VerticalAlignment="Top" Height="40">
<Border.Background>
<LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
<GradientStop Color="#2B313B" Offset="1"/>
<GradientStop Color="#181B21" Offset="0"/>
</LinearGradientBrush>
</Border.Background>
</Border>
<Grid x:Name="LayoutRoot" Margin="30,0,30,30" Background="{TemplateBinding Background}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid x:Name="PART_WindowTitleGrid" Grid.Row="0" Height="40">
<Grid.Background>
<LinearGradientBrush StartPoint="0.5,1" EndPoint="0.5,0">
<GradientStop Color="#2B313B" Offset="1"/>
<GradientStop Color="#181B21" Offset="0"/>
</LinearGradientBrush>
</Grid.Background>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="36" />
</Grid.ColumnDefinitions>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<Button VerticalAlignment="Center"
Margin="7,0,5,0" Content="{TemplateBinding Icon}"
Height="{x:Static SystemParameters.SmallIconHeight}"
Width="{x:Static SystemParameters.SmallIconWidth}"
WindowChrome.IsHitTestVisibleInChrome="True"
IsTabStop="False">
<Button.Template>
<ControlTemplate TargetType="{x:Type Button}">
<Image Source="{TemplateBinding Content}" />
</ControlTemplate>
</Button.Template>
<!--<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{x:Static SystemCommands.ShowSystemMenuCommand}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{x:Static SystemCommands.CloseWindowCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>-->
</Button>
<ContentControl IsTabStop="False"
Foreground="White"
HorizontalAlignment="Center"
VerticalAlignment="Center"
HorizontalContentAlignment="Center"
FontSize="16" FontFamily="Arial-BoldMT"
Content="{TemplateBinding Title}" />
</StackPanel>
<StackPanel x:Name="WindowCommandButtonsStackPanel"
Grid.Column="1"
HorizontalAlignment="Right"
VerticalAlignment="Stretch"
Background="Transparent"
Orientation="Horizontal"
WindowChrome.IsHitTestVisibleInChrome="True"
Margin="0,-1,-1,0">
<Button x:Name="Minimize"
ToolTip="Minimize"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}"
ContentTemplate="{StaticResource MinimizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
<Grid Margin="1,0,1,0">
<Button x:Name="Restore"
ToolTip="Restore"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}"
ContentTemplate="{StaticResource RestoreWhite}"
Style="{StaticResource TitleBarButtonStyle}"
Visibility="Collapsed" IsTabStop="False" />
<Button x:Name="Maximize" ToolTip="Maximize"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}"
ContentTemplate="{StaticResource MaximizeWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</Grid>
<Button x:Name="Close"
ToolTip="Close" Background="Red"
WindowChrome.IsHitTestVisibleInChrome="True"
Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}"
ContentTemplate="{StaticResource CloseWhite}"
Style="{StaticResource TitleBarButtonStyle}"
IsTabStop="False" />
</StackPanel>
</Grid>
<AdornerDecorator Grid.Row="1"
KeyboardNavigation.IsTabStop="False">
<ContentControl Content="{TemplateBinding Content}"
x:Name="MainContentPresenter"/>
</AdornerDecorator>
<ResizeGrip x:Name="ResizeGrip"
HorizontalAlignment="Right" VerticalAlignment="Bottom"
Grid.Row="1" IsTabStop="False" Visibility="Hidden"
WindowChrome.ResizeGripDirection="BottomRight" />
</Grid>
</Grid>
</Border>
<ControlTemplate.Triggers>
<!--<Trigger Property="IsActive" Value="False">
<Setter Property="BorderBrush" Value="#FF6F7785" />
</Trigger>-->
<Trigger Property="WindowState" Value="Maximized">
<Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
<Setter TargetName="Restore" Property="Visibility" Value="Visible" />
<Setter TargetName="LayoutRoot" Property="Margin" Value="7" />
</Trigger>
<Trigger Property="WindowState" Value="Normal">
<Setter TargetName="Maximize" Property="Visibility" Value="Visible" />
<Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
</Trigger>
<Trigger Property="ResizeMode" Value="NoResize">
<Setter TargetName="Minimize" Property="Visibility" Value="Collapsed" />
<Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
<Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="ResizeMode" Value="CanResizeWithGrip" />
<Condition Property="WindowState" Value="Normal" />
</MultiTrigger.Conditions>
<Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
2.Window派生类CustomWindow.cs
using System;
using System.Windows;
using System.Windows.Input;
namespace CustomSystemWindow.CustomWindow
{
public class CustomWindow : Window
{
public CustomWindow()
{
DefaultStyleKey = typeof(CustomWindow);
CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, CloseWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, MaximizeWindow, CanResizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, MinimizeWindow, CanMinimizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, RestoreWindow, CanResizeWindow));
CommandBindings.Add(new CommandBinding(SystemCommands.ShowSystemMenuCommand, ShowSystemMenu));
}
public event Action CloseWindowEvent;
//protected override void onm ouseLeftButtonDown(MouseButtonEventArgs e)
//{
// base.OnMouseLeftButtonDown(e);
// if (e.ButtonState == MouseButtonState.Pressed)
// DragMove();
//}
protected override void OnContentRendered(EventArgs e)
{
base.OnContentRendered(e);
if (SizeToContent == SizeToContent.WidthAndHeight)
InvalidateMeasure();
}
#region Window Commands
private void CanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ResizeMode == ResizeMode.CanResize || ResizeMode == ResizeMode.CanResizeWithGrip;
}
private void CanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = ResizeMode != ResizeMode.NoResize;
}
private void CloseWindow(object sender, ExecutedRoutedEventArgs e)
{
if (null != CloseWindowEvent)
{
CloseWindowEvent();
}
this.Close();
}
private void MaximizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MaximizeWindow(this);
}
private void MinimizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MinimizeWindow(this);
}
private void RestoreWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.RestoreWindow(this);
}
private void ShowSystemMenu(object sender, ExecutedRoutedEventArgs e)
{
var element = e.OriginalSource as FrameworkElement;
if (element == null)
return;
var point = WindowState == WindowState.Maximized ? new Point(0, element.ActualHeight)
: new Point(Left + BorderThickness.Left, element.ActualHeight + Top + BorderThickness.Top);
point = element.TransformToAncestor(this).Transform(point);
SystemCommands.ShowSystemMenu(this, point);
}
#endregion
}
}
3、普通窗口
- 前端代码PageWindow.xaml
<local:CustomWindow x:Class="CustomSystemWindow.CustomWindow.PageWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CustomSystemWindow.CustomWindow"
mc:Ignorable="d" Title="PageWindow" Height="300" Width="600">
</local:CustomWindow>
- 后端代码PageWindow.xaml.cs
4、对话框窗口
- 前端代码DialogWindow.xaml
<local:CustomWindow x:Class="CustomSystemWindow.CustomWindow.DialogWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:CustomSystemWindow.CustomWindow"
mc:Ignorable="d" Title="DialogWindow" Height="250" Width="460" >
<Border Background="#15181C">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="120"></RowDefinition>
<RowDefinition Height="90"></RowDefinition>
</Grid.RowDefinitions>
<TextBlock x:Name="MessageControl" Grid.Row="0"
FontSize="14" Foreground="White" TextWrapping="Wrap"
VerticalAlignment="Center" HorizontalAlignment="Center"/>
<Border Grid.Row="0" BorderBrush="#252A33" BorderThickness="1"
VerticalAlignment="Bottom"></Border>
<Grid Grid.Row="1" x:Name="YesNoControl" Visibility="Visible">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Button Grid.Column="0" HorizontalAlignment="Right"
Height="30" Width="150" Content="是" Foreground="White"
Margin="0,0,10,0" Background="#434B59"
Click="OkButtonClick"/>
<Button Grid.Column="1" HorizontalAlignment="Left"
Height="30" Width="150" Content="否" Foreground="White"
Margin="10,0,0,0" Background="#434B59"
Click="CancelButtonClick"/>
</Grid>
<Button Grid.Row="1" x:Name="OkControl" Visibility="Collapsed"
Height="30" Width="150" Content="确认"
Foreground="White" Background="#434B59"
Click="ConfirmButtonClick"/>
</Grid>
</Border>
</local:CustomWindow>
- 后端代码DialogWindow.xaml.cs
using System.Windows;
namespace CustomSystemWindow.CustomWindow
{
public partial class DialogWindow
{
public DialogWindow()
{
InitializeComponent();
}
public string Message
{
set { this.MessageControl.Text = value; }
get { return this.MessageControl.Text; }
}
public static bool? Show(string title, string msg, MessageBoxButton category)
{
var msgBox = new DialogWindow();
if (MessageBoxButton.OK == category)
{
msgBox.YesNoControl.Visibility = Visibility.Collapsed;
msgBox.OkControl.Visibility = Visibility.Visible;
}
else if (MessageBoxButton.YesNo == category)
{
msgBox.YesNoControl.Visibility = Visibility.Visible;
msgBox.OkControl.Visibility = Visibility.Collapsed;
}
msgBox.ResizeMode = ResizeMode.NoResize;
msgBox.WindowStartupLocation = WindowStartupLocation.CenterScreen;
msgBox.Title = title;
msgBox.Message = msg;
return msgBox.ShowDialog();
}
private void OkButtonClick(object sender, RoutedEventArgs e)
{
this.DialogResult = true;
this.Close();
}
private void CancelButtonClick(object sender, RoutedEventArgs e)
{
this.DialogResult = false;
this.Close();
}
private void ConfirmButtonClick(object sender, RoutedEventArgs e)
{
this.Close();
}
}
}
五、实现效果
-
普通窗口
-
对话框窗口
代码路径:https://download.csdn.net/download/m0_38045338/14953045参考1:https://blog.csdn.net/gentle_wolf/article/details/5908340
参考2:https://www.cnblogs.com/s0611163/p/9994529.html
标签:sender,自定义,Windows,void,object,private,SystemCommands,WPF,msgBox 来源: https://blog.csdn.net/m0_38045338/article/details/113367332