Jump to content
Topher

How to know if a font exists?

Recommended Posts

Topher

Is there anyway to tell if a certain font exists.

GUICtrlSetFont does not return false if the font does not exist.

And the name of the font isn't the name of the file.

I want to use a font that is only in Windows 7 and so would like to use a different font for Vista or XP.

I could test for the OS but would like the more certain approach of searching for whether a font exists or not.

But I have no idea how to code for this.

Edited by Topher

[left][hr]
$mood = "whimsy"
$mode = "confused"
$randomChaos = True
Do
Something()
Until $Tired
[/left][left]Reflex (Arcade game)[/left][left]IX (Board game)[/left][left]The Word Game (Word game)[/left][left]Plastic Sliding Squares Puzzle (Puzzle)[/left]

Share this post


Link to post
Share on other sites
Topher

Thanks

What I have scrounged and cobbled from that and others is:

#Include <Array.au3>
#Include <File.au3>
msgbox(0,"", Font_Exists("Times New Rman"))
Func Font_Exists($FontName)
Local $FileList = _FileListToArray(@WindowsDir & "Fonts", '*.*', 1)
Local $FontList[UBound($FileList) - 1]
For $i = 1 To $FileList[0]
  $FontList[$i - 1] = _WinAPI_GetFontResourceInfo($FileList[$i], 1)
Next
For $i = 0 To UBound($FontList)-1
  If $FontList[$i] == $FontName Then Return 1
Next
Return 0
EndFunc
; Code below is a subset of WinAPIEx by Yashied
; http://www.autoitscript.com/forum/topic/98712-winapiex-udf/
Func _WinAPI_RemoveFontMemResourceEx($hFont)
Local $Ret = DllCall('gdi32.dll', 'int', 'RemoveFontMemResourceEx', 'ptr', $hFont)
If (@error) Or (Not $Ret[0]) Then
  Return SetError(1, 0, 0)
EndIf
Return 1
EndFunc   ;==>_WinAPI_RemoveFontMemResourceEx
Func _WinAPI_GetFontResourceInfo($sFont, $fForce = 0)
If $fForce Then
  If Not _WinAPI_AddFontResourceEx($sFont, 0x20) Then
   Return SetError(1, 0, '')
  EndIf
EndIf
Local $Ret = DllCall('gdi32.dll', 'int', 'GetFontResourceInfoW', 'wstr', $sFont, 'dword*', 4096, 'wstr', '', 'dword', 0x01)
If (@error) Or (Not $Ret[0]) Then
  $Ret = 0
EndIf
If $fForce Then
  _WinAPI_RemoveFontResourceEx($sFont, 0x20)
EndIf
If Not IsArray($Ret) Then
  Return SetError(1, 0, '')
EndIf
Return $Ret[3]
EndFunc   ;==>_WinAPI_GetFontResourceInfo
Func _WinAPI_AddFontResourceEx($sFont, $iFlag = 0, $fNotify = 0)
Local $Ret = DllCall('gdi32.dll', 'int', 'AddFontResourceExW', 'wstr', $sFont, 'dword', $iFlag, 'ptr', 0)
If (@error) Or (Not $Ret[0]) Then
  Return SetError(1, 0, 0)
EndIf
If $fNotify Then
  DllCall('user32.dll', 'none', 'SendMessage', 'hwnd', 0xFFFF, 'uint', 0x001D, 'wparam', 0, 'lparam', 0)
EndIf
Return $Ret[0]
EndFunc   ;==>_WinAPI_AddFontResourceEx
Func _WinAPI_RemoveFontResourceEx($sFont, $iFlag = 0, $fNotify = 0)
Local $Ret = DllCall('gdi32.dll', 'int', 'RemoveFontResourceExW', 'wstr', $sFont, 'dword', $iFlag, 'ptr', 0)
If (@error) Or (Not $Ret[0]) Then
  Return SetError(1, 0, 0)
EndIf
If $fNotify Then
  DllCall('user32.dll', 'none', 'SendMessage', 'hwnd', 0xFFFF, 'uint', 0x001D, 'wparam', 0, 'lparam', 0)
EndIf
Return 1
EndFunc   ;==>_WinAPI_RemoveFontResourceEx

Is '@WindowsDir & "Fonts"' the font directory for all versions of Windows?

Edited by Topher

[left][hr]
$mood = "whimsy"
$mode = "confused"
$randomChaos = True
Do
Something()
Until $Tired
[/left][left]Reflex (Arcade game)[/left][left]IX (Board game)[/left][left]The Word Game (Word game)[/left][left]Plastic Sliding Squares Puzzle (Puzzle)[/left]

