■ 외곽선 텍스트 사용하기

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


TestProject.zip


OutlineTextBlock.cs

 

 

using System;

using System.ComponentModel;

using System.Globalization;

using System.Windows;

using System.Windows.Documents;

using System.Windows.Markup;

using System.Windows.Media;

 

namespace TestProject

{

    /// <summary>

    /// 외곽선 텍스트 블럭

    /// </summary>

    [ContentProperty("Text")]

    public class OutlineTextBlock : FrameworkElement

    {

        //////////////////////////////////////////////////////////////////////////////////////////////////// Field

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

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

 

        #region Field

 

        /// <summary>

        /// 채우기 속성

        /// </summary>

        public static readonly DependencyProperty FillProperty = DependencyProperty.Register

        (

            "Fill",

            typeof(Brush),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata

            (

                Brushes.Black,

                FrameworkPropertyMetadataOptions.AffectsRender

            )

        );

 

        /// <summary>

        /// 스트로크 속성

        /// </summary>

        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register

        (

            "Stroke",

            typeof(Brush),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata

            (

                Brushes.Black,

                FrameworkPropertyMetadataOptions.AffectsRender

            )

        );

 

        /// <summary>

        /// 스트로크 두께 속성

        /// </summary>

        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register

        (

            "StrokeThickness",

            typeof(double),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata

            (

                1d,

                FrameworkPropertyMetadataOptions.AffectsRender

            )

        );

 

        /// <summary>

        /// 폰트 패밀리 속성

        /// </summary>

        public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner

