WildByDesign Posted October 6, 2025 Posted October 6, 2025 I only had to use this once before but you need _WinAPI_GetFontResourceInfo() to read font name directly from a font file properties. Example: #include <WinAPIGdi.au3> Example() Func Example() Local $sFile = "C:\Windows\Fonts\segoeui.ttf" ConsoleWrite(_WinAPI_GetFontResourceInfo($sFile, True) & @CRLF) ConsoleWrite(@CRLF) FontGetInfoFromFile($sFile, 0, "Copyright") FontGetInfoFromFile($sFile, 1, "Font Family name") FontGetInfoFromFile($sFile, 2, "Font SubFamily name") FontGetInfoFromFile($sFile, 3, "Unique font identifier") FontGetInfoFromFile($sFile, 4, "Font full name") FontGetInfoFromFile($sFile, 5, "Version string") FontGetInfoFromFile($sFile, 6, "Postscript name") FontGetInfoFromFile($sFile, 7, "Trademark") FontGetInfoFromFile($sFile, 8, "Manufacturer Name") FontGetInfoFromFile($sFile, 9, "Designer") FontGetInfoFromFile($sFile, 10, "Description") FontGetInfoFromFile($sFile, 11, "URL Vendor") FontGetInfoFromFile($sFile, 16, "Preferred Family (Windows only)") FontGetInfoFromFile($sFile, 17, "Preferred SubFamily (Windows only)") FontGetInfoFromFile($sFile, 18, "Compatible Full (Mac OS only)") FontGetInfoFromFile($sFile, 19, "Sample text") FontGetInfoFromFile($sFile, 20, "PostScript CID findfont name") FontGetInfoFromFile($sFile, 256, "Font-specific names") EndFunc ;==>Example Func FontGetInfoFromFile($sFile, $n, $sElement) Local $s = _WinAPI_GetFontResourceInfo($sFile, Default, $n) If Not @error And $s Then ConsoleWrite($sElement & " = " & $s & @CRLF) EndFunc ;==>FontGetInfoFromFile ioa747 and Parsix 1 1
Parsix Posted October 7, 2025 Author Posted October 7, 2025 (edited) thanks WildByDesign Title needed Edited October 7, 2025 by Parsix
WildByDesign Posted October 7, 2025 Posted October 7, 2025 The following script, shared by @BrewManNH and has a few authors listed in the script, can get the Title from a font file. But what I've noticed is that it will not get the Title when it's located in C:\Windows\Fonts directory. If you check the same font in any other directory, it shows the Title. I even tried adding #RequireAdmin hoping that it would work there but it does not. So this script will work for you as long as it's not within C:\Windows\Fonts I've adapted the script to copy the file from C:\Windows\Fonts to a Temp folder if folder (if it's located in C:\Windows\Fonts) expandcollapse popup#include <FileConstants.au3> #include <File.au3> Global $sFontLocation = "C:\Windows\Fonts\MonaspaceNeon-Italic.otf" Global $sDrive = "", $sDir = "", $sFileName = "", $sExtension = "" Global $aPathSplit = _PathSplit($sFontLocation, $sDrive, $sDir, $sFileName, $sExtension) If StringInStr($sFontLocation, "C:\Windows\Fonts") Then FileCopy($sFontLocation, @TempDir & "\" & $aPathSplit[3] & $aPathSplit[4], $FC_OVERWRITE) $sFontLocation = @TempDir & "\" & $aPathSplit[3] & $aPathSplit[4] EndIf Global $sTitle = _FileGetProperty($sFontLocation, "Title") ConsoleWrite("Font Title: " & $sTitle & @CRLF) ;=============================================================================== ; Function Name.....: _FileGetProperty ; Description.......: Returns a property or all properties for a file. ; Version...........: 1.0.2 ; Change Date.......: 05-16-2012 ; AutoIt Version....: 3.2.12.1+ ; Parameter(s)......: $FGP_Path - String containing the file path to return the property from. ; $FGP_PROPERTY - [optional] String containing the name of the property to return. (default = "") ; $iPropertyCount - [optional] The number of properties to search through for $FGP_PROPERTY, or the number of items ; returned in the array if $FGP_PROPERTY is blank. (default = 300) ; Requirements(s)...: None ; Return Value(s)...: Success: Returns a string containing the property value. ; If $FGP_PROPERTY is blank, a two-dimensional array is returned: ; $av_array[0][0] = Number of properties. ; $av_array[1][0] = 1st property name. ; $as_array[1][1] = 1st property value. ; $av_array[n][0] = nth property name. ; $as_array[n][1] = nth property value. ; Failure: Returns an empty string and sets @error to: ; 1 = The folder $FGP_Path does not exist. ; 2 = The property $FGP_PROPERTY does not exist or the array could not be created. ; 3 = Unable to create the "Shell.Application" object $objShell. ; Author(s).........: - Simucal <Simucal@gmail.com> ; - Modified by: Sean Hart <autoit@hartmail.ca> ; - Modified by: teh_hahn <sPiTsHiT@gmx.de> ; - Modified by: BrewManNH ; URL...............: http://www.autoitscript.com/forum/topic/34732-udf-getfileproperty/page__view__findpost__p__557571 ; Note(s)...........: Modified the script that teh_hahn posted at the above link to include the properties that ; Vista and Win 7 include that Windows XP doesn't. Also removed the ReDims for the $av_ret array and ; replaced it with a single ReDim after it has found all the properties, this should speed things up. ; I further updated the code so there's a single point of return except for any errors encountered. ; $iPropertyCount is now a function parameter instead of being hardcoded in the function itself. ;=============================================================================== Func _FileGetProperty($FGP_Path, $FGP_PROPERTY = "", $iPropertyCount = 500) If $FGP_PROPERTY = Default Then $FGP_PROPERTY = "" $FGP_Path = StringRegExpReplace($FGP_Path, '["'']', "") ; strip the quotes, if any from the incoming string If Not FileExists($FGP_Path) Then Return SetError(1, 0, "") ; path not found Local Const $objShell = ObjCreate("Shell.Application") If @error Then Return SetError(3, 0, "") Local Const $FGP_File = StringTrimLeft($FGP_Path, StringInStr($FGP_Path, "\", 0, -1)) Local Const $FGP_Dir = StringTrimRight($FGP_Path, StringLen($FGP_File) + 1) Local Const $objFolder = $objShell.NameSpace($FGP_Dir) Local Const $objFolderItem = $objFolder.Parsename($FGP_File) Local $Return = "", $iError = 0 If $FGP_PROPERTY Then For $I = 0 To $iPropertyCount If $objFolder.GetDetailsOf($objFolder.Items, $I) = $FGP_PROPERTY Then $Return = $objFolder.GetDetailsOf($objFolderItem, $I) EndIf Next If $Return = "" Then $iError = 2 EndIf Else Local $av_ret[$iPropertyCount + 1][2] = [[0]] For $I = 1 To $iPropertyCount If $objFolder.GetDetailsOf($objFolder.Items, $I) Then $av_ret[$I][0] = $objFolder.GetDetailsOf($objFolder.Items, $I - 1) $av_ret[$I][1] = $objFolder.GetDetailsOf($objFolderItem, $I - 1) ;~ $av_ret[0][0] += 1 $av_ret[0][0] = $I EndIf Next ReDim $av_ret[$av_ret[0][0] + 1][2] If Not $av_ret[1][0] Then $iError = 2 $av_ret = $Return Else $Return = $av_ret EndIf EndIf Return SetError($iError, 0, $Return) EndFunc ;==>_FileGetProperty Parsix 1
Solution UEZ Posted October 7, 2025 Solution Posted October 7, 2025 (edited) Does this work? ;Coded by UEZ build 2025-10-07 #include <WinAPIGdi.au3> Local $sFontFile = FileOpenDialog("Select a font", "", "Fonts (*.ttf)") If $sFontFile = "" Or @error Then Exit ConsoleWrite("Title: " & _WinAPI_GetFontTitle($sFontFile) & @CRLF) Func _WinAPI_GetFontTitle($sFont) If Not _WinAPI_AddFontResourceEx($sFontFile, $FR_PRIVATE) Then Return SetError(1, 0, 0) Local $tFont = DllStructCreate("wchar title[4096]") Local $aRet = DllCall("gdi32.dll", "bool", "GetFontResourceInfoW", "wstr", $sFontFile, "dword*", DllStructGetSize($tFont), "struct*", $tFont, "dword", 1) If @error Or Not $aRet[0] Then _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return SetError(2, 0, 0) EndIf _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return $tFont.title EndFunc Edited October 7, 2025 by UEZ Parsix and WildByDesign 2 Please don't send me any personal message and ask for support! I will not reply! Selection of finest graphical examples at Codepen.io The own fart smells best! ✌Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!¯\_(ツ)_/¯ ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ
WildByDesign Posted October 7, 2025 Posted October 7, 2025 22 minutes ago, UEZ said: Does this work? Yes this works great. Works in C:\Windows\Fonts directory as well. Parsix 1
WildByDesign Posted October 7, 2025 Posted October 7, 2025 (edited) Although some of them show really long Title which does not show on Properties - Details tab: Title: Monaspace Argon Var ExtraLight Wide Italic & Monaspace Argon Var Light Wide Italic & Monaspace Argon Var Wide Italic & Monaspace Argon Var Medium Wide Italic & Monaspace Argon Var SemiBold Wide Italic & Monaspace Argon Var Bold Wide Italic & Monaspace Argon Var ExtraBold Wide Italic & Monaspace Argon Var ExtraLight Italic & Monaspace Argon Var Light Italic & Monaspace Argon Var Italic & Monaspace Argon Var Medium Italic & Monaspace Argon Var SemiBold Italic & Monaspace Argon Var Bold Italic & Monaspace Argon Var ExtraBold Italic & Monaspace Argon Var ExtraLight SemiWide Wide Italic & Monaspace Argon Var Light SemiWide Wide Italic & Monaspace Argon Var SemiWide Wide Italic & Monaspace Argon Var Medium SemiWide Wide Italic & Monaspace Argon Var SemiBold SemiWide Wide Italic & Monaspace Argon Var Bold SemiWide Wide Italic & Monaspace Argon Var ExtraBold SemiWide Wide Italic & Monaspace Argon Var ExtraLight SemiWide Italic & Monaspace Argon Var Light SemiWide Italic & Monaspace Argon Var SemiWide Italic & Monaspace Argon Var Medium SemiWide Italic & Monaspace Argon Var SemiBold SemiWide Italic & Monaspace Argon Var Bold SemiWide Italic & Monaspace Argon Var ExtraBold SemiWide Italic & Monaspace Argon Var ExtraLight Wide Wide Italic & Monaspace Argon Var Light Wide Wide Italic & Monaspace Argon Var Wide Wide Italic & Monaspace Argon Var Medium Wide Wide Italic & Monaspace Argon Var SemiBold Wide Wide Italic & Monaspace Argon Var Bold Wide Wide Italic & Monaspace Argon Var ExtraBold Wide Wide Italic & Monaspace Argon Var ExtraLight Wide Italic & Monaspace Argon Var Light Wide Italic & Monaspace Argon Var Wide Italic & Monaspace Argon Var Medium Wide Italic & Monaspace Argon Var SemiBold Wide Italic & Monaspace Argon Var Bold Wide Italic & Monaspace Argon Var ExtraBold Wide Italic EDIT: Now that I think of it, though, I think that yours is probably more accurate than what MS shows in Explorer's Properties - Details tab. MS seems to just cut it off at a certain amount of characters, I can only assume. Edited October 7, 2025 by WildByDesign Parsix 1
MattyD Posted October 7, 2025 Posted October 7, 2025 (edited) UEZ's solution is better - but I did the work so... Technically it'll be in the ttf/otf itself in the name table expandcollapse popup#include <AutoitConstants.au3> #include <FileConstants.au3> Local $hFontFile = FileOpen("C:\Windows\Fonts\wingding.ttf", $FO_BINARY) Local $tagTTCHeader = "align 4; uint sfntVersion; ushort numTables; ushort searchRange; ushort entrySelector; ushort rangeShift" Local $tTTCHeader = DllStructCreate($tagTTCHeader) Local $iTTCHeaderLen = DllStructGetSize($tTTCHeader) Local $tTTCHeaderBuff = DllStructCreate(StringFormat("byte data[%d]", $iTTCHeaderLen), DllStructGetPtr($tTTCHeader)) $tTTCHeaderBuff.Data = FileRead($hFontFile, $iTTCHeaderLen) Local $iNumTables = _ByteSwap($tTTCHeader.numTables, 16) Local $tagTableRecord = "align 4; char tag[4]; uint checksum; uint offset; uint length" Local $tTableRecord = DllStructCreate($tagTableRecord) Local $iTableRecordLen = DllStructGetSize($tTableRecord) Local $tTableRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iTableRecordLen), DllStructGetPtr($tTableRecord)) Local $iNameTabOffset, $iNameTabTotalLen For $i = 1 To $iNumTables $tTableRecordBuff.Data = FileRead($hFontFile, $iTableRecordLen) ConsoleWrite(StringFormat("table: %s Offset: %08x Length: %08x\r\n", _ $tTableRecord.tag, _ByteSwap($tTableRecord.Offset), _ByteSwap($tTableRecord.Length))) If $tTableRecord.tag = "name" Then $iNameTabOffset = _ByteSwap($tTableRecord.Offset) $iNameTabLen = _ByteSwap($tTableRecord.Length) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset, $FILE_BEGIN) Local $tagNameTable = "align 4; ushort version; ushort count; ushort storageOffset" Local $tNameTable = DllStructCreate($tagNameTable) Local $iNameTabLen = DllStructGetSize($tNameTable) Local $tNameTableBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameTabLen), DllStructGetPtr($tNameTable)) $tNameTableBuff.data = FileRead($hFontFile, $iNameTabLen) Local $iNameRecordCount = _ByteSwap($tNameTable.count, 16) Local $iNameStorageOffset = _ByteSwap($tNameTable.storageOffset, 16) Local $tagNameRecord = "align 4; ushort platformID; ushort encodingID; ushort languageID; ushort nameID; ushort length; ushort stringOffset;" Local $tNameRecord = DllStructCreate($tagNameRecord) Local $iNameRecordLen = DllStructGetSize($tNameRecord) Local $tNameRecordBuff = DllStructCreate(StringFormat("byte data[%d]", $iNameRecordLen), DllStructGetPtr($tNameRecord)) Local $iFontFamilyNameOffset, $iFontFamilyNameLen For $i = 1 To $iNameRecordCount $tNameRecordBuff.data = FileRead($hFontFile, $iNameRecordLen) ConsoleWrite(StringFormat("NameRecord: nameID: %04x length %04x offset %04x", _ _ByteSwap($tNameRecord.nameID, 16), _ByteSwap($tNameRecord.length, 16), _ByteSwap($tNameRecord.stringOffset, 16)) & @CRLF) If _ByteSwap($tNameRecord.nameID, 16) = 1 Then ; Font Family name. $iFontFamilyNameLen = _ByteSwap($tNameRecord.length, 16) $iFontFamilyNameOffset = _ByteSwap($tNameRecord.stringOffset, 16) ExitLoop EndIf Next FileSetPos($hFontFile, $iNameTabOffset + $iNameStorageOffset + $iFontFamilyNameOffset, $FILE_BEGIN) Local $tFontFamilyName = DllStructCreate(StringFormat("char Name[%d]", $iFontFamilyNameLen)) Local $tFontFamilyNameBuff = DllStructCreate(StringFormat("byte data[%d]", $iFontFamilyNameLen), DllStructGetPtr($tFontFamilyName)) $tFontFamilyNameBuff.Data = FileRead($hFontFile, $iFontFamilyNameLen) MsgBox(0, "Font Family Name", $tFontFamilyName.Name) FileClose($hFontFile) Func _ByteSwap($iInt, $iSize = 32) Switch $iSize Case 16 Return BitAND(0xFFFF, BitOR(BitAND(0xFF00, BitShift($iInt, -8)), BitShift($iInt, 8))) Case 32 Local $tBuff = DllStructCreate("byte[4]") For $i = 1 To 4 DllStructSetData($tBuff, 1, BitAND($iInt, 0xFF), 5-$i) $iInt = BitShift($iInt, 8) Next Local $tInt = DllStructCreate("int", DllStructGetPtr($tBuff)) Return DllStructGetData($tInt, 1) EndSwitch EndFunc Edited October 7, 2025 by MattyD tidy UEZ, ioa747 and WildByDesign 3
ioa747 Posted October 7, 2025 Posted October 7, 2025 some observations #include <WinAPIGdi.au3> ;Coded by WildByDesign 1st post Local $sFontFile = "C:\Windows\Fonts\Rubik-VariableFont_wght.ttf" ConsoleWrite("Title: " & _WinAPI_GetFontResourceInfo($sFontFile, True) & @CRLF) ConsoleWrite(@CRLF) ;Coded by UEZ build 2025-10-07 ;~ Local $sFontFile = FileOpenDialog("Select a font", "", "Fonts (*.ttf)") If $sFontFile = "" Or @error Then Exit ConsoleWrite("Title: " & _WinAPI_GetFontTitle($sFontFile) & @CRLF) Func _WinAPI_GetFontTitle($sFont) If Not _WinAPI_AddFontResourceEx($sFontFile, $FR_PRIVATE) Then Return SetError(1, 0, 0) Local $tFont = DllStructCreate("wchar title[4096]") Local $aRet = DllCall("gdi32.dll", "bool", "GetFontResourceInfoW", "wstr", $sFontFile, "dword*", DllStructGetSize($tFont), "struct*", $tFont, "dword", 1) If @error Or Not $aRet[0] Then _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return SetError(2, 0, 0) EndIf _WinAPI_RemoveFontResourceEx($sFontFile, $FR_PRIVATE) Return $tFont.title EndFunc From what I understand, Parsix is looking for this, which WildByDesign already published in the 1st post ;Coded by WildByDesign 1st post #include <WinAPIGdi.au3> Local $sFontFile = "C:\Windows\Fonts\Rubik-VariableFont_wght.ttf" FontGetInfoFromFile($sFontFile, 1, "Font Family name") FontGetInfoFromFile($sFontFile, 4, "Font full name") Func FontGetInfoFromFile($sFile, $n, $sElement) Local $s = _WinAPI_GetFontResourceInfo($sFile, Default, $n) If Not @error And $s Then ConsoleWrite($sElement & " = " & $s & @CRLF) EndFunc ;==>FontGetInfoFromFile WildByDesign the only thing that confused me is the 256 FontGetInfoFromFile($sFile, 256, "Font-specific names") since _WinAPI_GetFontMemoryResourceInfo only shows up to 20 (maybe undocumented)? Parsix and WildByDesign 2 I know that I know nothing
WildByDesign Posted October 7, 2025 Posted October 7, 2025 2 minutes ago, ioa747 said: From what I understand, Parsix is looking for this, I agree, the title generally should be equal to the information pulled from that first function. Although I have not checked too many fonts to compare. 3 minutes ago, ioa747 said: the only thing that confused me is the 256 Probably undocumented, not sure. I got that from the _WinAPI_GetFontResourceInfo docs, Example 3. ioa747 and Parsix 2
Parsix Posted October 8, 2025 Author Posted October 8, 2025 17 hours ago, WildByDesign said: I agree, the title generally should be equal to the information pulled from that first function. Although I have not checked too many fonts to compare. Probably undocumented, not sure. I got that from the _WinAPI_GetFontResourceInfo docs, Example 3. thanks all I was also skeptical due to the discrepancy in the features. On the other hand, the file attribute indicated something else. WildByDesign 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now