VB6 TextWidth vs .Net MeasureString

Ok - this should be simple - and it should work. I've been strugglingly for 2 hours to get this right, so I decided to whip up two simple examples to see if I could get the same figure from both VB6 TEXTWIDTH and .Net MEASURESTRING.

In VB6 - I put this code into FORM_LOAD:

Code:
Private Sub Form_Load() Form1.FontName = "Times New Roman" Form1.FontSize = 10 Debug.Print Form1.TextWidth("abcdef") End Sub
Returns a TWIP value of 540 in the IMMEDIATE WINDOW.

In .Net - I put this into FORM_LOAD (needed a PICTUREBOX1 control on the form first):

Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Dim g As Graphics = Me.PictureBox1.CreateGraphics Dim ft As Drawing.Font Dim fs As Drawing.FontStyle Dim sz As SizeF Dim x As Single = 1440 / g.DpiX Dim y As Single = 1440 / g.DpiY fs = 0 ft = New Font("Times New Roman", 10, fs) sz = g.MeasureString("abcdef", ft) Debug.WriteLine(sz.Width * x) End Sub
It comes back with 615.4948.

I need to be able to measure these strings in .Net with similar results to the VB6 program I am working against.

Does anyone have a clue what might be going on here
 
Then...
 
Ok - I just found this code:

Code:
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call MeasureStringSizeFFormatInts() End Sub Public Sub MeasureStringSizeFFormatInts() Dim sformat As StringFormat = StringFormat.GenericTypographic Dim s As String = "abcdef" Dim cr(0) As CharacterRange Dim reg(0) As Drawing.Region 'Dim gr As Graphics Dim fnt As New Font("Times New Roman", 10) Dim charactersFitted As Integer Dim linesFilled As Integer Dim layoutSize As New SizeF(Single.MaxValue, Single.MaxValue) Dim stringSize1 As New SizeF Dim stringSize2 As New SizeF Dim gr As Graphics = Me.PictureBox1.CreateGraphics cr(0) = New CharacterRange(0, s.Length) sformat.FormatFlags = StringFormatFlags.NoClip Or StringFormatFlags.NoWrap sformat.Trimming = StringTrimming.None sformat.SetMeasurableCharacterRanges(cr) reg = gr.MeasureCharacterRanges(s, fnt, New RectangleF(New PointF(0.0F, 0.0F), layoutSize), sformat) stringSize1 = New SizeF(reg(0).GetBounds(gr).Width, reg(0).GetBounds(gr).Height) gr.FillRegion(Brushes.Gray, reg(0)) stringSize2 = gr.MeasureString(s, fnt, layoutSize, sformat, charactersFitted, linesFilled) gr.DrawRectangle(New Pen(Color.Red, 1), 0.0F, 0.0F, stringSize2.Width, stringSize2.Height) gr.DrawString(s, fnt, Brushes.Blue, New PointF(0, 0), sformat) MessageBox.Show("MeasureCharacterRanges Width=" & stringSize1.Width.ToString & Environment.NewLine & _ "MeasureString Wdith=" & stringSize2.Width.ToString & Environment.NewLine & "MeasureCharacterRanges Height=" & _ stringSize1.Height.ToString & Environment.NewLine & "MeasureString Height=" & stringSize2.Height.ToString) End Sub


Seems to return a value, that when multiplied by the 15 dpi/twip ratio comes out to 532.91 - closer to 540 then the 615...

Does anyone understand MEASURECHARACTERRANGES


Answer this question

