Reputation: 52498
What is the best way to embed a truetype font within the application i'm developing? Basically i want to make sure a particular font is available to my application when installed on another machine. I have the *.ttf font file and just need a way of embedding it or automatically installing it when the application is run.
Do i need to set the installation program to install the font during installation or can i dynamically load the font during runtime of the application? In fact both would be nice to know.
The application is being developed in C# using .NET 2.0.
Upvotes: 17
Views: 39878
Reputation:
Its easier than this seems; you can embed the font as a resource in your app and access it as a strongly-typed property within the Properties namespace of your app. But the given link should be a good starting point.
For the VB-disabled:
Add the font as a resource in your application. Call the resource MyFontLol. You can access this resource (as a byte array) from Properties.Resources.MyFontLol.
I haven't tested the following, but it appears to be workable:
public void LoadMyFontLolKThx()
{
// get our font and wrap it in a memory stream
byte[] myFont = Properties.Resources.MyFontLol;
using (var ms = new MemoryStream(myFont))
{
// used to store our font and make it available in our app
PrivateFontCollection pfc = new PrivateFontCollection();
// The next call requires a pointer to our memory font
// I'm doing it this way; not sure what best practice is
GCHandle handle = GCHandle.Alloc(ms, GCHandleType.Pinned);
// If Length > int.MaxValue this will throw
checked
{
pfc.AddMemoryFont(
handle.AddrOfPinnedObject(), (int)ms.Length);
}
var font = new Font(pfc.Families[0],12);
// use your font here
}
}
One last note. The PFC stores the font as a GDI+ font. These aren't compatible with some forms controls. From the docs:
To use the memory font, text on a control must be rendered with GDI+. Use the SetCompatibleTextRenderingDefault method, passing true, to set GDI+ rendering on the application, or on individual controls by setting the control's UseCompatibleTextRendering property to true. Some controls cannot be rendered with GDI+.
Upvotes: 12
Reputation: 19810
This blog post should help you.
Basically you add the font as an embedded resource then load it into a PrivateFontCollection object.
Upvotes: 15
Reputation: 20757
Here's Will's answer, translated to C# (untested):
PrivateFontCollection pfc = new PrivateFontCollection();
using (Stream fontStream = GetType().Assembly.GetManifestResourceStream("Alphd___.ttf"))
{
if (null == fontStream)
{
return;
}
int fontStreamLength = (int) fontStream.Length;
IntPtr data = Marshal.AllocCoTaskMem(fontStreamLength);
byte[] fontData = new byte[fontStreamLength];
fontStream.Read(fontData, 0, fontStreamLength);
Marshal.Copy(fontData, 0, data, fontStreamLength);
pfc.AddMemoryFont(data, fontStreamLength);
Marshal.FreeCoTaskMem(data);
}
along with their Paint() method:
protected void Form1_Paint(object sender, PaintEventArgs e)
{
bool bold = false;
bool italic = false;
e.Graphics.PageUnit = GraphicsUnit.Point;
using (SolidBrush b = new SolidBrush(Color.Black))
{
int y = 5;
foreach (FontFamily fontFamily in pfc.Families)
{
if (fontFamily.IsStyleAvailable(FontStyle.Regular))
{
using (Font font = new Font(fontFamily, 32, FontStyle.Regular))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Bold))
{
bold = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Bold))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if (fontFamily.IsStyleAvailable(FontStyle.Italic))
{
italic = true;
using (Font font = new Font(fontFamily, 32, FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
if(bold && italic)
{
using(Font font = new Font(fontFamily, 32, FontStyle.Bold | FontStyle.Italic))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Underline))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
y += 40;
}
using (Font font = new Font(fontFamily, 32, FontStyle.Strikeout))
{
e.Graphics.DrawString(font.Name, font, b, 5, y, StringFormat.GenericTypographic);
}
}
}
}
Upvotes: 14
Reputation: 11702
it might not be the best way but couldn't you just include the font with your resources and then copy it to the font's folder on the windows dir?
Upvotes: -1