码迷,mamicode.com
首页 > Windows程序 > 详细

WPF窗口阴影

时间:2017-02-03 14:42:53      阅读:294      评论:0      收藏:0      [点我收藏+]

标签:rect   告诉   dir   原因   使用   defaults   use   one   ntp   

起因

在以前项目中,需要给用户一定提示。设计师建议在鼠标进入时显示窗口阴影,离开时取消窗口阴影。

尝试1

很自然,都会想到直接在窗口的内容或者自定义窗口的最外层元素上加效果。示例如下:

<Grid>
    <Grid.Effect>
        <DropShadowEffect x:Name="ShadowEffect"
                                                  BlurRadius="15"
                                                  Direction="270"
                                                  Opacity="0"
                                                  ShadowDepth="15"
                                                  Color="Yellow" />
    </Grid.Effect>
</Grid>

很不幸,上述方法不会生效。原因何在?窗口的非工作区(也就是Grid的四周)的渲染是由系统控制。虽然不清楚是绘出来了被遮住了还是根本没绘出来,但是告诉了我们此路不通。

解决方案

还好我们用的是WPF,可以自己定义模板和样式。于是简单测试了一下就发现了方案。下面就是我使用的样式一个示例(省略了模拟的控制按钮和其他的一些功能)

<Style x:Key="ShadowWindow" TargetType="Window">
    <Setter Property="OverridesDefaultStyle" Value="True" />
    <Setter Property="AllowsTransparency" Value="True" />
    <Setter Property="WindowStyle" Value="None" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Window">
                <Border Padding="15">
                    <Border Name="BdrShadow">
                        <ContentPresenter ContentSource="Content" />
                        <Border.Effect>
                            <DropShadowEffect x:Name="ShadowEffect"
                                              BlurRadius="15"
                                              Direction="270"
                                              Opacity="0"
                                              ShadowDepth="15"
                                              Color="Yellow" />
                        </Border.Effect>
                    </Border>
                </Border>
                <ControlTemplate.Triggers>
                    <EventTrigger RoutedEvent="MouseEnter">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:1"
                                                 Storyboard.TargetName="ShadowEffect"
                                                 Storyboard.TargetProperty="Opacity"
                                                 To="0.5" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                    <EventTrigger RoutedEvent="MouseLeave">
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Duration="0:0:1"
                                                 Storyboard.TargetName="ShadowEffect"
                                                 Storyboard.TargetProperty="Opacity" />
                            </Storyboard>
                        </BeginStoryboard>
                    </EventTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

注意事项

  • 必须将OverridesDefaultStyle和AllowsTransparency设为true。
  • 根据需要设置相应的属性,比如外层Border的Padding要与阴影的属性保持一致,示例中是15。

不足

  1. 有时阴影显隐失灵 。
  2. 效率低下,特别是经常需要更新界面时(所以最后我们放弃这个方案了) 。
  3. 上述样式存在一个问题,即在用到界面验证时,会发生验证提示无法显示的情况。改进也很简单,在样式中手动添加一个AdornerLayer。原因在于验证常用的AdornedElementPlaceholder中包含一个Adorner,而Adorner必须寄宿于AdornerLayer。系统默认的Window样式中包含AdornerLayer,所以显示正常。

WPF窗口阴影

标签:rect   告诉   dir   原因   使用   defaults   use   one   ntp   

原文地址:http://www.cnblogs.com/yiyan127/p/WPF-WindowShadow.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!