How do I embed my own fonts in a WinForms app?
Asked Answered
J

5

42

I want to embed fonts in my WinForms application so that I don't have to worry about them being installed on the machine. I've searched a bit on the MSDN site and found a few hints about using native Windows API calls, for instance Michael Caplan's (sp?) tutorial linked to by Scott Hanselman. Now, do I really have to go through all that trouble? Can't I just use the resource part of my app?

If not I'll probably go the installing route. In that case, can I do that programmatically? By just copying the font file to the Windows\Fonts folder?

I am aware of licensing issues.

Johore answered 17/2, 2009 at 9:59 Comment(1)
You could do that, but also be aware that like software fonts too have licenses and you need to ensure that you are not violating any licenses that prohibit embedding and deployment.Rooke
H
67

This is what worked for me in VS 2013, without having to use an unsafe block.

Embed the resource

  1. Double-click Resources.resx, and in the toolbar for the designer click Add Resource/Add Existing File and select your .ttf file
  2. In your solution explorer, right-click your .ttf file (now in a Resources folder) and go to Properties. Set the Build Action to "Embedded Resource"

Load the font into memory

  1. Add using System.Drawing.Text; to your Form1.cs file

  2. Add code above and inside your default constructor to create the font in memory (without using "unsafe" as other examples have shown). Below is my entire Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    using System.Reflection;
    
    using System.Drawing.Text;
    
    namespace WindowsFormsApplication1
    {
        public partial class Form1 : Form
        {
            [System.Runtime.InteropServices.DllImport("gdi32.dll")]
            private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont,
                IntPtr pdv, [System.Runtime.InteropServices.In] ref uint pcFonts);
    
            private PrivateFontCollection fonts = new PrivateFontCollection();
    
            Font myFont;
    
            public Form1()
            {
                InitializeComponent();
    
                byte[] fontData = Properties.Resources.MyFontName;
                IntPtr fontPtr = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length);
                System.Runtime.InteropServices.Marshal.Copy(fontData, 0, fontPtr, fontData.Length);
                uint dummy = 0;
                fonts.AddMemoryFont(fontPtr, Properties.Resources.MyFontName.Length);
                AddFontMemResourceEx(fontPtr, (uint)Properties.Resources.MyFontName.Length, IntPtr.Zero, ref dummy);
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(fontPtr);
    
                myFont = new Font(fonts.Families[0], 16.0F);
            }
        }
    }
    

Use your font

  1. Add a label to your main form, and add a load event to set the font in Form1.cs:

    private void Form1_Load(object sender, EventArgs e)
    {
        label1.Font = myFont;
    }
    
Hemminger answered 7/5, 2014 at 13:40 Comment(7)
This doesn't work for me. My font doesn't appear under Properties.Resources.Starcrossed
@JamesDonnelly It's not meant to appear under Properties.Resources. There is a separate folder called Resources that is created at the root of the project when you import the resource.Gaughan
how about multiple ttf like regular, bold and italic?Virginia
Sorry but I don't get it. Where can I set the font name so it knows what file to get from the resources folder? The font is in there but I'm not seeing where it is called in the code provided.Fie
@ChristianVerner replace MyFontName with the actual name of your fontSubstantialize
How to use custom font for all controls and respecting their own sizes?Substantialize
Following the instructions in step (1.), I opened the existing Resource1.resx file in my project and added my font file. Then change sample code in Form1() constructor to: byte[] fontData = Resource1.<fontName> //where <fontName> is the name in the resource file. Works perfectly. I made a class field: private Font Digital7; Then set Digital7 = new Font(fonts.Families[0], 27F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point); Then substitute Digital7 for "myFont" in the example load event handler.John
C
8
// specify embedded resource name
string resource = "embedded_font.PAGAP___.TTF";

// receive resource stream
Stream fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resource);

// create an unsafe memory block for the font data
System.IntPtr data = Marshal.AllocCoTaskMem((int)fontStream.Length);

// create a buffer to read in to
byte[] fontdata = new byte[fontStream.Length];

// read the font data from the resource
fontStream.Read(fontdata, 0, (int)fontStream.Length);

// copy the bytes to the unsafe memory block
Marshal.Copy(fontdata, 0, data, (int)fontStream.Length);

// pass the font to the font collection
private_fonts.AddMemoryFont(data, (int)fontStream.Length);

// close the resource stream
fontStream.Close();

// free up the unsafe memory
Marshal.FreeCoTaskMem(data);
Conjunctive answered 26/5, 2011 at 9:29 Comment(1)
Where is private_fonts defined?Abebi
W
7

I dragged and dropped a randomly downloaded font into my resources and this worked. Uses a file though. I guess you can use this as well to install fonts ?

public Form1()
{
    string filename = @"C:\lady.gaga";
    File.WriteAllBytes(filename, Resources.KBREINDEERGAMES);
    PrivateFontCollection pfc = new PrivateFontCollection();
    pfc.AddFontFile(filename);

    Label label = new Label();
    label.AutoSize = true;
    label.Font = new Font(pfc.Families[0], 16);
    label.Text = "hello world";
    Controls.Add(label);
}
Watch answered 21/7, 2014 at 12:12 Comment(0)
P
2

Can't I just use the resource part of my app?

Yes, but need to be native resources rather than .NET resources (i.e. using rc.exe, the native resource compiler).

Petersburg answered 17/2, 2009 at 15:2 Comment(0)
P
-8

i will go with knighter's way of embedding a font but when it comes to changing your font I choose this code:

YourLabel.Font = new Font("Arial", 24,FontStyle.Bold);

for more information: Easiest way to change font and font size

Pi answered 31/8, 2020 at 6:40 Comment(5)
This doesn't really answer the question.Mateo
dude, it solves the problem of changing your font. if you want to bold your font then you can easily change it using the code that I have provided, changing font size? use the codePi
@Pi - On my machine, the "Heletivica" font got changed to "Arial" due to patent & royality reasons so Microsoft don't get sued.Zymometer
the question is about embedding non-standard fonts into an application, not creating a Font object for an existing font.Asarum
@Pi dude?! have some manners!Smyth

© 2022 - 2024 — McMap. All rights reserved.