Share this post


Link to post
Share on other sites
Yashied

Is '@WindowsDir & "Fonts"' the font directory for all versions of Windows?

Preferable to use the following:

#Include <APIConstants.au3>
#Include <WinAPIEx.au3>

ConsoleWrite(_WinAPI_ShellGetSpecialFolderPath($CSIDL_FONTS) & @CR)

Or it could also be for Vista+:

#Include <APIConstants.au3>
#Include <WinAPIEx.au3>

ConsoleWrite(_WinAPI_ShellGetKnownFolderPath($FOLDERID_Fonts) & @CR)

But if you want to know about the existence of any font on your system, you can use the following function:

#Include <APIConstants.au3>
#Include <Array.au3>
#Include <WinAPIEx.au3>

;Global Const $ANSI_CHARSET = 0
Global Const $ARABIC_CHARSET = 178
;Global Const $BALTIC_CHARSET = 186
;Global Const $CHINESEBIG5_CHARSET = 136
;Global Const $DEFAULT_CHARSET = 1
;Global Const $EASTEUROPE_CHARSET = 238
;Global Const $GB2312_CHARSET = 134
;Global Const $GREEK_CHARSET = 161
;Global Const $HANGEUL_CHARSET = 129
Global Const $HEBREW_CHARSET = 177
Global Const $JOHAB_CHARSET = 130
;Global Const $MAC_CHARSET = 77
;Global Const $OEM_CHARSET = 255
;Global Const $RUSSIAN_CHARSET = 204
;Global Const $SHIFTJIS_CHARSET = 128
;Global Const $SYMBOL_CHARSET = 2
Global Const $THAI_CHARSET = 222
;Global Const $TURKISH_CHARSET = 162
;Global Const $VIETNAMESE_CHARSET = 163

Global Const $DEVICE_FONTTYPE = 0x2
Global Const $RASTER_FONTTYPE = 0x1
Global Const $TRUETYPE_FONTTYPE = 0x4

Global Const $TMPF_DEVICE = 0x8
Global Const $TMPF_FIXED_PITCH = 0x1
Global Const $TMPF_TRUETYPE = 0x4
Global Const $TMPF_VECTOR = 0x2

Global Const $NTM_BOLD = 0x00000020
Global Const $NTM_DSIG = 0x00200000
Global Const $NTM_ITALIC = 0x00000001
Global Const $NTM_MULTIPLEMASTER = 0x00080000
Global Const $NTM_NONNEGATIVE_AC = 0x00010000
Global Const $NTM_PS_OPENTYPE = 0x00020000
Global Const $NTM_REGULAR = 0x00000040
Global Const $NTM_TT_OPENTYPE = 0x00040000
Global Const $NTM_TYPE1 = 0x00100000

Opt('MustDeclareVars', 1)

Global $Data

; Enumerates all uniquely-named fonts excluding "@" fonts, which is designed for vertical text, in the ANSI character set
$Data = _WinAPI_EnumFontFamilies(0, '', $ANSI_CHARSET, BitOR($DEVICE_FONTTYPE, $TRUETYPE_FONTTYPE), '@*', 1)
If Not @error Then
    _ArrayDisplay($Data, '_WinAPI_EnumFontFamilies')
EndIf

; Enumerates all styles of "Arial" font in the ANSI character set
$Data = _WinAPI_EnumFontFamilies(0, 'Arial', $ANSI_CHARSET)
If Not @error Then
    _ArrayDisplay($Data, '_WinAPI_EnumFontFamilies')
EndIf

