{"id":453,"date":"2012-05-06T14:47:42","date_gmt":"2012-05-06T05:47:42","guid":{"rendered":"http:\/\/astel-labs.net\/blog\/diary\/?p=453"},"modified":"2012-05-06T15:06:47","modified_gmt":"2012-05-06T06:06:47","slug":"06-1","status":"publish","type":"post","link":"https:\/\/astel-labs.net\/blog\/diary\/2012\/05\/06-1.html","title":{"rendered":"WPF &#8211; \u6587\u5b57\u306e\u7e01\u53d6\u308a\u3092\u3059\u308b"},"content":{"rendered":"<p>\u7d50\u69cb\u524d\u306b WPF \u3067\u6587\u5b57\u306e\u7e01\u53d6\u308a\u306b\u3064\u3044\u3066\u8a71\u984c\u306b\u3057\u305f\u3053\u3068\u304c\u3042\u308a\u307e\u3057\u305f\u304c\u3001\u305d\u306e\u5f8c MSDN \u306e\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u3092\u57fa\u306b\u79c1\u306a\u308a\u306b\u5b9f\u88c5\u3092\u884c\u3063\u3066\u5229\u7528\u3057\u3066\u3044\u305f\u306e\u3067\u3059\u304c\u3001\u3064\u3044\u6700\u8fd1\u6d77\u5916\u306e\u30b5\u30a4\u30c8\u3092\u5de1\u3063\u3066\u3044\u305f\u969b\u3001\u30b9\u30de\u30fc\u30c8\u306a\u65b9\u6cd5\u3067\u6587\u5b57\u306e\u7e01\u53d6\u308a\u3092\u3057\u3066\u3044\u308b\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u3092\u898b\u3064\u3051\u305f\u305f\u3081\u7d39\u4ecb\u3057\u307e\u3059<\/p>\n<p>\uff08\u30a2\u30af\u30bb\u30b9\u89e3\u6790\u3067\u3082\u3001\u691c\u7d22\u30ef\u30fc\u30c9\u304c\u300c\u7e01\u53d6\u308a\u300d\u3067\u3053\u306e\u30b5\u30a4\u30c8\u306b\u6765\u308b\u65b9\u304c\u610f\u5916\u3068\u591a\u3044\u3088\u3046\u3067\u3057\u305f\uff09<\/p>\n<p>&nbsp;<\/p>\n<p>\u3061\u306a\u307f\u306b\u3001\u30b5\u30f3\u30d7\u30eb\u3092\u5b9f\u884c\u3059\u308b\u3068\u4ee5\u4e0b\u306e\u3088\u3046\u306b\u306a\u308a\u307e\u3059<\/p>\n<p><a href=\"http:\/\/astel-labs.net\/blog\/diary\/images\/2012\/05\/OutlineText_01.jpg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone\" title=\"OutlineText_01.jpg\" src=\"http:\/\/astel-labs.net\/blog\/diary\/images\/2012\/05\/OutlineText_01.jpg\" alt=\"\" width=\"402\" height=\"160\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<p><!--more--><\/p>\n<p>\u6587\u5b57\u5217\u8868\u793a\u306e xaml \u30b3\u30fc\u30c9\u3067\u3059<br \/>\n\u7e01\u53d6\u308a\u306e\u592a\u3055\u306f StrokeThickness\u3001\u7e01\u53d6\u308a\u306e\u8272\u306f\u00a0Stroke\u3001\u6587\u5b57\u8272\u306f\u00a0Fill \u3067\u6307\u5b9a\u3057\u307e\u3059<br \/>\n\u30d5\u30a9\u30f3\u30c8\u306e\u60c5\u5831\u306f Font\uff5e \u95a2\u9023\u30d7\u30ed\u30d1\u30c6\u30a3\u3067\u6307\u5b9a\u3057\u307e\u3059<\/p>\n<pre class=\"brush: xml; gutter: true\">\r\n&lt;Window x:Class=&quot;OutlineFont.MainWindow&quot;\r\n        xmlns=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml\/presentation&quot;\r\n        xmlns:x=&quot;http:\/\/schemas.microsoft.com\/winfx\/2006\/xaml&quot;\r\n        xmlns:local=&quot;clr-namespace:OutlineFont&quot;\r\n        Title=&quot;MainWindow&quot; Height=&quot;160&quot; Width=&quot;402&quot;&gt;\r\n    &lt;Grid&gt;\r\n        &lt;local:OutlineText FontFamily=&quot;Verdana&quot; FontSize=&quot;50&quot; FontWeight=&quot;ExtraBold&quot; TextWrapping=&quot;Wrap&quot;\r\n                           StrokeThickness=&quot;3&quot; Stroke=&quot;Red&quot; Fill=&quot;Yellow&quot;\r\n                           Text=&quot;Hello world!&quot; \/&gt;\r\n    &lt;\/Grid&gt;\r\n&lt;\/Window&gt;<\/pre>\n<p>&nbsp;<\/p>\n<p>\u3067\u3001\u6587\u5b57\u5217\u7e01\u53d6\u308a\u7528\u306e\u30b3\u30fc\u30c9\u304c\u4ee5\u4e0b\u306b\u306a\u308a\u307e\u3059<br \/>\n\u4f8b\u306b\u3088\u3063\u3066 GW \u306e\u6700\u7d42\u65e5\u3067\u3044\u308d\u3044\u308d\u3068\u75b2\u308c\u3066\u7720\u3044\u305f\u3081\u3001\u8aac\u660e\u306f\u7701\u7565\u3067\u3059\u3002\u3002\u3002<\/p>\n<pre class=\"brush: csharp; gutter: true\">using System;\r\nusing System.ComponentModel;\r\nusing System.Globalization;\r\nusing System.Windows;\r\nusing System.Windows.Documents;\r\nusing System.Windows.Markup;\r\nusing System.Windows.Media;\r\n\r\nnamespace OutlineFont\r\n{\r\n    [ContentProperty( &quot;Text&quot; )]\r\n    internal class OutlineText : FrameworkElement\r\n    {\r\n        private FormattedText FormattedText;\r\n        private Geometry TextGeometry;\r\n\r\n        public static readonly DependencyProperty TextProperty = DependencyProperty.Register(\r\n            &quot;Text&quot;, typeof( string ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( OnFormattedTextInvalidated ) );\r\n\r\n        public static readonly DependencyProperty TextAlignmentProperty = DependencyProperty.Register(\r\n            &quot;TextAlignment&quot;, typeof( TextAlignment ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty TextDecorationsProperty = DependencyProperty.Register(\r\n            &quot;TextDecorations&quot;, typeof( TextDecorationCollection ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty TextTrimmingProperty = DependencyProperty.Register(\r\n            &quot;TextTrimming&quot;, typeof( TextTrimming ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty TextWrappingProperty = DependencyProperty.Register(\r\n            &quot;TextWrapping&quot;, typeof( TextWrapping ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( TextWrapping.NoWrap, OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty FillProperty = DependencyProperty.Register(\r\n            &quot;Fill&quot;, typeof( Brush ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( Brushes.Red, FrameworkPropertyMetadataOptions.AffectsRender ) );\r\n\r\n        public static readonly DependencyProperty StrokeProperty = DependencyProperty.Register(\r\n            &quot;Stroke&quot;, typeof( Brush ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( Brushes.Black, FrameworkPropertyMetadataOptions.AffectsRender ) );\r\n\r\n        public static readonly DependencyProperty StrokeThicknessProperty = DependencyProperty.Register(\r\n            &quot;StrokeThickness&quot;, typeof( double ), typeof( OutlineText ),\r\n            new FrameworkPropertyMetadata( 1d, FrameworkPropertyMetadataOptions.AffectsRender ) );\r\n\r\n        public static readonly DependencyProperty FontFamilyProperty = TextElement.FontFamilyProperty.AddOwner(\r\n            typeof( OutlineText ), new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty FontSizeProperty = TextElement.FontSizeProperty.AddOwner(\r\n            typeof( OutlineText ), new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty FontStretchProperty = TextElement.FontStretchProperty.AddOwner(\r\n            typeof( OutlineText ), new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty FontStyleProperty = TextElement.FontStyleProperty.AddOwner(\r\n            typeof( OutlineText ), new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public static readonly DependencyProperty FontWeightProperty = TextElement.FontWeightProperty.AddOwner(\r\n            typeof( OutlineText ), new FrameworkPropertyMetadata( OnFormattedTextUpdated ) );\r\n\r\n        public OutlineText()\r\n        {\r\n            this.TextDecorations = new TextDecorationCollection();\r\n        }\r\n\r\n        public Brush Fill\r\n        {\r\n            get { return (Brush)GetValue( FillProperty ); }\r\n            set { SetValue( FillProperty, value ); }\r\n        }\r\n\r\n        public FontFamily FontFamily\r\n        {\r\n            get { return (FontFamily)GetValue( FontFamilyProperty ); }\r\n            set { SetValue( FontFamilyProperty, value ); }\r\n        }\r\n\r\n        [TypeConverter( typeof( FontSizeConverter ) )]\r\n        public double FontSize\r\n        {\r\n            get { return (double)GetValue( FontSizeProperty ); }\r\n            set { SetValue( FontSizeProperty, value ); }\r\n        }\r\n\r\n        public FontStretch FontStretch\r\n        {\r\n            get { return (FontStretch)GetValue( FontStretchProperty ); }\r\n            set { SetValue( FontStretchProperty, value ); }\r\n        }\r\n\r\n        public FontStyle FontStyle\r\n        {\r\n            get { return (FontStyle)GetValue( FontStyleProperty ); }\r\n            set { SetValue( FontStyleProperty, value ); }\r\n        }\r\n\r\n        public FontWeight FontWeight\r\n        {\r\n            get { return (FontWeight)GetValue( FontWeightProperty ); }\r\n            set { SetValue( FontWeightProperty, value ); }\r\n        }\r\n\r\n        public Brush Stroke\r\n        {\r\n            get { return (Brush)GetValue( StrokeProperty ); }\r\n            set { SetValue( StrokeProperty, value ); }\r\n        }\r\n\r\n        public double StrokeThickness\r\n        {\r\n            get { return (double)GetValue( StrokeThicknessProperty ); }\r\n            set { SetValue( StrokeThicknessProperty, value ); }\r\n        }\r\n\r\n        public string Text\r\n        {\r\n            get { return (string)GetValue( TextProperty ); }\r\n            set { SetValue( TextProperty, value ); }\r\n        }\r\n\r\n        public TextAlignment TextAlignment\r\n        {\r\n            get { return (TextAlignment)GetValue( TextAlignmentProperty ); }\r\n            set { SetValue( TextAlignmentProperty, value ); }\r\n        }\r\n\r\n        public TextDecorationCollection TextDecorations\r\n        {\r\n            get { return (TextDecorationCollection)this.GetValue( TextDecorationsProperty ); }\r\n            set { this.SetValue( TextDecorationsProperty, value ); }\r\n        }\r\n\r\n        public TextTrimming TextTrimming\r\n        {\r\n            get { return (TextTrimming)GetValue( TextTrimmingProperty ); }\r\n            set { SetValue( TextTrimmingProperty, value ); }\r\n        }\r\n\r\n        public TextWrapping TextWrapping\r\n        {\r\n            get { return (TextWrapping)GetValue( TextWrappingProperty ); }\r\n            set { SetValue( TextWrappingProperty, value ); }\r\n        }\r\n\r\n        protected override void OnRender( DrawingContext drawingContext )\r\n        {\r\n            this.EnsureGeometry();\r\n\r\n            drawingContext.DrawGeometry( this.Fill, new Pen( this.Stroke, this.StrokeThickness ), this.TextGeometry );\r\n        }\r\n\r\n        protected override Size MeasureOverride( Size availableSize )\r\n        {\r\n            this.EnsureFormattedText();\r\n\r\n            this.FormattedText.MaxTextWidth = Math.Min( 3579139, availableSize.Width );\r\n            this.FormattedText.MaxTextHeight = availableSize.Height;\r\n\r\n            return new Size( this.FormattedText.Width, this.FormattedText.Height );\r\n        }\r\n\r\n        protected override Size ArrangeOverride( Size finalSize )\r\n        {\r\n            this.EnsureFormattedText();\r\n\r\n            this.FormattedText.MaxTextWidth = finalSize.Width;\r\n            this.FormattedText.MaxTextHeight = finalSize.Height;\r\n\r\n            this.TextGeometry = null;\r\n\r\n            return finalSize;\r\n        }\r\n\r\n        private static void OnFormattedTextInvalidated( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e )\r\n        {\r\n            var outlinedTextBlock = (OutlineText)dependencyObject;\r\n            outlinedTextBlock.FormattedText = null;\r\n            outlinedTextBlock.TextGeometry = null;\r\n\r\n            outlinedTextBlock.InvalidateMeasure();\r\n            outlinedTextBlock.InvalidateVisual();\r\n        }\r\n\r\n        private static void OnFormattedTextUpdated( DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e )\r\n        {\r\n            var outlinedTextBlock = (OutlineText)dependencyObject;\r\n            outlinedTextBlock.UpdateFormattedText();\r\n            outlinedTextBlock.TextGeometry = null;\r\n\r\n            outlinedTextBlock.InvalidateMeasure();\r\n            outlinedTextBlock.InvalidateVisual();\r\n        }\r\n\r\n        private void EnsureFormattedText()\r\n        {\r\n            if( this.FormattedText != null || this.Text == null )\r\n                return;\r\n\r\n            this.FormattedText = new FormattedText(\r\n                this.Text,\r\n                CultureInfo.CurrentUICulture,\r\n                this.FlowDirection,\r\n                new Typeface( this.FontFamily, this.FontStyle, this.FontWeight, FontStretches.Normal ),\r\n                this.FontSize,\r\n                Brushes.Black );\r\n\r\n            this.UpdateFormattedText();\r\n        }\r\n\r\n        private void UpdateFormattedText()\r\n        {\r\n            if( this.FormattedText == null )\r\n                return;\r\n\r\n            this.FormattedText.MaxLineCount = this.TextWrapping == TextWrapping.NoWrap ? 1 : int.MaxValue;\r\n            this.FormattedText.TextAlignment = this.TextAlignment;\r\n            this.FormattedText.Trimming = this.TextTrimming;\r\n\r\n            this.FormattedText.SetFontSize( this.FontSize );\r\n            this.FormattedText.SetFontStyle( this.FontStyle );\r\n            this.FormattedText.SetFontWeight( this.FontWeight );\r\n            this.FormattedText.SetFontFamily( this.FontFamily );\r\n            this.FormattedText.SetFontStretch( this.FontStretch );\r\n            this.FormattedText.SetTextDecorations( this.TextDecorations );\r\n        }\r\n\r\n        private void EnsureGeometry()\r\n        {\r\n            if( this.TextGeometry != null )\r\n                return;\r\n\r\n            this.EnsureFormattedText();\r\n            this.TextGeometry = this.FormattedText.BuildGeometry( new Point() );\r\n        }\r\n    }\r\n}<\/pre>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u7d50\u69cb\u524d\u306b WPF \u3067\u6587\u5b57\u306e\u7e01\u53d6\u308a\u306b\u3064\u3044\u3066\u8a71\u984c\u306b\u3057\u305f\u3053\u3068\u304c\u3042\u308a\u307e\u3057\u305f\u304c\u3001\u305d\u306e\u5f8c MSDN \u306e\u30b5\u30f3\u30d7\u30eb\u30b3\u30fc\u30c9\u3092\u57fa\u306b\u79c1\u306a\u308a\u306b\u5b9f\u88c5\u3092\u884c\u3063\u3066\u5229\u7528\u3057\u3066\u3044\u305f\u306e\u3067\u3059\u304c\u3001\u3064\u3044\u6700\u8fd1\u6d77\u5916\u306e\u30b5\u30a4\u30c8\u3092\u5de1\u3063\u3066\u3044\u305f\u969b\u3001\u30b9\u30de\u30fc\u30c8\u306a\u65b9\u6cd5\u3067\u6587\u5b57\u306e\u7e01\u53d6\u308a\u3092\u3057 [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,7,4],"tags":[],"class_list":["post-453","post","type-post","status-publish","format-standard","hentry","category-c","category-wpf","category-4"],"_links":{"self":[{"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/posts\/453","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/comments?post=453"}],"version-history":[{"count":5,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/posts\/453\/revisions"}],"predecessor-version":[{"id":461,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/posts\/453\/revisions\/461"}],"wp:attachment":[{"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/media?parent=453"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/categories?post=453"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/astel-labs.net\/blog\/diary\/wp-json\/wp\/v2\/tags?post=453"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}