使用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 |
| { |
| |
| |
| |
| 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
2019-11-13 C# Dynamic与Newtonsoft.Json的应用