WPF带阴影的无边框窗体

使用Window的WindowChrome属性保留无边框窗体的阴影效果、标题栏的双击、标题栏的拖拽事件
标题栏关闭按钮区别于最小化、最大化、恢复按钮样式,先BasedOn="{StaticResource WindowButtonStyle}",然后使用不同MouseOver后的背景色,注意关闭按钮中Path中的DataTrigger的使用

关闭按钮


<Button Name="Close"
Command="SystemCommands.CloseWindowCommand"
IsTabStop="True">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource WindowButtonStyle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#e81123"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Path Width="11" Height="11" Stretch="Fill"
Data="M681.92382811 547.06835938c0 23.09765625-18.7734375 41.87109375-41.92382813 41.87109375s-41.87109375-18.72070313-41.87109375-41.87109375V183.88671875c0-23.09765625 18.7734375-41.87109375 41.87109375-41.87109375s41.92382813 18.7734375 41.92382813 41.87109375V547.06835938z M288.99999998 531.24804688c0-125.296875 66.18164063-235.45898438 165.21679689-297.15820313 19.35351563-12.33984375 45.24609375-6.43359375 57.48046873 13.18359375 12.234375 19.66992188 6.328125 45.40429689-13.23632812 57.63867188-75.46289063 47.40820313-125.61328125 130.72851563-125.61328125 226.23046874C373.16406248 678.640625 492.44921873 797.97851563 639.99999998 798.29492188c147.55078125-0.36914063 266.78320313-119.70703125 267.046875-267.15234376 0-97.76953125-52.734375-182.8828125-131.25585938-229.60546874-19.93359375-11.8125-26.47265625-37.546875-14.71289062-57.48046876 11.86523438-19.88085938 37.59960938-26.41992188 57.53320313-14.66015625 102.9375 60.80273438 172.49414063 173.1796875 172.49414062 301.64062501 0 193.74609375-157.09570313 350.89453125-350.94726564 350.89453124-194.00976563 0.31640625-351.15820313-156.77929689-351.15820311-350.68359374">
<Path.Style>
<Style TargetType="Path">
<Setter Property="Fill" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Fill" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>

完整的XAML


