Search code examples
c#.netvb.netfontstruetype

How to get the title (not the name) of a text font file? (TTF and OTF)


QUESTION

In C# or VB.NET, under WinForms class library or WPF, and without requiring 3rd party applications or APIs, I would like to know how to retrieve the title of a text font file, in the same way as it is shown when doing right click on a text font file and going to the details property page.

In other words, I need to obtain the exact name as which the font will be registered in the Windows Registry, which is not the same name as gives me the System.Drawing.FontFamily.Name property neither the System.Drawing.Font.Name property.

RESEARCH

There are some questions in StackOverflow about how to get the font name, like this and this, but none for the font title.

Nothing of that could help me. I'll give an example of the difference:

I have a true type font file with file name "OpenSans-Light.ttf", which in the details property page is shown as "Open Sans Light", but using a System.Drawing.FontFamily based solution i get the name "Open Sans".

Then, after I've seen that maybe .NET Framework (WindowsForms) class library does not provide a functionality to obtain the font title, I tried to discover which function from the Windows API could be using the windows shell extension of the file details property sheet to obtain the font title...

...I found nothing about it, no information, nothing of nothing, just the GetFontData function which does not provides me the info that I need.


Solution

  • I noticed that the "Title" column in the Explorer list view shows the exact font name string that I need, and so knowing that, then I realized that the problem can be easily solved by using the win32 shell property wrapper of the WindowsAPICodePack library to retrieve the Title property of a font file.

    I'm aware that I requested a solution without 3rd party libraries, however I'm almost sure it will not be a more ideal solution than using this, because... well, the consistent alternative seems to implement the Win32 shell property wrapper ourselves.

    A sample code:

    Imports Microsoft.WindowsAPICodePack.Shell
    
    Dim diInfo As New DirectoryInfo("C:\Fonts\")
    
    For Each fiInfo As FileInfo In diInfo.GetFiles("*.ttf", SearchOption.TopDirectoryOnly)
        Dim sFile As ShellFile = ShellFile.FromFilePath(fiInfo.FullName)
        Dim title As String = sFile.Properties.System.Title.Value
    
        Dim sb As New StringBuilder()
        sb.AppendLine(String.Format("Name.: {0}", fiInfo.Name))
        sb.AppendLine(String.Format("Title: {0}", title))
    
        Console.WriteLine(sb.ToString())
    Next
    

    An example output:

    Name.: OpenSans LightItalic.ttf
    Title: Open Sans Light Italic
    
    Name.: OpenSans Light_0.ttf
    Title: Open Sans Light
    
    Name.: OpenSans-Bold.ttf
    Title: Open Sans Bold
    
    Name.: OpenSans-BoldItalic.ttf
    Title: Open Sans Bold Italic
    
    Name.: OpenSans-ExtraBold.ttf
    Title: Open Sans Extrabold
    
    Name.: OpenSans-ExtraBoldItalic.ttf
    Title: Open Sans Extrabold Italic
    
    Name.: OpenSans-Italic.ttf
    Title: Open Sans Italic
    
    Name.: OpenSans-Light.ttf
    Title: Open Sans Light
    
    Name.: OpenSans-LightItalic.ttf
    Title: Open Sans Light Italic
    
    Name.: OpenSans-Regular.ttf
    Title: Open Sans
    
    Name.: OpenSans-Semibold.ttf
    Title: Open Sans Semibold
    
    Name.: OpenSans-SemiboldItalic.ttf
    Title: Open Sans Semibold Italic
    

    The only missing thing is to add "(TrueType)" or "(OpenType)" at the end of the string if we really need the exact same string as in the Windows Registry is shown (in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts key).