Introduction
Don't you just hate it when your tooltips struggle across the face of your app, looking like they need a good haircut? Here's an easy way to turn them into multi-line tooltips. You can still write the tooltip directly into the Properties window of the control, and format them at runtime to any width that you want.
Discussion
Most of the apps that I write include a subroutine that does various things to the controls, to enhance their appearance or behavior. This subroutine runs through all the controls in my app and adds a little nicety to them, depending on the type of control. This is the place where I format the tooltips.
The first thing to do is to decide on how wide a box you want your tooltips to occupy. Typographic guidelines tell us that the human eye does best when a line of characters is about 2.5 times as long as the alphabet (and the length of the alphabet depends on the typeface and the point size). Well, that's just too complicated. So I decided to make my tooltips not more than 78 characters wide, with an optimum width of 70-75. If a tooltip is shorter than 75 characters, I just leave it alone. But if it's longer, I run it through a short function to divide it into multiple lines. The function creates an array of words, each array element being one word of the tooltip. It then concatenates the words, checking the length as it adds each word, and inserts line breaks wherever the length of the concatenated string reaches my optimum width.
Example
In my subroutine that enhances all controls, I check the length of the tooltip to decide if I need to split it into shorter lines:
Dim tt As String = ToolTip1.GetToolTip(ctrl
If Not tt = Nothing Then
If tt.Length > 75 Then ToolTip1.SetToolTip(ctrl, SplitToolTip(tt))
End If
Here's the function that splits up the long tooltips:
Friend Function SplitToolTip(ByVal strOrig As String) As String
Dim strArray As String()
Dim SPACE As String = " "
Dim CR As String = vbCrLf
Dim strOneWord As String
Dim strBuilder As String
Dim strReturn As String
strArray = strOrig.Split(SPACE)
For Each strOneWord In strArray
strBuilder = strBuilder & strOneWord & SPACE
If Len(strBuilder) > 70 Then
strReturn = strReturn & strBuilder & CR
strBuilder = ""
End If
Next
If Len(strBuilder) < 8 Then strReturn = strReturn.Substring(0, _
strReturn.Length - 2)
Return strReturn & strBuilder
End Function
Notes
The function is pretty straightforward. But I do want to mention the last If
statement. I don't like it when just one word hangs onto a line by itself. So if I have just a little bit left after splitting things up, I tack the last few characters onto the end of the last full line. Yes, it might make it slightly longer, but to me that's better than one word dangling. Can you tell I used to be a typographer?
I used a For...Next
loop because then I don't have to worry about how many elements are there in the array. If you are not familiar with this type of looping structure, check it out in the documentation. It's no more complicated than what you see here, and saves you the trouble of figuring out how many times to loop. Simply by establishing a variable that has the same data type as the array, you can loop through each element of the array.
Finally, note that because my variable CR
is actually two characters (a carriage return and a line feed), I have to lop two characters off the end of strReturn
if I want to correctly append the little bit of leftover text.