C#?wpf?無(wú)邊框窗口添加陰影效果的實(shí)現(xiàn)
前言
制作無(wú)邊框窗口時(shí),系統(tǒng)自帶陰影會(huì)消失,這時(shí)就需要我自己給窗口添加陰影以防止窗口融入背景。添加陰影的方法很簡(jiǎn)單,直接用effect就可以了,但這里還是有個(gè)不容易注意到的細(xì)節(jié)需要處理,加陰影后窗口最大化可能會(huì)有問題。
一、如何實(shí)現(xiàn)?
1、去除邊框
(1)方法一
使用WindowStyle可以去除窗口邊框,AllowsTransparency+Background制造透明窗口為陰影留出透明邊距。
注:此方法較影響窗口渲染性能。
<Window WindowStyle="None" AllowsTransparency="True" Background="Transparent" >
(2)方法二
使用WindowChrome也可以實(shí)現(xiàn)無(wú)邊框窗口,.net4.5之后可以使用此組件。WindowChrome通常不會(huì)影響渲染性能。
<Window WindowStyle="None" Background="Transparent" ResizeMode="NoResize"> <WindowChrome.WindowChrome> <WindowChrome GlassFrameThickness="-1" CaptionHeight="0" /> </WindowChrome.WindowChrome <Grid> </Grid> </Window>
2、添加陰影
使用DropShadowEffect 加Margin屬性即可。添加陰影特效后,需要設(shè)置margin給陰影留出邊距,否則是看不到陰影的。通常到這一步就結(jié)束了,如果窗口需要最大化則繼續(xù)往下。
<Window > <Grid Margin="10" Background="White"> <Grid.Effect> <DropShadowEffect ShadowDepth="0" BlurRadius="10" Opacity="0.8" Color="#AAAAAA"/> </Grid.Effect> </Grid> </Window>
3、添加觸發(fā)器
1、 為何添加觸發(fā)器?
根據(jù)上述2個(gè)步驟添加完陰影后,如果將窗口最大化就會(huì)發(fā)現(xiàn),Margin依然生效,全屏窗口有一個(gè)透明外邊距,為了解決這問題所以需要添加觸發(fā)器。
2、 具體實(shí)現(xiàn)
在style中使用觸發(fā)器,綁定窗口狀態(tài),當(dāng)最大化時(shí)邊距設(shè)為0,其他情況設(shè)為陰影需要的邊距。在這里需要注意的是此時(shí)Grid不可以設(shè)置Margin屬性了只能在觸發(fā)器中設(shè)置,因?yàn)橘x值優(yōu)先級(jí)的原因,在Grid中設(shè)置Margin后觸發(fā)器的賦值會(huì)失效。
<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> ? ? ? ? <!--標(biāo)題欄--> ? ? ? ? <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> ? ? ? ? ? ? ? ? <!--關(guān)閉按鈕--> ? ? ? ? ? ? ? ? <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(); } } }
三、效果預(yù)覽
總結(jié)
以上就是今天要講的內(nèi)容,給窗口添加陰影的方法還是比較簡(jiǎn)單的,只是需要注意窗口最大化的情況。但實(shí)際上窗口陰影對(duì)性能影響還是比較大的,尤其是有渲染視頻的情況下,消耗更多的cpu。所以陰影只適合對(duì)性能要求不高的場(chǎng)景。
相關(guān)文章
C#實(shí)現(xiàn)對(duì)用戶輸入數(shù)據(jù)進(jìn)行校驗(yàn)的類實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)對(duì)用戶輸入數(shù)據(jù)進(jìn)行校驗(yàn)的類,實(shí)例分析了C#針對(duì)各種用戶輸入數(shù)據(jù)的常用校驗(yàn)技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-03-03C#中Thread(線程)和Task(任務(wù))實(shí)例詳解
.NET Framework在System.Threading命名空間中具有與線程相關(guān)的類,線程是一小組可執(zhí)行指令,這篇文章主要給大家介紹了關(guān)于C#中Thread(線程)和Task(任務(wù))的相關(guān)資料,需要的朋友可以參考下2022-03-03詳解C#如何實(shí)現(xiàn)一個(gè)安全的事件訂閱器
事件訂閱器是一個(gè)對(duì)象,它訂閱(或監(jiān)聽)某個(gè)事件,并在事件發(fā)生時(shí)執(zhí)行相應(yīng)的操作,本文主要介紹了C#實(shí)現(xiàn)一個(gè)安全的事件訂閱器的相關(guān)知識(shí),感興趣的可以了解下2024-01-01WPF利用CommunityToolkit.Mvvm實(shí)現(xiàn)級(jí)聯(lián)選擇器
這篇文章主要介紹了WPF如何利用CommunityToolkit.Mvvm實(shí)現(xiàn)級(jí)聯(lián)選擇器,文中的示例代碼講解詳細(xì),對(duì)我們的學(xué)習(xí)或工作有一定幫助,需要的小伙伴可以參考一下2023-12-12C#實(shí)現(xiàn)操作windows系統(tǒng)服務(wù)(service)的方法
這篇文章主要介紹了C#實(shí)現(xiàn)操作windows系統(tǒng)服務(wù)(service)的方法,可實(shí)現(xiàn)系統(tǒng)服務(wù)的啟動(dòng)和停止功能,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2015-04-04