AutoSized, Wrapping RadioButton and CheckBox (VB)
The following RadioButton and CheckBox automatically text wrap when placed in a TableLayoutPanel or FlowLayoutPanel.
Imports System.Windows.Forms
Imports System.Collections
Imports System.Drawing
Imports System
Namespace Microsoft.Samples
Friend Class WrappingCheckBox
Inherits System.Windows.Forms.CheckBox
Dim cachedSizeOfOneLineOfText As System.Drawing.Size = System.Drawing.Size.Empty
Dim preferredSizeHash As New Dictionary(Of Size, Size)(3) ' testing this out - typically we've got three different constraints.
Friend Sub New()
MyBase.New()
Me.AutoSize = True
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
CacheTextSize()
End Sub
Protected Overrides Sub OnFontChanged(ByVal e As System.EventArgs)
MyBase.OnFontChanged(e)
CacheTextSize()
End Sub
Private Sub CacheTextSize()
'When the text has changed, the preferredSizeHash is invalid...
preferredSizeHash.Clear()
If String.IsNullOrEmpty(Me.Text) Then
cachedSizeOfOneLineOfText = System.Drawing.Size.Empty
Else
cachedSizeOfOneLineOfText = TextRenderer.MeasureText(Me.Text, Me.Font, New Size(Int32.MaxValue, Int32.MaxValue), TextFormatFlags.WordBreak)
End If
End Sub
Public Overrides Function getpreferredsize(ByVal proposedsize As System.Drawing.Size) As System.Drawing.Size
Dim prefSize As Size = MyBase.GetPreferredSize(proposedsize)
If (proposedsize.Width > 1) AndAlso (prefSize.Width > proposedsize.Width) AndAlso (Not String.IsNullOrEmpty(Me.Text) AndAlso Not proposedsize.Width.Equals(Int32.MaxValue) OrElse Not proposedsize.Height.Equals(Int32.MaxValue)) Then
' we have the possiblility of wrapping... back out the single line of text
Dim bordersAndPadding As Size = prefSize - cachedSizeOfOneLineOfText
' add back in the text size, subtract baseprefsize.width and 3 from proposed size width so they wrap properly
Dim newConstraints As Size = proposedsize - bordersAndPadding - New Size(3, 0)
If newConstraints.Width < 0 Then
newConstraints.Width = 0
End If
If newConstraints.Height < 0 Then
newConstraints.Height = 0
End If
If (Not preferredSizeHash.ContainsKey(newConstraints)) Then
prefSize = bordersAndPadding + TextRenderer.MeasureText(Me.Text, Me.Font, newConstraints, TextFormatFlags.WordBreak)
preferredSizeHash(newConstraints) = prefSize
Else
prefSize = preferredSizeHash(newConstraints)
End If
End If
Return prefSize
End Function
End Class
Friend Class WrappingRadioButton
Inherits System.Windows.Forms.RadioButton
Dim cachedSizeOfOneLineOfText As System.Drawing.Size = System.Drawing.Size.Empty
Dim preferredSizeHash As New Dictionary(Of Size, Size)(3) ' testing this out - typically we've got three different constraints.
Friend Sub New()
MyBase.New()
Me.AutoSize = True
End Sub
Protected Overrides Sub OnTextChanged(ByVal e As System.EventArgs)
MyBase.OnTextChanged(e)
CacheTextSize()
End Sub
Protected Overrides Sub OnFontChanged(ByVal e As System.EventArgs)
MyBase.OnFontChanged(e)
CacheTextSize()
End Sub
Private Sub CacheTextSize()
'When the text has changed, the preferredSizeHash is invalid...
preferredSizeHash.Clear()
If String.IsNullOrEmpty(Me.Text) Then
cachedSizeOfOneLineOfText = System.Drawing.Size.Empty
Else
cachedSizeOfOneLineOfText = TextRenderer.MeasureText(Me.Text, Me.Font, New Size(Int32.MaxValue, Int32.MaxValue), TextFormatFlags.WordBreak)
End If
End Sub
Public Overrides Function getpreferredsize(ByVal proposedsize As System.Drawing.Size) As System.Drawing.Size
Dim prefSize As Size = MyBase.GetPreferredSize(proposedsize)
If (proposedsize.Width > 1) AndAlso (prefSize.Width > proposedsize.Width) AndAlso (Not String.IsNullOrEmpty(Me.Text) AndAlso Not proposedsize.Width.Equals(Int32.MaxValue) OrElse Not proposedsize.Height.Equals(Int32.MaxValue)) Then
' NOTE: WinForm pass (1,0) to ask the default size of the control, when it hasn't got prefered Width. We should prefer to arrange everything in one line, but not break to multilines.
' we have the possiblility of wrapping... back out the single line of text
Dim bordersAndPadding As Size = prefSize - cachedSizeOfOneLineOfText
' add back in the text size, subtract baseprefsize.width and 3 from proposed size width so they wrap properly
Dim newConstraints As Size = proposedsize - bordersAndPadding - New Size(3, 0)
If newConstraints.Width < 0 Then
newConstraints.Width = 0
End If
If newConstraints.Height < 0 Then
newConstraints.Height = 0
End If
If (Not preferredSizeHash.ContainsKey(newConstraints)) Then
prefSize = bordersAndPadding + TextRenderer.MeasureText(Me.Text, Me.Font, newConstraints, TextFormatFlags.WordBreak)
preferredSizeHash(newConstraints) = prefSize
Else
prefSize = preferredSizeHash(newConstraints)
End If
End If
Return prefSize
End Function
End Class
End Namespace