VB6 TextWidth vs .Net MeasureString

  • VNewbie

    When I created my print preview class wrapper, I ran into the same problem.  I never found a satisfactory solution.  I did get close, however, by first converting all units to inches (you can get pixels per inch from both the printer device and the screen device). 

    The second thing I did, was to create a routine to get the size of the text by creating a dummy print document (setting it up with a Printing.StandardPrintController so you don't get any dialog boxes) and using it's graphic object to do a Graphics.MeasureString on the supplied font and text (fire off it's print event then measure in the print page event then kill the document when you exit).

    Seems a bit convoluted, granted, but the results between screen and printer are pretty darn close.


  • TMD_2006_3_20

    I'm not exactly sure why your code doesn't seem to be working - it seems to be missing the gutter edges around the text.  However, this does seem to work for me and appears much simpler:

    Dim f As New Font("Times New Roman", 20)
    Dim g As Graphics = Me.Picture1.CreateGraphics

    Dim rect As New Rectangle(New Point(0, 0), g.MeasureString("H", f).ToSize)

    g.DrawString(
    "H", f, Brushes.Blue, 0, 0)
    g.DrawRectangle(Pens.Red, rect)

    Hope this helps,
    Adam


  • athena

    Adam - thanks for the code, but it's still not getting me the "exact" size that I require.

    I changed your code to this:

    Dim g As Graphics = Me.PictureBox1.CreateGraphics

    Dim f As New Font("Times New Roman", 20)

    Dim rect As New Rectangle(New Point(0, 0), g.MeasureString("H", f).ToSize)

    Dim rect2 As New Rectangle(New Point(rect.Width, 0), g.MeasureString("W", f).ToSize)

    g.DrawString("HW", f, Brushes.Blue, 0, 0)

    g.DrawRectangle(Pens.Red, rect)

    g.DrawRectangle(Pens.Red, rect2)

    Notice that the first rectangle is really too big - causing the second rectangle to not surround the W properly.

    In VB6 with TEXTWIDTH this "extra spacing" issue did not exist.

    We are trying to develop a UI for a REPORT WRITER ENGINE and this is a real deal breaker for us.

    Is there a non-forum method that I can use to get this problem really solved   Someone suggested I log a support call with MS - is that possible or recommended


  • Martin_NL

    Maybe this will help you out

    http://blogs.msdn.com/jfoscoding/archive/2005/10/13/480632.aspx

    Best regards,
    Johan Stenberg



  • Geoff Garside

    Ok - I've done this in VS 2005 - created a new project - put two picture boxes and a command button on the form.

    I put this code into the command button - I want the box to surround the letter "H" and it's not happening that way.

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    Dim g As Graphics = Me.PictureBox1.CreateGraphics

    Dim f As New Font("Times New Roman", 20)

    g.DrawString("H", f, Brushes.Blue, 0, 0)

    Dim g2 As Graphics = Me.PictureBox2.CreateGraphics

    Dim r(0) As Drawing.Region

    Dim l As New SizeF(Single.MaxValue, Single.MaxValue)

    Dim s As StringFormat = StringFormat.GenericTypographic

    Dim cr(0) As CharacterRange

    Dim sz As New SizeF

    cr(0) = New CharacterRange(0, "H".Length)

    s.FormatFlags = StringFormatFlags.NoClip Or StringFormatFlags.NoWrap

    s.Trimming = StringTrimming.None

    s.SetMeasurableCharacterRanges(cr)

    r = g2.MeasureCharacterRanges("H", f, New RectangleF(New PointF(0, 0), l), s)

    'sz = g2.MeasureString("H", f, l, s, 0, 0) ** this line doesn't put the rectangle on the letter any better **

    sz = New SizeF(r(0).GetBounds(g).Width, r(0).GetBounds(g).Height)

    g2.DrawRectangle(New Pen(Color.Red, 1), 0, 0, sz.Width, sz.Height)

    g2.DrawString("H", f, Brushes.Blue, 0, 0)

    End Sub


  • Mehrdad Abdi

    212 reads on this thread and not a single post back   Am I the only measuring text in .Net
  • Ales

    After getting suggestions from other forums I've come upon this code snippet that basically does what I want:

            Dim f As New Font("Times New Roman", 20)

            Dim g2 As Graphics = Me.PictureBox2.CreateGraphics

            Dim s As StringFormat = StringFormat.GenericTypographic

            'get the dimesions of the picturebox2's client rectangle so the measurestring function
            'knows what it has to work with and include the type of string formatting
            Dim lsz As SizeF = g2.MeasureString("H", f, Me.PictureBox2.ClientRectangle.Size, s, 0, 0)
            Dim lsz2 As SizeF = g2.MeasureString("W", f, Me.PictureBox2.ClientRectangle.Size, s, 0, 0)

            g2.DrawRectangle(New Pen(Color.Red, 1), 0, 0, lsz.Width, lsz.Height)
            g2.DrawRectangle(New Pen(Color.Red, 1), lsz.Width, 0, lsz2.Width, lsz2.Height)
            'make sure to include your string formatting here as well when drawing the
            'string.
            g2.DrawString("HW", f, Brushes.Blue, 0, 0, s)

    The STRINGFORMAT.GENERICTYPEGRAPHIC seems to make things align properly.

    So at this point I think my problems has been solved.

    I hope this helps others who are looking at similar issues in the future.


  • Ricardo Ibarra

    Ok - so I went and installed VS 2005 on my laptop...

    Created a project and put this in FORM1_LOAD...

    Dim fnt as New Font("Times New Roman", 10)

    Dim sz as SizeF

    sz = TextRenderer.MeasureText("abcdef",fnt)

    When I hover over the "sz" variable I see WIDTH=46 - this makes no sense.

    In VB6 the TEXTWIDTH of "abcdef" is 540 twips - there is no way to make 46 be 540 - I cannot multiple by 15 twips-per-pixel.  There has to be a way to measure text in a fashion similar to VB6...

     


  • VB6 TextWidth vs .Net MeasureString