Results 1 to 17 of 17

Thread: How to save a font to the program?

  1. #1

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    How to save a font to the program?

    Hello! How do you save a font to the program so any computer can see it? (Not just the ones with the font installed.) This is my current code: (In form1_load)
    vb Code:
    1. Dim MyFont As PrivateFontCollection = New PrivateFontCollection
    2. MyFont.AddFontFile("visitor.ttf")
    3. Me.Font = New Font(MyFont.Families(0), 12)
    It sends an error when another computer runs the program. (Visitor.ttf is in the resources!)
    So, what I need to jnow is, is there another way or another place to save the font instead of downloading it to another computer? Thanks.

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Re: How to save a font to the program?

    As the name suggests, AddFontFile adds a font file. You have to have a file to add if you want to use AddFontFile. A resource is not a file, which is the whole point. A resource is compiled into the binary code of your EXE or DLL. You would have to extract the resource and save it as a file first in order to use it like that.

    I've never actually embedded a font as a resource. What do you get back from My.Resources if you do? It may well be a Font object so you don't need to do anything more to use it.

  3. #3
    Code Monkey wild_bill's Avatar
    Join Date
    Mar 2005
    Location
    Montana
    Posts
    2,993

    Re: How to save a font to the program?

    It looks like you get back a byte array, so something like this is what JMC is suggesting
    Code:
            ' get file from resources & write to file system
            Dim path = System.IO.Path.Combine(My.Computer.FileSystem.SpecialDirectories.CurrentUserApplicationData, "visitor.ttf")
    
            If Not System.IO.File.Exists(path) Then
                IO.File.WriteAllBytes(path, My.Resources.visitor)
            End If
    
            ' apply font
            Dim MyFont = New System.Drawing.Text.PrivateFontCollection
            MyFont.AddFontFile(path)
            Me.Font = New Font(MyFont.Families(0), 12)
    That is the very essence of human beings and our very unique capability to perform complex reasoning and actually use our perception to further our understanding of things. We like to solve problems. -Kleinma

    Does your code in post #46 look like my code in #45? No, it doesn't. Therefore, wrong is how it looks. - jmcilhinney

  4. #4

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    Re: How to save a font to the program?

    I appreciate the help, but the labels are still the default font. I don't get an error message.
    Edit:
    Aha... I see.
    vb Code:
    1. Dim MyFont As PrivateFontCollection = New PrivateFontCollection
    2. MyFont.AddFontFile("visitor.ttf")
    3. Me.Font = New Font(MyFont.Families(0), 12)
    Only checks the same folder that the program is in for that specific font. So If you wanted to send your program to someone else then you'd have to send them the .ttf file too. :/
    So you cannot save fonts to the resources?
    Last edited by NinjaNic; Jul 29th, 2014 at 10:25 PM.

  5. #5
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Re: How to save a font to the program?

    Quote Originally Posted by NinjaNic View Post
    I appreciate the help, but the labels are still the default font. I don't get an error message.
    You haven't shown us anything to do with Labels so far. As far as we know, there is no such code and that's the issue. Show us the exact code you're using now to create the Font object and change the Label's Font.

  6. #6

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    Re: How to save a font to the program?

    Me.Font =
    is supposed to change all the labels's fonts to what it is set to. But anyway, here's the full code (to one of the forms.)
    (There are only 2 labels in this form.)
    Attachment 116965
    vb Code:
    1. Imports System.Drawing.Text
    2. Public Class FormHelp
    3.  
    4.     Private Sub FormHelp_KeyDown(sender As Object, e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
    5.  
    6.         If e.KeyCode = Keys.Escape Then
    7.  
    8.             Me.Close()
    9.  
    10.         End If
    11.  
    12.     End Sub
    13.  
    14.     Private Sub FormHelp_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
    15.  
    16.         Dim MyFont As PrivateFontCollection = New PrivateFontCollection
    17.         MyFont.AddFontFile("visitor.ttf")
    18.         Me.Font = New Font(MyFont.Families(0), 12)
    19.  
    20.         Me.Text = Me.ProductName & " - " & Me.ProductVersion
    21.  
    22.         Me.KeyPreview = True
    23.  
    24.     End Sub
    25.  
    26.     Private Sub FormHelp_FormClosing(sender As Object, e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
    27.  
    28.         FormStart.Show()
    29.  
    30.     End Sub
    31.  
    32. End Class

  7. #7
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    110,344

    Re: How to save a font to the program?

    You've posted a screen shot of some code that includes a compilation error and then you've posted some different code. Are we supposed to guess which one you're actually using?

  8. #8

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    Re: How to save a font to the program?

    It's the same code, but in the picture I have
    MyFont.AddfontFile(My.Resources.Visitor)
    and in the code I have
    MyFont.AddfontFile("Visitor.ttf")
    I'm just showing what happens when I put
    MyFont.AddfontFile(My.Resources.Visitor)

  9. #9
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: How to save a font to the program?

    If you have added the font to the project resources (Project Menu -> ProjName Properties; Resource Tab -> Add Existing File), then you could do something like this:
    Code:
    Private Function FontByteArray(ByVal fontData() As Byte, Optional ByVal sizeInPoints As Single = 12.0F, Optional ByVal style As FontStyle = FontStyle.Regular) As Font
       Dim ret As Font
       Dim ptrFontData As IntPtr
       Try
          ptrFontData = System.Runtime.InteropServices.Marshal.AllocHGlobal(fontData.Length)
          System.Runtime.InteropServices.Marshal.Copy(fontData, 0, ptrFontData, fontData.Length)
          Using pfc As New System.Drawing.Text.PrivateFontCollection
             pfc.AddMemoryFont(ptrFontData, fontData.Length)
             ret = New Font(pfc.Families.Last, sizeInPoints, style, GraphicsUnit.Point)
          End Using
       Finally
          If ptrFontData <> IntPtr.Zero Then System.Runtime.InteropServices.Marshal.FreeHGlobal(ptrFontData)
       End Try
       Return ret
    End Function
    Assuming the name of the resource is "myFont" then:
    Code:
    Me.Font = FontByteArray(My.Resources.myFont)
    Last edited by TnTinMN; Jul 29th, 2014 at 10:56 PM.

  10. #10

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    Re: How to save a font to the program?

    That code is hard to understand! I'm still pretty basic in Visual Basic ...(chirp chirp)... and I don't know what or how to use unmanaged memory. Anyway I tried the code but I still get the default font. Thank you all for the help though, but it seems like my attempt was in vain. If you used that code and it worked, it is probably because you have the font pre-installed on your pc. Seems like creating a file path is better for this one. Thanks again.

  11. #11
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: How to save a font to the program?

    Quote Originally Posted by NinjaNic View Post
    ...If you used that code and it worked, it is probably because you have the font pre-installed on your pc. Seems like creating a file path is better for this one. Thanks again.
    You are correct. I missed that in my testing. For the MemoryFont to work, the control must be rendered in GDI+. Loading the font from a file as Wild_Bill showed should work though.

  12. #12
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: How to save a font to the program?

    Ok, after a bit of research, I found that it is possible to install a font on a per process level using the AddFontMemResourceEx API function. Coupling that with the previous attempt now allows you to load a font from your project resources.


    Code:
    ''' <summary>
    ''' adds the font resource from a memory image to the system.
    ''' </summary>
    ''' <param name="FontData"></param>
    ''' <param name="lengthFontData"></param>
    ''' <param name="MustBeZero"></param>
    ''' <param name="numFontsAdded"></param>
    ''' <returns>If the function succeeds, the return value specifies the handle to the font added. This handle uniquely identifies the fonts that were installed on the system. If the function fails, the return value is zero. No extended error information is available.</returns>
    ''' <remarks>A font that is added by AddFontMemResourceEx is always private to the process that made the call and is not enumerable.  To remove the fonts that were installed, call RemoveFontMemResourceEx. However, when the process goes away, the system will unload the fonts even if the process did not call RemoveFontMemResource.</remarks>
    <Runtime.InteropServices.DllImport("gdi32.dll", ExactSpelling:=True)> _
    Private Shared Function AddFontMemResourceEx(ByVal FontData() As Byte, ByVal lengthFontData As Int32, ByVal MustBeZero As IntPtr, ByRef numFontsAdded As UInt32) As IntPtr
    End Function
    
    Private Function FontFromByteArray(ByVal fontData() As Byte, Optional ByVal sizeInPoints As Single = 12.0F, Optional ByVal style As FontStyle = FontStyle.Regular) As Font
       Dim ret As Font
       Dim ptrFontData As IntPtr
       Try
    
          AddFontMemResourceEx(fontData, fontData.Length, IntPtr.Zero, 1UI)
    
          ptrFontData = System.Runtime.InteropServices.Marshal.AllocCoTaskMem(fontData.Length)
          System.Runtime.InteropServices.Marshal.Copy(fontData, 0, ptrFontData, fontData.Length)
    
          Using pfc As New System.Drawing.Text.PrivateFontCollection
             pfc.AddMemoryFont(ptrFontData, fontData.Length)
             ret = New Font(pfc.Families.Last, sizeInPoints, style, GraphicsUnit.Point)
          End Using
       Finally
          If ptrFontData <> IntPtr.Zero Then System.Runtime.InteropServices.Marshal.FreeCoTaskMem(ptrFontData)
       End Try
       Return ret
    End Function

  13. #13
    PowerPoster Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Bottesford, North Lincolnshire, England.
    Posts
    2,429

    Re: How to save a font to the program?

    Hi NinjaNic,

    I'm looking for help with embedded fonts and have found this thread, it's a bit late in the day since your last post was Jul 30th, 2014, 05:11 AM.

    But... I'm surprised none of the guys helping you pointed out that Me.Font will only affect the font of the actual form, i.e. anything you place as the title of the form. It wouldn't affect the font of any label or textbox or whatever...
    I wonder if when you were working on this project you were looking in the wrong place for font changes ?

    In order to change the font of any object (a label, say) you have to specifically change the font of that object, as you did (tried to do) with the Title of your form.

    Poppa.
    Last edited by Poppa Mintin; May 1st, 2016 at 02:42 AM. Reason: Replacing spacing omitted by host application...
    Along with the sunshine there has to be a little rain sometime.

  14. #14
    PowerPoster Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Bottesford, North Lincolnshire, England.
    Posts
    2,429

    Re: How to save a font to the program?

    Quote Originally Posted by TnTinMN View Post
    Ok, after a bit of research, I found that it is possible to install a font on a per process level using the AddFontMemResourceEx API function. Coupling that with the previous attempt now allows you to load a font from your project resources.
    Hi TnTinMN,

    It's a bit late to be asking this now, since your post was made July 30th 2014, however, I'm resurrecting that project and can't figure out just how to couple "that with the previous attempt".

    The 'previous attempt' works, but only if the relevant font is already in the C:/Windows/Font directory.

    I don't understand where to place: -
    Code:
    ''' <summary>''' adds the font resource from a memory image to the system.
    ''' </summary>
    ''' <param name="FontData"></param>
    ''' <param name="lengthFontData"></param>
    ''' <param name="MustBeZero"></param>
    ''' <param name="numFontsAdded"></param>
    ''' <returns>If the function succeeds, the return value specifies the handle to the font added. This handle uniquely identifies the fonts that were installed on the system. If the function fails, the return value is zero. No extended error information is available.</returns>
    ''' <remarks>A font that is added by AddFontMemResourceEx is always private to the process that made the call and is not enumerable.  To remove the fonts that were installed, call RemoveFontMemResourceEx. However, when the process goes away, the system will unload the fonts even if the process did not call RemoveFontMemResource.</remarks>
    <Runtime.InteropServices.DllImport("gdi32.dll", ExactSpelling:=True)> _
    Private Shared Function AddFontMemResourceEx(ByVal FontData() As Byte, ByVal lengthFontData As Int32, ByVal MustBeZero As IntPtr, ByRef numFontsAdded As UInt32) As IntPtr
    End Function
    The first bit looks like remarking out the first 9 lines, but I'm certain that's not the case.
    I don't believe it's for a module because the word 'module' doesn't appear anywhere.
    I've tried placing it before Public Class Form1 but it doesn't like that, neither does it like to be placed straight after it... Nor anywhere else as far as I can discover.

    Poppa.
    Along with the sunshine there has to be a little rain sometime.

  15. #15

    Thread Starter
    Addicted Member NinjaNic's Avatar
    Join Date
    Dec 2013
    Location
    Earth
    Posts
    230

    Re: How to save a font to the program?

    From what I've learned, this is the function that saves and uses a .ttf from the program's resources. I tested it and it works. It creates a folder in your C:\ drive, however. (In this example, the font is named "nulshock.")

    vb Code:
    1. Private Function SaveFont(FontSize As Integer) As Font
    2.  
    3.         Dim FilePath As String = "C:\Temporary"
    4.         Dim FileName As String = "\nulshock.ttf"
    5.         Dim MyFont As New Text.PrivateFontCollection
    6.  
    7.         Try
    8.  
    9.             MyFont.AddFontFile(FilePath & FileName)
    10.  
    11.         Catch ex As Exception
    12.  
    13.             IO.Directory.CreateDirectory(FilePath)
    14.             Dim b() As Byte = My.Resources.nulshock.ToArray
    15.             IO.File.WriteAllBytes(FilePath & FileName, b)
    16.             MyFont.AddFontFile(FilePath & FileName)
    17.  
    18.         End Try
    19.  
    20.         Return New Font(MyFont.Families(0), FontSize)
    21.  
    22.     End Function

    To delete the folder, simply use this. But for me, it's giving me an error stating that I do not have access.

    vb Code:
    1. Private Sub CloseFont()
    2.  
    3.         Dim FilePath As String = "C:\Temporary"
    4.         Dim FileName As String = "\nulshock.ttf"
    5.         IO.File.Delete(FilePath & FileName)
    6.         IO.Directory.Delete(FilePath)
    7.  
    8.     End Sub

    And lastly, this is how you would use the first function:

    vb Code:
    1. Label1.Font = SaveFont(20)
    2. Label1.Text = "nulshock"

  16. #16
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: How to save a font to the program?

    Quote Originally Posted by Poppa Mintin View Post
    Hi TnTinMN,

    It's a bit late to be asking this now, since your post was made July 30th 2014, however, I'm resurrecting that project and can't figure out just how to couple "that with the previous attempt".
    Just copy all the code from post #12 and add it to either a Class (your form class for instance) or you can place it in a Module if you like. If you place it in a Module, removed the Shared qualifier on AddFontMemResourceEx

    Quote Originally Posted by Poppa Mintin View Post
    The first bit looks like remarking out the first 9 lines, but I'm certain that's not the case.
    I don't believe it's for a module because the word 'module' doesn't appear anywhere.
    Those first nine lines are know as XML documentation. It is the source for the Intellisence help that pops up when you type AddFontMemResourceEx. You can delete it if you want.

    Just remember that any font that you use this way will need to be explicitly assigned in your code. You can not assign these fonts through the designer.

  17. #17
    PowerPoster Poppa Mintin's Avatar
    Join Date
    Mar 2009
    Location
    Bottesford, North Lincolnshire, England.
    Posts
    2,429

    Re: How to save a font to the program?

    Hi TnTinMN,

    Thanks for the rapid reply, I was trying to 'Couple' Post 12 with the previous code, didn't realise you'd already done it.
    Once I'd spotted that you'd also changed the function's name it all worked well. I even left the XML stuff in. I know nothing about XML as you can tell.

    Poppa.
    Along with the sunshine there has to be a little rain sometime.

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width