C# wpf 无边框窗口添加阴影效果的实现

 更新时间:2022年11月22日 09:05:52   作者:CodeOfCC  
在本篇内容中小编给大家整理了一篇关于C# wpf 无边框窗口添加阴影效果的具体方法内容,有兴趣的朋友们可以学习参考下

前言

制作无边框窗口时,系统自带阴影会消失,这时就需要我自己给窗口添加阴影以防止窗口融入背景。添加阴影的方法很简单,直接用effect就可以了,但这里还是有个不容易注意到的细节需要处理,加阴影后窗口最大化可能会有问题。

一、如何实现?

1、去除边框

(1)方法一

使用WindowStyle可以去除窗口边框,AllowsTransparency+Background制造透明窗口为阴影留出透明边距。
注:此方法较影响窗口渲染性能。

<Window  WindowStyle="None" AllowsTransparency="True"  Background="Transparent" >

(2)方法二

使用WindowChrome也可以实现无边框窗口,.net4.5之后可以使用此组件。WindowChrome通常不会影响渲染性能。

<Window  WindowStyle="None"  Background="Transparent"  ResizeMode="NoResize">
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"   CaptionHeight="0"   />
    </WindowChrome.WindowChrome   
    <Grid>
    </Grid>
</Window>

2、添加阴影

使用DropShadowEffect 加Margin属性即可。添加阴影特效后,需要设置margin给阴影留出边距,否则是看不到阴影的。通常到这一步就结束了,如果窗口需要最大化则继续往下。

<Window >
    <Grid Margin="10" Background="White">
        <Grid.Effect>
            <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.8" Color="#AAAAAA"/>
        </Grid.Effect>
    </Grid>
</Window>

3、添加触发器

1、 为何添加触发器?

根据上述2个步骤添加完阴影后,如果将窗口最大化就会发现,Margin依然生效,全屏窗口有一个透明外边距,为了解决这问题所以需要添加触发器。

2、 具体实现

在style中使用触发器,绑定窗口状态,当最大化时边距设为0,其他情况设为阴影需要的边距。在这里需要注意的是此时Grid不可以设置Margin属性了只能在触发器中设置,因为赋值优先级的原因,在Grid中设置Margin后触发器的赋值会失效。

<Grid  Background="#1e1e1e">
    <Grid.Style>
        <Style TargetType="Grid">
            <!--给阴影留出边距-->
            <Style.Triggers>
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Normal">
                    <Setter Property="Margin" Value="10" />
                </DataTrigger>
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Minimized">
                    <Setter Property="Margin" Value="10" />
                </DataTrigger>
                <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Maximized">
                    <Setter Property="Margin" Value="0" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </Grid.Style>
</Grid>

二、示例代码

MainWindow.xaml

<Window x:Class="WpfApp8.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:WpfApp8"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800"
        WindowStyle="None"
        Background="Transparent"
        ResizeMode="NoResize"
        >
    <WindowChrome.WindowChrome>
        <WindowChrome GlassFrameThickness="-1"   CaptionHeight="0"   />
    </WindowChrome.WindowChrome>
    <Grid  Background="white">
        <Grid.Effect>
            <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.8" Color="#AAAAAA"/>
        </Grid.Effect>
        <Grid.Style>
            <Style TargetType="Grid">
                <!--给阴影留出边距-->
                <Style.Triggers>
                    <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Normal">
                        <Setter Property="Margin" Value="10" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Minimized">
                        <Setter Property="Margin" Value="10" />
                    </DataTrigger>
                    <DataTrigger Binding="{Binding WindowState, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Window}}" Value="Maximized">
                        <Setter Property="Margin" Value="0" />
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Grid.Style>
        <!--标题栏-->
        <Grid  VerticalAlignment="Top"  >
            <StackPanel Margin="0,0,10,0" HorizontalAlignment="Right" Orientation="Horizontal">
                <!--最小化按钮-->
                <Button Width="50" Height="50" Focusable="False" VerticalAlignment="Center" Cursor="Hand"  Click="Button_Click_1" >
                    <Button.Template>
                        <ControlTemplate TargetType="Button">
                            <Grid x:Name="grd" Background="Transparent">
                                <Rectangle Width="20" Height="3" Fill="#1e1e1e" ></Rectangle>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="grd" Property="Background" Value="#666666"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <!--最大化按钮-->
                <Button Width="50" Height="50" Focusable="False" VerticalAlignment="Center" Cursor="Hand"  Visibility="{DynamicResource MaximizeButtonVisibility}" Click="Button_Click">
                    <Button.Template>
                        <ControlTemplate>
                            <Grid x:Name="grd" Background="Transparent">
                                <Rectangle Width="20" Height="20" Stroke="#1e1e1e"  StrokeThickness="3"></Rectangle>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="grd" Property="Background" Value="#666666"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
                <!--关闭按钮-->
                <Button Width="50" Height="50"  Focusable="False"  VerticalAlignment="Center" Cursor="Hand" Click="Button_Click_2">
                    <Button.Template>
                        <ControlTemplate>

                            <Grid x:Name="grd" Background="Transparent">
                                <Line Width="20" Height="20" X1="0" Y1="0" X2="20" Y2="20" StrokeThickness="3" Stroke="#1e1e1e" ></Line>
                                <Line Width="20" Height="20" X1="20" Y1="0" X2="0" Y2="20" StrokeThickness="3" Stroke="#1e1e1e" ></Line>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter TargetName="grd" Property="Background" Value="#666666"></Setter>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </StackPanel>
        </Grid>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;
