[Webinar] Learn how to a build a cloud-first strategyRegister Now


Text size calculation problem.

Posted on 2004-11-22
Medium Priority
Last Modified: 2011-09-20
I'm working on a RichTextBox that allows for specific portions of the text to have a ToolTip.  So far everything works, but there are two small problems.

I'm accomplishing this by handling the MouseMove event and using GetCharIndexFromPosition to figure out where the cursor is.  This works fine, except the function returns the character nearest the cursor at all times.  So if a ToolTip region of text is at the edge of a line, the ToolTip is displayed even when the mouse is over blank space.  The same thing happens if a ToolTip region is on the last line of the box and the cursor is over the blank region underneath.

The solution to this seemed pretty straightforward at first.  I'd use the Font.GetHeight property and MeasureString to calculate the bounds of the line the character belonged to, and if the cursor is within the region display the ToolTip.  However, I've played with this for several hours now, and I cannot seem to make the calculations right.  Using 16 point MS Sans Serif (actually it gets rounded to 15.75 points), the value returned by Font.GetHeight is off by a tiny bit, and the error is amplified more each line.  I discovered this first through outputting the current line index, the predicted location of the next line, and the current Y coordinate to the console.  So I decided to get Windows to draw me a picture; I drew lines where the upper bounds of each line should be, and this screenshot shows the problem:

Notice how each line is more and more outside of the calculated lines.  The code I used to calculate the lines is below (messy because I'm still hacking at it):


        Dim g As Graphics = RichTextBox1.CreateGraphics()
        Dim p As Pen = New Pen(Color.Green)

        For index As Integer = 1 To 11
            g.DrawLine(p, 0, index * RichTextBox1.Font.GetHeight(g), RichTextBox1.Width, index * RichTextBox1.Font.GetHeight(g))


Now's where it gets weird.  If I set the text to 8.25 point or 20 point, the lines are perfect.  If I use GetHeight as the measurement for successive DrawStrings, the text is drawn perfectly no matter what font size I choose.  The problem has to be something stupid I'm overlooking.  Can anyone tell me how to accurately get this value for an arbitrary font size?
Question by:GohdanTheMoblin
  • 2
  • 2
LVL 25

Accepted Solution

RonaldBiemans earned 2000 total points
ID: 12653351
Hi GohdanTheGoblin,

The problem is both the GetHeight, and the measurestring return a single, but the text in a richtextbox is positioned by integers (roundedup), also to get the correct height of the string in the RTB use StringFormat.GenericTypographic instead of the default StringFormat.GenericDefault, also the first line doesn't start at Y position 0 but at Y position 1

this will demonstrated it (this will draw the lines perfectly whatever the font)

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim g As Graphics = RichTextBox1.CreateGraphics()
        Dim p As Pen = New Pen(Color.Green)
        Dim sf As StringFormat = New StringFormat(StringFormat.GenericTypographic)
        Dim stringHeight As Single = Math.Round(g.MeasureString(RichTextBox1.Lines(0), RichTextBox1.Font, RichTextBox1.Width, sf).Height() + 1.5)
        g.DrawLine(p, CInt(0), CInt(stringHeight) + 1, CInt(RichTextBox1.Width), CInt(stringHeight) + 1)

        For index As Integer = 2 To RichTextBox1.Lines.GetUpperBound(0)
            g.DrawLine(p, CInt(0), CInt(index * stringHeight) + 1, CInt(RichTextBox1.Width), CInt(index * stringHeight) + 1)
    End Sub

hopes this helps, if you need more help just let me know

Author Comment

ID: 12656639
Yes, this works perfectly!  I'm not exactly sure about why some of it works, but I think a little research into GenericTypographic could do me some good.

The only real question I have, not really part of the main question but about your code, is why the extra 1.5?  I'm assuming it's a padding "magic number" that 's not documented (like the little bit you have to add to a ListViewColumn to account for the border), but what exactly is it for?
LVL 25

Expert Comment

ID: 12656691
Well actually it is 1 + 0.5, 1 is for the space between the lines and the 0.5 is for rounding up

Author Comment

ID: 12658870
Oh, I understand; there's a little bit of space between the lines in addition to the value returned from GetHeight..  I need to remember that that space is there, the program doesn't work properly without accounting for it.  I wish little details like that were documented!  Thanks for the help :)

Featured Post

Concerto's Cloud Advisory Services

Want to avoid the missteps to gaining all the benefits of the cloud? Learn more about the different assessment options from our Cloud Advisory team.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This tutorial demonstrates one way to create an application that runs without any Forms but still has a GUI presence via an Icon in the System Tray. The magic lies in Inheriting from the ApplicationContext Class and passing that to Application.Ru…
Introduction As chip makers focus on adding processor cores over increasing clock speed, developers need to utilize the features of modern CPUs.  One of the ways we can do this is by implementing parallel algorithms in our software.   One recent…
In a question here at Experts Exchange (https://www.experts-exchange.com/questions/29062564/Adobe-acrobat-reader-DC.html), a member asked how to create a signature in Adobe Acrobat Reader DC (the free Reader product, not the paid, full Acrobat produ…
Look below the covers at a subform control , and the form that is inside it. Explore properties and see how easy it is to aggregate, get statistics, and synchronize results for your data. A Microsoft Access subform is used to show relevant calcul…
Suggested Courses

867 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question