The MASM Forum Archive 2004 to 2012

General Forums => The Campus => Topic started by: starzboy on December 17, 2008, 10:45:58 AM

Title: Enumerate all fonts installed
Post by: starzboy on December 17, 2008, 10:45:58 AM
Hello guys, i have been looking lately at EnumFonts, as i need to list all fonts installed on the system.
So far i have been unsuccessfull, can some please some shed some light on it or perhaps an example.

Thnakyou
Title: Re: Enumerate all fonts installed
Post by: kromag on December 17, 2008, 02:00:15 PM
I just seen a post by Donkey (http://www.masm32.com/board/index.php?topic=10327.msg75617#msg75617") where
he claims to have something doing the same on his site!
---
Will
Title: Re: Enumerate all fonts installed
Post by: donkey on December 17, 2008, 04:31:22 PM
The example is for a font menu, the actual snippet for enumerating fonts is this....

// load the LOGFONT structure to pass info to the enumeration API
mov B[lf.lfCharSet],ANSI_CHARSET
mov B[lf.lfFaceName],0
mov B[lf.lfPitchAndFamily],0
// We need a device context in order to enumerate fonts, any screen window will do (or printer DC if you want printer fonts)
invoke GetDlgItem,[hDlg],1001
mov esi,eax
invoke GetDC,esi
mov ebx,eax
invoke EnumFontFamiliesExA,ebx,ADDR lf,OFFSET EnumFontFamExProc,[SubMenuHandle],0
// release the device context
invoke ReleaseDC,esi,ebx


EnumFontFamExProc FRAME lpelfe,lpntme,FontType,lParam
uses ebx

// The font data is passed in a ENUMLOGFONTEX struct at address lpelfe
// you can get the font name from that structure in ENUMLOGFONTEX.LOGFONT.lfFaceName
// Or alternatively you can use the full font name in ENUMLOGFONTEX.elfFullName
// Note that ENUMLOGFONTEX.elfFullName doesn't provide the same data on 9x and NT based systems
mov ebx,[lpelfe]
add ebx,ENUMLOGFONTEX.elfFullName
// EBX points to the full font name

... Do what you want to with the font name here

// continue the enumeration until all fonts are processed
mov eax,TRUE
RET
ENDF
Title: Re: Enumerate all fonts installed
Post by: Rainstorm on December 18, 2008, 02:29:53 AM
just a related question. . .
suppose i want to display info on  fonts that are not in the font table but like in a folder, what would i do ?
successively load each font into the font table, get the info i want.. then unload it ? or is there some other way ?
- - - - - - - - - - -
Also, suppose i supply a typeface name in the LOGFONT structure, but that font wasn't found..would the function return some other font that matched the criteria most closely ? - and if it did.. would it alert me to the fact that it is not the typeface name i asked for .

thanks!
Title: Re: Enumerate all fonts installed
Post by: donkey on December 18, 2008, 03:16:49 AM
Since the API really only allows you to get information about a font with reference to the device context and handle of the font, it must be added to the font table before you can examine it. Windows allows an application to add a font (for its use only if you like) and remove it, you can add the font using AddFontResource (http://msdn.microsoft.com/en-us/library/ms534231(VS.85).aspx) enumerate it then remove it using RemoveFontResource. Alternatively you can examine the file directly by writing a parser to read the TTF file format (http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6.html) (if you are working with true type fonts) which is very similar to RIFF files in structure.
Title: Re: Enumerate all fonts installed
Post by: Rainstorm on December 18, 2008, 11:59:45 AM
thanks for the advice & the useful link   :thumbu
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 07, 2011, 11:55:48 PM
    i kinda took this from your post donkey and made an example out of it, Very simple thingy. Thanks for the help donkey. It was something i dodnt know how to do.
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 12:58:06 PM
   Hey... i was trying to upgrade the enumfonts thingy to show the actually font draw within the listbox but things aren't working yet. I'm just processing ODA_DRAWENTIRE at the moment. I don't know if there's something wrong with the ENUMLOGFONTEX pointer. Can someone check this out? Thanks
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 01:21:10 PM
your attachment has no enumeration code
it makes a nice window, is all   :bg

i did notice the absence of
WndProc PROC uses edi hWnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 01:27:50 PM
   Sorry. I'm not sure what you mean but i'm devastated. Thanks
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 01:31:33 PM
in WndProc, you use EDI without preserving it
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 01:33:47 PM
   yeah.... i tried uses edi esi and doesn't work wither.
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 01:39:05 PM
well - that is A problem - not the only problem

in the EnumFontFamExProc callback function, you are not accessing the LOGFONT structure members
it says you can cast it as a ENUMLOGFONTEX struc, but that over-complicates things if you do not need the metrics
just cast it as a LOGFONT to access the members
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 01:45:16 PM
if you do want the metrics, to access members of the LOGFONT part of the ENUMLOGFONTEX struc, use...
assume  esi:PTR ENUMLOGFONTEX
mov eax,dword ptr [esi].elfLogFont.lfFaceName

to get the first 4 letters of the name of the font, for example

the LOGFONT struc is a sub-member of the ENUMLOGFONTEX struc
it is named elfLogFont
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 02:03:05 PM
   Damn i get register value overwritten by invoke. Any ideas on what this means? Can fix it.
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 02:09:55 PM
it probably means that you ran out of registers by using ADDR
show me the invoke line   :bg
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 02:21:32 PM
i see another little issue
you are filling the list during WM_CREATE, then sending strings to it
the window hasn't been created, yet

not sure, but i think that thing will enumerate fonts all day long
it will list each font, size, pitch/family until it goes through all of them   :P
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 02:24:55 PM
;assemble as a GUI app

        include \masm32\include\masm32rt.inc

        .data

lf      LOGFONT <>
cf      CHOOSEFONT <>

        .code

start:  mov     cf.lStructSize,sizeof CHOOSEFONT
        mov     cf.rgbColors,NULL
        mov     cf.hwndOwner,NULL
        mov     cf.lpLogFont,offset lf
        mov     cf.Flags,CF_SCREENFONTS or CF_EFFECTS
        INVOKE  ChooseFont,offset cf
        exit

        end     start


:P
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 02:25:54 PM
    Oh yeah.... that might be the issue. Thanks
invoke Line:
mov eax,dword ptr [esi].elfLogFont.lfFaceName
invoke DrawText,[edi].hdc,eax,-1,[edi].rcItem,DT_LEFT
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 02:30:39 PM
also - you want an address in EAX
change this
mov eax,dword ptr [esi].elfLogFont.lfFaceName
to this
lea eax,[esi].elfLogFont.lfFaceName

and - [edi].rcItem - it wants a pointer to a RECT struc
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 02:57:12 PM
i have enumerated sizes of a single font
it is much simpler than enumerting all the fonts
in the callback, i just put the info i wanted into a buffer, then display it all after enumeration is done

here is the invoke
        INVOKE  GetDC,NULL
        mov     hDc,eax

        mov dword ptr LogFnt.lfFaceName,6D726554h            ;'Term'
        mov dword ptr LogFnt.lfFaceName+4,6C616E69h          ;'inal'
        mov byte ptr LogFnt.lfFaceName+8,0
        mov byte ptr LogFnt.lfCharSet,OEM_CHARSET            ;EQU 255
        mov byte ptr LogFnt.lfPitchAndFamily,0
        INVOKE  EnumFontFamiliesEx,hDc,offset LogFnt,EnumFntCB,0,0

and i store the pointer into the buffer in lstPtr...
        OPTION  PROLOGUE:None
        OPTION  EPILOGUE:None

EnumFntCB PROC  lpLogFont:DWORD,lpMetric:DWORD,fType:DWORD,lParam:DWORD

        mov     edx,[esp+4]
        mov     eax,lstPtr
        movzx   ecx,byte ptr[edx]
        mov     ch,[edx+4]
        mov     [eax],ecx
        add     eax,4
        mov     lstPtr,eax
        ret     16

EnumFntCB ENDP

        OPTION  PROLOGUE:PrologueDef
        OPTION  EPILOGUE:EpilogueDef

after it is done, the buffer contains a list of dwords, one for each size of that font
lstPtr tells me how many are in the list
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 03:12:35 PM
   Thanks but i feel kinda defeated. Moving on to something else.
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 03:14:40 PM
   btw. If im trying to execute code that must be done once outside WM_CREATE like in this case what should i do? Should i send a WM_USER or something. i tried to process WM_CREATE for the listbox but don't know why it doesnt seem to send the message.
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 04:14:30 PM
easy enough
you can put it in WinMain at the appropriate place
you can create the list in a buffer before the window is created
just make sure you don't over-run your buffer - you are enumerating a lot of stuff   :bg
you could put a failsafe in the enumeration callback that skips entries if the buffer is full
then - let WM_PAINT show the text from the buffer
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 05:17:55 PM
   Well.... i guess that all i can say is thanks and i'm looking into it tho it seems kinda hard. I've managed some other hard things before ( for my semi-initiate level ) so i guess i can  handle it. latters and thanks
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 09, 2011, 05:47:47 PM
not that bad - i may play with it later if i make good progress on my project
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 08:10:48 PM
   yeah, please do. I kinda tried lots of things and came up with this accoording with your advice. It's kinda clean but the pointers are bad. The font is always the same and lfFaceName too. Thanks
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 08:11:23 PM
   ooops. forgot to attach
Title: Re: Enumerate all fonts installed
Post by: Gunner on January 09, 2011, 10:17:48 PM
I don't use assume myself, but you do:
assume  edi:PTR DRAWITEMSTRUCT
assume  esi:PTR LOGFONT


once you are done casting the regs, you are supposed to "un assume" them

assume esi:nothing
assume edi:nothing

or bugs will def creep in...
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 09, 2011, 10:52:53 PM
   really? i've seen that before but didn't realise what it was about. Could that be important? i'm not using esi/edi on anything else inside WndProc. Thanks Gunner
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 10, 2011, 01:29:51 AM
well - that is important - and i forgot about it, too
but, the last attempt i looked at had some other problems
mainly, the enumerate call was in the message handler and called whenever there was no handled message
that function only needs to be called once, in this case
and, because you are trying to enumerate all fonts, it may take some time
i had a busy day today, so didn't get to play with it
perhaps tomorrow i'll give it a shot   :bg
Title: Re: Enumerate all fonts installed
Post by: Gunner on January 10, 2011, 02:00:54 AM
I found this rar (converted to zip just now) file on the net a long while ago (Took some time to find in all my files).  It enumerates all the installed fonts and loads up a combobox with the names...  You should be able to modify it to draw the font names in the font.

I might even try this  :bg
Title: Re: Enumerate all fonts installed
Post by: donkey on January 10, 2011, 03:26:58 AM
Just looked at this thread, the code snippet at the beginning was part of a demo available on my website to create a font menu, each font on the menu drawn in that font.

Font Menu (http://www.quickersoft.com/donkey/files/FontMenu.zip)

You might find it useful for some ideas.

Edgar
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 10, 2011, 05:13:34 AM
both are good examples, guys   :U
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 10, 2011, 07:07:55 PM
   yes dave. But you might have missed the face that the enum call is only made if ENUM_FLAG==FALSE. After the enumeration is done i set ENUM_FLAG to TRUE ( or some other value, it's irrelevant cause it only responds to false ), and, so, the call is only made once. Going to check gunner's example. Thanks
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 10, 2011, 07:13:56 PM
   Gunner, tho the WM_DRAWITEM processing is not yet fine, the problems i'm dealing with , have to do with pointers. Mainly DRAWITEM.itemID, which is sent with LB_ADDSTRING as an ENUMLOGFONTEX stucture. The Font that is created dispite the itemID changes and the lfFaceName always seems to be the same. Don't know why but as dave would say.... : working on it. Thanks
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 11, 2011, 08:31:15 PM
   The best that could be done for now. Nothing wrong with the pointers. Not sure why things go wrong with the listbox. I Could add a scroller if i knew how to process it. Thanks
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 12:19:36 PM
   Go it working with the listbox. It's not ready to process item selection or anything. It only draws items on creation so if you try it out try not to click the items. I noticed that sometimes it crashes so it needs some fixing. Thanks guys
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 01:45:33 PM
    I think that there might be some sort of problem with memory alloc/free because the program errors on exit. does anyone know why? Thanks
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 15, 2011, 03:54:46 PM
could it be that you are missing a call to LocalUnlock ?
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 09:38:37 PM
   no... it has localunlock but maybe it aint working somehow, thanks and bye. working on it
Title: Re: Enumerate all fonts installed
Post by: dedndave on January 15, 2011, 10:07:35 PM
i suggest you double-check
it has LocalAlloc, LocalLock, and LocalFree
i don't see LocalUnlock
now, i am not sure that's the problem
but, it seems to me that the block cannot be freed unless the lock count is 0

easy enough to check
LocalFree should return EAX = 0
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 10:13:31 PM
   Maybe not on the one i posted. Right not on that one. The problem has to do with it. But it seems to work fine with LPTR flag on allocation and neither unlock ( which from what i've read doesn't work with LMEM_FIXED ) nor Freeing.
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 10:17:43 PM
   Final version yet to be released. LOL.
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 15, 2011, 10:18:23 PM
  ooops. forgot to attach
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 16, 2011, 12:18:55 AM
   New version available. Allows selection tho it does nothing but its cool.
Title: Re: Enumerate all fonts installed
Post by: xandaz on January 16, 2011, 01:20:51 PM
   Does anyone know how many times WM_DRAWITEM is called when drawing an item. I was trying to make a window that'd display the alphabet for the selected font, but, when i select an item appears more than one window. The WM_DRAWITEM causes the CreateThread function when ODS_SELEECTED.
Title: Re: Enumerate all fonts installed
Post by: elmo on April 01, 2011, 03:53:13 AM
hi Donkey, your code will replace font type of all text that the user type on the Editor.
As the result, this can't be used by the user who want to use more than 1 font type in the editor. lol
I think how to modify your code. So, it only change the font type of the Text that User selected.

like the following code. It only do BOLD to the Text that the user selected in the Editor.


        .data?
cfm CHARFORMAT2 <>
nLastError DWORD ?
.
.
.

.code
.
.
.
.
mov cfm.cbSize, sizeof cfm
mov cfm.dwMask, (CFM_BOLD or CFM_FACE)
mov cfm.cbSize,60
;GET BOLD STATUS
invoke SendMessage, hEdit1, EM_GETCHARFORMAT, TRUE, ADDR cfm
;TOGGLE BOLD EFFECT
xor cfm.dwEffects, CFE_BOLD
;SET NEW BOLD STATUS
invoke SendMessage, hEdit1, EM_SETCHARFORMAT, SCF_SELECTION, ADDR cfm
.if eax == NULL
invoke GetLastError
mov nLastError,eax
invoke FormatMessage,FORMAT_MESSAGE_FROM_SYSTEM,NULL, nLastError, NULL, ADDR szMsgBuff, 128, NULL
invoke MessageBoxEx, NULL, ADDR szMsgBuff, SADD("Error in EM_SETPARAFORMAT"),MB_OK+MB_ICONINFORMATION, LANG_ENGLISH
.endif
xor eax, eax
Title: Re: Enumerate all fonts installed
Post by: donkey on April 01, 2011, 04:52:25 AM
Hi elmo,

The code was only a demo to show how to enumerate fonts, if I remember correctly I only put in the edit window as an after thought, it was never meant to be a real editor. Feel free to modify it to your needs though.