2012-06-01 4 views
0

WPF를 사용합니다. 내 애플 리케이션 내부 텍스트를 변경할 수있는 일부 textblocks있다. 각각의 너비는 200이고 높이는 150입니다. 문제는 필자가 그와 같은 7 개의 텍스트 블록을 가지고 있으며 같은 글꼴 크기를 갖기를 원합니다. 텍스트는 자동 맞춤 설정되어야합니다. 나는 그것들을 자동 완성시킬 수 있다는 것을 안다. 그러나 한 문장 안에 두 단어 만있는 경우 글꼴 크기가 너무 다름 ... 비동기 적으로 크기를 다시 계산해야합니다 (예 : OnTextChange와 같은 일부 이벤트 만들기). 블록 내부의 텍스트가 동적으로 변경됩니다. 함수를 작성하는 방법? 텍스트, 글꼴 (글꼴 패밀리 + 글꼴 스타일) 및 텍스트 블록 크기의 3 가지 매개 변수를 전달하고 적합한 글꼴 크기를 반환합니다.비동기식으로 글꼴 크기 계산

답변

2

적절한 글꼴 크기를 결정하는 가장 좋은 방법은 임의의 크기로 텍스트를 측정 한 다음 해당 크기의 크기 비를 곱하는 것입니다.

예를 들어, 텍스트를 측정 할 때 텍스트가있는 컨테이너의 크기의 절반이면 2를 곱하여 컨테이너를 채울 수 있습니다. 사용할 너비 또는 높이 비율 중 최소값을 선택하려고합니다.

WPF에서 FormattedText 클래스는 텍스트 측정을 수행합니다.

public double GetFontSize(string text, Size availableSize, Typeface typeFace) 
{ 
    FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black); 

    double ratio = Math.Min(availableSize.Width/formtxt.Width, availableSize.Height/formtxt.Height); 

    return 10 * ratio; 
} 

당신과 같이 당신의 TextBlocks의 텍스트를 변경할 때마다이 기능을 사용합니다 :

txtBlock.FontSize = GetFontSize(txt.Text, new Size(txt.ActualWidth, txt.ActualHeight), new Typeface(txt.FontFamily, txt.FontStyle, txt.FontWeight, txt.FontStretch)); 

편집 : 실용성의 목적

, 당신이 될 수도 있습니다 텍스트를이 사전 정의 된 경계 사각형에 세로로 가운데 놓을 수 있습니다. 이를 수행하는 좋은 방법은 TextBlock을 Border 요소와 같은 다른 객체 안에 래핑하는 것입니다. 이렇게하면 테두리 중앙에 정렬되도록 TextBlock을 알릴 수 있으며 내용에 맞게 자동 크기 조정이 가능합니다.

0

확인. 잘 작동합니다. 하지만 또 다른 문제가 있습니다. MainWindow.cs에서 2 가지 방법을 썼습니다.

private void fitFontSize() 
    { 
     propertiesList.Clear(); 

     TextUtils.FontProperty fontProps = new TextUtils.FontProperty(); 
     foreach (TextBlock tb in findVisualChildren<TextBlock>(statusOptionsGrid)) 
     { 
      fontProps.Text = tb.Text; 
      fontProps.Size = new Size(tb.ActualWidth, tb.ActualHeight); 
      fontProps.FontFamily = tb.FontFamily; 
      fontProps.FontStyle = tb.FontStyle; 
      fontProps.FontWeight = tb.FontWeight; 
      fontProps.FontStretch = tb.FontStretch; 
      propertiesList.Add(fontProps); 
     } 

     MessageBox.Show(TextUtils.recalculateFontSize(propertiesList) + ""); 
    } 

    public IEnumerable<T> findVisualChildren<T>(DependencyObject depObj) where T : DependencyObject 
    { 
     if (depObj != null) 
     { 
      for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++) 
      { 
       DependencyObject child = VisualTreeHelper.GetChild(depObj, i); 
       if (child != null && child is T) 
       { 
        yield return (T)child; 
       } 

       foreach (T childOfChild in findVisualChildren<T>(child)) 
       { 
        yield return childOfChild; 
       } 
      } 
     } 
    } 

그 후 텍스트 처리를위한 새로운 클래스를 만들었습니다. 여기 코드는 다음과 같습니다

public class TextUtils 
{ 
    public class FontProperty 
    { 
     public FontFamily FontFamily { get; set; } 
     public FontStyle FontStyle { get; set; } 
     public FontWeight FontWeight { get; set; } 
     public FontStretch FontStretch { get; set; } 
     public string Text { get; set; } 
     public Size Size { get; set; } 

     public Typeface getTypeFace() 
     { 
      return new Typeface(FontFamily, FontStyle, FontWeight, FontStretch); 
     } 
    } 

    public static double recalculateFontSize(List<FontProperty> propertiesList) 
    { 
     List<double> fontSizes = new List<double>(); 
     foreach (FontProperty fp in propertiesList) 
     { 
      fontSizes.Add(getFontSizeForControl(fp)); 
     } 

     return fontSizes.Min<double>(); 
    } 

    private static double getFontSizeForControl(FontProperty fp) 
    { 
     string text = fp.Text; 
     Size availableSize = fp.Size; 
     Typeface typeFace = fp.getTypeFace(); 

     FormattedText formtxt = new FormattedText(text, CultureInfo.CurrentCulture, FlowDirection.LeftToRight, typeFace, 10, Brushes.Black); 
     double ratio = Math.Min(availableSize.Width/formtxt.Width, availableSize.Height/formtxt.Height); 

     return 10 * ratio; 
    } 
} 

코드는 나쁜 보이지만 나는 그것을 나중에 ...

확인을 수정합니다. 이제 매초 글꼴 크기를 확인하는 새로운 타이머를 만들고 싶습니다. fitFontSize() 메서드를 사용하려고하면 msg : "다른 스레드가 소유하고 있기 때문에 호출하는 스레드가이 개체에 액세스 할 수 없습니다." 그런 문제를 피하려면 어떻게해야합니까? 이 메서드를 호출하는 새 스레드를 만들려고했습니다. findVisualChildren <>() 메서드와 동일한 문제가 있습니다. fitFontSize()에서 호출되었습니다. 내 문제를 해결하는 방법에 대한 아이디어가 없습니다 ...