Post: [Tutorial] C# Embedded Fonts by FarSideX (Requested)
03-21-2014, 05:12 AM #1
FarSideX
I’m too L33T
(adsbygoogle = window.adsbygoogle || []).push({});
You must login or register to view this content.


Title: C# Embedded Fonts Tutorial

Purpose: To explain the use of embedded fonts in a .NET environment. Other on line tutorials do not function as intended including MicroSoft's own documentation, unless used in native code. It also shows my technique of using the designer when laying out drawn text.

Target Audience: Advanced Beginner

Prerequisites: Knowledge of basic programming terms, techniques, Visual Studio and basic reading comprehension. Ability to install and remove system fonts.

Tools required: MS Visual Studio (2012 minimum to open project)

Other resources: Font used in sample project is Meath by the defunct company Casady & Greene Inc. Downloaded from You must login or register to view this content..

The fully commented source project may be downloaded at the bottom of the page for further information. I recommend you follow the tutorial to build the project yourself for better understanding of the concepts used. Remember you won't learn anything by just copy/pasting. None of the concepts will be described in great detail but can be upon request.

Install the custom font you wish to use on your system. (You will be removing it later for testing)

Open a new C# WinForms project in Visual Studio.

In the default form that VS creates add a few labels, as many as you like as the code will be the same regardless to the number of labels.

Set these labels up with the font, font style, size and colour of your choosing. For demonstration purposes leave at least one label with all default font info.

Set the Visible property of all the labels that will be using the embedded font to false. (This is how we will know which labels to change the font on at runtime)

Now add the font file to the project and set its Build Action property to 'Embedded Resource'.

We will be using these namespaces so make sure you have them, delete the ones you don't need.
    using System;                       // IntPtr and EventArgs
using System.Drawing; // Font and PointF
using System.Drawing.Text; // PrivateFontCollection
using System.Windows.Forms; // Form inheritance
using System.IO; // Stream
using System.Reflection; // Assembly
using System.Linq; // OfType
If you don't like using Linq you can remove it and just add an if statement in the PaintEventHandler. Probably a good idea if you have a lot of labels.

Either add a new class file called MyGlobals.cs (or whatever) to the project or add this after the Form1 class.
        static class MyGlobal    
{
private static PrivateFontCollection _pfc;


public static PrivateFontCollection pfc
{
get { return _pfc; }
set { _pfc = value; }
}
} // end of MyGlobal class
By keeping the PFC in a static class it can be accessed by more than one form.

Next we need to setup a Load event handler so the font can be read into the PFC, add this to Form1's constructor:
    this.Load += new System.EventHandler(this.onLoadEvent);
Once the EventHandler has been added the actual handler needs to be added:
    private void onLoadEvent(object sender, EventArgs e)
{
MyGlobal.pfc = new PrivateFontCollection();

Assembly assembly = Assembly.GetExecutingAssembly();

string assemblyName = assembly.FullName.Substring(0, assembly.FullName.IndexOf(","));

string fontFname = "MeathFLF.ttf"; // use the name of the file you embedded.

Stream fontStrm = assembly.GetManifestResourceStream( assemblyName + "." + fontFname );

byte[] fdata = new byte[fontStrm.Length];

fontStrm.Read(fdata, 0, (int)fontStrm.Length);
fontStrm.Close();
fontStrm.Dispose();

unsafe // Why I hate C# sometimes
{
fixed (byte* pFontData = fdata)
{
MyGlobal.pfc.AddMemoryFont((IntPtr)pFontData, fdata.Length);
}
} // end of unsafe code

this.Paint += new System.Windows.Forms.PaintEventHandler(this.onPaintEvent);

} // End of onLoadEvent
The above code is fully commented in the downloadable project.

To go over it quickly, it first initializes an instance of PrivateFontCollection for our static class. Then uses reflection to get the current assembly (us). Since we have the assembly any way the assembly name is pulled from it rather than hard coding the name. The string 'fontName' is the name of the font you embedded into your project, it is case sensitive so get it right! A Stream is created to read the embedded resource into a byte array. Once read, the stream is disposed of.

