MeasureString, FillRectangle, and DrawString

  • Thread starter Thread starter eBob.com
  • Start date Start date
E

eBob.com

I think that this code (in an OnPaint) ...

grfx.FillRectangle(Brushes.White, Me.ClientRectangle)
msr = grfx.MeasureString("aaa", bigfont) 'msr is Dimed as SizeF
grfx.FillRectangle(Brushes.LightBlue, 0, 0, msr.Width, msr.Height)
grfx.DrawString("aaaaaa", bigfont, Brushes.Black, 0, 0)

should result in aaa on a light blue background followed immediately by aaa
on the white background. Almost, but not quite. The light blue background,
or highlighting, extends beyond the first three a's, about halfway into the
fourth a. In other words, the combination of the MeasureString and
FillRectangle ends up Filling more Rectangle than it should. I'm using .NET
Framework 1.1 w/SP1.

(What I am trying to do is develop a control which supports highlighting
various strings, more than one at a time, in text.)

Does anyone have any idea what is going on here?

The code is below if anyone cares to play with it. It just needs a blank
form, the control is added dynamically.

Thanks, Bob

Public Class Form1
Inherits System.Windows.Forms.Form
Public sampstring As String = "The quick brown fox jumped over the lazy
dog."

Dim stb As New SpecialTextBox

#Region " Windows Form Designer generated code "
#End Region

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
stb.Text = sampstring
stb.Location = New Point(100, 100)
stb.Width = 200
stb.Height = 150

Controls.Add(stb)
End Sub
End Class

Public Class SpecialTextBox
Inherits System.Windows.Forms.Control

Public Sub New()
MyBase.New()
End Sub
Public Overrides Property Text() As String
Get
End Get
Set(ByVal Value As String)
MyBase.Text = Value
End Set
End Property

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

Dim rectf As RectangleF
Dim grfx As Graphics = e.Graphics
grfx.FillRectangle(Brushes.White, Me.ClientRectangle)

Dim bigfont As Font = New Font(FontFamily.GenericSerif, 20)

'grfx.FillRectangle(Brushes.Yellow, 0, 0, 90, 20)
'rectf = New RectangleF(New PointF(0, 0), New
SizeF(Me.ClientRectangle.Width, Me.ClientRectangle.Height))

Dim msr As SizeF 'MeasureString Result

msr = grfx.MeasureString("aaa", bigfont)
grfx.FillRectangle(Brushes.LightBlue, 0, 0, msr.Width, msr.Height)
grfx.DrawString("aaaaaa", bigfont, Brushes.Black, 0, 0)

MyBase.OnPaint(e)

End Sub
End Class
 
I think that this code (in an OnPaint) ...

grfx.FillRectangle(Brushes.White, Me.ClientRectangle)
msr = grfx.MeasureString("aaa", bigfont) 'msr is Dimed as SizeF
grfx.FillRectangle(Brushes.LightBlue, 0, 0, msr.Width, msr.Height)
grfx.DrawString("aaaaaa", bigfont, Brushes.Black, 0, 0)

should result in aaa on a light blue background followed immediately by aaa
on the white background. Almost, but not quite. The light blue background,
or highlighting, extends beyond the first three a's, about halfway into the
fourth a. In other words, the combination of the MeasureString and
FillRectangle ends up Filling more Rectangle than it should. I'm using .NET
Framework 1.1 w/SP1.

(What I am trying to do is develop a control which supports highlighting
various strings, more than one at a time, in text.)

Does anyone have any idea what is going on here?

From the Remarks section at
<http://msdn2.microsoft.com/en-us/library/6xe5hazb.aspx>:

The MeasureString method is designed for use with individual strings
and includes a small amount of extra space before and after the string
to allow for overhanging glyphs. Also, the DrawString method adjusts
glyph points to optimize display quality and might display a string
narrower than reported by MeasureString. To obtain metrics suitable
for adjacent strings in layout (for example, when implementing
formatted text), use the MeasureCharacterRanges method or one of the
MeasureString methods that takes a StringFormat, and pass
GenericTypographic. Also, ensure the TextRenderingHint for the
Graphics is AntiAlias.
 
Jack Jackson said:
From the Remarks section at
<http://msdn2.microsoft.com/en-us/library/6xe5hazb.aspx>:

The MeasureString method is designed for use with individual strings
and includes a small amount of extra space before and after the string
to allow for overhanging glyphs. Also, the DrawString method adjusts
glyph points to optimize display quality and might display a string
narrower than reported by MeasureString. To obtain metrics suitable
for adjacent strings in layout (for example, when implementing
formatted text), use the MeasureCharacterRanges method or one of the
MeasureString methods that takes a StringFormat, and pass
GenericTypographic. Also, ensure the TextRenderingHint for the
Graphics is AntiAlias.

Jack, Thanks so much for you help. I feel sort of dumb for not finding that
myself. But I am surprised that such a major gotcha was not mentioned by my
Petzold book and did not turn up in my Google searches - probably because
most people know better than to play with text layout! Actually I may have
even seen it but dismissed it because it sounds so technical and I thought
probably did not apply to what I am doing because what I am doing (I
thought) was so straightforward and basic.

So far MeasureCharacterRanges is not working for me but I have more research
to do before asking for assistance.

Thanks again for your help, I really appreciate it.

Bob
 
Back
Top