News:

MASM32 SDK Description, downloads and other helpful links
MASM32.com New Forum Link
masmforum WebSite

Determining if a font is installed

Started by NoCforMe, November 10, 2011, 07:15:46 PM

Previous topic - Next topic

NoCforMe

I need to know whether a particular font is installed on the computer that my program is running on.

Not a font family, not a font that fits certain attributes: a specific font.

My first thought was that I could use the lfFaceName member of the LOGFONT structure to get the name of the font after calling CreateFontIndirect():



FontName DB "CrashNumberingSerif", 0

(zero out entire structure first)

INVOKE strcpy, ADDR FontName, ADDR lf.lfFaceName

MOV lf.lfHeight, $fontSize
MOV lf.lfCharSet, SYMBOL_CHARSET
MOV lf.lfOutPrecision, OUT_DEFAULT_PRECIS
MOV lf.lfClipPrecision, CLIP_DEFAULT_PRECIS
MOV lf.lfQuality, ANTIALIASED_QUALITY
MOV lf.lfPitchAndFamily, DEFAULT_PITCH
INVOKE CreateFontIndirect, ADDR lf
MOV FontHandle, EAX

(Look at lf.lfFaceName: it will still contain the original font name, unchanged)


(Note: don't worry about strcpy(); that's my own creation, not from the MSVCRT library)

but alas, the function doesn't update the structure. The problem was that even if the specific font I requested ("CrashNumberingSerif") didn't exist, CreateFontIndirect() would happily load another font that it thought was "close enough", given the parameters I set. (I checked this by setting the font name member to "boogers", which definitely doesn't exist as a font on my machine: the function still didn't fail. Makes me wonder what the purpose of that field really is: it seems to be more of a suggestion than a mandate to the function.)

So I came up with this scheme, which seems to work reliably:


; Check to see that the font we requested actually got created:
INVOKE GetDC, MainWinHandle
MOV hDC, EAX
INVOKE SelectObject, hDC, FontHandle
INVOKE GetTextFace, hDC, SIZEOF buffer, ADDR buffer
INVOKE ReleaseDC, MainWinHandle, hDC
INVOKE strcmp, OFFSET FontName, ADDR buffer
OR EAX, EAX
JNZ @f
INVOKE MessageBox, MainWinHandle, ADDR NoFontMsg, NULL, MB_OK
JMP exit

@@: (continue on ...)


My question is whether there's another way to do this, possibly a better way. This seems just a little bit klugey, not too much, but maybe that's the way it has to be done.

This also raises some questions about device contexts, which I'll save for another thread ...

MichaelW

eschew obfuscation

NoCforMe

I guess that would be another (the other?) way to do it. Seems like a lot of work, though, having to set up a callback function and all. Plus, I wonder if it might not be kinda time-consuming, at least on machines with a lot of fonts installed.

If I don't hear any strong objections, I think I'll stick with my method above.

dedndave

the callback enumerations are much easier than they appear   :P

NoCforMe

I know; I've done them.

At this point it seems like 6 of one, half a dozen of the other. Since enumeration would actually require a little more code, I prefer my method.

jj2007

#5
Quote from: dedndave on November 10, 2011, 11:03:31 PM
the callback enumerations are much easier than they appear   :P

They are incredibly simple, actually :8)

EDIT: The attachment has less than 40 lines and lists all installed fonts. Credits go to dedndave.

dedndave

another thought - if they don't have the font, you can carry it with you in resource
fonts take up a bit of space, of course
or you can give them a chance to install it

just spit-balling some options   :P