65.9K
CodeProject 正在变化。 阅读更多。
Home

在 .NET 2.0 中 RichTextBox 的行号

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.07/5 (16投票s)

2006年6月25日

CPOL

2分钟阅读

viewsIcon

135819

downloadIcon

2669

使用 PictureBox 控件绘画的 RichTextBox 控件的行号。

Sample Image - sample.jpg

引言

本文演示了如何向 RichTextBox 控件添加行号。这是通过在富文本框控件的左侧添加一个 PictureBox 控件来完成的。当 FormRichTextBox 控件上发生适当的事件时,我们调用一个方法,该方法在 PictureBox 控件上绘制行号。这种方法比我见过的其他方法更准确、更有效,在其他方法中,使用另一个文本框控件来打印行号。PictureBox 将只打印当前在 RichTextBox 控件中可见的行号。在构建此代码示例的过程中,我最初是基于文章中提供的代码示例:https://codeproject.org.cn/cs/miscctrl/numberedtextbox.asp,并通过以下方式对其进行了增强

  1. PictureBox 替换用于编号的 Label 控件。
  2. 我修复了该实现中由于 RichTextBox 使用平滑滚动(使用滚动条滚动以像素为单位而不是以行为单位滚动)而导致的滚动问题。因此,有时第一行可能会显示一半,在这种情况下,行号应该解决这个问题。

以下是打印行号的代码。请注意,我们有一个名为 MyRichTextBoxRichTextBox 控件和一个名为 MyPictureBoxPictureBox 控件。该方法获取一个参数,即 PictureBox 控件的 Graphics。这是 DrawRichTextBoxLineNumbers 方法

Private Sub DrawRichTextBoxLineNumbers(ByRef g As Graphics)
  'Calculate font heigth as the difference in Y coordinate 
  'between line 2 and line 1
  'Note that the RichTextBox text must have at least two lines. 
  '  So the initial Text property of the RichTextBox 
  '  should not be an empty string. It could be something 
  '  like vbcrlf & vbcrlf & vbcrlf 
  With MyRichTextBox
   Dim font_height As Single 
   font_height = .GetPositionFromCharIndex(.GetFirstCharIndexFromLine(2)).Y _
         - .GetPositionFromCharIndex(.GetFirstCharIndexFromLine(1)).Y
   If font_height = 0 Then Exit Sub

   'Get the first line index and location
   Dim first_index As Integer
   Dim first_line As Integer
   Dim first_line_y As Integer
   first_index = .GetCharIndexFromPosition(New _
         Point(0, g.VisibleClipBounds.Y + font_height / 3))
   first_line = .GetLineFromCharIndex(first_index)
   first_line_y = .GetPositionFromCharIndex(first_index).Y

   'Print on the PictureBox the visible line numbers of the RichTextBox
   g.Clear(Control.DefaultBackColor)
   Dim i As Integer = first_line
   Dim y As Single
   Do While y < g.VisibleClipBounds.Y + g.VisibleClipBounds.Height
    y = first_line_y + 2 + font_height * (i - first_line - 1)
    g.DrawString((i).ToString, .Font, Brushes.DarkBlue, MyPictureBox.Width _
          - g.MeasureString((i).ToString, .Font).Width, y)
    i += 1
   Loop
   'Debug.WriteLine("Finished: " & firstLine + 1 & " " & i - 1)
  End With
End Sub

此方法应从以下位置调用

  1. RichTextBoxResize 事件上:DrawRichTextBoxLineNumbers(MyPictureBox.CreateGraphics)
  2. VScroll 事件发生在 RichTextBox 上时:(MyRichTextBox.VScroll).DrawRichTextBoxLineNumbers(MyPictureBox.CreateGraphics)
  3. Paint 事件发生时:(MyPictureBox.Paint).DrawRichTextBoxLineNumbers(e.Graphics)。请注意,在这种方法中,我们发送 e.Graphics 而不是 MyPictureBox.CreateGraphics,因为我们只想重绘 PictureBox 控件内的所需区域。

这些是我们调用行号方法的位置

Private Sub r_Resize(ByVal sender As Object, ByVal e As System.EventArgs) _
     Handles MyRichTextBox.Resize
     MyPictureBox.Invalidate()
End Sub

Private Sub r_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) _
        Handles MyRichTextBox.VScroll
  MyPictureBox.Invalidate()
End Sub

Private Sub p_Paint(ByVal sender As Object, _
        ByVal e As System.Windows.Forms.PaintEventArgs) _
        Handles MyPictureBox.Paint
  DrawRichTextBoxLineNumbers(e.Graphics)
End Sub

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles MyBase.Load
  MyRichTextBox.Text = vbCrLf & vbCrLf & vbCrLf
End Sub

其他一般说明

  1. 上面的代码假设 RichTextBox 控件的字体名称和大小对于整个文本是相同的。
  2. RichTextBox 控件的 WordWrap 属性应设置为 False
  3. 我将此代码放在 Form_Load 方法中,以确保文本框始终至少有两行
  4. MyRichTextBox.Text = vbCrLf & vbCrLf & vbCrLf
  5. 我建议将 PictureBox 停靠在左侧,然后根据 g.MeasureString("000", MyRichTextBox.Font).Width 计算 PictureBox 的宽度。当 RichTextBox 的字体更改时,应重新计算 PictureBox 的宽度,并应重新绘制 PictureBox
  6. PictureBox 控件可以替换为 Panel 或任何其他公开 CreateGraphics() 方法的控件。
  7. 该控件是为 WordWrap = FalseRichTextBox 控件设计的。
© . All rights reserved.