Next we have a small 'unsafe' block, I could rage for days about how stupid 'unsafe' is but I'll try not to. They should have called it notNoobFriendly or something. An unsafe block does nothing except make you type it out to allow pointer use, that's it! The reason C became popular; it was a high level language that allowed low level control mostly due to pointers, C sharp should have been called D flat, same thing just not C.

But I digress, the fixed block tells the .NET VM to not move our byte array 'fdata' around in memory, it 'fixes' it place. It also creates a byte pointer to the data in memory. A call to pfc's AddMemoryFont is made with the arguments of the pointer cast to an int* called a 'IntPtr' and the length of the data. We now have our font ready to use.

Because the font can not be added to the system memory fonts it can not be used like a a regular font. It's a managed/unmanaged code thing I believe. So, we need to create a PaintEventHandler and draw the font ourselves (this is why we have the labels hidden at runtime, we don't actually need them but it makes design easier)

The Paint EventHandler:
    private void onPaintEvent(object sender, PaintEventArgs e){
foreach (Label lbl in this.Controls.OfType<Label>())
{
if (lbl.Visible == false)
{
using (Font myEmbeddedFont = new Font(MyGlobal.pfc.Families[0], lbl.Font.Size, lbl.Font.Style))
{
PointF myPointF = new PointF(lbl.Location.X, lbl.Location.Y);

if (lbl.Font.Size > 10)
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
else
e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault;

SolidBrush myBrush = new SolidBrush(lbl.ForeColor);

e.Graphics.DrawString(lbl.Text, myEmbeddedFont, myBrush, myPointF);
}
} // end of if Visible
} // end of foreach
} // end of onPaintEvent
This a PaintEvenHandler for Form1, it does not handle paint events for nested containers. If you use the embedded font in a nested container you will need to add a PaintEventHandler for the containers. Or better yet use the sender object to determine the ControlCollection for the foreach, then just reuse the same Handler. (something for another day)

So here we loop through all the labels on the form checking their Visible property (remember we had set it to false if we want to use the private font).

A new font is created with the properties set on the label in the designer. This is where MS made a mistake, Font() has an overload that takes the font name, but it only works with System Fonts not private fonts. When using a PrivateFontCollection the only override that works is the one that takes a FontFamily as its first argument. Sometimes the documentation is just wrong! That's when you have to look at .NET's source code.

A PointF is created using the label's location. AntiAlias is turned on for larger fonts (optional) and a brush is created using the colour from the label. Finally the text from the label is used for the DrawString method.

Before you can compile this you have to go into the project's properties and check 'Allow unsafe code' (Oh how I rage). Now compile and run the code. Debug any typos that you may have. Once you have it running uninstall the font to test that it is using the embedded font and not the system font.

For further learning:
Make a second form open and use the font on that.
Modify the Paint EventHandler to use 'sender' rather than 'this' and connect one handler to nested containers.
Add a second font.

Don't go crazy with too many different fonts on the same form, rule of thumb should be two fonts per form. Well that's what they taught me in typesetting any ways.


You must login or register to view this content.

Virus Scan.. Em, it's source code.
(adsbygoogle = window.adsbygoogle || []).push({});

The following 6 users say thank you to FarSideX for this useful post:

One, Kappa, BaSs_HaXoR, BrunoBlak, Exploited, Xcesar1911X
04-01-2014, 11:49 PM #2
Originally posted by FarSideX View Post
You must login or register to view this content.


Title: C# Embedded Fonts Tutorial

Purpose: To explain the use of embedded fonts in a .NET environment. Other on line tutorials do not function as intended including MicroSoft's own documentation, unless used in native code. It also shows my technique of using the designer when laying out drawn text.

Target Audience: Advanced Beginner

Prerequisites: Knowledge of basic programming terms, techniques, Visual Studio and basic reading comprehension. Ability to install and remove system fonts.

