【解决方案】OuterGlowBitmapEffect在WPF 4.0中过时并失效了怎么办?

26 篇文章 0 订阅
12 篇文章 0 订阅

先上图



第一个按钮用了OuterGlowBitmapEffect的效果,第二个按钮用了广泛推荐的DropShadowEffect,第三个按钮用了我自己写的OuterGlowAdorner。

    <UniformGrid>
        <UniformGrid.Resources>
            <Style TargetType="Button">
                <Style.Setters>
                    <Setter Property="Margin" Value="20"/>
                    <Setter Property="Width" Value="150"/>
                    <Setter Property="Height" Value="100"/>
                </Style.Setters>
            </Style>
        </UniformGrid.Resources>
        <Button Content="OuterGlowBitmapEffect">
            <Button.BitmapEffect>
                <OuterGlowBitmapEffect GlowSize="20" Opacity="0.8" />
            </Button.BitmapEffect>
        </Button>

        <Button Content="DropShadowEffect">
            <Button.Effect>
                <DropShadowEffect BlurRadius="20" ShadowDepth="0" Color="Gold" />
            </Button.Effect>
        </Button>

        <Button Name="adorneredButton" FontStyle="Italic" Content="OuterGlowAdorner"/>
    </UniformGrid>

很明显,DropShadowEffect从显示效果上来看并不尽人意。我三者都设置了颜色为金色,20单位,但DropShadowEffect颜色明显和其他人不一样,光晕范围也很小。当设置为绿色或其他颜色时候,这种颜色差别更为明显。

所以我自己写了OuterGlowAdorner,注意,它并不在GPU上运行,所以可能比已经过时的OuterGlowBitmapEffect更花资源。

using System.Windows;
using System.Windows.Documents;
using System.Windows.Media;

namespace Gqqnbig.Windows.Controls
{
    public class OuterGlowAdorner : Adorner
    {
        public static readonly DependencyProperty GlowSizeProperty =
            DependencyProperty.Register("GlowSize", typeof(double), typeof(OuterGlowAdorner), new FrameworkPropertyMetadata(5d, FrameworkPropertyMetadataOptions.AffectsRender));


        public static readonly DependencyProperty GlowColorProperty =
            DependencyProperty.Register("GlowColor", typeof(Color), typeof(OuterGlowAdorner), new FrameworkPropertyMetadata(Colors.Gold, FrameworkPropertyMetadataOptions.AffectsRender, (OnGlowColorChanged)));

        static OuterGlowAdorner()
        {
            SnapsToDevicePixelsProperty.OverrideMetadata(typeof(OuterGlowAdorner), new FrameworkPropertyMetadata(true));
        }


        static void OnGlowColorChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
        {
            var instance = (OuterGlowAdorner)o;
            instance.ltBrush = null;
        }


        private RadialGradientBrush ltBrush;
        private LinearGradientBrush tBrush;
        private RadialGradientBrush rtBrush;

        private LinearGradientBrush lBrush;
        private LinearGradientBrush rBrush;

        private RadialGradientBrush lbBrush;
        private LinearGradientBrush bBrush;
        private RadialGradientBrush rbBrush;

        private GradientStop endColor;
        private GradientStop startColor;

        private PathGeometry ltGeo;
        private RectangleGeometry tGeo;
        private PathGeometry rtGeo;
        private RectangleGeometry lGeo;
        private RectangleGeometry rGeo;
        private PathGeometry lbGeo;
        private RectangleGeometry bGeo;
        private PathGeometry rbGeo;

        public OuterGlowAdorner(UIElement adornedElement)
            : base(adornedElement)
        { }

        public double GlowSize
        {
            get { return (double)GetValue(GlowSizeProperty); }
            set { SetValue(GlowSizeProperty, value); }
        }



        public Color GlowColor
        {
            get { return (Color)GetValue(GlowColorProperty); }
            set { SetValue(GlowColorProperty, value); }
        }



        protected override void OnRender(DrawingContext drawingContext)
        {
            if (ltBrush == null)
                CreateBrushes();
            if (ltGeo == null)
                CreateGeometries();

            drawingContext.DrawGeometry(ltBrush, null, ltGeo);
            drawingContext.DrawGeometry(tBrush, null, tGeo);
            drawingContext.DrawGeometry(rtBrush, null, rtGeo);

            drawingContext.DrawGeometry(lBrush, null, lGeo);
            drawingContext.DrawGeometry(rBrush, null, rGeo);

            drawingContext.DrawGeometry(lbBrush, null, lbGeo);
            drawingContext.DrawGeometry(bBrush, null, bGeo);
            drawingContext.DrawGeometry(rbBrush, null, rbGeo);
        }

