C# 如何使用GDI在多行文本的某些部分加下划线?

C# 如何使用GDI在多行文本的某些部分加下划线?,c#,.net,graphics,gdi+,C#,.net,Graphics,Gdi+,我正在使用Graphics.DrawString绘制usercontrol的文本,如下所示: protected override void OnPaint(PaintEventArgs e) { RectangleF bounds = DisplayRectangle; bounds.Inflate(-4, -4); // Padding StringFormat format = new StringFormat(); format.Alignment = S

我正在使用
Graphics.DrawString
绘制usercontrol的文本,如下所示:

protected override void OnPaint(PaintEventArgs e)
{
    RectangleF bounds = DisplayRectangle;
    bounds.Inflate(-4, -4); // Padding
    StringFormat format = new StringFormat();
    format.Alignment = StringAlignment.Near;
    format.LineAlignment = StringAlignment.Near;
    format.Trimming = StringTrimming.None;
    using (Brush bFore = new SolidBrush(ForeColor))
    {
        g.DrawString(Text, Font, bFore, bounds, format);
    }
}
如果控件的
文本
显示矩形
宽,
抽绳
很好地将
文本
在单词边界处分成多行

现在我想在
文本
中的一些单词下面画下划线,但我没能画出来。我尝试拆分
文本
,然后在下划线部分开始之前测量字符串,
DrawString
普通部分,然后
DrawString
下划线部分。但这仅在
文本
为单行时有效


我确信使用child
LinkLabel
RichTextBox
呈现控件的文本可以解决这个问题,但我不喜欢使用child控件仅在几个单词下面划线的想法。还有其他方法吗?

这是一个粗略的示例,它将字符串拆分为多个部分和两种不同的字体样式,而不是单独绘制下划线(尽管也可以)。在实际操作中,我建议按单词而不是短语分割文本,并在循环中单独处理每个单词。否则,如本例中所示,换行操作并不完全正确

Dim fntNormal As New Font(myFontFamily, myFontSize, FontStyle.Regular, GraphicsUnit.Pixel)
  Dim fntUnderline As New Font(myFontFamily, myFontSize, FontStyle.Underline, GraphicsUnit.Pixel)

  g.DrawString("This is ", fntNormal, Brushes.Black, rctTextArea)
  w1 = g.MeasureString("This is ", fntNormal).Width
  w2 = g.MeasureString("underlined", fntUnderline).Width
  If w1 + w2 > rctTextArea.Width Then
     yPos = rctTextArea.Y + g.MeasureString("This is ", fntNormal).Height + 5
     xPos = rctTextArea.X
  Else
     yPos = rctTextArea.Y
     xPos = 0
  End If

  g.DrawString("underlined", fntUnderline, Brushes.Black, xPos, yPos)

  w1 = g.MeasureString("underlined", fntUnderline).Width
  w2 = g.MeasureString(", and this is not.", fntNormal).Width

  If w1 + w2 > rctTextArea.Width Then
     yPos += g.MeasureString("underlined", fntUnderline).Height + 5
     xPos = rctTextArea.X
  Else
     xPos = 0
  End If


  g.DrawString(", and this is not.", fntNormal, Brushes.Black, xPos, yPos)
这段代码真的可以被清理,使其更有效,让您可以循环遍历文本字符串中的每个单词

这个例子也不包括任何代码来检查你是否已经超过了矩形边界的垂直限制


对于VB代码很抱歉,我刚刚注意到您的问题在C#中。

上面xPos=0的两行。它们不应该是xPos=xPos+w1吗?谢谢,我想这是我能做的最好的了。我还尝试在单词边界上使用MeasureCharacterRanges,但它似乎不适用于多行文本。是的,xPos=0是错误的。我的剪贴画太匆忙了。:)