Tools required: MS Visual Studio (2012 minimum to open project)

Other resources: Font used in sample project is Meath by the defunct company Casady & Greene Inc. Downloaded from You must login or register to view this content..

The fully commented source project may be downloaded at the bottom of the page for further information. I recommend you follow the tutorial to build the project yourself for better understanding of the concepts used. Remember you won't learn anything by just copy/pasting. None of the concepts will be described in great detail but can be upon request.

Install the custom font you wish to use on your system. (You will be removing it later for testing)

Open a new C# WinForms project in Visual Studio.

In the default form that VS creates add a few labels, as many as you like as the code will be the same regardless to the number of labels.

Set these labels up with the font, font style, size and colour of your choosing. For demonstration purposes leave at least one label with all default font info.

Set the Visible property of all the labels that will be using the embedded font to false. (This is how we will know which labels to change the font on at runtime)

Now add the font file to the project and set its Build Action property to 'Embedded Resource'.

We will be using these namespaces so make sure you have them, delete the ones you don't need.
    using System;                       // IntPtr and EventArgs
using System.Drawing; // Font and PointF
using System.Drawing.Text; // PrivateFontCollection
using System.Windows.Forms; // Form inheritance
using System.IO; // Stream
using System.Reflection; // Assembly
using System.Linq; // OfType
If you don't like using Linq you can remove it and just add an if statement in the PaintEventHandler. Probably a good idea if you have a lot of labels.

Either add a new class file called MyGlobals.cs (or whatever) to the project or add this after the Form1 class.
        static class MyGlobal    
{
private static PrivateFontCollection _pfc;


public static PrivateFontCollection pfc
{
get { return _pfc; }
set { _pfc = value; }
}
} // end of MyGlobal class
By keeping the PFC in a static class it can be accessed by more than one form.

Next we need to setup a Load event handler so the font can be read into the PFC, add this to Form1's constructor:
    this.Load += new System.EventHandler(this.onLoadEvent);
Once the EventHandler has been added the actual handler needs to be added:
    private void onLoadEvent(object sender, EventArgs e)
{
MyGlobal.pfc = new PrivateFontCollection();

Assembly assembly = Assembly.GetExecutingAssembly();

string assemblyName = assembly.FullName.Substring(0, assembly.FullName.IndexOf(","));

string fontFname = "MeathFLF.ttf"; // use the name of the file you embedded.

Stream fontStrm = assembly.GetManifestResourceStream( assemblyName + "." + fontFname );

byte[] fdata = new byte[fontStrm.Length];

fontStrm.Read(fdata, 0, (int)fontStrm.Length);
fontStrm.Close();
fontStrm.Dispose();

unsafe // Why I hate C# sometimes
{
fixed (byte* pFontData = fdata)
{
MyGlobal.pfc.AddMemoryFont((IntPtr)pFontData, fdata.Length);
}
} // end of unsafe code

this.Paint += new System.Windows.Forms.PaintEventHandler(this.onPaintEvent);

} // End of onLoadEvent
The above code is fully commented in the downloadable project.

To go over it quickly, it first initializes an instance of PrivateFontCollection for our static class. Then uses reflection to get the current assembly (us). Since we have the assembly any way the assembly name is pulled from it rather than hard coding the name. The string 'fontName' is the name of the font you embedded into your project, it is case sensitive so get it right! A Stream is created to read the embedded resource into a byte array. Once read, the stream is disposed of.

Next we have a small 'unsafe' block, I could rage for days about how stupid 'unsafe' is but I'll try not to. They should have called it notNoobFriendly or something. An unsafe block does nothing except make you type it out to allow pointer use, that's it! The reason C became popular; it was a high level language that allowed low level control mostly due to pointers, C sharp should have been called D flat, same thing just not C.

But I digress, the fixed block tells the .NET VM to not move our byte array 'fdata' around in memory, it 'fixes' it place. It also creates a byte pointer to the data in memory. A call to pfc's AddMemoryFont is made with the arguments of the pointer cast to an int* called a 'IntPtr' and the length of the data. We now have our font ready to use.