        private void CreateGeometries()
        {
            Size arcSize = new Size(GlowSize, GlowSize);
            Size adornedSize = AdornedElement.RenderSize;

            //上层
            ltGeo = new PathGeometry();
            var fig = new PathFigure();
            fig.StartPoint = new Point(0, -GlowSize);
            fig.Segments.Add(new ArcSegment
                                 {
                                     Size = arcSize,
                                     SweepDirection = SweepDirection.Counterclockwise,
                                     Point = new Point(-GlowSize, 0),
                                     //IsStroked = false
                                 });
            fig.Segments.Add(new LineSegment(new Point(0, 0), false));
            ltGeo.Figures.Add(fig);

            tGeo = new RectangleGeometry();
            tGeo.Rect = new Rect(new Point(0, -GlowSize), new Size(adornedSize.Width, GlowSize));

            rtGeo = new PathGeometry();
            fig = new PathFigure();
            fig.StartPoint = new Point(adornedSize.Width, -GlowSize);
            fig.Segments.Add(new ArcSegment
            {
                Size = arcSize,
                SweepDirection = SweepDirection.Clockwise,
                Point = new Point(adornedSize.Width + GlowSize, 0),
                //IsStroked = false
            });
            fig.Segments.Add(new LineSegment(new Point(adornedSize.Width, 0), false));
            rtGeo.Figures.Add(fig);

            //中层
            lGeo = new RectangleGeometry();
            lGeo.Rect = new Rect(new Point(-GlowSize, 0), new Size(GlowSize, adornedSize.Height));

            rGeo = new RectangleGeometry();
            rGeo.Rect = new Rect(new Point(adornedSize.Width, 0), new Size(GlowSize, adornedSize.Height));

            //下层
            lbGeo = new PathGeometry();
            fig = new PathFigure();
            fig.StartPoint = new Point(-GlowSize, adornedSize.Height);
            fig.Segments.Add(new ArcSegment
            {
                Size = arcSize,
                SweepDirection = SweepDirection.Counterclockwise,
                Point = new Point(0, adornedSize.Height + GlowSize),
            });
            fig.Segments.Add(new LineSegment(new Point(0, adornedSize.Height), false));
            lbGeo.Figures.Add(fig);

            bGeo = new RectangleGeometry();
            bGeo.Rect = new Rect(new Point(0, adornedSize.Height), new Size(adornedSize.Width, GlowSize));

            rbGeo = new PathGeometry();
            fig = new PathFigure();
            fig.StartPoint = new Point(adornedSize.Width, adornedSize.Height + GlowSize);
            fig.Segments.Add(new ArcSegment
            {
                Size = arcSize,
                SweepDirection = SweepDirection.Counterclockwise,
                Point = new Point(adornedSize.Width + GlowSize, adornedSize.Height),
                //IsStroked = false
            });
            fig.Segments.Add(new LineSegment(new Point(adornedSize.Width, adornedSize.Height), false));
            rbGeo.Figures.Add(fig);

            //冻结所有图形
            ltGeo.Freeze();
            tGeo.Freeze();
            rtGeo.Freeze();

            lGeo.Freeze();
            rGeo.Freeze();

            lbGeo.Freeze();
            bGeo.Freeze();
            rGeo.Freeze();
        }

        private void CreateBrushes()
        {
            startColor = new GradientStop(GlowColor, 0);
            startColor.Freeze();
            endColor = new GradientStop(Colors.Transparent, 1);
            endColor.Freeze();

            //上层
            ltBrush = new RadialGradientBrush();
            ltBrush.Center = new Point(1, 1);
            ltBrush.GradientOrigin = new Point(1, 1);
            ltBrush.RadiusX = 1;
            ltBrush.RadiusY = 1;
            ltBrush.GradientStops.Add(startColor);
            ltBrush.GradientStops.Add(endColor);

            tBrush = new LinearGradientBrush();
            tBrush.StartPoint = new Point(0.5, 1);
            tBrush.EndPoint = new Point(0.5, 0);
            tBrush.GradientStops.Add(startColor);
            tBrush.GradientStops.Add(endColor);

            rtBrush = new RadialGradientBrush();
            rtBrush.Center = new Point(0, 1);
            rtBrush.GradientOrigin = new Point(0, 1);
            rtBrush.RadiusX = 1;
            rtBrush.RadiusY = 1;
            rtBrush.GradientStops.Add(startColor);
            rtBrush.GradientStops.Add(endColor);

            //中层
            lBrush = new LinearGradientBrush();
            lBrush.StartPoint = new Point(1, 0.5);
            lBrush.EndPoint = new Point(0, 0.5);
            lBrush.GradientStops.Add(startColor);
            lBrush.GradientStops.Add(endColor);

            rBrush = new LinearGradientBrush();
            rBrush.StartPoint = new Point(0, 0.5);
            rBrush.EndPoint = new Point(1, 0.5);
            rBrush.GradientStops.Add(startColor);
            rBrush.GradientStops.Add(endColor);

            //下层
            lbBrush = new RadialGradientBrush();
            lbBrush.Center = new Point(1, 0);
            lbBrush.GradientOrigin = new Point(1, 0);
            lbBrush.RadiusX = 1;
            lbBrush.RadiusY = 1;
            lbBrush.GradientStops.Add(startColor);
            lbBrush.GradientStops.Add(endColor);

            bBrush = new LinearGradientBrush();
            bBrush.StartPoint = new Point(0.5, 0);
            bBrush.EndPoint = new Point(0.5, 1);
            bBrush.GradientStops.Add(startColor);
            bBrush.GradientStops.Add(endColor);

            rbBrush = new RadialGradientBrush();
            rbBrush.Center = new Point(0, 0);
            rbBrush.GradientOrigin = new Point(0, 0);
            rbBrush.RadiusX = 1;
            rbBrush.RadiusY = 1;
            rbBrush.GradientStops.Add(startColor);
            rbBrush.GradientStops.Add(endColor);

            //冻结所有笔刷
            ltBrush.Freeze();
            tBrush.Freeze();
            rtBrush.Freeze();

            lBrush.Freeze();
            rBrush.Freeze();

            lbBrush.Freeze();
            bBrush.Freeze();
            rbBrush.Freeze();
        }
    }
}

其实呢。。DropShadowEffect颜色偏淡的问题可以用decorator等容器,套两个DropShadowEffect,这样颜色就浓了。颜色偏移的问题可以调整GlowColor来解决。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值