 |
 |

07-10-2012, 04:18 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
Lenght of multiline textboxes
|
What I want is a multiline textbox that can't be filled with more lines than its size. So when just before the scrollbar should be activated it wont accept any more lines. I have googled it for half an hour and found nothing similar to what I'm trying to achieve. Does anyone have a solution?
Thank you in advance!
//Ferion
|
|

07-10-2012, 05:22 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,272
|
|
|
It's a pain is the backside to try and do.
It's not really something that's typically done (you generally limit textboxes to a number of characters and the space that those characters takes up depends on the font which is something the user chooses). Any solution would end up fighting numerous shortcomings (like, it's not too bad doing keypresses by users but then pasting into the textbox starts to get difficult).
In those types of scenarios it's typically easier to rethink the design, i.e. why you want to do this, instead of trying to fight to the end of this solution.
So really the question is why you want to do this? Is there a better way of trying to do whatever it is you want to achieve?
|
__________________
There are no computers in heaven!
|

07-10-2012, 05:51 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
|
What I'm making is a program that displays music lyrics. The problem when looking them up on internet is that you always must scroll down because they are to long. So my program creates several textboxes depending on screen width and place them side by side. Then I want to paste the lyrics in the first, and when its full paste lyrics in the second, and when its full in the third and so on. Is this impossible?
|
|

07-10-2012, 06:15 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,272
|
|
|
Nothing is impossible but a lot of stuff is more effort than it's worth.
I appreciate the problem. I have scrolled through many a lyrics site whilst trying to play at the same time.
I'm not too sure on how your solution improves it though. All you are really doing is making the text smaller to fit more of it on the screen. That is not necessarily the best approach. You don't have to scroll but it might be harder to actually read.
One thing to note is that it's very difficult to know how much text you can fit onto one line of a textbox. For example, 10 i characters take up less space than 10 m characters (with a non fixed width font) And you also have to take word wrapping into account. A line of text might take up two lines in a textbox if, say, the last word is long and wouldn't fit and it wraps it onto the next line. That tends to mean that solutions for this kind of thing have to work by processing the text in the string word by word and then you get into splitting words issues.
Maybe making something that's easier to page is a way to go. You could display a verse/chorus at a time, make the text as big as possible for readability and make it forward and back through the song via a simple keypress. That would be much easier to achieve.
|
__________________
There are no computers in heaven!
|

07-10-2012, 06:33 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,272
|
|
|
If you want solutions to your problems instead of my ramblings that don't answer the question then I suggest googling something like "multiline textbox limit lines" and you should find various solutions and discussions on their shortcomings.
|
__________________
There are no computers in heaven!
|

07-10-2012, 07:31 PM
|
|
Contributor
* Expert *
|
|
Join Date: Feb 2004
Posts: 522
|
|
Quote:
|
Originally Posted by DrPunk
If you want solutions to your problems instead of my ramblings that don't answer the question then I suggest googling something like "multiline textbox limit lines" and you should find various solutions and discussions on their shortcomings.
|
That's what I did and found this " Limit number of lines in .net textbox" stackoverflow thread.
It should also be noted there is a TextBox.MaxLength property, but I'm not sure its the best solution for your scenario.
However, it might be a good way to find related threads on the forum.
If you google for:
site:xtremevbtalk.com textbox.maxlength
..you get a bunch of results, like these ( 1, 2, 3, 4, 5, 6)..I even found a thread with some code for limiting text length in a richtextbox.
I know there is also a TextBoxBase.Lines property which has:
Quote:
An array of strings that contains the text in a text box control.
Each element in the array becomes a line of text in the text box control.
If the Multiline property of the text box control is set to true,
and a newline character appears in the text,
the text following the newline character is added
to a new element in the array and displayed on a separate line.
|
..that might be useful for parsing lines (stings) for length validation?
There is some VB.Net code from vbHelper that
"Detects whether text in a multiline TextBox is wrapped in Visual Basic .NET"
I did have an old social.msdn thread bookmarked that had an interesting
"function checkTextAreaMaxLength" in the last post,
so I used this online C# to VB.net converter and came out with this code:
Code:
Private Function checkTextAreaMaxLength(ByVal , As textBox, ByVal , As e, ByVal Unknown As maxLength) As function
If Not checkSpecialKeys(e) Then
If (textBox.value.length _
> (maxLength - 1)) Then
If window.event Then
e.returnValue = false
Else
e.preventDefault
End If
End If
End If
onBlurTextCounter(textBox, maxLength)
End Function
Private Function checkSpecialKeys(ByVal Unknown As e) As function
If ((e.keyCode <> 8) _
AndAlso ((e.keyCode <> 46) _
AndAlso ((e.keyCode <> 37) _
AndAlso ((e.keyCode <> 38) _
AndAlso ((e.keyCode <> 39) _
AndAlso (e.keyCode <> 40)))))) Then
Return false
Else
Return true
End If
End Function
Private Function onBlurTextCounter(ByVal , As textBox, ByVal Unknown As maxLength) As function
If (textBox.value.length > maxLength) Then
textBox.value = textBox.value.substr(0, maxLength)
End If
End Function
I don't know if this code will specifically address your problem,
but I'm hoping this thread won't be totally theoretically
(i.e. it will, at least, have some code to start with in developing a solution..)
|
Last edited by hDC_0; 07-10-2012 at 08:31 PM.
|

07-11-2012, 04:54 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
|
Thank you both for your replies!
When trying to find a solution to my problem I found that txtbox.lines.length is helpful but it doesn't do the whole trick. Because I also need a value of the amount of lines that fit into the textbox. I'm not sure if hDC_0:s links contained such a function because I'm not capable of understanding the code 100%.
But I'm thinking if there are information about the scrollbar, whether it's "active" at the time being, then I have my other value that is needed. The problem is only that I don't know if there are such properties, do you?
Also Me.Controls("lyricsbox0").lines.length() gives me the error: "lines" is not a member of 'System.windows.forms.control'. What did I do wrong? textbox1.lines.length works fine.
// Ferion
|
|

07-11-2012, 06:07 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,272
|
|
The error you're getting there is because Me.Controls returns a Control type, not a Textbox type, and Lines is not a property of Control.
You have to cast the object into the type you want to be able to access those properties
Code:
ctype(Me.Controls("lyricsbox0"), TextBox).Lines.Length
That line would error at runtime if the control called lyricsbox0 is not a Textbox. It cannot know that at design time.
Quote:
|
Because I also need a value of the amount of lines that fit into the textbox.
|
You could calculate that. You can get the size of the font of the textbox and then divide the height of the textbox by that value to get an idea of how many lines will fit in the textbox.
Code:
MessageBox.Show(TextBox1.ClientRectangle.Height \ TextBox1.Font.Height)
|
__________________
There are no computers in heaven!
|

07-11-2012, 07:35 AM
|
 |
Multi-Technologist
Super Moderator * Expert *
|
|
Join Date: May 2004
Location: Michigan
Posts: 3,734
|
|
Quote:
Originally Posted by DrPunk
You could calculate that. You can get the size of the font of the textbox and then divide the height of the textbox by that value to get an idea of how many lines will fit in the textbox.
Code:
MessageBox.Show(TextBox1.ClientRectangle.Height \ TextBox1.Font.Height)
|
A more accurate fit might be accomplished by applying a magic number (presumably top/bottom border correction) to the equation:
Code:
MessageBox.Show((TextBox1.ClientRectangle.Height - 2) \ TextBox1.Font.Height)
I'm loathe to convert these yucky magic corrections to a constant unless I know exactly what to call it.
|
__________________
"May the code that you write never work in ways that you didn't expect; and may the code that you didn't write never require you to maintain it". - Ancient Chinese Proverb
|

07-11-2012, 10:16 AM
|
 |
Fabulous Florist
Forum Leader * Guru *
|
|
Join Date: Feb 2004
Location: Austin, TX
Posts: 9,415
|
|
Here's my crazy idea, because sometimes doing something different is a little easier.
Text boxes are sort of a poor choice for this because you don't have much control over their rendering and accurately predicting where a line will end up is a little troublesome. Besides, that it's a text box at all makes it look like the text should be editable and that's not really what you're going for. In my opinion, the best thing to do is ask if it'd be easy to write this as a custom control.
It turns out that's pretty easy. Graphics.MeasureString() will tell you how much space a string will take up given a width it must fit in; that accounts for word wrap. A simple algorithm suggests how to display multicolumn text:
Code:
* Split the text into lines.
* For each line:
* If the wrapped line is taller than the remaining space:
* Move to a new column.
* Draw the line at the current position.
* Move the current position beneath the line that was drawn.
I've attached a simple implementation of this algorithm in a custom control with a few flaws because it's just an example. The column width should really be a property. Support for scrolling would be a little bit of work. It probably doesn't do too well if you give it a line so long it can't fit in a single column; that ought to never happen given your use case. Otherwise, it's plenty functional.
|
|

07-12-2012, 05:35 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
Thank you very much for the help guys! I tried Dr Punk's solution
Quote:
|
MessageBox.Show(TextBox1.ClientRectangle.Height \ TextBox1.Font.Height)
|
and it worked very well. AtmaWeapon's solution was very smart also.
//Ferion
|
|

07-12-2012, 05:41 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
|
Here is a picture of the result!
|
|

07-12-2012, 06:28 AM
|
 |
Senior Contributor
* Expert *
|
|
Join Date: Apr 2003
Location: Never where I want to be
Posts: 1,272
|
|
|
Ideally you want to use a fixed width font (like courier new) so that the tab lines up correctly.
|
__________________
There are no computers in heaven!
|

07-16-2012, 08:55 AM
|
|
Newcomer
|
|
Join Date: Jun 2012
Posts: 14
|
|
Actually the method didn't work after all, my theory is that font.height doesn't include the space between the lines. But I solved it with a quite more advanced method.
The idea of the solution is that the program paste one VBNewLine at a time and check if the scrollbarposition changes. Then when it does the previous linevalue is the max amount of lines that fit into the textbox.
In the following example I have a very long text and two textboxes. The program fills the first one with text and then the leftover text is pasted to the other textbox.
Here is the code:
Code:
Public Enum SBorientation As Integer
SB_HORZ = &H0
SB_VERT = &H1
SB_CTL = &H2
SB_BOTH = &H3
End Enum
Public Declare Function GetScrollPos Lib "user32" (ByVal hWnd As IntPtr, ByVal nBar As SBorientation) As Long
Public Sub Form_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
textbox1.ScrollBars = ScrollBars.Horizontal
textbox1.WordWrap = False
textbox2.ScrollBars = Scrollbars.Both
textbox2.WordWrap = False
End Sub
Public sub splittext
Dim fullvalue As Integer = full(textbox1.Lines.Length)
If fullvalue = -1 Then
exit sub
Else
Dim text As String = textbox1.Text
Dim txtboxlen As Integer = textbox1.Text.Length
Dim charsuntilline As Integer = CountCharsUntilLine(text, fullvalue)
Dim charsleft As Integer = txtboxlen - charsuntilline
textbox2.Text = Mid(text, charsuntilline + 1, charsleft - 1)
textbox1.Text = Mid(text, 1, charsuntilline)
End If
End sub
Private Function CountCharsUntilLine(ByVal input As String, ByVal stopline As Integer)
Dim lenght As Integer = input.Length
Dim i As Integer = 1
Dim chars As Integer = 0
Dim lines As Integer = 0
Do While i <= lenght
Dim temp As String = ""
temp = Mid(input, i, 1)
chars += 1
If Asc(temp) = 13 Then
lines += 1
End If
If lines = stopline Then
i = lenght + 1
End If
i += 1
Loop
Return chars
End Function
Public Function full(ByVal lines As Integer)
Dim temp As String = textbox1.Text
textbox1.Text = ""
textbox1.ScrollBars = ScrollBars.Vertical
Dim orgscrollpos As Long = GetScrollPos(textbox1.Handle, SBorientation.SB_VERT)
Dim n As Integer = 1
Do While n <= lines
textbox1.Text &= vbNewLine
textbox1.SelectionStart = textbox1.Text.Length
textbox1.ScrollToCaret()
Dim scrollpos As Long = GetScrollPos(textbox1.Handle, SBorientation.SB_VERT)
If scrollpos > orgscrollpos Then
textbox1.Text = temp
textbox1.ScrollBars = ScrollBars.Horizontal
Return n - 1
Exit Function
End If
n += 1
Loop
textbox1.Text = temp
textbox1.ScrollBars = ScrollBars.Horizontal
Return -1
End Function
|
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
|
|
 |
|