<Window x:Class="Chromeless.MainWindow"
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:Chromeless"
mc:Ignorable="d"
ResizeMode="CanResizeWithGrip"
Title="MainWindow" Height="450" Width="800">
<Window.Resources>
<Style x:Key="WindowButtonStyle" TargetType="Button">
<Setter Property="Width" Value="40" />
<Setter Property="Height" Value="30" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#15333333" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Opacity" Value="0.8" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Window.Style>
<Style TargetType="Window">
<Setter Property="WindowChrome.WindowChrome">
<Setter.Value>
<WindowChrome CaptionHeight="40"
ResizeBorderThickness="0"
UseAeroCaptionButtons="False"/>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Window">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<Grid Margin="{TemplateBinding Padding}">
<AdornerDecorator>
<ContentPresenter />
</AdornerDecorator>
<ResizeGrip Name="ResizeGrip"
Margin="0 0 2 2"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
IsTabStop="False"
Visibility="Collapsed"
WindowChrome.ResizeGripDirection="BottomRight"/>
<StackPanel Height="40"
Margin="0 0 10 0"
HorizontalAlignment="Right"
VerticalAlignment="Top"
Orientation="Horizontal" WindowChrome.IsHitTestVisibleInChrome="True">
<Button Name="Minimize" Style="{StaticResource WindowButtonStyle}"
Command="SystemCommands.MinimizeWindowCommand"
IsTabStop="True">
<Path Width="11" Height="2" Stretch="Fill"
Fill="Black" Data="F1M0,6L0,9 9,9 9,6 0,6z"/>
</Button>
<Button Name="Maximize" Style="{StaticResource WindowButtonStyle}"
Command="SystemCommands.MaximizeWindowCommand"
IsTabStop="True">
<Path Width="11" Height="11" Stretch="Fill"
Fill="Black" Data="M255.488 768.512V403.456l365.568 365.056zM768.512 620.544L403.456 255.488h365.056z"/>
</Button>
<Button Name="Restore" Style="{StaticResource WindowButtonStyle}"
Command="SystemCommands.RestoreWindowCommand"
IsTabStop="True">
<Path Width="11" Height="11" Stretch="Fill"
Fill="Black" Data="F1M0,10L0,3 3,3 3,0 10,0 10,2 4,2 4,3 7,3 7,6 6,6 6,5 1,5 1,10z M1,10L7,10 7,7 10,7 10,2 9,2 9,6 6,6 6,9 1,9z"/>
</Button>
<Button Name="Close"
Command="SystemCommands.CloseWindowCommand"
IsTabStop="True">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource WindowButtonStyle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#e81123"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
<Path Width="11" Height="11" Stretch="Fill"
Data="M681.92382811 547.06835938c0 23.09765625-18.7734375 41.87109375-41.92382813 41.87109375s-41.87109375-18.72070313-41.87109375-41.87109375V183.88671875c0-23.09765625 18.7734375-41.87109375 41.87109375-41.87109375s41.92382813 18.7734375 41.92382813 41.87109375V547.06835938z M288.99999998 531.24804688c0-125.296875 66.18164063-235.45898438 165.21679689-297.15820313 19.35351563-12.33984375 45.24609375-6.43359375 57.48046873 13.18359375 12.234375 19.66992188 6.328125 45.40429689-13.23632812 57.63867188-75.46289063 47.40820313-125.61328125 130.72851563-125.61328125 226.23046874C373.16406248 678.640625 492.44921873 797.97851563 639.99999998 798.29492188c147.55078125-0.36914063 266.78320313-119.70703125 267.046875-267.15234376 0-97.76953125-52.734375-182.8828125-131.25585938-229.60546874-19.93359375-11.8125-26.47265625-37.546875-14.71289062-57.48046876 11.86523438-19.88085938 37.59960938-26.41992188 57.53320313-14.66015625 102.9375 60.80273438 172.49414063 173.1796875 172.49414062 301.64062501 0 193.74609375-157.09570313 350.89453125-350.94726564 350.89453124-194.00976563 0.31640625-351.15820313-156.77929689-351.15820311-350.68359374">
<Path.Style>
<Style TargetType="Path">
<Setter Property="Fill" Value="Black"/>
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" Value="True">
<Setter Property="Fill" Value="White"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Path.Style>
</Path>
</Button>
</StackPanel>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="WindowState" Value="Maximized">
<Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
<Setter TargetName="Restore" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="WindowState" Value="Normal">
<Setter TargetName="Maximize" Property="Visibility" Value="Visible" />
<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>
</Window.Style>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Background="#303030" WindowChrome.IsHitTestVisibleInChrome="True"/>
<Grid Column="1">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid Row="1" Background="#e3efff">
</Grid>
</Grid>
</Grid>
</Grid>
</Window>

完整的C#代码


using System.Windows;
using System.Windows.Input;
namespace Chromeless
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, OnCloseWindow));
this.CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, OnMaximizeWindow, OnCanResizeWindow));
this.CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, OnMinimizeWindow, OnCanMinimizeWindow));
this.CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, OnRestoreWindow, OnCanResizeWindow));
}
private void OnCanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = this.ResizeMode != ResizeMode.NoResize;
}
private void OnMinimizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MinimizeWindow(this);
}
private void OnCanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
{
e.CanExecute = this.ResizeMode == ResizeMode.CanResize || this.ResizeMode == ResizeMode.CanResizeWithGrip;
}
private void OnMaximizeWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.MaximizeWindow(this);
}
private void OnRestoreWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.RestoreWindow(this);
}
private void OnCloseWindow(object sender, ExecutedRoutedEventArgs e)
{
SystemCommands.CloseWindow(this);
}
}
}

运行效果展示


源码地址


http://hub.dbugs.work/linxmouse/GettingStarted/src/master/WPFChromeless

posted @   非法关键字  阅读(668)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
历史上的今天:
2019-11-13 C# Dynamic与Newtonsoft.Json的应用
点击右上角即可分享
微信分享提示