; #FUNCTION# ====================================================================================================================
; Name...........: _WinAPI_EnumFontFamilies
; Description....: Enumerates all uniquely-named fonts in the system that match the specified font characteristics.
; Syntax.........: _WinAPI_EnumFontFamilies ( [$hDC [, $sFaceName [, $iCharSet [, $iFontType [, $sPattern [, $fExclude]]]]]] )
; Parameters.....: $hDC       - A handle to the device context from which to enumerate the fonts. If this parameter is 0, the function
;                               uses a DC for the application's current screen.
;                  $sFaceName - The typeface name of the font. If this parameter is an empty string, the function enumerates one font is
;                               each available typeface name. If this parameter is a valid typeface name, the function enumerates all
;                               fonts with the specified name.
;                  $iCharSet  - The character set. It can be one of the following predefined values. If this parameter is set to
;                               $DEFAULT_CHARSET, the function enumerates all uniquely-named fonts in all character sets. (If there
;                               are two fonts with the same name, only one is enumerated.) If this parameter is set to a valid
;                               character set value, the function enumerates only fonts in the specified character set.
;
;                               $ANSI_CHARSET
;                               $ARABIC_CHARSET
;                               $BALTIC_CHARSET
;                               $CHINESEBIG5_CHARSET
;                               $DEFAULT_CHARSET
;                               $EASTEUROPE_CHARSET
;                               $GB2312_CHARSET
;                               $GREEK_CHARSET
;                               $HANGEUL_CHARSET
;                               $HEBREW_CHARSET
;                               $JOHAB_CHARSET
;                               $MAC_CHARSET
;                               $OEM_CHARSET
;                               $RUSSIAN_CHARSET
;                               $SHIFTJIS_CHARSET
;                               $SYMBOL_CHARSET
;                               $THAI_CHARSET
;                               $TURKISH_CHARSET
;                               $VIETNAMESE_CHARSET
;
;                  $iFontType - The type of the fonts to enumerating. This parameter can be 0 (vector fonts), (-1) (all fonts),
;                               or any combination of the following values.
;
;                               $DEVICE_FONTTYPE
;                               $RASTER_FONTTYPE
;                               $TRUETYPE_FONTTYPE
;
;                  $sPattern  - The pattern string to include (exclude) the fonts in (from) the enumerating. This makes sense only
;                               if the typeface name is not specified. This string can contain wildcard characters. The pattern
;                               will be ignored if this parameter is omitted or an empty string.
;                  $fExclude  - Specifies whether to use the pattern to exclude the fonts, valid values:
;                  |TRUE  - Exclude the matching fonts.
;                  |FALSE - Include the matching fonts. (Default)
; Return values..: Success    - The 2D array containing the following information:
;
;                               [0][0] - Number of rows in array (n)
;                               [0][1] - Unused
;                               [n][0] - The typeface name of the font.
;                               [n][1] - The style of the font.
;                               [n][2] - The unique name of the font.
;                               [n][3] - The script, that is, the character set, of the font.
;                               [n][4] - The type of the font ($*_FONTTYPE).
;                               [n][5] - The pitch, technology, and family of the font (same as in the TEXTMETRIC structure).
;                               [n][6] - The character set of the font ($*_CHARSET).
;                               [n][7] - The font flags ($NTM_*).
;
;                  Failure   - 0 and sets the @error flag to non-zero.
; Author.........: Yashied
; Modified.......:
; Remarks........: The fonts for many East Asian languages have two typeface names: an English name and a localized name. The function
;                  returns the English typeface name if the system locale does not match the language of the font.
;
;                  When the graphics mode on the device context is set to $GM_ADVANCED and the $DEVICE_FONTTYPE flag is specified,
;                  _WinAPI_EnumFontFamilies() returns a list of Type 1 and OpenType fonts on the system. When the graphics mode is not
;                  set to $GM_ADVANCED, this function returns a list of Type 1, OpenType, and TrueType fonts on the system.
; Related........:
; Link...........: @@MsdnLink@@ EnumFontFamiliesEx
; Example........: Yes
; ===============================================================================================================================

Func _WinAPI_EnumFontFamilies($hDC = 0, $sFaceName = '', $iCharSet = 1, $iFontType = 0x07, $sPattern = '', $fExclude = 0)

    Local $tLOGFONT = DllStructCreate('long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;wchar[32]')
;   Local $tLOGFONT = DllStructCreate($tagLOGFONT)
    Local $tPattern = DllStructCreate('uint;uint;ptr;wchar[' & (StringLen($sPattern) + 1) & ']')
    Local $hCDC, $hEnumProc, $Ret

    DllStructSetData($tPattern, 1, $iFontType)
    If Not $sPattern Then
        DllStructSetData($tPattern, 2, 0)
        DllStructSetData($tPattern, 3, 0)
    Else
        DllStructSetData($tPattern, 2, $fExclude)
        DllStructSetData($tPattern, 3, DllStructGetPtr($tPattern, 4))
        DllStructSetData($tPattern, 4, $sPattern)
    EndIf
    DllStructSetData($tLOGFONT, 9,  $iCharSet)
    DllStructSetData($tLOGFONT, 13, 0)
    DllStructSetData($tLOGFONT, 14, StringLeft($sFaceName, 32))
    If Not $hDC Then
        $hCDC = _WinAPI_CreateCompatibleDC(0)
    Else
        $hCDC = $hDC
    EndIf
    Dim $__Data[101][8] = [[0]]
    $hEnumProc = DllCallbackRegister('__EnumFontFamiliesProc', 'int', 'ptr;ptr;dword;ptr')
    $Ret = DllCall('gdi32.dll', 'int', 'EnumFontFamiliesExW', 'hwnd', $hCDC, 'ptr', DllStructGetPtr($tLOGFONT), 'ptr', DllCallbackGetPtr($hEnumProc), 'ptr', DllStructGetPtr($tPattern), 'dword', 0)
    If (@error) Or (Not $Ret[0]) Or (Not $__Data[0][0]) Then
        $__Data = 0
    EndIf
    DllCallbackFree($hEnumProc)
    If Not $hDC Then
        _WinAPI_DeleteDC($hCDC)
    EndIf
    If Not IsArray($__Data) Then
        Return SetError(1, 0, 0)
    EndIf
    __Inc($__Data, -1)
    Return $__Data
