WinForms FAQ - Fonts

MeasureString seems to have problems with white space and punctuation. Is there a better method to use

Try calling one of the overloads of MeasureString that takes an StringFormat parameter and pass it StringFormat.GenericTypographic. Here is some code that shows the same string and font giving different results depending upon the StringFormat parameter.

StringFormat sf = new  StringFormat(StringFormat.GenericTypographic);

SizeF size =  e.Graphics.MeasureString('this has some words', Font, 500, sf);
SizeF size1 = e.Graphics.MeasureString('this has some words', Font);
string s = string.Format('GenericTypographic={0:f2}   GenericDefault={1:f2}', size.Width, size1.Width);
MessageBox.Show(s);
Permalink
How do I display adjacent text

Check out this article by David C. Brown of the Windows Forms team at windowsforms.net. It discusses several reasons why you GDI+ output may lok differently that GDI output. One of the topics discussed is how to draw adjacent text.

Permalink
When I try to set a particular font style, say italics, I get an error message ‘Property cannot be assigned to — it is read only’. How can I set this read only property

Code such as

	tabControl1.Font.Italic = true;

will not work. Instead, you have to create a new Font object, and set the property during its creation. This code will work.

	tabControl1.Font = new Font(tabControl1.Font, FontStyle.Italic);
Permalink
How can I draw font samples from the available fonts

James DeBroeck of Microsoft gave this response on the microsoft.public.dotnet.framework.windowsforms.

Here is some C# OnPaint code that will show you how to use FontFamily to get a list of fonts:

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
    int i, nCount;
    SolidBrush  b = new SolidBrush( Color.Black );
    int x = 0, y = 0;

    nCount = FontFamily.Families.Length;
    
    for(i=0;i<nCount;i++)
    {
        FontStyle fs = FontStyle.Regular;
        Font f;
        string StylesDesc = '';

        if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Regular))
            StylesDesc += 'Regular ';
        else if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Italic))
        {
            fs = FontStyle.Italic;
            StylesDesc += 'Italic ';
        }
        else if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Bold))
        {
            fs = FontStyle.Bold;
            StylesDesc += 'Bold ';
        }
        else if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Underline))
        {
            fs = FontStyle.Underline;
            StylesDesc += 'Underline ';
        }
        else if (FontFamily.Families[i].IsStyleAvailable(FontStyle.Strikeout))
        {
            fs = FontStyle.Strikeout;
            StylesDesc += 'Strikeout ';
        }

        if (StylesDesc.Length > 0)
	    StylesDesc = StylesDesc.Substring(0,StylesDesc.Length-1);

        f = new Font( FontFamily.Families[i].Name, 12, fs);

        String s = FontFamily.Families[i].Name + ' ' + StylesDesc;
        e.Graphics.DrawString( s, f, b, x, y );
        y += f.Height;

    }
}
Permalink
How can I fill a combobox with available fonts

Try

	comboBox1.Items.AddRange(FontFamily.Families);
Permalink
How do I set the font for a control

Use the Font property for the control along with the Font class in the System.Drawing class.

	button1.Font = new Font ('Courier', 10, FontStyle.Bold);
Permalink
How can I draw a single line of text with different fonts using DrawString

The key is that you have to calculate the ascent height of the font. The font ascent as reported by FontFamily.GetCellAscent is in what is called ’Design Units’. The Cell Spacing design unit value of fonts is proportional to the actual height of the font on the device. We use this relationship to calculate cell ascent in device units.

The rendering code has to just ensure that the x, y position passed to DrawString takes care of the ascent.

	private void HandlePaint(object sender, PaintEventArgs args)
	{
		// clear the background
		Graphics g = args.Graphics;
		g.Clear(Color.AliceBlue);
		
		// create a pen
		Pen pen = new Pen(Color.Red, 1f);
		
		// the string to be drawn
		string s = 'Side by side';
		
		// the first font
		Font f1 = new Font('Arial', 10f);
		float strWidth1 = g.MeasureString(s, f1).Width;
		float fontHeight1 = f1.GetHeight(g);	
		float fontAscentHeight1 = (fontHeight1/f1.FontFamily.GetLineSpacing(f1.Style))*f1.FontFamily.GetCellAscent(f1.Style);
			
		// the second font
		Font f2 = new Font('Times New Roman', 48);
			float fontHeight2 = f2.GetHeight(g);	
			float fontAscentHeight2 = (fontHeight2/f2.FontFamily.GetLineSpacing(f2.Style))*f2.FontFamily.GetCellAscent(f2.Style);

		// draw the base line	
		Point ptStart = new Point(0, this.ClientSize.Height/2);
		Point ptEnd = new Point(this.ClientSize.Width, this.ClientSize.Height/2);
		g.DrawLine(Pens.Black, ptStart, ptEnd);
	
		// draw string with first font
		g.DrawString(s, f1, Brushes.Red, new PointF(0, ptStart.Y - fontAscentHeight1));
		// draw string with second font
		g.DrawString(s, f2, Brushes.Red, new PointF(strWidth1, ptStart.Y - fontAscentHeight2));
	}
Permalink