Measuring text in WPF

后端 未结 4 1317
旧时难觅i
旧时难觅i 2020-12-03 04:59

Using WPF, what is the most efficient way to measure a large number of short strings? Specifically, I\'d like to determine the display height of each string, given uniform

相关标签:
4条回答
  • 2020-12-03 05:30

    The most low-level technique (and therefore giving the most scope for creative optimisations) is to use GlyphRuns.

    It's not very well documented but I wrote up a little example here:

    http://smellegantcode.wordpress.com/2008/07/03/glyphrun-and-so-forth/

    The example works out the length of the string as a necessary step before rendering it.

    0 讨论(0)
  • 2020-12-03 05:33

    You can use the DesiredSize property on a rendered TextBox to get the height and width

    using System.Windows.Threading;
    
    ...
    
    Double TextWidth = 0;
    Double TextHeight = 0;
    ...
    
    MyTextBox.Text = "Words to measure size of";
    this.Dispatcher.BeginInvoke(
        DispatcherPriority.Background,
        new DispatcherOperationCallback(delegate(Object state) {
            var size = MyTextBox.DesiredSize;
            this.TextWidth = size.Width;
            this.TextHeight = size.Height;
            return null; 
        }
    ) , null);
    

    If you have a large number of strings it may be quicker to first pre-calualte the height and width of every indiviudal letter and symbol in a given font, and then do a calculation based on the string chars. This may not be 100% acurate due to kerning etc

    0 讨论(0)
  • 2020-12-03 05:38

    In WPF:

    Remember to call Measure() on the TextBlock before reading the DesiredSize property.

    If the TextBlock was created on-the-fly, and not yet shown, you have to call Measure() first, like so:

    MyTextBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    
    return new Size(MyTextBlock.DesiredSize.Width, MyTextBlock.DesiredSize.Height);
    

    In Silverlight:

    No need to measure.

    return new Size(TextBlock.ActualWidth, TextBlock.ActualHeight);
    

    The complete code looks like this:

    public Size MeasureString(string s) {
    
        if (string.IsNullOrEmpty(s)) {
            return new Size(0, 0);
        }
    
        var TextBlock = new TextBlock() {
            Text = s
        };
    
    #if SILVERLIGHT
        return new Size(TextBlock.ActualWidth, TextBlock.ActualHeight);
    #else
        TextBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
    
        return new Size(TextBlock.DesiredSize.Width, TextBlock.DesiredSize.Height);
    #endif
    }
    
    0 讨论(0)
  • 2020-12-03 05:43

    It is very simple and done by FormattedText class! Try it.

    0 讨论(0)
提交回复
热议问题