You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取GraphicsPath.DrawString绘制文本时的截断位置及实际显示内容

解决方案

你可以通过以下两种方式获取到和绘制效果完全匹配的截断后文本:

方案1:使用MeasureCharacterRanges计算(匹配GraphicsPath截断逻辑)

这个方法和你当前用的GraphicsPath.AddString的截断规则完全一致,不需要调整现有绘制逻辑:

Private Function GetTruncatedText(g As Graphics, bounds As RectangleF, text As String, font As Font, sf As StringFormat) As String
    ' 拷贝原StringFormat配置避免修改原值
    Using sfCopy As StringFormat = CType(sf.Clone(), StringFormat)
        ' 设置要测量的字符范围为整个字符串
        Dim charRanges() As CharacterRange = {New CharacterRange(0, text.Length)}
        sfCopy.SetMeasurableCharacterRanges(charRanges)
        
        ' 测量指定边界内能容纳的字符范围
        Dim regions As Region() = g.MeasureCharacterRanges(text, font, bounds, sfCopy)
        Dim textBounds As RectangleF = regions(0).GetBounds(g)
        
        ' 获取最后一个可容纳的字符索引
        Dim lastCharIndex As Integer = CInt(Math.Floor(textBounds.Width / g.MeasureString(" ", font, New SizeF(Integer.MaxValue, Integer.MaxValue), sf).Width))
        ' 修正索引边界
        lastCharIndex = Math.Min(lastCharIndex, text.Length - 1)
        
        ' 拼接省略号
        If lastCharIndex < text.Length - 1 Then
            Return text.Substring(0, lastCharIndex).TrimEnd() & "..."
        End If
        Return text
    End Using
End Function

你直接在绘制逻辑后调用这个方法就能拿到实际显示的文本,参数和你FillTextSolid方法的参数完全一致即可。

方案2:预拆分文本(适合分页滚动需求)

如果你后续要做滚动分页效果,更推荐提前把整个文本按显示边界拆分成多个分页片段缓存起来,避免每次滚动重复计算:

Private Function SplitTextToPages(g As Graphics, bounds As RectangleF, text As String, font As Font, sf As StringFormat) As List(Of String)
    Dim pages As New List(Of String)()
    Dim remainingText As String = text
    Do While Not String.IsNullOrEmpty(remainingText)
        Dim fitLength As Integer = 0
        ' 逐字测试最大容纳长度
        For i As Integer = 1 To remainingText.Length
            Dim testText As String = remainingText.Substring(0, i)
            Dim textSize As SizeF = g.MeasureString(testText, font, bounds.Size, sf)
            If textSize.Height > bounds.Height OrElse textSize.Width > bounds.Width Then
                Exit For
            End If
            fitLength = i
        Next
        
        If fitLength = 0 Then Exit Do ' 边界过小无法容纳任何字符,终止
        
        Dim pageText As String = remainingText.Substring(0, fitLength).TrimEnd()
        If fitLength < remainingText.Length Then
            pageText &= "..."
            ' 下一页从当前截断位置的下一个字符开始
            remainingText = remainingText.Substring(fitLength).TrimStart()
        Else
            remainingText = String.Empty
        End If
        pages.Add(pageText)
    Loop
    Return pages
End Function

调用后返回的列表就是所有分页的文本内容,滚动的时候直接按索引取对应页的文本即可。

注意事项

  • 计算时使用的Graphics实例、Font、StringFormat配置必须和绘制时完全一致,避免DPI、文本渲染模式差异导致计算结果和实际显示不符
  • 如果你用的是GraphicsPath.AddString的字号单位是GraphicsUnit.Point,计算时要注意单位统一

内容的提问来源于stack exchange,提问作者stigzler

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 05:24:01