Using custom fonts in C# application revisited

By | 4. August 2016

I response to our article Using custom fonts in C# application from March 2016 we had question about loading multiple fonts.  After looking the the previous code I made few changes what makes it simpler and also allows to load more than one font.

To see details  about embedding actual font files please see previous article.

Used fonts are just two first one appeared on http://www.1001fonts.com/ page. Great thanks to site and fonts authors.

Registered users can download full solution EmbeddedFontsExaple.zip (12 downloads) (Visual Studio 2015)

 

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Text;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;

/*
http://www.1001fonts.com/
Bully Regular by Bully  http://www.1001fonts.com/bully-font.html
Romochka Regular by Jovanny Lemonad http://www.1001fonts.com/romochka-font.html
  
 */

namespace EmbeddedFontsExaple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        [DllImport("gdi32.dll")]
        private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, [In] ref uint pcFonts);

        public static PrivateFontCollection private_fonts = new PrivateFontCollection();

        public static void LoadFont(string FontResourceName)
        {
            // receive resource stream
            Stream fontStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(FontResourceName);

            //create an unsafe memory block for the data
            System.IntPtr data = Marshal.AllocCoTaskMem((int)fontStream.Length);
            //create a buffer to read in to
            Byte[] fontData = new Byte[fontStream.Length];
            //fetch the font program 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);

            // We HAVE to do this to register the font to the system (Weird .NET bug !)
            uint cFonts = 0;
            AddFontMemResourceEx(data, (uint)fontData.Length, IntPtr.Zero, ref cFonts);

            //pass the font to the font collection
            private_fonts.AddMemoryFont(data, (int)fontStream.Length);
            //close the resource stream
            fontStream.Close();
            //free the unsafe memory
            Marshal.FreeCoTaskMem(data);

        }


        public static void LoadFont(Byte[] fontData)
        {

            //create an unsafe memory block for the data
            System.IntPtr data = Marshal.AllocCoTaskMem(fontData.Length);
            //copy the bytes to the unsafe memory block
            Marshal.Copy(fontData, 0, data, fontData.Length);

            // We HAVE to do this to register the font to the system (Weird .NET bug !)
            uint cFonts = 0;
            AddFontMemResourceEx(data, (uint)fontData.Length, IntPtr.Zero, ref cFonts);

            //pass the font to the font collection
            private_fonts.AddMemoryFont(data, fontData.Length);
            //free the unsafe memory
            Marshal.FreeCoTaskMem(data);

        }


        private void Form1_Load(object sender, EventArgs e)
        {
         
            LoadFont(EmbeddedFontsExaple.Properties.Resources.Bully);
            Font bullyFont = new Font(private_fonts.Families[0], 20);

            LoadFont(EmbeddedFontsExaple.Properties.Resources.Romochka);
            Font romochkaFont = new Font(private_fonts.Families[1], 20);

            label1.Font = bullyFont;
            label2.Font = romochkaFont;

            label1.Text += " " + bullyFont.Name;
            label2.Text += " " + romochkaFont.Name;

        }
    }

}

And the final result:

Embed Font 2

Leave a Reply