tags:

views:

3077

answers:

6

Hi there,

I'd like to know if there's a better approach to this problem. I want to resize a label (vertically) to accomodate certain amount of text. My label has a fixed width (about 60 chars wide before it must wrap), about 495 pixels. The font is also a fixed size (12points afaik), but the text is not.

What I want to do is increase the Label Height when there's a "NewLine" or the text must wrap; the idea is that the text is fully visible in the label. The AutoSize doesn't work because it will grow in width, not in height.

Of course I could count the number of NewLines and add: Newlines * LineHeight, and then -given that I manage to put 60 chars per line, just divide the number of chars and add as many LineHeight pixels as needed.

I was wondering if there was a more professional way to do it. Is my approach too "lame" ?

Thanks in advance.

+6  A: 

Graphics.MeasureString() will probably help you.

This is also one of the only usecases for using the Control.CreateGraphics() call!

Quibblesome
+1 for the +1. :)
MusiGenesis
:) Thanks too. All the answers are great. Do i get anything in return for finding "one of the only usercases" ? ;)
Martín Marconcini
What is another use case for CreateGraphics? I can't think of any other.
MusiGenesis
I said "one of the only" just in case there is another but I think it is the only one. To be honest i'm only parroting Bob Powell's GDI FAQ.
Quibblesome
The only other one I can think of is for creating custom graphics that go away when you drag another window over them, but that's more of a mis-use case. :)
MusiGenesis
I can think of one other use, sort of: I wrote a double-buffered Canvas usercontrol that overrides the CreateGraphics method to return a Graphics object from the double buffer instead of the control itself. Not sure this counts, since it's an override.
MusiGenesis
Wait.. we can make a game that relies on the properties of your mis-use case. Like wack-a-mole but where you use windows to kill the moles! We have a second use case! :D
Quibblesome
+19  A: 

How about Graphics.MeasureString, with the overload that accepts a string, the font, and the max width? This returns a SizeF, so you can round round-off the Height.

        using(Graphics g = CreateGraphics()) {
            SizeF size = g.MeasureString(text, lbl.Font, 495);
            lbl.Height = (int) Math.Ceiling(size.Height);
            lbl.Text = text;
        }
Marc Gravell
That's what I get for adding detail.
MusiGenesis
Thank you, you won MusiGenesis by a few secs :) I wish I could tag both questions as Answer :S
Martín Marconcini
Code example FTW!
Quibblesome
@Quarrelsome - added, refresh ;-p
Marc Gravell
+1 from me, too, but c'mon! Math.Ceiling? Mouse, meet howitzer. :)
MusiGenesis
@MusiGenesis - it ensures we round up and don't lose any pixels. Regular int cast rounds down, but yes: we could just add one to be safe...
Marc Gravell
Great line, btw. Made me chuckle.
Marc Gravell
+12  A: 

System.Drawing.Graphics has a MeasureString method that you can use for this purpose. Use the overload that takes a string, a font, and an int "width" parameter; this last parameter specifies the maximum width allowed for the string - use the set width of your label for this parameter.

MeasureString returns a SizeF object. Use the Height property of this returned object to set the height of your label.

Note: to get a Graphics object for this purpose, you can call this.CreateGraphics.

MusiGenesis
There we go, +1 for detail :D
Quibblesome
Sure thing. :) This is ALSO the answer. I'll respect "Order of Arrival" but I appreciate your detail. Tyvm.
Martín Marconcini
To reduce the frustration, +1 from me too ;-p
Marc Gravell
Better late than never, another +1 for details.
Eric J.
A: 

Well the 60 chars might be valid for your test text, but not all characters have the same width. For instance, compare
llllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
and
wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

They both have 60 characters, and yet have vastly differing widths.

Yuliy
OP said it was fixed font, like courier new.
Quibblesome
Indeed, but I have a fixed font and measeure string will probably take care of this. Thanks.
Martín Marconcini
A: 

Is there any downside to using the TextRenderer class to measure the string (like in Marc's response) instead of going through the work to create a Graphics object, etc?

jean
TextRenderer is slower than Graphics.MeasureString. I have no idea why. They're both plenty fast for most use cases, however.
MusiGenesis
+1  A: 

This "answer" is for future reference and to combat the initial assumption that AutoSize = true implies that it (a WinForms label) will never grow in height.

The following link shows the various effects of AutoSize = true with other properties such as MaximumSize. Depending upon the expected use of the question it may be appropriate to follow one of these approaches.

http://blogs.msdn.com/jfoscoding/articles/478299.aspx

pst
Cool. Now I know why all the code I ever wrote to resize labels like this never worked quite right. I'd like to go back in time and slap myself, but I'd have trouble picking just one date to go back to.
MusiGenesis