EndFunc   ;==>_WinAPI_EnumFontFamilies

Func __EnumFontFamiliesProc($pELFEX, $pNTMEX, $iFontType, $pPattern)

    Local $tELFEX = DllStructCreate('long;long;long;long;long;byte;byte;byte;byte;byte;byte;byte;byte;wchar[32];wchar[64];wchar[32];wchar[32]', $pELFEX)
;   Local $tELFEX = DllStructCreate($tagLOGFONT & ';wchar FullName[64];wchar Style[32];wchar Script[32]', $pELFEX)
    Local $tNTMEX = DllStructCreate('long;long;long;long;long;long;long;long;long;long;long;wchar;wchar;wchar;wchar;byte;byte;byte;byte;byte;dword;uint;uint;uint;dword[4];dword[2]', $pNTMEX)
;   Local $tNTMEX = DllStructCreate($tagNEWTEXTMETRICEX, $pNTMEX)
    Local $tPattern = DllStructCreate('uint;uint;ptr', $pPattern)
    Local $Ret

    If ($iFontType) And (Not BitAND($iFontType, DllStructGetData($tPattern, 1))) Then
        Return 1
    EndIf
    If DllStructGetData($tPattern, 3) Then
        $Ret = DllCall('shlwapi.dll', 'int', 'PathMatchSpecW', 'ptr', DllStructGetPtr($tELFEX, 14), 'ptr', DllStructGetData($tPattern, 3))
        If Not @error Then
            If DllStructGetData($tPattern, 2) Then
                If $Ret[0] Then
                    Return 1
                Else

                EndIf
            Else
                If $Ret[0] Then

                Else
                    Return 1
                EndIf
            EndIf
        EndIf
    EndIf
    __Inc($__Data)
    $__Data[$__Data[0][0]][0] = DllStructGetData($tELFEX, 14)
    $__Data[$__Data[0][0]][1] = DllStructGetData($tELFEX, 16)
    $__Data[$__Data[0][0]][2] = DllStructGetData($tELFEX, 15)
    $__Data[$__Data[0][0]][3] = DllStructGetData($tELFEX, 17)
    $__Data[$__Data[0][0]][4] = $iFontType
    $__Data[$__Data[0][0]][5] = DllStructGetData($tNTMEX, 19)
    $__Data[$__Data[0][0]][6] = DllStructGetData($tNTMEX, 20)
    $__Data[$__Data[0][0]][7] = DllStructGetData($tNTMEX, 21)
    Return 1
EndFunc   ;==>__EnumFontFamiliesProc

The third ([2]) array element contains the full name of the font which you need to pass to the GUISetFont() or GUICtrlSetFont() function.

Share this post


Link to post
Share on other sites
Inverted

The Help appendix has a "Standard Windows Fonts" section with info about OSes and fonts' availability. ;)

I think EnumFontFamiliesEx is overkill. A default font is used in case of failure afaik, so no big deal.

Share this post


Link to post
Share on other sites
Yashied

The problem in specifying the full name of the font. For different localizations, they may be different. For example

Times New Roman Bold Italic

Times New Roman Полужирный Курсив

etc.

Edited by Yashied

Share this post


Link to post
Share on other sites
Zedna

The Help appendix has a "Standard Windows Fonts" section with info about OSes and fonts' availability. ;)

I think EnumFontFamiliesEx is overkill. A default font is used in case of failure afaik, so no big deal.

Another example of use this can be barcode special fonts used by application

See my Barcode UDF in Examples

I can imagine that author of AutoIt's application using nonstandard barcode fonts could add this check if apropriate font is installed.

Share this post


Link to post
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now

×