C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to display lines in column next to richtextbox?
Originally Posted by Niya
Are you looking for a Control to use as a code editor?
Thanks for your reply
Yeah, I need a code editor control that has the line number column and that can take plaintext as well. Also needs to be flexible just like a RichTextBox is because I'd like to be able to program my own syntax highlighting for a language that no editor has ever heard of. That's why a plain RichTextBox would have been ideal, because (I'm guessing) it will be easier to customize.
Re: How to display lines in column next to richtextbox?
You're probably going to have to look for a 3rd party solution. I was looking into this myself a couple months ago. I stumbled onto some potential solutions but I never went any further than reading about them so I don't know how well they would work in practice.
While I've done quite a bit of custom controls over the course of little over a decade both in VB6 and VB.Net, I've never dealt with text boxes to any great degree and for good reason. Text boxes are probably the most difficult of all controls to deal with. This is not to say customizing the RTB is not possible. It may very well be quite simple but I just don't know. I never attempted to mess with text box controls. I've always had the instinct to simply look for 3rd party controls when I need fancy text box controls.
Code editor controls should be relatively easy to find. I found potential leads as I said earlier. You could try looking for them, see what you come up with.
Also, someone else on these forums might have a better answer than me so you could wait and see if anyone else has something to say.
C++ programmers will dismiss you as a cretinous simpleton for your inability to keep track of pointers chained 6 levels deep and Java programmers will pillory you for buying into the evils of Microsoft. Meanwhile C# programmers will get paid just a little bit more than you for writing exactly the same code and VB6 programmers will continue to whitter on about "footprints". - FunkyDexter
There's just no reason to use garbage like InputBox. - jmcilhinney
The threads I start are Niya and Olaf free zones. No arguing about the benefits of VB6 over .NET here please. Happiness must reign. - yereverluvinuncleber
Re: How to display lines in column next to richtextbox?
Thanks for your help Niya
I've tried looking into a few controls that looked promising, even diving into the realm of C#. However, none of them worked very well.
The closest I've got to a solution is the following (not my own code - It took me 2 read-throughs to even begin to understand it):
Code:
Public Class Form1
Dim total_lines As Integer
Private Sub DrawRichTextBoxLineNumbers(ByRef g As Graphics)
With RichTextBox1
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
'get the total number of lines in the richtextbox
'total_lines = MyRichTextBox.Lines.Length
total_lines = RichTextBox1.GetLineFromCharIndex(Int32.MaxValue) + 1
'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)
If total_lines >= i Then
g.DrawString((i).ToString, .Font, Brushes.DarkBlue, PictureBox1.Width _
- g.MeasureString((i).ToString, .Font).Width, y)
Else
Exit Do
End If
i += 1
Loop
End With
End Sub
Private Sub r_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.Resize
PictureBox1.Invalidate()
End Sub
Private Sub r_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.VScroll
PictureBox1.Invalidate()
End Sub
Private Sub p_Paint(ByVal sender As Object, ByVal e As System.Windows.Forms.PaintEventArgs) Handles PictureBox1.Paint
DrawRichTextBoxLineNumbers(e.Graphics)
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RichTextBox1.Text = vbCrLf & vbCrLf & vbCrLf
End Sub
Private Sub MyRichTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RichTextBox1.TextChanged
If RichTextBox1.GetLineFromCharIndex(Int32.MaxValue) + 1 <> total_lines Then PictureBox1.Invalidate()
End Sub
End Class
The picturebox is the left panel that shows the numbers.
The issues with this solution is as follows:
When I run the application, the richtextbox starts with 4 lines by default.
When clearing the contents of the richtextbox, the numbers go away, you have to enter more than 2 lines to finally register the line numbers again.
Sometimes when entering 2 lines, this happens.
This gets fixed if you add a couple morel lines.
Does anybody know any fixes to this? I've tried modifying some of the numbers in the code (particularly when trying to target the problem with there being 4 lines on load, however I haven't found any real fixes.
Can someone help me out please. By help, by the way, I do mean try to point me into the right direction, you don't have to write the modified code for me .
I know this is not the answer you wanted, but it should be easier for you to figure out the code to have a RTB display numbered lines the way you want them, plus you wouldn't have to worry about figuring out how to synchronize a picture box image with a RTB scroll.
One trick you'll have to do is once the numbered richtextbox's scrollbar appears, this RTB needs to resize it's width to hide it's scrollbar under the other RTB. The numbered RTB will also need to resize if the number is too great, to include repositioning the other RTB.
Last edited by Peter Porter; Dec 16th, 2017 at 09:00 PM.
I don't remember if I ever had to tweak it or not, but I do have it working perfectly in an old project of mine. One trick you'll have to do is that the richtextbox that shows the numbers, make sure it's far enough left from the RTB for the text. This way you can hide the numbered RTB's scrollbar with a panel when it gets too long.
I know this is not the answer you wanted, but it should be easier to have a 2nd RTB to display numbered lines the way you want them, plus you wouldn't have to worry about figuring out how to synchronize a picture box image with a RTB scroll.
This actually looks really useful. That's probably another question that I might have had in the future resolved. Thanks for your help!
Imports System.Runtime.InteropServices
Public Class Win32
Public Const GWL_STYLE As Integer = -16
Public Const WS_VSCROLL As Integer = 2097152
Public Const WS_HSCROLL As Integer = 1048576
<DllImport("user32.dll", SetLastError:=True)>
Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
End Function
End Class
Now add this function to the class that contains your richtextboxes:
Code:
Protected Shared Function GetVisibleScrollbars(ByVal ctl As Control) As ScrollBars
Dim wndStyle As Integer = Win32.GetWindowLong(ctl.Handle, Win32.GWL_STYLE)
Dim hsVisible As Boolean = (wndStyle And Win32.WS_HSCROLL) <> 0
Dim vsVisible As Boolean = (wndStyle And Win32.WS_VSCROLL) <> 0
If hsVisible Then Return If(vsVisible, ScrollBars.Both, ScrollBars.Horizontal) Else Return If(vsVisible, ScrollBars.Vertical, ScrollBars.None)
End Function
Within the Richtextbox_TextChanged sub, add this to detect it's scrollbars:
Code:
If GetVisibleScrollbars(RichTextBox1) Then
'to get the scrollbar width
Dim RTBW as integer
RTBW = RichTextBox1.Width - RichTextBox1.ClientSize.Width
'to adjust the richtextbox width once the scrollbar appears
richtextbox1.width = richtextbox1.width + RTBW
'whatever code for repositioning the other if needed
Else
'when scrollbar disappears
If RTBW > 0 then
'return richtextbox to original width before resize
richtextbox1.width = richtextbox1.width - RTBW
RTBW = 0
Else
End if
End If
Last edited by Peter Porter; Dec 16th, 2017 at 11:22 PM.
Re: How to display lines in column next to richtextbox?
Hi,
perhaps another option to work on..
Code:
Private Function AddLineNumbersToText(ByVal text As String) As String
Dim sb As New StringBuilder()
Dim splitStrings As String() = {vbCr, vbCr & vbLf, vbLf}
Dim lines As String() = text.Split(splitStrings, StringSplitOptions.None)
Dim lineCounter As Integer = 0
For Each s As String In lines
sb.Append(lineCounter.ToString())
sb.Append(": ") ' & vbTab)
sb.Append(s)
sb.Append(Environment.NewLine)
lineCounter += 1
Next
Return sb.ToString()
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'Name of Richtextbox is: Rtb
Rtb.Text = AddLineNumbersToText(Rtb.Text)
End Sub
to hunt a species to extinction is not logical !
since 2010 the number of Tigers are rising again in 2016 - 3900 were counted. with Baby Callas it's 3901, my wife and I had 2-3 months the privilege of raising a Baby Tiger.
Re: How to display lines in column next to richtextbox?
Update 3 Jan 2018:
The numbered richtextbox is now perfectly synchronized with the text lines of the other.
There are no editing functions, but that can be easily added. You can paste text into it by pressing Ctrl-P besides typing.
RichTextBox1's backcolor is set to "Control" in properties, borderstyle "None", scrollbars "None", readonly "True", docked "Left", with a width of 70.
RichTextbox2's backcolor is "Window", borderstyle "None", wordwrap "False", docked "Fill".
Enjoy!
Code:
Public Class Form1
Const WM_USER As Integer = &H400
Const EM_GETSCROLLPOS As Integer = WM_USER + 221
Const EM_SETSCROLLPOS As Integer = WM_USER + 222
Declare Function SendMessage Lib "user32.dll" Alias "SendMessageW" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByRef lParam As Point) As Integer
Private Sub Form1_Load_1(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
RichTextBox1.SelectionAlignment = HorizontalAlignment.Right
RichTextBox1.Text = "1"
RichTextBox1.Enabled = False
End Sub
Private Sub RichTextBox2_KeyUp(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles RichTextBox2.KeyUp
If (e.KeyCode = Keys.P AndAlso e.Modifiers = Keys.Control) Then
RichTextBox2.Text = Clipboard.GetText()
RichTextBox2.SelectAll()
RichTextBox2.SelectionFont = New Font("Microsoft Sans Serif", 10, FontStyle.Regular)
RichTextBox1.SelectAll()
RichTextBox1.SelectionFont = New Font("Microsoft Sans Serif", 10, FontStyle.Regular)
End If
End Sub
Private Sub RichTextBox2_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RichTextBox2.TextChanged
Dim count As Integer
Dim count2 As String
Dim myList As List(Of String) = RichTextBox1.Lines.ToList()
Dim minus As Integer
Dim holder As String
count = RichTextBox2.Lines.Length
holder = CStr(RichTextBox1.Lines.Length)
count2 = " "
If RichTextBox1.Lines.Length > count Then
For minus = 1 To CInt(CDbl(holder) - count)
If myList.Count > count Then
myList.RemoveAt(myList.Count - 1)
RichTextBox1.Lines = myList.ToArray()
RichTextBox1.Refresh()
End If
Next
Else
If count = RichTextBox1.Lines.Length Then
count = RichTextBox1.Lines.Length
End If
End If
If count > RichTextBox1.Lines.Length + 1 Then
count2 = CStr(count - RichTextBox1.Lines.Length)
For minus = 1 To CInt(count2)
RichTextBox1.AppendText(Environment.NewLine & minus + count - CDbl(count2))
Next
End If
If RichTextBox1.Text.Length = 0 Then
RichTextBox1.Text = "1"
Else
End If
If RichTextBox1.Lines.Length < count Then
RichTextBox1.AppendText(Environment.NewLine & count)
Else
End If
If RichTextBox1.Text.Length = 2 Then
RichTextBox1.AppendText("2")
Else
End If
Dim pt2 As Point
SendMessage(RichTextBox2.Handle, EM_GETSCROLLPOS, 0, pt2)
SendMessage(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, New Point(0, pt2.Y))
End Sub
Private Sub RichTextBox2_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox2.VScroll
Dim pt2 As Point
SendMessage(RichTextBox2.Handle, EM_GETSCROLLPOS, 0, pt2)
SendMessage(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, New Point(0, pt2.Y))
End Sub
Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Resize
Dim pt2 As Point
SendMessage(RichTextBox2.Handle, EM_GETSCROLLPOS, 0, pt2)
SendMessage(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, New Point(0, pt2.Y))
End Sub
End Class
The zipped project below uses an image divider separating the richtextboxes.
Last edited by Peter Porter; Jan 3rd, 2018 at 07:20 PM.
Re: How to display lines in column next to richtextbox?
Thank you so much for your help with this Peter! I had actually abandoned the idea of using a coding style RTB in favour of a plain RTB as I could not get it to work. Using this makes my application look so much more professional and is far more relevant for what my application actually does.