2011-01-21 10 views
5

WPFキャンバスに単語を表示する必要があります。WPFでテキストを描画して、指定された矩形に完全に収まるようにする

通常、1つのボックスには1文字から数語の1行のテキストが含まれます。

ボックス内のテキストは、可能な限り大きくなければなりません。ボックスのすべての境界に触れます(異常なボックスのwitdh /高さの比率によってテキストの歪みが大きくなる場合を除いて)。

テキストの内容に基づいて、適切なフォントの高さ、スケーリング、オフセットを計算する良い方法が見つかりませんでした。

元のテキストの幅/高さの比率を変更できない最初の解決策は、すでに非常に優れています。

私はTextBlock要素を使用したいと思いますが、それ以外はうまくいくはずです。

答えて

5

Robery Levyの回答によると、Viewboxを使用してこれを達成できます。テキスト自体は伸びませんので、テキストに応じて0以上の余白にも余裕があります(気づいたとおり)。この問題を回避するには、FormattedTextからGeometryを作成し、これをOnRenderにDrawGeometryで描画するカスタムコントロールを作成します。テキストの品質がどのように向上するのかがわかりますFontSize。あなたは少し

enter image description here

いくつかのサンプルのXAML

<Canvas Background="Black"> 
    <Viewbox Canvas.Left="10" Canvas.Top="10" 
      Stretch="Fill" Width="200" Height="50"> 
     <Border Background="Red"> 
      <local:StretchText Text="Text" Foreground="Green" FontSize="100"/> 
     </Border> 
    </Viewbox> 
    <Viewbox Canvas.Left="230" Canvas.Top="10" 
      Stretch="Fill" Width="200" Height="50"> 
     <Border Background="Red"> 
      <local:StretchText Text="B" Foreground="Green" FontSize="500"/> 
     </Border> 
    </Viewbox> 
</Canvas> 

StretchTextに実験する必要がありますので、非常に小さなテキスト(例えばFontSize="10"は)大きなViewboxに非常に鋭い見ていないだろう.cs

public class StretchText : Control 
{ 
    protected override void OnRender(DrawingContext drawingContext) 
    { 
     FormattedText formattedText = new FormattedText(
      Text, 
      CultureInfo.GetCultureInfo("en-us"), 
      FlowDirection.LeftToRight, 
      new Typeface(FontFamily, FontStyle, FontWeight, FontStretches.Normal), 
      FontSize, 
      Foreground); 

     Geometry textGeometry = formattedText.BuildGeometry(new Point(0, 0)); 
     this.MinWidth = textGeometry.Bounds.Width; 
     this.MinHeight = textGeometry.Bounds.Height; 

     TranslateTransform translateTransform = new TranslateTransform(); 
     translateTransform.X = -textGeometry.Bounds.Left; 
     translateTransform.Y = -textGeometry.Bounds.Top; 
     drawingContext.PushTransform(translateTransform); 
     drawingContext.DrawGeometry(Foreground, new Pen(Foreground, 1.0), textGeometry); 
    } 

    public string Text 
    { 
     get { return (string)GetValue(TextProperty); } 
     set { SetValue(TextProperty, value); } 
    } 
    public static readonly DependencyProperty TextProperty = 
     DependencyProperty.Register("Text", 
     typeof(string), 
     typeof(StretchText), 
     new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.AffectsRender)); 
} 
+0

ありがとう!私はそれをテストし、それはかなりうまくいく。その間、私は一時的なFormattedTextオブジェクト(プロパティ "Width"、 "Extent"、 "OverhangAfter"のおかげで)を使ってテキスト要素を測定し、それに応じてScale + TranslateTransformをそれに応じて適用しました。しかし、それには2つの欠点があります。実際のテキストブロックのオブジェクトが大きすぎる(ツールチップが邪魔になる)、レンダリングが私の望むほど高速ではありません。 – Jem

+1

@ Jem:問題ありません:)ソリューション間のレンダリング時間はどうでしたか?どちらの場合でも「遅くなる」のですか?私は 'StretchText'を' Grid'で同時に10個試してから、 'Window'をすばやくサイズ変更しました。私はかなりうまく動作していたようですが、 'DrawGeometry'はかなり遅いと知られています –

+0

表示する単語の数は約1〜2千ですが、ページのサイズを変更することはあなたの解決策では十分です。私はそれが鉱山より約3倍速く、安定していると言いたいと思います(「遅延」はありません)。しかし、テキストの品質は、小さなテキストではそれほど急ではありません(これはおそらく「テキスト」ではなく「ジオメトリ」なので)、十分です。理想的には、より良いパフォーマンスと最高のテキスト品質をお望みですが、あなたのソリューションは今のところ最高の妥協点です。 – Jem

4
+0

、ちょうど試みた。面白いですが、私が必要としていることを正確に行うことはできません。テキストコンテンツをそのまま認識しません。たとえば、文字がベースラインを横切っていない限り、テキストの下に余白が残っています( 'g'、 'p'、 'y' 'q'など)。私は本当に入力ボックスをテキスト "bouding box"にする必要があります。 – Jem

0

をあなたはチャールズ・ペゾルドの記事「Render Text on a Path with WPF」をチェックアウトすることができます。残念ながら、MSDNサイトで何か問題が発生したため、現時点での主題に関する私の知識をリフレッシュすることはできませんが、パス内でのテキストのスケール方法について説明しました。

関連する問題