Because the font can not be added to the system memory fonts it can not be used like a a regular font. It's a managed/unmanaged code thing I believe. So, we need to create a PaintEventHandler and draw the font ourselves (this is why we have the labels hidden at runtime, we don't actually need them but it makes design easier)

The Paint EventHandler:
    private void onPaintEvent(object sender, PaintEventArgs e){
foreach (Label lbl in this.Controls.OfType<Label>())
{
if (lbl.Visible == false)
{
using (Font myEmbeddedFont = new Font(MyGlobal.pfc.Families[0], lbl.Font.Size, lbl.Font.Style))
{
PointF myPointF = new PointF(lbl.Location.X, lbl.Location.Y);

if (lbl.Font.Size > 10)
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
else
e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault;

SolidBrush myBrush = new SolidBrush(lbl.ForeColor);

e.Graphics.DrawString(lbl.Text, myEmbeddedFont, myBrush, myPointF);
}
} // end of if Visible
} // end of foreach
} // end of onPaintEvent
This a PaintEvenHandler for Form1, it does not handle paint events for nested containers. If you use the embedded font in a nested container you will need to add a PaintEventHandler for the containers. Or better yet use the sender object to determine the ControlCollection for the foreach, then just reuse the same Handler. (something for another day)

So here we loop through all the labels on the form checking their Visible property (remember we had set it to false if we want to use the private font).

A new font is created with the properties set on the label in the designer. This is where MS made a mistake, Font() has an overload that takes the font name, but it only works with System Fonts not private fonts. When using a PrivateFontCollection the only override that works is the one that takes a FontFamily as its first argument. Sometimes the documentation is just wrong! That's when you have to look at .NET's source code.

A PointF is created using the label's location. AntiAlias is turned on for larger fonts (optional) and a brush is created using the colour from the label. Finally the text from the label is used for the DrawString method.

Before you can compile this you have to go into the project's properties and check 'Allow unsafe code' (Oh how I rage). Now compile and run the code. Debug any typos that you may have. Once you have it running uninstall the font to test that it is using the embedded font and not the system font.

For further learning:
Make a second form open and use the font on that.
Modify the Paint EventHandler to use 'sender' rather than 'this' and connect one handler to nested containers.
Add a second font.

Don't go crazy with too many different fonts on the same form, rule of thumb should be two fonts per form. Well that's what they taught me in typesetting any ways.


You must login or register to view this content.

Virus Scan.. Em, it's source code.


Happy Thanks bro.
04-05-2014, 02:39 PM #3
Originally posted by FarSideX View Post
You must login or register to view this content.


Title: C# Embedded Fonts Tutorial

Purpose: To explain the use of embedded fonts in a .NET environment. Other on line tutorials do not function as intended including MicroSoft's own documentation, unless used in native code. It also shows my technique of using the designer when laying out drawn text.

Target Audience: Advanced Beginner

Prerequisites: Knowledge of basic programming terms, techniques, Visual Studio and basic reading comprehension. Ability to install and remove system fonts.

Tools required: MS Visual Studio (2012 minimum to open project)

Other resources: Font used in sample project is Meath by the defunct company Casady & Greene Inc. Downloaded from You must login or register to view this content..

The fully commented source project may be downloaded at the bottom of the page for further information. I recommend you follow the tutorial to build the project yourself for better understanding of the concepts used. Remember you won't learn anything by just copy/pasting. None of the concepts will be described in great detail but can be upon request.

Install the custom font you wish to use on your system. (You will be removing it later for testing)

Open a new C# WinForms project in Visual Studio.

In the default form that VS creates add a few labels, as many as you like as the code will be the same regardless to the number of labels.

Set these labels up with the font, font style, size and colour of your choosing. For demonstration purposes leave at least one label with all default font info.

Set the Visible property of all the labels that will be using the embedded font to false. (This is how we will know which labels to change the font on at runtime)

Now add the font file to the project and set its Build Action property to 'Embedded Resource'.

