I have TextBox with enabled MultiLine. How can i get number of clicked line in TextBox.Click event?
4 Answers
The TextBoxBase class (from which the TextBox derives) has many methods that can help you in this task.
Assume you have this event handler for the MouseDown event of your TextBox1 control
Sub TextBox1_MouseDown(sender as Object, e as MouseEventArgs) Handles TextBox1.MouseDown
' In the MouseEventArgs we have the click location
' We can use that point to get the CharIndex from the TextBox
Dim charIndex as Integer = TextBox1.GetCharIndexFromPosition(e.Location)
' Now the charIndex could be passed to another method to get the line index
Dim line As Integer = TextBox1.GetLineFromCharIndex(charIndex)
' Lines start from 0
MessageBox.Show("Click on line=" + line + ", Text=" + TextBox1.Lines(line))
End Sub

- 213,761
- 22
- 232
- 286
one solution is determining it by textbox line height, such this:
Dim LineHeight = 16 ' you may change this value
Private Sub richTextBox1_MouseClick(sender As Object, e As MouseEventArgs)
'the number of the selected line
Dim i = e.Location.Y/LineHeight
'get the value of the number line.
MessageBox.Show(Me.richTextBox1.Lines(i))
End Sub

- 6,135
- 6
- 43
- 80

- 3,697
- 2
- 23
- 47
Steve has a great answer that taught me a few things, but since he used MouseDown instead of Click I thought I could give another option and expand on the difference between the two a little bit.
I'll show you my code in case that is all you want, but if you want a bit more information then you can read on.
The code (using Click as requested):
Private Sub mainTextBox_Click(sender As Object, e As EventArgs) Handles mainTextBox.Click
Dim line As Integer = mainTextBox.GetLineFromCharIndex(mainTextBox.SelectionStart)
End Sub
This gets the location of the selection cursor, which moves to where you click, instead of the mouse location. Since this click event is on the TextBox itself the cursor should move every time and thus it should be relatively equivalent to Steve's answer using the mouse location, but I haven't tested it thoroughly to be sure about all the edge cases (yes, the selection cursor moves before the click event is called, I have tested that much).
Oh, and don't forget that it gives the index of the line, so the first line is actually going to return 0, the second returns 1, etc.
Extra bits:
Since Steve used MouseDown I thought I'd mention how it is different from Click/MouseClick in case you (or some future reader) aren't aware. MouseDown is called as soon as the mouse button is pressed down, MouseUp is then called when it is released, and then Click/MouseClick are called after that. If the exact timing doesn't matter for your use then you should be fine using whichever you'd like, if it does matter then there are some great answers out there that explain the differences in more detail (here is one that explains Click vs MouseClick for example).
You can see here how you can do the same trick with MouseClick and MouseDown as well:
Private Sub mainTextBox_MouseClick(sender As Object, e As MouseEventArgs) Handles mainTextBox.MouseClick
Dim line As Integer = mainTextBox.GetLineFromCharIndex(mainTextBox.SelectionStart)
End Sub
Private Sub mainTextBox_MouseDown(sender As Object, e As MouseEventArgs) Handles mainTextBox.MouseDown
Dim line As Integer = mainTextBox.GetLineFromCharIndex(mainTextBox.SelectionStart)
End Sub
I was able to do a quick test since I have a TextBox in something I am currently working on, but I haven't tested either Steve's method or my own extensively and can't say if one is definitely better then the other. You may want to try both and see what works best for you.
-
Wow. I wasn't planning on writing that much but as I started I realized I could learn a few new things as well and started testing some things and got a little carried away. :) (read: if someone feels like they can whittle this down to something more concise without changing the basic answer, go for it) – RTHarston Feb 09 '19 at 21:43
-
1`if someone wants to change this C# in to VB I would be most grateful` As you wish :-) It's a pretty straightforward conversion—the biggest difference is wiring up the event handlers using the `Handles` keyword. – InteXX Feb 10 '19 at 08:15
-
@InteXX Thanks! I have literally never written a single line of VB so I wasn't sure what all it involved. Looking at Steve's answer I was thinking about trying the conversion myself and looking at what you changed it to I think I would have been pretty close! I think the only thing I would have missed was ByVal. Anyway, thanks again. I guess you could say I learned some VB today. :-) – RTHarston Feb 10 '19 at 21:04
-
`ByVal` Actually, that was an 'oops' on my part. `ByVal` is inferred by default and is no longer required. [Telerik's converter](http://converter.telerik.com/) inserts it automatically and I forgot to take it out, that's all. `I guess you could say I learned some VB today` Good man :-) – InteXX Feb 10 '19 at 22:52
-
Nice power wagon you've got there :-) – InteXX Feb 10 '19 at 22:54
-
@InteXX Had, unfortunately. I loved that thing. :-) It was my first car and I ran it until it died (had an engine fire -> fixed it up but forgot to add more water to radiator -> engine seized...). It came with that paint job. XD It was a 1978 Subaru 4WD Wagon. (Dear moderator: I know this comment is off topic, just please wait for InteXX to see it before removing it. Thanks ;-) ) – RTHarston Feb 11 '19 at 19:15
-
@InteXX Ah, so I would have had it right. Cool. Glad you did it for me though so I could be sure. – RTHarston Feb 11 '19 at 19:16
-
@InteXX Thanks for the offer, but I don't know how to use it because I don't use it. ;) If I ever do though I'll try and remember your offer. Thanks again. :) – RTHarston Feb 18 '19 at 18:27
For a textbox named tbData (line is zero-based, hence need to add 1):
Private Sub tbData_MouseClick(ByVal sender As System.Object, ByVal e As MouseEventArgs) Handles tbData.MouseClick
Dim msg As String
Dim lineClicked As Int32
lineClicked = tbData.GetLineFromCharIndex(tbData.GetCharIndexFromPosition(e.Location)) + 1
msg = "clicked line " + lineClicked.ToString()
MsgBox(msg)
End Sub

- 114
- 1
- 6