Today I am going to show you how you can take a font file, and include it in your VB.NET WinForms application. This means you can load the font at runtime, and use it on your controls without requiring the user to have the font installed on their system. This can come in handy when you want to use a custom font, but your app needs to run without admin rights (because of ClickOnce or other least privileged requirements). Without admin rights you cannot install fonts on a system. (Note: I have seen some workarounds to this, but they require 3rd party utilities).
This is a pretty simple example, and there is not a ton of code. So lets get right down to it:
First lets see the end result.
Here is what the form looks like when I run it normally
Here is what the form looks like when I click the button and load the custom font (which happens to be a digital clock looking font)
The code to do this? Let's take a look. I created a new Windows Forms application, and added a ttf (true type font) file to the resources section of my project. It will be stored under the "files" section of the resources, which means accessing this font in code from the resources will just return a byte array of the file.
I created a module and put all the code needed to load the custom font in there. That way you can make quick calls to it to setup the custom font on your controls.
'CUSTOM FONT LOADED DYNAMICALLY FROM A RESOURCE
'PRIVATE FONT COLLECTION TO HOLD THE DYNAMIC FONT
Private _pfc As PrivateFontCollection = Nothing
Public ReadOnly Property GetInstance(ByVal Size As Single, _
ByVal style As FontStyle) As Font
'IF THIS IS THE FIRST TIME GETTING AN INSTANCE
'LOAD THE FONT FROM RESOURCES
If _pfc Is Nothing Then LoadFont()
'RETURN A NEW FONT OBJECT BASED ON THE SIZE AND STYLE PASSED IN
Return New Font(_pfc.Families(0), Size, style)
Private Sub LoadFont()
'INIT THE FONT COLLECTION
_pfc = New PrivateFontCollection
'LOAD MEMORY POINTER FOR FONT RESOURCE
Dim fontMemPointer As IntPtr = _
'COPY THE DATA TO THE MEMORY LOCATION
0, fontMemPointer, _
'LOAD THE MEMORY FONT INTO THE PRIVATE FONT COLLECTION
'FREE UNSAFE MEMORY
Catch ex As Exception
'ERROR LOADING FONT. HANDLE EXCEPTION HERE
It is pretty straight forward, and the code has comments so you can see what is going on.
Then in the form, when the button is clicked, we make a single call to the module's GetInstance method to return the font.
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Label1.Font = CustomFont.GetInstance(12, FontStyle.Bold)
IMPORTANT: One key thing to note here, is that on the control you want to set this custom font on, you will need to set the UseCompatibleTextRendering property to true (the default is false). If you don't want to do this for some reason, then another method you can do is to use the given controls Paint event and custom draw the text using the custom font. However this is generally less ideal because not all controls fire paint events without tweaking them, and even some that do would put the burden on drawing the entire control in your hands. So setting UseCompatibleTextRendering to true is the easier route to go.
That is all there is to it. You can modify this to meet the specific needs of your application. Below is a link to download the WinForms application (VS2008) that contains the code (and font) used in this article.
Nov 20 2009, 06:05 AM