Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Embedding fonts into your application.

Embedded Resources

Embedding fonts into your application.

by  Sypher2  Posted    (Edited  )
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 [tt][color blue]Imports[/color] System[/tt] statement at the top of your code file.

[tt][color blue]Private Declare Auto Function[/color] AddFontMemResourceEx [color blue]Lib[/color] "Gdi32.dll" _
([color blue]ByVal[/color] pbFont [color blue]As[/color] IntPtr, [color blue]ByVal[/color] cbFont [color blue]As Integer[/color], _
[color blue]ByVal[/color] pdv [color blue]As Integer[/color], [color blue]ByRef[/color] pcFonts [color blue]As Integer[/color]) [color blue]As[/color] IntPtr

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

So what does all this do?[ul][li]Pass an array of the font names to the function.[/li][li]The function gets NameSpc which is the name of your currently running applicaton.[/li][li]A stream, a private font collection, and a loop counter are declared.[/li][li]The stream is set to the font that's within the resource stream.[/li][li]The font is read into a byte array from the stream.[/li][li]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.[/li][li]The byte array is then copied to this allocated location on the global heap.[/li][li]Now that you have a valid IntPtr pointing to the font, you can added it to the PrivateFontCollection using AddMemoryFont.[/li][li]The memory on the global heap is then freed. You must do this or you'll have a memory leak.[/li][li]Each font in the array you passed is repeated.[/li][li]After the loop is finished, the PrivateFontCollection is returned to the caller.[/ul]
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:
[tt][color green]'Use a 10 point font of the first font in your PrivateFontCollection[/color]
[color blue]Me[/color].Font = [color blue]New[/color] Font(FntFC.Families(0), 10)[/tt]

The next time you want to use a nifty font, you'll be able to embed it right in your app.
Register to rate this FAQ  : BAD 1 2 3 4 5 6 7 8 9 10 GOOD
Please Note: 1 is Bad, 10 is Good :-)

Part and Inventory Search

Back
Top