lebb
05-26-2006, 04:46 PM
I've been trying to develop a reasonably accurate auto-sizing label control. The idea is that the control will have a fixed width, and will adjust its own height based on its contents. However, so far all my attempts are slightly off with some input strings (especially long ones) and widths. Can anyone spot the flaw in my approach or suggest a better method?
Public Class SmartSizeLabel
Inherits System.Windows.Forms.Label
Private _noReentry As Boolean = False
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
If Not _noReentry Then _SetBestHeight()
End Sub
Protected Overrides Sub OnStyleChanged(ByVal e As System.EventArgs)
MyBase.OnStyleChanged(e)
_SetBestHeight()
End Sub
Public Overrides Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal value As String)
MyBase.Text = value
_SetBestHeight()
End Set
End Property
Private Sub _SetBestHeight()
Dim gfx As Graphics = Me.CreateGraphics()
_SetBestHeight(gfx)
gfx.Dispose()
End Sub
Private Sub _SetBestHeight(ByVal gfx As Graphics)
Dim diff As Integer = Me.Height - Me.ClientSize.Height
_noReentry = True
Me.Height = Convert.ToInt32(_BestHeight(gfx)) + diff + Me.Margin.Top + Me.Margin.Bottom
_noReentry = False
End Sub
Private Function _BestHeight(ByVal gfx As Graphics) As Single
Dim srcSize As New SizeF(Me.ClientRectangle.Width, Single.MaxValue)
Dim bestSize As SizeF = gfx.MeasureString(Me.Text, Me.Font, srcSize, _
Drawing.StringFormat.GenericTypographic)
Return bestSize.Height
End Function
End Class
Note: For testing, I am setting the control's AutoSize property to False and BorderStyle to FixedSingle (just to be able to more clearly see the problems).
Public Class SmartSizeLabel
Inherits System.Windows.Forms.Label
Private _noReentry As Boolean = False
Protected Overrides Sub OnResize(ByVal e As System.EventArgs)
MyBase.OnResize(e)
If Not _noReentry Then _SetBestHeight()
End Sub
Protected Overrides Sub OnStyleChanged(ByVal e As System.EventArgs)
MyBase.OnStyleChanged(e)
_SetBestHeight()
End Sub
Public Overrides Property Text() As String
Get
Return MyBase.Text
End Get
Set(ByVal value As String)
MyBase.Text = value
_SetBestHeight()
End Set
End Property
Private Sub _SetBestHeight()
Dim gfx As Graphics = Me.CreateGraphics()
_SetBestHeight(gfx)
gfx.Dispose()
End Sub
Private Sub _SetBestHeight(ByVal gfx As Graphics)
Dim diff As Integer = Me.Height - Me.ClientSize.Height
_noReentry = True
Me.Height = Convert.ToInt32(_BestHeight(gfx)) + diff + Me.Margin.Top + Me.Margin.Bottom
_noReentry = False
End Sub
Private Function _BestHeight(ByVal gfx As Graphics) As Single
Dim srcSize As New SizeF(Me.ClientRectangle.Width, Single.MaxValue)
Dim bestSize As SizeF = gfx.MeasureString(Me.Text, Me.Font, srcSize, _
Drawing.StringFormat.GenericTypographic)
Return bestSize.Height
End Function
End Class
Note: For testing, I am setting the control's AutoSize property to False and BorderStyle to FixedSingle (just to be able to more clearly see the problems).