首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何计算已知字体大小和字符的WPF TextBlock宽度?

如何计算已知字体大小和字符的WPF TextBlock宽度?
EN

Stack Overflow用户
提问于 2012-02-14 00:47:56
回答 7查看 73.3K关注 0票数 82

假设我有带文本的TextBlock "Some Text"字体大小10.0

如何计算适当的TextBlock width

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-02-14 03:00:35

使用FormattedText类。

我在代码中创建了一个helper函数:

代码语言:javascript
复制
private Size MeasureString(string candidate)
{
    var formattedText = new FormattedText(
        candidate,
        CultureInfo.CurrentCulture,
        FlowDirection.LeftToRight,
        new Typeface(this.textBlock.FontFamily, this.textBlock.FontStyle, this.textBlock.FontWeight, this.textBlock.FontStretch),
        this.textBlock.FontSize,
        Brushes.Black,
        new NumberSubstitution(),
        1);

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

它返回可在WPF布局中使用的与设备无关的像素。

票数 164
EN

Stack Overflow用户

发布于 2014-11-01 01:53:54

声明一下..。我假设操作员正在尝试以编程方式确定textBlock在被添加到可视化树之后将占用的宽度。我有一个比formattedText更好的解决方案(您如何处理像textWrapping这样的东西?)将在示例TextBlock上使用测量和排列。例如:

代码语言:javascript
复制
var textBlock = new TextBlock { Text = "abc abd adfdfd", TextWrapping = TextWrapping.Wrap };
// auto sized
textBlock.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
textBlock.Arrange(new Rect(textBlock.DesiredSize));

Debug.WriteLine(textBlock.ActualWidth); // prints 80.323333333333
Debug.WriteLine(textBlock.ActualHeight);// prints 15.96

// constrain the width to 16
textBlock.Measure(new Size(16, Double.PositiveInfinity));
textBlock.Arrange(new Rect(textBlock.DesiredSize));

Debug.WriteLine(textBlock.ActualWidth); // prints 14.58
Debug.WriteLine(textBlock.ActualHeight);// prints 111.72
票数 44
EN

Stack Overflow用户

发布于 2017-04-10 04:07:01

提供的解决方案适用于.Net Framework4.5,但是,随着Windows10DPI scaling和Framework4.6.x添加了不同程度的支持,用于测量文本的构造函数现在标记为[Obsolete],以及该方法上不包括pixelsPerDip参数的任何构造函数。

不幸的是,它有点复杂,但它将通过新的缩放功能带来更高的准确性。

###PixelsPerDip

根据MSDN的说法,这代表:

每密度独立像素值,相当于比例因子。例如,如果屏幕的DPI为120 (或1.25,因为120/96 = 1.25),则绘制每个与密度无关的像素的1.25像素。DIP是WPF使用的独立于设备分辨率和DPI的测量单位。

以下是我根据具有Microsoft/WPF-Samples缩放意识的DPI库的指导对选择的答案的实现。

从Windows10周年纪念(下面的代码)开始,需要一些额外的配置才能完全支持DPI缩放,这是我无法工作的,但如果没有它,就可以在配置了缩放的单个显示器上工作(并且支持缩放更改)。上面代码库中的Word文档就是这些信息的来源,因为一旦我添加了这些值,我的应用程序就不会启动。来自同一个repo的This sample code也是一个很好的参考点。

代码语言:javascript
复制
public partial class MainWindow : Window
{
    private DpiScale m_dpiInfo;
    private readonly object m_sync = new object();

    public MainWindow()
    {
        InitializeComponent();
        Loaded += OnLoaded;
    }
    
    private Size MeasureString(string candidate)
    {
        DpiScale dpiInfo;
        lock (m_dpiInfo)
            dpiInfo = m_dpiInfo;

        if (dpiInfo == null)
            throw new InvalidOperationException("Window must be loaded before calling MeasureString");

        var formattedText = new FormattedText(candidate, CultureInfo.CurrentUICulture,
                                              FlowDirection.LeftToRight,
                                              new Typeface(this.textBlock.FontFamily, 
                                                           this.textBlock.FontStyle, 
                                                           this.textBlock.FontWeight, 
                                                           this.textBlock.FontStretch),
                                              this.textBlock.FontSize,
                                              Brushes.Black, 
                                              dpiInfo.PixelsPerDip);
        
        return new Size(formattedText.Width, formattedText.Height);
    }

// ... The Rest of Your Class ...

    /*
     * Event Handlers to get initial DPI information and to set new DPI information
     * when the window moves to a new display or DPI settings get changed
     */
    private void OnLoaded(object sender, RoutedEventArgs e)
    {            
        lock (m_sync)
            m_dpiInfo = VisualTreeHelper.GetDpi(this);
    }

    protected override void OnDpiChanged(DpiScale oldDpiScaleInfo, DpiScale newDpiScaleInfo)
    {
        lock (m_sync)
            m_dpiInfo = newDpiScaleInfo;

        // Probably also a good place to re-draw things that need to scale
    }
}

其他要求

根据Microsoft/WPF-Samples上的文档,您需要向应用程序的清单中添加一些设置,以涵盖Windows 10周年纪念在多显示器配置中为每个显示器提供不同DPI设置的能力。合理的猜测是,如果没有这些设置,当使用不同的设置将窗口从一个显示器移动到另一个显示器时,可能不会引发OnDpiChanged事件,这将使您的测量结果继续依赖于以前的DpiScale。我正在编写的应用程序是为我自己编写的,我没有这样的设置,所以我没有什么可以测试的,当我遵循指导时,我最终得到了一个由于明显错误而无法启动的应用程序,所以我放弃了,但最好仔细查看一下并调整您的应用程序清单以包含:

代码语言:javascript
复制
<application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
        <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
        <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitor</dpiAwareness>
    </windowsSettings>
</application>

根据文档:

这两个标签的组合具有以下效果: 1)针对Windows10周年纪念更新的每个显示器2)系统

票数 14
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9264398

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档