Kevin Ragsdale: Visual FoxPro 9.0

Respecting The User's Font Settings

Updated December 16, 2013: Source code from this post is available here.

All versions of Windows have a system font, which is used for menus, title bars, messageboxes, etc.

The Windows XP system font (except for a couple of Windows Classic themes) is Tahoma.

The system font for Windows Vista, Windows 7, and Windows 8 is Segoe UI.

I’ve seen apps which use a variety of fonts within the application. Some may use Arial for labels, but Courier New (or some other font) for all data-bound controls. I’ve seen arguments online about the pros and cons of using multiple fonts. For myself, though, I just don’t like seeing a mix-and-match approach to fonts in an app. The app menu and form captions will have the Windows system font, and the form itself may have two or three different fonts. This is simply too much for my old eyes (and slow brain) to take in.

This is, of course, a personal preference. I’m not making any right or wrong statements here - just sharing my opinion.

Since I want my apps to have a level of consistency and a professional Windows look and feel, I like for my forms and form objects to use the same font that Windows is using.

In an effort to define the lowest common denominator, I’ve decided to use Tahoma exclusively in Windows XP, and Segoe UI in Windows Vista and later.

In Doug’s Windows 7 session, he showed how he added code in the Init event of classes to change the font to Segoe UI if the user is running Windows Vista or later. I do the opposite: I check the OS and change the font to Tahoma if the user is running a pre-Vista version of Windows. This is again a personal preference; since I do my development work in Windows 7, I like to see the Segoe UI font while I’m doing my dev work.

Doug has posted a LOT of his whitepapers, articles and sample code on his web site. Comments about Segoe and Windows 7 can be found in this whitepaper.

It was mentioned during one of my sessions that if I am working on a team, and any members of the team are using Windows XP (or earlier), I’d want to develop in Tahoma exclusively and follow Doug’s method of switching to Segoe UI at runtime. An excellent suggestion!

Does The User Want Large Fonts?

I now have a way of ensuring my apps use one particular font. Now we need to see if the user has told Windows that she would like to use large fonts. I try to determine if the user wants to use large fonts for one simple reason: if the user wants large fonts, she usually has a reason (large monitor with high resolution, personal comfort, or perhaps she has a disability and needs to use large fonts). This way, my app can resize the forms and form controls automatically, to match the users needs.

With a couple of Windows API calls, I know right away if the user has selected large fonts in Windows. I’ve used the code listed below in the past for determining the font size setting, slightly modified from an article Doug Hennig wrote several years ago:

	
LOCAL liHDC, liPixelsPerInchX, ;
      liPixelsPerInchY, lnFontFactor

DECLARE INTEGER GetDC IN Win32API ;
   INTEGER iHDC

DECLARE INTEGER GetDeviceCaps IN WIN32API ;
   INTEGER iHDC, INTEGER iIndex

#DEFINE cnLOG_PIXELS_X 88
#DEFINE cnLOG_PIXELS_Y 90

liHDC = GetDC(ThisForm.HWnd)
liPixelsPerInchX = GetDeviceCaps(liHDC, cnLOG_PIXELS_X)
liPixelsPerInchY = GetDeviceCaps(liHDC, cnLOG_PIXELS_Y)

IF liPixelsPerInchX <= 96
   ** The user has selected "normal" font size
   lnFontFactor = 1
ELSE
   ** The user wants to use large fonts. The
   ** calculation will determine how large
   ** (by percentage) the fonts should be.
   lnFontFactor = 1 + ((liPixelsPerInchX - 96)/96)
ENDIF

MESSAGEBOX("The DPI 'font factor' is: " + ; 
		   ALLTRIM(TRANSFORM(lnFontFactor)),0,"Font Factor")

This code simply calls Windows and says, “Hey Windows, what’s the current DPI setting?” and displays the percentage I should bump up my visual controls by in order to match the users settings. When I run the code in Windows XP, with DPI set to the normal 96dpi, I get the following:

A font factor of 1 means I don’t need to do any resizing of any forms or form objects.

Setting the DPI in Windows XP to 120dpi results in this:

A font factor of 1.25 means the user wants to see things larger than the normal 96dpi, so I need to resize all of my visual controls in the app to be 25% larger.

For good measure, here’s the result when the DPI is set to 144dpi:

In this case, I’ll want to resize all of the visual controls by increasing their size by 50%.

So now it’s just a matter of resizing all controls on my form by multiplying the design time font size by the font factor.

Of course, I’ll also need to resize the forms height and width by the same percentage, and move each control accordingly.

I’ll be adding a class (cusResizer) for this series which automatically performs the calculations and resizing of forms and form objects. It will be available for download soon.

And, we’re done!

Well, not quite yet.

The code above works fine in XP, but how does it do in Vista and Windows 7 and 8?

That depends...