Resolved Need to use Resource Embedded font in Application

tim8w

Well-known member
Joined
Sep 8, 2020
Messages
147
Programming Experience
10+
I have a Font that I want my application to use. I have tried MANY suggestions on the web and have not found one that works. I tried embedding the file in the Application's Resources, but could never get that to work. I also tried to get ClickOnce to install the font for me, but also couldn't get that to work. Is this not something very commonly done? Anyway if anyone any suggestions, I would appreciate it.
 
The above is if you are using GDI.

Below is if you are using DirectWrite:
 
I tried AddFontMemResourceEx but am having problems with the fontStream. It comes back null.

C#:
Expand Collapse Copy
        [System.Runtime.InteropServices.DllImport("gdi32.dll")] private static extern IntPtr AddFontMemResourceEx(IntPtr pbFont, uint cbFont, IntPtr pdv, ref uint pcFonts);

            try
            {
                string resource = "LEDFont.ttf"; // specify embedded resource name

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

                // create an unsafe memory block for the font data
                System.IntPtr data = System.Runtime.InteropServices.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
                System.Runtime.InteropServices.Marshal.Copy(fontdata, 0, data, (int)fontStream.Length);

                ///IMPORTANT line to register font in system
                uint cFonts = 0;
                AddFontMemResourceEx(data, (uint)fontdata.Length, IntPtr.Zero, ref cFonts);

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

                // close the resource stream
                fontStream.Close();
                // free up the unsafe memory
                System.Runtime.InteropServices.Marshal.FreeCoTaskMem(data);

                lblTaktTime.Font = new Font(pFC.Families[0], 60, FontStyle.Bold);
            }
            catch (Exception exp)
            {
            }

1755638884654.png


Any ideas?
 
That would suggest that the resource is not named what you think it is. E.g. Line 5 las the wrong value.
 
As you can see from your screenshot, the resource is named "LEDFont", not "LEDFont.ttf". Adding resources the way you have will always drop the file extension.

I'm still not sure that you'll be able to access that resource that way though. You'll probably need to use My.Resources to get a Stream. If you want to use GetManifestResourceStream then I think you'll have to add the file to your project and change its Build Action to Embedded Resource. Not 100% sure about that though.
 
That would suggest that the resource is not named what you think it is. E.g. Line 5 las the wrong value.
I have tried both "LEDFont" and "LEDFont.ttf" and the results are the same...

Maybe I'm looking at this the wrong way. Is there a way for the ClickOnce installer to install the Font without specifying an absolute path?
 
Last edited:
As you can see from your screenshot, the resource is named "LEDFont", not "LEDFont.ttf". Adding resources the way you have will always drop the file extension.

I'm still not sure that you'll be able to access that resource that way though. You'll probably need to use My.Resources to get a Stream. If you want to use GetManifestResourceStream then I think you'll have to add the file to your project and change its Build Action to Embedded Resource. Not 100% sure about that though.
I would like to do it this way,:

lblTaktTime.Font = new Font(TaktTimeDisplay.Properties.Resources.LEDFont, 60, FontStyle.Bold);

but when you add the Font to the Resource it adds it as a binary (byte[]) type.
 
Use GetManifestResourceNames() to see what the resource compiler actually put into the assembly.

I have a feeling that the string that needs to be passed to GetManifestResourceStream() needs to be "TaktTimeDisplay.Properties.Resources.LEDFont"
 
Use GetManifestResourceNames() to see what the resource compiler actually put into the assembly.

I have a feeling that the string that needs to be passed to GetManifestResourceStream() needs to be "TaktTimeDisplay.Properties.Resources.LEDFont"
I get the following when I use GetManifestResourceNames():

TaktTimeDisplay.frmTaktTimeDisplay.Resources

No Resource name at all, but it's interesting that it adds the Form name. How do I get the actual resource name?

I thought the following code would return each individual Resource name, but it returns TaktTimeDisplay.frmTaktTimeDisplay.Resources for only 2 resources in the assembly I have 6 Images, 1 Icon and one File. The one "File" is the Font File. Its curious that it didn't loop eight times and give me "TaktTimeDisplay.frmTaktTimeDisplay.Resources.SomeName" for each of the eight files...

C#:
Expand Collapse Copy
                System.Reflection.Assembly asmb = System.Reflection.Assembly.GetExecutingAssembly();
                string[] sNames = asmb.GetManifestResourceNames();
                foreach (string s in sNames)
                {
                    System.IO.Stream strm = asmb.GetManifestResourceStream(s);
                    if (strm != null)
                    {
                    }
                }
 
I'm an idiot. Just because the Font was added to the Resources doesn't make it "Embedded". Once I Right-Mouse-Clicked on the the Font in the Project Resources folder and changed the Build Action to "Embedded Resource", then the font showed up in the "GetManifestResourceNames" call...

Thanks for all the suggestions and help.
 
Back
Top Bottom