在Windows窗口應用開發過程中,經常會設計一些非矩形窗口,並包含一些投影效果,本文介紹一種實現窗口投影+裁剪效果的方法。
本文裁剪效果參考劉鐵猛老師《深入淺出WPF》一書第十二章:繪圖和動畫,裁剪米老鼠外形窗口,區別在於給窗口添加投影效果。
窗口裁剪
WPF中可以方便的設計各種不規則形狀的窗口或控件,使用Clip屬性即可,Clip屬性的數據類型是Geometry類型,可以使用路徑標記語法設置其值。如下示例所示,該示例將窗口輪廓裁剪為米老鼠樣式
注意:若要裁剪窗口,需將AllowsTransparency設置為True,WindowStyle設置為None。
<Window ...
Title="MickeyWindow" Height="250" Width="300" WindowStyle="None" AllowsTransparency="True"
ResizeMode="NoResize" Background="Gray">
<Window.Clip>
<PathGeometry Figures="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z"/>
</Window.Clip>
<Grid>
...
</Grid>
</Window>
效果如下圖:

窗口投影
投影效果可以通過設置BitmapEffect屬性或Effect屬性實現,建議使用Effect屬性。BitmapEffect已標記為Obsolete,它使用CPU計算,會影響程序性能。Effect使用GPU運算,減少了對CPU資源的浪費。
Effect為抽象類,通過派生可以實現各種效果。WPF官方僅提供了模糊效果(BlurEffect)與投影效果(DropShadowEffect),其它自定義效果可通過派生ShaderEffect實現。本文使用DropShadowEffect實現投影效果。
投影效果無法直接應用於Window,可以為Window的內部元素添加投影效果,並需要設置其Margin屬性,Window的AllowsTransparency需設置為True。
DropShadowEffect中有幾個關鍵屬性,Color屬性設置投影顏色,BlurRadius屬性設置模糊效果半徑,ShadowDepth屬性設置投影距元素的距離,Opacity屬性設置投影的不透明度,Direction屬性設置投影方向。
本文實現暈影效果,將ShadowDepth置為0即可,無需設置Direction。
<Window ...
Title="MickeyWindow" Height="250" Width="300" WindowStyle="None" AllowsTransparency="True"
ResizeMode="NoResize" Background="Transparent">
<Grid>
<Border Margin="15" BorderBrush="Gray" BorderThickness="2">
<Border.Effect>
<DropShadowEffect Color="Black" BlurRadius="15" ShadowDepth="0"/>
</Border.Effect>
</Border>
</Grid>
</Window>
效果如下圖:

合並裁剪與投影效果
投影效果添加到了窗口內部Border元素上,因此需要調整Clip屬性。直接將Clip也應用到Border上是不行的,需要將其應用到子元素上。
<Grid>
<Border Margin="15">
<Border.Effect>
<DropShadowEffect Color="Black" BlurRadius="15" ShadowDepth="0"/>
</Border.Effect>
<Grid Background="lightgray">
<Grid.Clip>
<PathGeometry Figures="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z"/>
</Grid.Clip>
</Grid>
</Border>
</Grid>
效果如下圖:

如果不想填充顏色,也可以這樣做:
<Grid>
<Border Margin="15">
<Border.Effect>
<DropShadowEffect Color="Red" BlurRadius="15" ShadowDepth="0"/>
</Border.Effect>
<Grid>
<Grid.Clip>
<PathGeometry Figures="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z"/>
</Grid.Clip>
<Path Stroke="Black" StrokeThickness="5">
<Path.Data>
<PathGeometry Figures="M 55,100 A 50,50 0 1 1 100,60 A 110,95 0 0 1 200,60 A 50,50 0 1 1 250,100 A 110,95 0 1 1 55,100 Z"/>
</Path.Data>
</Path>
</Grid>
</Border>
</Grid>
效果如下圖:

完整代碼見GitHub。
