INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Log In

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips Forums!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.

Jobs

Embedded Resources

Embedding fonts into your application. by Sypher2
Posted: 21 Jan 04 (Edited 24 Jan 05)

You have a really nice font (or several fonts) that you want to use with your application.  However, you don't want to mess with the hassle of installing the font on every computer that uses your app.

So what can you do?

Embed the font as a resource.

.NET allows you to embed pretty much any file into the executable.  It's just a matter of extracting the resource when you need it.

With fonts, there is a PrivateFontCollection object with an AddMemoryFont method.  This method takes an IntPtr pointing to a location in memory and the length to read.

Step 1:  The first thing you need to do is add the font to your solution.  Go to the Project menu and select Add Existing Item (Ctrl-D shortcut).  Navigate to the font you want to use and click Open.  The font will be copied to your solution's folder, and you will see it in the Solution Explorer.

Step 2:  Click on the font in Solution Explorer to highlight it.  In Properties (under Solution Explorer) there is a line for Build Action.  This defaults to Compile.  You need to change it to Embedded Resource by selecting from the drop down list.

(Repeat steps 1 and 2 for any addtional fonts you want to embed.)

Step 3:  Ok, now that the font is an embedded resource, you just have to write the code to extract it.

The following code assumes you have an Imports System  statement at the top of your code file.

Private Declare Auto Function AddFontMemResourceEx Lib "Gdi32.dll" _
    (ByVal pbFont As IntPtr, ByVal cbFont As Integer, _
    ByVal pdv As Integer, ByRef pcFonts As Integer) As IntPtr

Public Function GetFont(ByVal FontResource() As String) As _
    Drawing.Text.PrivateFontCollection
        'Get the namespace of the application    
        Dim NameSpc As String = _
            Reflection.Assembly.GetExecutingAssembly().GetName().Name.ToString()
        Dim FntStrm As IO.Stream
        Dim FntFC As New Drawing.Text.PrivateFontCollection()
        Dim i As Integer
        For i = 0 To FontResource.GetUpperBound(0)
            'Get the resource stream area where the font is located
            FntStrm = _
        Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream( _
        NameSpc + "." + FontResource(i))
            'Load the font off the stream into a byte array
            Dim ByteStrm(CType(FntStrm.Length, Integer)) As Byte
            FntStrm.Read(ByteStrm, 0, Int(CType(FntStrm.Length, Integer)))
            'Allocate some memory on the global heap
            Dim FntPtr As IntPtr = _
                Runtime.InteropServices.Marshal.AllocHGlobal( _
                Runtime.InteropServices.Marshal.SizeOf(GetType(Byte)) * _
                    ByteStrm.Length)
            'Copy the byte array holding the font into the allocated memory.
            Runtime.InteropServices.Marshal.Copy(ByteStrm, 0, _
                FntPtr, ByteStrm.Length)
            'Add the font to the PrivateFontCollection
            FntFC.AddMemoryFont(FntPtr, ByteStrm.Length)
            Dim pcFonts As Int32
            pcFonts = 1
            AddFontMemResourceEx(FntPtr, ByteStrm.Length, 0, pcFonts)
            'Free the memory
            Runtime.InteropServices.Marshal.FreeHGlobal(FntPtr)
        Next
        Return FntFC
    End Function


So what does all this do?
  • Pass an array of the font names to the function.
  • The function gets NameSpc which is the name of your currently running applicaton.
  • A stream, a private font collection, and a loop counter are declared.
  • The stream is set to the font that's within the resource stream.
  • The font is read into a byte array from the stream.
  • Now a little unmanaged code has to be written...First an IntPtr variable is set to point to memory allocated on the global heap in the same size as the byte array holding the font.
  • The byte array is then copied to this allocated location on the global heap.
  • Now that you have a valid IntPtr pointing to the font, you can added it to the PrivateFontCollection using AddMemoryFont.
  • The memory on the global heap is then freed.  You must do this or you'll have a memory leak.
  • Each font in the array you passed is repeated.
  • [li]After the loop is finished, the PrivateFontCollection is returned to the caller.
Now to use the fonts in the PrivateFontCollection you can use any of the many overloads of the Font constructor.  Pass the index of the FontFamily you want to use.

Example:
'Use a 10 point font of the first font in your PrivateFontCollection
Me.Font = New Font(FntFC.Families(0), 10)


The next time you want to use a nifty font, you'll be able to embed it right in your app.

Back to Visual Basic (Microsoft) VB.NET FAQ Index
Back to Visual Basic (Microsoft) VB.NET Forum

My Archive

Resources

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close