如何在vb.net中使用TextRenderer DrawText函数换行长单词

3
我应该如何使用vb.net中的TextRenderer DrawText()绘制带有断词的长单词表格?我认为这是一个简单的问题,并尝试了所有TextFormatFlags组合,但我找不到解决方案。有人能帮忙吗?以下是一个示例:
sText = "C:\Users\abiga\OneDrive\Works\AdreNDSzinkron\bin\Debug\AdreService.exe"
TextRenderer.DrawText(e.Graphics, sText, Font, New Rectangle(0, 0, Me.Width, Me.Height),
                      Me.Color,TextFormatFlags.<what is the correct flag?>) 

我需要这个(不要裁剪):
C:\Users\abiga\OneDrive\Works\Adr
eNDSzinkron\bin\Debug\AdreService
.exe

错误的解决方案:

C:\Users\abiga\OneDrive\Works\Adr
C:\Users\abiga\OneDrive\Works\...
C:\Users\ab...bug\AdreService.exe

谢谢你的帮助!
2个回答

3

首先尝试使用TextFormatFlags.WordBreak或TextFormatFlags.TextBoxControl作为标志。

文档中说:

WordBreak:在单词结尾处断开文本

TextBoxControl:指定应为在TextBox控件上显示而格式化文本

组合这些标志应该会得到预期的结果。

如果这样不行,则尝试改用Graphics.DrawString

e.Graphics.DrawString(sText, Font, Me.Color, New RectangleF(0, 0, Me.Width, Me.Height))


2
TextFormatFlags.WordBreak or TextFormatFlags.TextBoxControl - Jimi
@Jimi - TextBoxControl 是关键。没有它,WordBreak 只会在空格处换行,而不会“断开”单词。谢谢解决方案! - Abigail La'Fay
我会相应地编辑我的答案,很高兴问题已经解决 :) - A Friend

2

补充一些实现细节,以便评估TextRendererDrawText()方法和GraphicsDrawString()方法之间的差异。

单击表单后,两种方法在测量和呈现文本方面显示出它们的不同之处。

Dim sText As String() = New String() {
    "C:\FirstLevelDir\FirstSubDir\AnotherDir\ADeepLevelDir\LostDeepDir\SomeFile.exe",
    "C:\FirstLevelDir\AnotherFirstSubDir\AnotherGreatDir\AwsomeDeepLevelDir\LostDeepDir\Some.exe",
    "C:\FirstLevelDir\SomeFirstSubDir\SomeOtherDir\AnotherDeepLevelDir\VeryLostDeepDir\FinalBuriedDir\SomeFile.exe"
}

在表单的 Click() 事件中,使用 TextRenderer.MeasureText() 测量 sText 行的宽度和高度,并使用 TextRenderer.DrawText() 打印它们。请保留 HTML 标签。
Private Sub Form1_Click(sender As Object, e As EventArgs) Handles Me.Click
    Dim relPositionY As Integer = 0
    Dim lineSpacing As Single = 0.5
    Dim paragraphSpacing As Integer = CInt(Font.Height * lineSpacing)

    Dim flags As TextFormatFlags = TextFormatFlags.Top Or
                                   TextFormatFlags.WordBreak Or 
                                   TextFormatFlags.TextBoxControl

     Using g As Graphics = CreateGraphics()
         For x = 0 To sText.Length - 1
             Dim textSize As Size = TextRenderer.MeasureText(
                 g, sText(x), Font,
                 New Size(ClientSize.Width, ClientSize.Height), flags
             )

             TextRenderer.DrawText(g, sText(x), Font,
                 New Rectangle(0, relPositionY, textSize.Width, textSize.Height),
                 ForeColor, flags)
             relPositionY += textSize.Height + paragraphSpacing
         Next
     End Using
End Sub

在表单的 Paint() 事件中,使用 .Graphics.MeasureString() 测量 sText 行的宽度和高度,并用 .Graphics.DrawString() 打印它们。请注意,TextRenderer 中文本框的大小是相对于 Form.ClientSize 的,而在 Graphics 中是相对于 Form 的全宽度。
Private Sub Form1_Paint(sender As Object, e As PaintEventArgs) Handles MyBase.Paint
    Dim relPositionY As Single = 0
    Dim lineSpacing As Single = 0.5
    Dim paragraphSpacing As Single = CSng(Font.Height) * lineSpacing

    Dim flags As StringFormatFlags = StringFormatFlags.LineLimit Or
                                     StringFormatFlags.FitBlackBox

    Using format As StringFormat = New StringFormat(flags)
        For x = 0 To sText.Length - 1
            Dim textSize As SizeF = e.Graphics.MeasureString(sText(x), Font,
                New SizeF(CSng(Width), CSng(Height)), format
            )
            e.Graphics.DrawString(sText(x), Font, Brushes.Black,
                New RectangleF(0, relPositionY, textSize.Width, textSize.Height))
            relPositionY += textSize.Height + paragraphSpacing
        Next
    End Using
End Sub

哇,非常详细的回答,我不知道这些差异。 - A Friend
@一位朋友,图形方法使用旧的GDI+ API,而TextRederer方法使用较新的GDI API。当您在OnPaint()事件中使用e.Graphics时,可能会出现一些意外情况,因为项目通常是使用Application.SetCompatibleTextRenderingDefault(False)进行初始化的(其中“True”表示“使用GDI +”),因此Windows.Forms控件将使用GDI而不是GDI +进行渲染。 - Jimi
哦,我知道了,我的意思是引用块中的那一部分,但还是谢谢你 :) - A Friend

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接