Is Your App DPI-Aware?

When you tell Windows Vista (and 7 & 8) that your app is DPI-aware, Windows will not use DPI virtualization for your app and will no longer “lie” when you ask about the DPI settings.

Please note that by telling Windows that your app is DPI-aware, it is completely up to your app (you) to resize your UI in order to match user expectations based on their settings.

There are 2 different ways to tell Windows Vista, 7 and 8 that your app is DPI-aware:

  • a Windows API function, or
  • adding a section to your apps manifest file.

Using a Windows API Function

Windows Vista, 7 and 8 contain an API function named SetProcessDPIAware. The function has no parameters. It returns a zero if the function fails, and a non-zero result if the function succeeds.

Using it from within Visual FoxPro is easy:

DECLARE INTEGER SetProcessDPIAware IN WIN32API
SetProcessDPIAware()

The function simply tells Windows, “This app (process) is DPI Aware, so please do not lie to me. I will handle all of the resizing myself, so my users will see things the way they want to.”

Easy, right? Well, kind of. If you run the code listing above from the VFP Command Window, and if your Windows DPI setting has been set to 144dpi with DPI Virtualization turned on, you’ll get the correct (truthful) font factor from Windows (when you follow the API call with the code listing from a previous post).

BUT, remember this function has told Windows that this process is DPI-aware. And since you’re running the code from within the VFP IDE, you’re essentially telling Windows that Visual FoxPro is DPI-aware.

Unfortunately, Visual FoxPro is not DPI-aware, and has already been “DPI virtualized” by Windows. Causing Windows to suddenly accept that Visual FoxPro is DPI-aware can wreak havoc with the IDE.

If you don’t trust me on this, try it. It’s u-g-l-y!

So, one way we can force Windows to accept the fact that our app is DPI-aware is to simply call the SetProcessDPIAware function – preferably as early in your app as possible. I have seen several forum postings which report calling the function too late can cause Windows to continue to “lie” and use DPI virtualization anyway, though I have not recreated this problem myself.

 

Using Your App Manifest File

Another way to tell Windows Vista (and 7) that the app is DPI-aware is to add the following section to your app manifest file:

<asmv3:application xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
   <asmv3:windowsSettings xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
      <dpiAware>true</dpiAware>
   </asmv3:windowsSettings>
</asmv3:application>

If you are not sure about manifest files and adding manifest resources to your Visual FoxPro applications, I recommend the following articles (I’ve been using Markus’ Manifest Tools in my work):

Calvin Hsia: Add a Manifest to Control Your Application Vista UAC Behavior

Craig Boyd: Apply Application Manifest At Compile Time With ProjectHook

Markus Winhard: ManifestTools.zip (based on code from Calvin’s blog above)

If you are not comfortable with messing around with manifest files, the SetProcessDPIAware API function is the way to go. Just be sure it only runs on Vista/Win7/Win8 (or call it in a TRY-CATCH-ENDTRY block) to prevent an error in pre-Vista versions of Windows!

Additional thoughts and (better) explanations of DPI-awareness in Vista can be found in the following article: http://www.rw-designer.com/DPI-aware