We will be using these namespaces so make sure you have them, delete the ones you don't need.
    using System;                       // IntPtr and EventArgs
using System.Drawing; // Font and PointF
using System.Drawing.Text; // PrivateFontCollection
using System.Windows.Forms; // Form inheritance
using System.IO; // Stream
using System.Reflection; // Assembly
using System.Linq; // OfType
If you don't like using Linq you can remove it and just add an if statement in the PaintEventHandler. Probably a good idea if you have a lot of labels.

Either add a new class file called MyGlobals.cs (or whatever) to the project or add this after the Form1 class.
        static class MyGlobal    
{
private static PrivateFontCollection _pfc;


public static PrivateFontCollection pfc
{
get { return _pfc; }
set { _pfc = value; }
}
} // end of MyGlobal class
By keeping the PFC in a static class it can be accessed by more than one form.

Next we need to setup a Load event handler so the font can be read into the PFC, add this to Form1's constructor:
    this.Load += new System.EventHandler(this.onLoadEvent);
Once the EventHandler has been added the actual handler needs to be added:
    private void onLoadEvent(object sender, EventArgs e)
{
MyGlobal.pfc = new PrivateFontCollection();

Assembly assembly = Assembly.GetExecutingAssembly();

string assemblyName = assembly.FullName.Substring(0, assembly.FullName.IndexOf(","));

string fontFname = "MeathFLF.ttf"; // use the name of the file you embedded.

Stream fontStrm = assembly.GetManifestResourceStream( assemblyName + "." + fontFname );

byte[] fdata = new byte[fontStrm.Length];

fontStrm.Read(fdata, 0, (int)fontStrm.Length);
fontStrm.Close();
fontStrm.Dispose();

unsafe // Why I hate C# sometimes
{
fixed (byte* pFontData = fdata)
{
MyGlobal.pfc.AddMemoryFont((IntPtr)pFontData, fdata.Length);
}
} // end of unsafe code

this.Paint += new System.Windows.Forms.PaintEventHandler(this.onPaintEvent);

} // End of onLoadEvent
The above code is fully commented in the downloadable project.

To go over it quickly, it first initializes an instance of PrivateFontCollection for our static class. Then uses reflection to get the current assembly (us). Since we have the assembly any way the assembly name is pulled from it rather than hard coding the name. The string 'fontName' is the name of the font you embedded into your project, it is case sensitive so get it right! A Stream is created to read the embedded resource into a byte array. Once read, the stream is disposed of.

Next we have a small 'unsafe' block, I could rage for days about how stupid 'unsafe' is but I'll try not to. They should have called it notNoobFriendly or something. An unsafe block does nothing except make you type it out to allow pointer use, that's it! The reason C became popular; it was a high level language that allowed low level control mostly due to pointers, C sharp should have been called D flat, same thing just not C.

But I digress, the fixed block tells the .NET VM to not move our byte array 'fdata' around in memory, it 'fixes' it place. It also creates a byte pointer to the data in memory. A call to pfc's AddMemoryFont is made with the arguments of the pointer cast to an int* called a 'IntPtr' and the length of the data. We now have our font ready to use.

Because the font can not be added to the system memory fonts it can not be used like a a regular font. It's a managed/unmanaged code thing I believe. So, we need to create a PaintEventHandler and draw the font ourselves (this is why we have the labels hidden at runtime, we don't actually need them but it makes design easier)

