views:

413

answers:

3

I have a series of buttons that display filenames. If I set the Text property when the filename is wider than the number of pixels available the text "wraps" and instead if the text being displayed LeftMiddle it is displayed LeftTop. Therefore I only display as many characters as can be shown (using the PathCompactPathEx() method).

However - How can I tell how many pixels are available? My current approach is:

button.Width - button.Image.Width - button.Padding.Horizontal

This doesn't always work and sometimes the text still wraps.

Any clues as to what the correct way of determining the number of pixels available for text is?

A: 

Maybe you could use a monospaced font as Courier, if you determine the pixel's width of each char, then you just need to take care of not exceed your TextBox width

Hope this helps

Rulas
The question was how to calculated the space available in a button for the text.FYI - see comment above. There is no need to use a monospaced font, you can use methods to determine how wide a string is for any font.
JohnBarton
+2  A: 

You can use Graphics.MeasureString to determine the actual number of pixels used by a particular piece of text using a particular font.
There is also Graphics.MeasureCharacterRanges which I believe may be more accurate for text alignment but I've not personally used it.

zebrabox
Apologies - I already know wide the string is - I am looking for how to determine the number of pixels AVAILABLE in the button - so I can then determine how many characters to draw. The code comment in my question shows how I am currently calculating the space available, but this doesn't always work as the text still wraps.FYI - TextRenderer.MeasureText() is preferable to the methods in the Graphics class as it takes into account DPI settings.
JohnBarton
+2  A: 

The best approach you can get is to subscribe to Paint event (or make Button descendant and override OnPaint), and draw string the following way:

private void OnPaint(object sender, PaintEventArgs)
{
    Button SenderButton = (Button)sender;
    Rectangle TextRect = SenderButton.ClientRectangle;
    TextRect.Inflate(-10, -5); // You can use any rectangle you want
    // To avoid internal Button text drawing, assign "" to Button.Text, and use Tag instead
    string Text = (string)SenderButton.Tag;
    e.Graphics.DrawText(e.Graphics, Text, SenderButton.Font, TextRect, SenderButton.ForeColor,
        TextFormatFlags.PathEllipsis | TextFormatFlags.NoPrefix);
}

This is the only method that guaranteed that you never have wrapping again. Any width measurement (including MeasureString) may differ from internal Button painting processing, and as result you will have wrapping.

arbiter
Yes, I suppose I could - given that I know approximately the space available (see question). I am still curious as why TextRenderer.MeasureText() may differ to the internal Button painting processing... Surely the number of pixels available for text in a button must be able to be calculated?
JohnBarton
Because button can paint text in different ways. For example when FlatStyle == System, then text is painted by system, if FlatStyle == Default, then text painting is depend on UseCompatibleTextRendering property, and so on. You also do not know text margins that used by button class in different paint modes.
arbiter
Thanks for taking the time to answer the question, much appreciated.
JohnBarton