 |
 |

05-26-2006, 04:46 PM
|
 |
Disillusioned Code Poet
Retired Moderator * Guru *
|
|
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
|
|
Text height calculation with wrapped text
|
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?
Code:
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).
|
__________________
Laura
Ita erat quando hic adveni.
|

05-27-2006, 08:45 PM
|
|
Senior Contributor
Forum Leader * Expert *
|
|
Join Date: Feb 2005
Location: London
Posts: 1,050
|
|
|
Try stringformat.default. If you use measurestring with the typographic version then it is probably wrapping/clipping the text in a different way to the control itself when it paints the text.
|
|

05-27-2006, 08:48 PM
|
 |
Disillusioned Code Poet
Retired Moderator * Guru *
|
|
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
|
|
|
Thanks jo0ls. I have tried with both methods, and can't tell much difference (it's possible that they're "off" in slightly different ways, but in any case neither is correct).
Any other thoughts?
|
__________________
Laura
Ita erat quando hic adveni.
|

05-27-2006, 08:57 PM
|
|
Senior Contributor
Forum Leader * Expert *
|
|
Join Date: Feb 2005
Location: London
Posts: 1,050
|
|
Ah, I had a small label.
If you override OnPaint too, then you can definately get them matching.
Code:
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), Me.Bounds, StringFormat.GenericTypographic)
End Sub
|
|

05-27-2006, 09:34 PM
|
 |
Disillusioned Code Poet
Retired Moderator * Guru *
|
|
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
|
|
|
*scratches head*
If I use Me.Bounds, then the calculations don't seem to work at all -- why would I use that instead of Me.ClientRectangle?
I've tried this with just adding your suggestion as-is, with changing your Me.Bounds to Me.ClientRectangle, and with changing my Me.ClientRectangle to Me.Bounds. With both as ClientRectangle, I get the same results as previously. With either of the other two combinations, they are even more wrong than they were before.
Am I misunderstanding something in your suggestion?
|
__________________
Laura
Ita erat quando hic adveni.
|

05-28-2006, 04:57 AM
|
|
Senior Contributor
Forum Leader * Expert *
|
|
Join Date: Feb 2005
Location: London
Posts: 1,050
|
|
|
Argh, I was convinced it was working, it was very late though. I was doing something similar a while ago. I'll have another look.
|
Last edited by jo0ls; 05-28-2006 at 06:29 AM.
|

05-28-2006, 06:42 AM
|
|
Senior Contributor
Forum Leader * Expert *
|
|
Join Date: Feb 2005
Location: London
Posts: 1,050
|
|
The height needs rounding up, and then paint the text with a matching stringformat.
Code:
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, StringFormat.GenericTypographic)
Return Math.Ceiling(bestSize.Height)
End Function
Protected Overrides Sub OnPaint(ByVal e As System.Windows.Forms.PaintEventArgs)
e.Graphics.DrawString(Me.Text, Me.Font, New SolidBrush(Me.ForeColor), _
New RectangleF(0, 0, Me.ClientSize.Width, Me.ClientSize.Height), _
StringFormat.GenericTypographic)
End Sub
|
|

05-28-2006, 06:36 PM
|
 |
Disillusioned Code Poet
Retired Moderator * Guru *
|
|
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
|
|
You've done it! Thanks so much, jo0ls -- I hadn't even considered the rounding issue. With a little tweaking to account for margins, this is perfect. 
|
__________________
Laura
Ita erat quando hic adveni.
|

05-29-2006, 12:01 AM
|
 |
Disillusioned Code Poet
Retired Moderator * Guru *
|
|
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
|
|
In case it's of interest to anyone else, here is the final solution I ended up with. As best I can tell, this works fine for any border style or margin combination.
Thanks again for all your help.
|
__________________
Laura
Ita erat quando hic adveni.
|
|
Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
|
|
|
| Thread Tools |
|
|
| Display Modes |
Linear Mode
|
Posting Rules
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
HTML code is Off
|
|
|
|
|
|
|
|
 |
|