如何获取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
相关产品推荐
相关产品推荐