        (

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 폰트 크기 속성

        /// </summary>

        public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner

        (

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 폰트 신축성 속성

        /// </summary>

        public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner

        (

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 폰트 스타일 속성

        /// </summary>

        public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner

        (

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 폰트 가중치 속성

        /// </summary>

        public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner

        (

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 텍스트 속성

        /// </summary>

        public static readonly DependencyProperty TextProperty = DependencyProperty.Register

        (

            "Text",

            typeof(string),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(TextPropertyChangedCallback)

        );

 

        /// <summary>

        /// 텍스트 정렬 속성

        /// </summary>

        public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register

        (

            "TextAlignment",

            typeof(TextAlignment),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 텍스트 장식 속성

        /// </summary>

        public static readonly DependencyProperty TextDecorationsProperty = DependencyProperty.Register

        (

            "TextDecorations",

            typeof(TextDecorationCollection),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 텍스트 트리밍 속성

        /// </summary>

        public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register

        (

            "TextTrimming",

            typeof(TextTrimming),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata(FontPropertyChangedCallback)

        );

 

        /// <summary>

        /// 텍스트 랩핑 속성

        /// </summary>

        public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register

        (

            "TextWrapping",

            typeof(TextWrapping),

            typeof(OutlineTextBlock),

            new FrameworkPropertyMetadata

            (

                TextWrapping.NoWrap,

                FontPropertyChangedCallback

            )

        );

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region Field

 

        /// <summary>

        /// 포맷 텍스트

        /// </summary>

        private FormattedText formattedText;

 

        /// <summary>

        /// 텍스트 기하

        /// </summary>

        private Geometry textGeometry;

 

        #endregion

 

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

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

 

        #region 채우기 - Fill

 

        /// <summary>

        /// 채우기

        /// </summary>

        public Brush Fill

        {

            get

            {

                return (Brush)GetValue(FillProperty);

            }

            set

            {

                SetValue(FillProperty, value);

            }

        }

 

        #endregion

        #region 폰트 패밀리 - FontFamily

 

        /// <summary>

        /// 폰트 패밀리

        /// </summary>

        public FontFamily FontFamily

        {

            get

            {

                return (FontFamily)GetValue(FontFamilyProperty);

            }

            set

            {

                SetValue(FontFamilyProperty, value);

            }

        }

 

        #endregion

        #region 폰트 크기 - FontSize

 

        /// <summary>

        /// 폰트 크기

        /// </summary>

        [TypeConverter(typeof(FontSizeConverter))]

        public double FontSize

        {

            get

            {

                return (double)GetValue(FontSizeProperty);

            }

            set

            {

                SetValue(FontSizeProperty, value);

            }

        }

 

        #endregion

        #region 폰트 신축성 - FontStretch

 

        /// <summary>

        /// 폰트 신축성

        /// </summary>

        public FontStretch FontStretch

        {

            get

            {

                return (FontStretch)GetValue(FontStretchProperty);

            }

            set

            {

                SetValue(FontStretchProperty, value);

            }

        }

 

        #endregion

        #region 폰트 스타일 - FontStyle

 

        /// <summary>

        /// 폰트 스타일

        /// </summary>

        public FontStyle FontStyle

        {

            get

            {

                return (FontStyle)GetValue(FontStyleProperty);

            }

            set

            {

                SetValue(FontStyleProperty, value);

            }

        }

 

        #endregion

        #region 폰트 가중치 - FontWeight

 

        /// <summary>

        /// 폰트 가중치

        /// </summary>

        public FontWeight FontWeight

        {

            get

            {

                return (FontWeight)GetValue(FontWeightProperty);

            }

            set

            {

                SetValue(FontWeightProperty, value);

            }

        }

 

        #endregion

        #region 스트로크 - Stroke

 

        /// <summary>

        /// 스트로크

        /// </summary>

        public Brush Stroke

        {

            get

            {

                return (Brush)GetValue(StrokeProperty);

            }

            set

            {

                SetValue(StrokeProperty, value);

            }

        }

 

        #endregion

        #region 스트로크 두께 - StrokeThickness

 

        /// <summary>

        /// 스트로크 두께

        /// </summary>

        public double StrokeThickness

        {

            get

            {

                return (double)GetValue(StrokeThicknessProperty);

            }

            set

            {

                SetValue(StrokeThicknessProperty, value);

            }

        }

 

        #endregion

        #region 텍스트 - Text

 

        /// <summary>

        /// 텍스트

        /// </summary>

        public string Text

        {

            get

            {

                return (string)GetValue(TextProperty);

            }

            set

            {

                SetValue(TextProperty, value);

            }

        }

 

        #endregion

        #region 텍스트 정렬 -TextAlignment

 

        /// <summary>

        /// 텍스트 정렬

        /// </summary>

        public TextAlignment TextAlignment

        {

            get

            {

                return (TextAlignment)GetValue(TextAlignmentProperty);

            }

            set

            {

                SetValue(TextAlignmentProperty, value);

            }

        }

 

        #endregion

        #region 텍스트 장식 - TextDecorations

 

        /// <summary>

        /// 텍스트 장식

        /// </summary>

        public TextDecorationCollection TextDecorations

        {

            get

            {

                return (TextDecorationCollection)this.GetValue(TextDecorationsProperty);

            }

            set

            {

                this.SetValue(TextDecorationsProperty, value);

            }

        }

 

        #endregion

        #region 텍스트 트리밍 - TextTrimming

 

        /// <summary>

        /// 텍스트 트리밍

        /// </summary>

        public TextTrimming TextTrimming

        {

            get

            {

                return (TextTrimming)GetValue(TextTrimmingProperty);

            }

            set

            {

                SetValue(TextTrimmingProperty, value);

            }

        }

 

        #endregion

        #region 텍스트 랩핑 - TextWrapping

 

        /// <summary>

        /// 텍스트 랩핑

        /// </summary>

        public TextWrapping TextWrapping

        {

            get

            {

                return (TextWrapping)GetValue(TextWrappingProperty);

            }

            set

            {

                SetValue(TextWrappingProperty, value);

            }

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////////////////////////// Constructor

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

 

        #region 생성자 - OutlineTextBlock()

 

        /// <summary>

        /// 생성자

        /// </summary>

        public OutlineTextBlock()

        {

            this.TextDecorations = new TextDecorationCollection();

        }

 

        #endregion

 

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

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

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region 폰트 속성 변경시 콜백 처리하기 - FontPropertyChangedCallback(d, e)

 

        /// <summary>

        /// 폰트 속성 변경시 콜백 처리하기

        /// </summary>

        /// <param name="d">의존 객체</param>

        /// <param name="e">이벤트 인자</param>

        private static void FontPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            OutlineTextBlock textBlock = d as OutlineTextBlock;

 

            textBlock.UpdateFormattedText();

 

            textBlock.textGeometry = null;

 

            textBlock.InvalidateMeasure();

 

            textBlock.InvalidateVisual();

        }

 

        #endregion

        #region 텍스트 속성 변경시 콜백 처리하기 - TextPropertyChangedCallback(d, e)

 

        /// <summary>

        /// 텍스트 속성 변경시 콜백 처리하기

        /// </summary>

        /// <param name="d">의존 객체</param>

        /// <param name="e">이벤트 인자</param>

        private static void TextPropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)

        {

            OutlineTextBlock textBlock = d as OutlineTextBlock;

 

            textBlock.formattedText = null;

            textBlock.textGeometry  = null;

 

            textBlock.InvalidateMeasure();

 

            textBlock.InvalidateVisual();

        }

 

        #endregion

 

        ////////////////////////////////////////////////////////////////////////////////////////// Instance

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

 

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

 

        /// <summary>

        /// 렌더시 처리하기

        /// </summary>

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

        protected override void OnRender(DrawingContext drawingContext)

        {

            SetTextGeometry();

 

            drawingContext.DrawGeometry(Fill, new Pen(Stroke, StrokeThickness), this.textGeometry);

        }

 

        #endregion

        #region 측정하기 (오버라이드) - MeasureOverride(availableSize)

 

        /// <summary>

        /// 측정하기 (오버라이드)

        /// </summary>

        /// <param name="availableSize">이용 가능한 크기</param>

        /// <returns>희망 크기</returns>

        protected override Size MeasureOverride(Size availableSize)

        {

            SetFormattedText();

 

            this.formattedText.MaxTextWidth  = Math.Min(3579139, availableSize.Width );

            this.formattedText.MaxTextHeight = Math.Max(0.0001d, availableSize.Height);

 

            return new Size(this.formattedText.Width, this.formattedText.Height);

        }

 

        #endregion

        #region 정렬하기 (오버라이드) - ArrangeOverride(finalSize)

 

        /// <summary>

        /// 정렬하기 (오버라이드)

        /// </summary>

        /// <param name="finalSize">최종 크기</param>

        /// <returns>크기</returns>

        protected override Size ArrangeOverride(Size finalSize)

        {

            SetFormattedText();

 

            this.formattedText.MaxTextWidth  = finalSize.Width;

            this.formattedText.MaxTextHeight = finalSize.Height;

 

            this.textGeometry = null;

 

            return finalSize;

        }

 

        #endregion

 

        //////////////////////////////////////////////////////////////////////////////// Private

 

        #region 포맷 텍스트 업데이트하기 - UpdateFormattedText()

 

        /// <summary>

        /// 포맷 텍스트 업데이트하기

        /// </summary>

        private void UpdateFormattedText()

        {

            if(this.formattedText == null)

            {

                return;

            }

 

            this.formattedText.MaxLineCount  = TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;

            this.formattedText.TextAlignment = TextAlignment;

            this.formattedText.Trimming      = TextTrimming;

 

            this.formattedText.SetFontSize(FontSize);

            this.formattedText.SetFontStyle(FontStyle);

            this.formattedText.SetFontWeight(FontWeight);

            this.formattedText.SetFontFamily(FontFamily);

            this.formattedText.SetFontStretch(FontStretch);

            this.formattedText.SetTextDecorations(TextDecorations);

        }

 

        #endregion

        #region 포맷 텍스트 설정하기 - SetFormattedText()

 

        /// <summary>

        /// 포맷 텍스트 설정하기

        /// </summary>

        private void SetFormattedText()

        {

            if(this.formattedText != null || Text == null)

            {

                return;

            }

 

            this.formattedText = new FormattedText

            (

                Text,

                CultureInfo.CurrentUICulture,

                FlowDirection,

                new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal),

                FontSize,

                Brushes.Black

            );

 

            UpdateFormattedText();

        }

 

        #endregion

        #region 텍스트 기하 설정하기 - SetTextGeometry()

 

        /// <summary>

        /// 텍스트 기하 설정하기

        /// </summary>

        private void SetTextGeometry()

        {

            if(this.textGeometry != null)

            {

                return;

            }

 

            SetFormattedText();

 

            this.textGeometry = this.formattedText.BuildGeometry(new Point(0, 0));

        }

 

        #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="외곽선 텍스트 사용하기"

    FontFamily="나눔고딕코딩"

    FontSize="16">

    <Grid>

        <local:OutlineTextBlock x:Name="textOutline"

            HorizontalAlignment="Center"

            VerticalAlignment="Center"

            StrokeThickness="2"

            Stroke="Orange"

            Fill="Yellow"

            FontSize="48"

            FontWeight="Bold"

            Text="외곽선 텍스트 입니다." />

    </Grid>

</Window>

 

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

Posted by 사용자 icodebroker
TAG