The Paint EventHandler:
    private void onPaintEvent(object sender, PaintEventArgs e){
foreach (Label lbl in this.Controls.OfType<Label>())
{
if (lbl.Visible == false)
{
using (Font myEmbeddedFont = new Font(MyGlobal.pfc.Families[0], lbl.Font.Size, lbl.Font.Style))
{
PointF myPointF = new PointF(lbl.Location.X, lbl.Location.Y);

if (lbl.Font.Size > 10)
e.Graphics.TextRenderingHint = TextRenderingHint.AntiAlias;
else
e.Graphics.TextRenderingHint = TextRenderingHint.SystemDefault;

SolidBrush myBrush = new SolidBrush(lbl.ForeColor);

e.Graphics.DrawString(lbl.Text, myEmbeddedFont, myBrush, myPointF);
}
} // end of if Visible
} // end of foreach
} // end of onPaintEvent
This a PaintEvenHandler for Form1, it does not handle paint events for nested containers. If you use the embedded font in a nested container you will need to add a PaintEventHandler for the containers. Or better yet use the sender object to determine the ControlCollection for the foreach, then just reuse the same Handler. (something for another day)

So here we loop through all the labels on the form checking their Visible property (remember we had set it to false if we want to use the private font).

A new font is created with the properties set on the label in the designer. This is where MS made a mistake, Font() has an overload that takes the font name, but it only works with System Fonts not private fonts. When using a PrivateFontCollection the only override that works is the one that takes a FontFamily as its first argument. Sometimes the documentation is just wrong! That's when you have to look at .NET's source code.

A PointF is created using the label's location. AntiAlias is turned on for larger fonts (optional) and a brush is created using the colour from the label. Finally the text from the label is used for the DrawString method.

Before you can compile this you have to go into the project's properties and check 'Allow unsafe code' (Oh how I rage). Now compile and run the code. Debug any typos that you may have. Once you have it running uninstall the font to test that it is using the embedded font and not the system font.

For further learning:
Make a second form open and use the font on that.
Modify the Paint EventHandler to use 'sender' rather than 'this' and connect one handler to nested containers.
Add a second font.

Don't go crazy with too many different fonts on the same form, rule of thumb should be two fonts per form. Well that's what they taught me in typesetting any ways.


You must login or register to view this content.

Virus Scan.. Em, it's source code.


Not the right section
05-26-2014, 02:12 AM #4
FarSideX
I’m too L33T
Originally posted by AlmightySo View Post
Not the right section


Not a very informative are you. NGU doesn't have a programming tutorial section as far as I can tell.

The following user thanked FarSideX for this useful post:

BrunoBlak
05-26-2014, 06:05 AM #5
Originally posted by FarSideX View Post
Not a very informative are you. NGU doesn't have a programming tutorial section as far as I can tell.


You must login or register to view this content.
So what is this?

The following user thanked Black Panther for this useful post:

04jberry
05-26-2014, 06:20 PM #6
FarSideX
I’m too L33T
Originally posted by AlmightySo View Post
So what is this?


See you can be a little more informative if you only try. Next time you might want to just use a link rather than a big picture. I could teach you how if you like, it is not very hard. Unless of course you are one of those users that need a video tutorial to learn anything.

The following user thanked FarSideX for this useful post:

BrunoBlak
05-27-2014, 04:31 AM #7
Originally posted by FarSideX View Post
See you can be a little more informative if you only try. Next time you might want to just use a link rather than a big picture. I could teach you how if you like, it is not very hard. Unless of course you are one of those users that need a video tutorial to learn anything.


You fucking what? You didn't even know there was a computer programming section to this site so pls check yourself before you wreck yourself
05-27-2014, 06:23 AM #8
FarSideX
I’m too L33T
Originally posted by AlmightySo View Post
You fucking what? You didn't even know there was a computer programming section to this site so pls check yourself before you wreck yourself


I was only offering to help you. First you made a post completely devoid of any useful information, just copy/paste criticism. You followed that up by posting a huge picture when a simple link would have been more appropriate.
I made an honest offer to help you learn something to which you responded with profanity. If all you can offer is empty criticism and profanity, go away and leave those that are actually trying to help others alone. Your comments are as useful as you are, try changing that from useless to something else.

The following user thanked FarSideX for this useful post:

BrunoBlak
12-19-2014, 02:09 PM #9
Fsx 1x0 doctor strange
12-19-2014, 02:48 PM #10
moved to the correct section.

Copyright © 2026, NextGenUpdate.
All Rights Reserved.

Gray NextGenUpdate Logo