첨부 실행 코드는 나눔고딕코딩 폰트를 사용합니다.
유용한 소스 코드가 있으면 icodebroker@naver.com으로 보내주시면 감사합니다.
블로그 자료는 자유롭게 사용하세요.

728x90
반응형

■ Decorator 클래스 : 그림자 효과 사용하기

------------------------------------------------------------------------------------------------------------------------


TestProject.zip


FastShadow.cs

 

 

using System;

using System.ComponentModel;

using System.Windows;

using System.Windows.Controls;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 고속 그림자

    /// </summary>

    public class FastShadow : Decorator

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Dependency Property

        ////////////////////////////////////////////////////////////////////////////////////////// Static

        //////////////////////////////////////////////////////////////////////////////// Public

 

        #region 색상 속성 - ColorProperty

 

        /// <summary>

        /// 색상 속성

        /// </summary>

        public static readonly DependencyProperty ColorProperty = DependencyProperty.Register

        (

            "Color",

            typeof(Color),

            typeof(FastShadow),

            new FrameworkPropertyMetadata

            (

                Color.FromArgb(0x71, 0x00, 0x00, 0x00),

                FrameworkPropertyMetadataOptions.AffectsRender

            )

        );

 

        #endregion

        #region 그림자 깊이 속성 - ShadowDepthProperty

 

        /// <summary>

        /// 그림자 깊이 속성

        /// </summary>

        public static readonly DependencyProperty ShadowDepthProperty = DependencyProperty.Register

        (

            "ShadowDepth",

            typeof(double),

            typeof(FastShadow),

            new FrameworkPropertyMetadata

            (

                5.0,

                FrameworkPropertyMetadataOptions.AffectsRender,

                new PropertyChangedCallback

                (

                    (s, e) =>

                    {

                        FastShadow fastShadow = s as FastShadow;

 

                        if((double)e.NewValue < 0)

                        {

                            fastShadow.ShadowDepth = 0;

                        }

                    }

                )

            )

        );

 

        #endregion

        #region BLUE 반경 속성 - BlurRadiusProperty

 

        /// <summary>

        /// BLUE 반경 속성

        /// </summary>

        public static readonly DependencyProperty BlurRadiusProperty = DependencyProperty.Register

        (

            "BlurRadius",

            typeof(double),

            typeof(FastShadow),

            new FrameworkPropertyMetadata

            (

                10.0,

                FrameworkPropertyMetadataOptions.AffectsRender,

                new PropertyChangedCallback

                (

                    (s, e) =>

                    {

                        FastShadow fastShadow = s as FastShadow;

 

                        if((double)e.NewValue < 0)

                        {

                            fastShadow.BlurRadius = 0;

                        }

                    }

                )

            )

        );

 

        #endregion

        #region 방향 속성 - DirectionProperty

 

        /// <summary>

        /// 방향 속성

        /// </summary>

        public static readonly DependencyProperty DirectionProperty = DependencyProperty.Register

        (

            "Direction",

            typeof(int),

            typeof(FastShadow),

            new FrameworkPropertyMetadata

            (

                315,

                FrameworkPropertyMetadataOptions.AffectsRender

            )

        );

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Property

        ////////////////////////////////////////////////////////////////////////////////////////// Public

 

        #region 색상 - Color

 

        /// <summary>

        /// 색상

        /// </summary>

        [Category("FastShadow")]

        public Color Color

        {

            get

            {

                return (Color)GetValue(ColorProperty);

            }

            set

            {

                SetValue(ColorProperty, value);

            }

        }

 

        #endregion

        #region 그림자 깊이 - ShadowDepth

 

        /// <summary>

        /// 그림자 깊이

        /// </summary>

        [Category("FastShadow")]

        [Description("중심에서 거리")]

        public double ShadowDepth

        {

            get

            {

                return (double)GetValue(ShadowDepthProperty);

            }

            set

            {

                SetValue(ShadowDepthProperty, value);

            }

        }

 

        #endregion

        #region BLUR 반경 - BlurRadius

 

        /// <summary>

        /// BLUR 반경

        /// </summary>

        [Category("FastShadow")]

        [Description("DROP 그림자 반경")]

        public double BlurRadius

        {

            get

            {

                return (double)GetValue(BlurRadiusProperty);

            }

            set

            {

                SetValue(BlurRadiusProperty, value);

            }

        }

 

        #endregion

        #region 방향 - Direction

 

        /// <summary>

        /// 방향

        /// </summary>

        [Category("FastShadow")]

        [Description("그림자 각도")]

        public int Direction

        {

            get

            {

                return (int)GetValue(DirectionProperty);

            }

            set

            {

                SetValue(DirectionProperty, value);

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Method

        ////////////////////////////////////////////////////////////////////////////////////////// Protected

 

        #region 렌더링시 처리하기 - OnRender(drawingContext)

 

        /// <summary>

        /// 렌더링시 처리하기

        /// </summary>

        /// <param name="drawingContext">드로잉 컨텍스트</param>

        protected override void OnRender(DrawingContext drawingContext)

        {

            double distance   = Math.Max(0         , ShadowDepth);

            double blurRadius = Math.Max(BlurRadius, 0          );

            double angle      = Direction + 45;

 

            Rect shadowRectangle = new Rect

            (

                new Point(0, 0),

                new Size(RenderSize.Width, RenderSize.Height)

            );

 

            shadowRectangle.Inflate(blurRadius, blurRadius);

 

            Color color = Color;

 

            double radianAngle = angle * Math.PI / 180.0;

            double xDistance   = distance;

            double yDistance   = distance;

            double newX        = xDistance * Math.Cos(radianAngle) - yDistance * Math.Sin(radianAngle);

            double newY        = yDistance * Math.Cos(radianAngle) + xDistance * Math.Sin(radianAngle);

 

            TranslateTransform translateTransform = new TranslateTransform(newX, newY);

 

            Rect transformRectangle = translateTransform.TransformBounds(shadowRectangle);

 

            Rect[] edgeArray = new Rect[]

            {

                new Rect

                (

                    new Point(transformRectangle.X, transformRectangle.Y),

                    new Size(blurRadius, blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.X + blurRadius, transformRectangle.Y),

                    new Size(Math.Max(transformRectangle.Width - (blurRadius * 2), 0), blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.Right - blurRadius, transformRectangle.Y),

                    new Size(blurRadius, blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.Right - blurRadius, transformRectangle.Y + blurRadius),

                    new Size(blurRadius, Math.Max(transformRectangle.Height - (blurRadius * 2), 0))

                ),

                new Rect

                (

                    new Point(transformRectangle.Right - blurRadius, transformRectangle.Bottom - blurRadius),

                    new Size(blurRadius, blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.X + blurRadius, transformRectangle.Bottom - blurRadius),

                    new Size(Math.Max(transformRectangle.Width - (blurRadius * 2), 0), blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.X, transformRectangle.Bottom - blurRadius),

                    new Size(blurRadius, blurRadius)

                ),

                new Rect

                (

                    new Point(transformRectangle.X, transformRectangle.Y + blurRadius),

                    new Size(blurRadius, Math.Max(transformRectangle.Height - (blurRadius * 2), 0))

                ),

                new Rect

                (

                    new Point(transformRectangle.X + blurRadius, transformRectangle.Y + blurRadius),

                    new Size

                    (

                        Math.Max(transformRectangle.Width  - (blurRadius * 2), 0),

                        Math.Max(transformRectangle.Height - (blurRadius * 2), 0)

                    )

                )

            };

 

            GradientStopCollection collection = new GradientStopCollection();

 

            Color stopColor = color;

 

            stopColor.A = (byte)(color.A);

 

            collection.Add(new GradientStop(color, 0.0));

 

            stopColor.A = (byte)(0.74336 * color.A);

 

            collection.Add(new GradientStop(stopColor, 0.1));

 

            stopColor.A = (byte)(0.38053 * color.A);

 

            collection.Add(new GradientStop(stopColor, 0.3));

 

            stopColor.A = (byte)(0.12389 * color.A);

 

            collection.Add(new GradientStop(stopColor, 0.5));

 

            stopColor.A = (byte)(0.02654 * color.A);

 

            collection.Add(new GradientStop(stopColor, 0.7));

 

            stopColor.A = (byte)(0);

 

            collection.Add(new GradientStop(stopColor, 0.9));

 

            collection.Freeze();

 

            Brush[] brushArray = new Brush[]

            {

                new RadialGradientBrush(collection)

                {

                    Center         = new Point(1, 1),

                    GradientOrigin = new Point(1, 1),

                    RadiusX        = 1,

                    RadiusY        = 1

                },

                new LinearGradientBrush(collection, 0)

                {

                    StartPoint = new Point(0, 1),

                    EndPoint   = new Point(0, 0)

                },

                new RadialGradientBrush(collection)

                {

                    Center         = new Point(0, 1),

                    GradientOrigin = new Point(0, 1),

                    RadiusX        = 1,

                    RadiusY        = 1

                },

                new LinearGradientBrush(collection, 0)

                {

                    StartPoint = new Point(0, 0),

                    EndPoint   = new Point(1, 0)

                },

                new RadialGradientBrush(collection)

                {

                    Center         = new Point(0, 0),

                    GradientOrigin = new Point(0, 0),

                    RadiusX        = 1,

                    RadiusY        = 1

                },

                new LinearGradientBrush(collection, 0)

                {

                    StartPoint = new Point(0, 0),

                    EndPoint   = new Point(0, 1)

                },

                new RadialGradientBrush(collection)

                {

                    Center         = new Point(1, 0),

                    GradientOrigin = new Point(1, 0),

                    RadiusX        = 1,

                    RadiusY        = 1

                },

                new LinearGradientBrush(collection, 0)

                {

                    StartPoint = new Point(1, 0),

                    EndPoint   = new Point(0, 0)

                },

                new SolidColorBrush(color)

            };

 

            double[] guidelineSetXArray = new double[]

            {

                transformRectangle.X,

                transformRectangle.X + blurRadius,

                transformRectangle.Right - blurRadius,

                transformRectangle.Right

            };

 

            double[] guidelineSetYArray = new double[]

            {

                transformRectangle.Y,

                transformRectangle.Y + blurRadius,

                transformRectangle.Bottom - blurRadius,

                transformRectangle.Bottom

            };

 

            drawingContext.PushGuidelineSet(new GuidelineSet(guidelineSetXArray, guidelineSetYArray));

 

            for(int i = 0; i < edgeArray.Length; i++)

            {

                drawingContext.DrawRoundedRectangle(brushArray[i], null, edgeArray[i], 0.0, 0.0);

            }

 

            drawingContext.Pop();

        }

 

        #endregion

    }

}

 

 

MainWindow.xaml

 

 

<Window x:Class="TestProject.MainWindow"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    xmlns:local="clr-namespace:TestProject"

    Width="800"

    Height="600"

    Title="Decorator 클래스 : 그림자 효과 사용하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid>

        <local:FastShadow

            HorizontalAlignment="Center"

            VerticalAlignment="Center"

            Color="Gray"

            ShadowDepth="5"

            BlurRadius="30">

            <Rectangle

                Width="300"

                Height="300"

                Fill="Blue" />

        </local:FastShadow>

    </Grid>

</Window>

 

------------------------------------------------------------------------------------------------------------------------

728x90
반응형
Posted by 사용자 icodebroker
TAG , , , ,

댓글을 달아 주세요