namespace WpfApp8
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {        
            WindowState = WindowState== WindowState.Maximized? WindowState .Normal: WindowState.Maximized;
        }
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            WindowState = WindowState.Minimized;
        }
        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            Close();
        }
    }
}

三、效果预览

总结

以上就是今天要讲的内容,给窗口添加阴影的方法还是比较简单的,只是需要注意窗口最大化的情况。但实际上窗口阴影对性能影响还是比较大的,尤其是有渲染视频的情况下,消耗更多的cpu。所以阴影只适合对性能要求不高的场景。

相关文章

  • C#中out与ref作用区别示例分析

    C#中out与ref作用区别示例分析

    这篇文章主要为大家介绍了C#中out与ref作用区别示例分析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • C#在复杂多线程环境下使用读写锁同步写入文件

    C#在复杂多线程环境下使用读写锁同步写入文件

    这篇文章介绍了C#在复杂多线程环境下使用读写锁同步写入文件的方法,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-04-04
  • C#实现Json文件读写的方法代码

    C#实现Json文件读写的方法代码

    这篇文章主要给大家介绍了关于C#实现Json文件读写的相关资料,C# 读取JSON文件并读取某一个关键字的值可以使用Newtonsoft.Json库,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • c# 实现计时器功能

    c# 实现计时器功能

    这篇文章主要介绍了c# 实现计时器功能的示例代码,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2020-12-12
  • C#验证码识别类完整实例

    C#验证码识别类完整实例

    这篇文章主要介绍了C#验证码识别类,以一个完整实例形式较为详细的分析了验证码图片处理所涉及的各种常用技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-07-07
  • c# dynamic的好处

    c# dynamic的好处

    这篇文章主要介绍了c# dynamic的好处,以示例代码帮助大家更好的了解和学习,感兴趣的朋友可以了解下
    2020-12-12
  • 详解c# 可空类型(Nullable)

    详解c# 可空类型(Nullable)

    这篇文章主要介绍了c# 可空类型(Nullable)的相关资料,文中示例代码非常详细,帮助大家更好的理解和学习,感兴趣的朋友可以了解下
    2020-07-07
  • C#实现对文件进行加密解密的方法

    C#实现对文件进行加密解密的方法

    这篇文章主要介绍了C#实现对文件进行加密解密的方法,涉及C#加密与解密的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-04-04
  • 浅析C# web访问mysql数据库-整理归纳总结

    浅析C# web访问mysql数据库-整理归纳总结

    本篇文章是对C#中的web访问mysql数据库的一些知识点进行了整理归纳总结,需要的朋友可以参考下
    2013-07-07
  • javascript函数中执行c#函数的方法

    javascript函数中执行c#函数的方法

    这篇文章主要介绍了javascript和c#函数和变量互相调用的方法,大家参考使用吧
    2014-01-01

最新评论