Go Back  Xtreme Visual Basic Talk > Visual Basic .NET (2002/2003/2005/2008, including Express editions) > .NET Interface and Graphics > Text height calculation with wrapped text


Reply
 
Thread Tools Display Modes
  #1  
Old 05-26-2006, 04:46 PM
lebb's Avatar
lebb lebb is offline
Disillusioned Code Poet

Retired Moderator
* Guru *
 
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
Default 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.
Reply With Quote
  #2  
Old 05-27-2006, 08:45 PM
jo0ls jo0ls is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Feb 2005
Location: London
Posts: 1,050
Default

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.
Reply With Quote
  #3  
Old 05-27-2006, 08:48 PM
lebb's Avatar
lebb lebb is offline
Disillusioned Code Poet

Retired Moderator
* Guru *
 
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
Default

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.
Reply With Quote
  #4  
Old 05-27-2006, 08:57 PM
jo0ls jo0ls is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Feb 2005
Location: London
Posts: 1,050
Default

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
Reply With Quote
  #5  
Old 05-27-2006, 09:34 PM
lebb's Avatar
lebb lebb is offline
Disillusioned Code Poet

Retired Moderator
* Guru *
 
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
Default

*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.
Reply With Quote
  #6  
Old 05-28-2006, 04:57 AM
jo0ls jo0ls is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Feb 2005
Location: London
Posts: 1,050
Default

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.
Reply With Quote
  #7  
Old 05-28-2006, 06:42 AM
jo0ls jo0ls is offline
Senior Contributor

Forum Leader
* Expert *
 
Join Date: Feb 2005
Location: London
Posts: 1,050
Default

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
Reply With Quote
  #8  
Old 05-28-2006, 06:36 PM
lebb's Avatar
lebb lebb is offline
Disillusioned Code Poet

Retired Moderator
* Guru *
 
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
Default

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.
Reply With Quote
  #9  
Old 05-29-2006, 12:01 AM
lebb's Avatar
lebb lebb is offline
Disillusioned Code Poet

Retired Moderator
* Guru *
 
Join Date: Apr 2002
Location: Tennessee, USA
Posts: 12,808
Default

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.
Reply With Quote
Reply


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off

Forum Jump

Advertisement:





Free Publications
The ASP.NET 2.0 Anthology
101 Essential Tips, Tricks & Hacks - Free 156 Page Preview. Learn the most practical features and best approaches for ASP.NET.
subscribe
Programmers Heaven C# School Book -Free 338 Page eBook
The Programmers Heaven C# School book covers the .NET framework and the C# language.
subscribe
Build Your Own ASP.NET 3.5 Web Site Using C# & VB, 3rd Edition - Free 219 Page Preview!
This comprehensive step-by-step guide will help get your database-driven ASP.NET web site up and running in no time..
subscribe
 
 
-->