Translate

Saturday, September 6, 2008

Change Height of TextBoxes Using Font Size

Download sample code

I had a c# project that required a single-line text box with adjustable height. I found many examples of how to adjust the width, but nothing on how to dynamically change the height of a text box. I did not want to use multi-line because I wanted to use the auto-complete features of the single-line text box.

Single-line textbox height is set by the size of the font, not the TextBox.Height property. This makes it difficult if you are looking for an exact height. Luckily, the font property uses a float for the font size (emSize). You can use fractions of fonts to fine-tune the textbox height.

The calculation the textbox uses to determine its height is:

Height
= ( Font Size * Font Line Spacing / Font Em Height ) + 7
  • Font Size - It is easiest to measure font in pixels so you do not have to factor in screen dpi.
  • Font Line Spacing - The distance, in design units, between two consecutive lines of text.
  • Font Em Height - height, in design units of the font's widest letter - typically the letter M.
Text boxes have a 3-pixel lower and 4-pixel upper white space around the font height. Therefore, the calculation adjusts the height by 7 pixels.

We can reverse this calculation to obtain the font size needed for a desired height:

Font Size
= ( height - 7 ) * Font Em Height / Font Line Spacing

This method will return a font object that will set the size of your text box:



private Font GetFontForTextBoxHeight(int TextBoxHeight)
{
// What is the target size of the text box?
float desiredheight = (float)TextBoxHeight;

// Set the font from the existing TextBox font.
// We use the fnt = new Font(...) method so we can ensure that
// we're setting the GraphicsUnit to Pixels. This avoids all
// the DPI conversions between point & pixel.
Font fnt = new Font(textBox1.Font.FontFamily,
textBox1.Font.Size,
textBox1.Font.Style,
GraphicsUnit.Pixel);

// TextBoxes never size below 8 pixels. This consists of the
// 4 pixels above & 3 below of whitespace, and 1 pixel line of
// greeked text.
if (desiredheight < 8)
desiredheight = 8;

// Determine the Em sizes of the font and font line spacing
// These values are constant for each font at the given font style.
// and screen DPI.
float FontEmSize = fnt.FontFamily.GetEmHeight(fnt.Style);
float FontLineSpacing = fnt.FontFamily.GetLineSpacing(fnt.Style);

// emSize is the target font size. TextBoxes have a total of
// 7 pixels above and below the FontHeight of the font.
float emSize = (desiredheight - 7) * FontEmSize / FontLineSpacing;

// Create the font, with the proper size to change the TextBox Height to the desired size.
fnt = new Font(fnt.FontFamily, emSize, fnt.Style, GraphicsUnit.Pixel);

return fnt;
}

Whenever you have to set the textbox size, set the font property using the above method:

TextBox.Font = GetFontForTextBoxHeight(int TextBoxHeight)

No comments: