One Ugly App… LIVE!!!

Looking at screenshots is kind of boring, and there’s only about 100 people in the world that have seen my ugly app in-person, so I decided to do a screencast to show it off.

It’s 3 minutes and 56 seconds long. If you don’t want to watch the whole video, but would like to see how to go from “Fox Ugly” to “Fox Foxy” in just two clicks, feel free to jump ahead to the 3:30 mark.

Enjoy!

For what it’s worth, I made up the fiverr story for the video (and the fiverr post is made up). If you use fiverr, no offense is intended.

If the YouTube frame isn’t shown on the page, click here to watch One Ugly App… LIVE!!!

 

 

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

Windows Is Lying To You… With DPI Virtualization

DPI Virtualization in Windows

Windows Vista (and subsequently, Windows 7 & 8) introduced a new feature called DPI Virtualization.

DPI Virtualization means Windows will automatically “resize” your forms and form objects for you, with no coding or resizing required on your part.

Sounds great, doesn’t it? Well, not quite. Remember my “ugly” form in an earlier post, running at 144dpi? It was DPI Virtualized by Windows 7, and the result was a blurry window.

DPI Virtualization also requires the code listing from a previous post to fail, every time. Why? Because when the code asks Windows, “Hey, what’s the current setting?”, Windows Vista, 7 and 8 will always answer “your font factor is 1” (no resizing required) if the user has selected to use DPI Virtualization.

“Whoa, whoa, whoa, Kevin! If the user has selected DPI Virtualization?”

Yes. Windows Vista, 7 and 8 have two different modes of DPI scaling: XP Style, and DPI Virtualization.

Setting the DPI scale mode in Windows 7

Setting the DPI scale mode in Windows 7

If the user changes her DPI setting, and checks the “Use Windows XP style DPI scaling” checkbox, Windows Vista, 7 and 8 will return the expected (truthful) result from the previous code listing – just like XP did.

So, a DPI of 144dpi (150%) with this box unchecked, results in the following:

The correct font factor with XP style scaling turned on

The correct font factor with XP style scaling turned on

And, just like I would do with the XP result from earlier, I would want to resize my forms and form objects, making them 50% larger than “normal.”

But if the user has not checked the box, here’s what Windows tells me about the “font factor” (notice the messagebox is also a bit blurry):

Thanks, Windows, for lying and making my forms blurry

Thanks, Windows, for lying to me and making my forms blurry

Great. The user has selected 144dpi, but my app does not know this because Windows has said, “Don’t worry, no need to resize anything. All is good.”

And my user gets to see “somewhat” resized, yet blurry, forms in my app.

What we need is a “Windows Lie Detector” to make sure Windows stops lying to us.

How do we do this?

We need to tell Windows that the app is “DPI Aware”.

And that’s exactly what we’ll look at in tomorrow’s post.

 

Related Links (With much better explanations)

High DPI Settings In Windows
Fixing Windows Programming

 

Respecting The User’s Color Settings

Before we talk about color settings, it’s important to know upfront where Visual FoxPro gets the default values for forms and form objects.

Have you ever wondered where the VFP IDE comes up with its default colors for forms (and other objects)? They come right from the Windows API.

According to the VFP Help File: “The color settings, or Themes, of the operating system set the default color settings for the BackColor and ForeColor properties.”

This explains why, on my machine, when I create a new form in Windows 7 the properties sheet contains the following (BackColor = 240,240,240):

Default form BackColor on my Windows 7 machine

The default BackColor for a new form on my Windows 7 machine is 240,240,240

The BackColor property depends completely on the current color scheme (theme) I’m using in Windows at design time. If I am set to Windows Classic in Windows 7, the BackColor is different. If I decide to punish myself and create a new form while the High Contrast (Black) theme is running, the default BackColor will be 0,0,0.

When I open this form in Windows XP, I get a different BackColor:

Default form BackColor on my Windows XP machine

The default BackColor of a new form in XP (depends on your theme)

What this means is if I do not change the BackColor of a new form, even if I created the form in Windows 7 with an Aero theme, my form BackColor will match whatever theme I’m using in other versions of Windows (and Windows themes) at design time and runtime – without me having to do anything!

In short, “Your Default BackColor = the Windows API System Color”.

This is pretty powerful stuff. In Windows 7, I’ve created the form pictured below. I left the BackColor property as the Default. When I run it in Windows 7, I see this:

Same BackColor as my default

Just as I expected. The exact same BackColor as the default in my design environment.

When I run the same form on Windows XP (with the Windows XP Blue Theme), I get this:

A bit different

It’s different, but the same

It’s different, but it’s exactly what Windows wants the BackColor to be, based on the theme.

When I change the XP theme to Windows Classic Spruce, I get this:

Perfect!

Perfect! And I didn’t have to change a thing!

And once again, the BackColor matches the Windows theme at runtime. All without a single property change or a single line of code!

I wonder what happens when I make a change to the BackColor?

I flip back to my Windows 7 dev machine, change the BackColor to 192,192,192, save and run the form – and here’s what I see:

Big deal. It's exactly what I told it to be, right?

Big deal. It’s exactly what I told it to be, right?

And running the same form on XP (again with the Blue Theme):

Same BackColor as Windows 7, because I told it to change

Same BackColor as Windows 7, because I told it to change

Whew! I’ve set my form BackColor to 192,192,192, and it looks relatively the same on my Windows 7 and Windows XP. So, I’m done, right?

Not quite. I changed my theme in Windows XP back to “Spruce”:

That's different. REAL different. And, dare I say it? Ugly!

That’s different. REAL different. And, dare I say it? Ugly!

OK, I don’t like that. So, I’ll just jump back into VFP and change the color back to what Windows 7 said the default should be: 240,240,240.

Let’s see it in Windows 7:

And we're back to the default! Or, are we?

And we’re back to the default! Or, are we?

So far, so good. Let’s see how it looks in Windows XP “Spruce”:

What happened? I changed it back to the default!

What happened? I changed it back to the default!

I expected my form BackColor to pick up the Windows theme again. But, it didn’t. Let’s take a look at the property sheet:

Hmm... It's the Default, but it's not the "Default"

Hmm… It’s the Default, but it’s not the “Default”

When a property is shown in Bold in the VFP Properties window, it’s not the Default – even if the value is the same as the Default value you expected.

So, how can we get it back to the way it was originally? Reset to Default. Right-click the property in the Properties window, and select “Reset to Default” from the context menu:

Fixed. Finally!

Fixed. Finally!

 

So, what’s the big tip for forms and form objects?

Don’t touch the default values for “color” properties if you want your forms (and form objects) to be consistent with Windows themes.

If you do change them, then later decide to go back to the “Default”, make sure you “Reset to Default”!

Just in case you need more evidence of just how ugly the form is when the BackColor is not set to the Default (i.e. Windows System Color), here’s the same form in High Contrast with the BackColor set to 192,192,192:

At least the label and the button used the correct colors.

At least the label and the button used the correct colors.

After a “Reset to Default”, the form looks like this:

Whew, that's better!

Whew, that’s better!

As you can see from the previous images, the BackColor, ForeColor (in fact, all of the color properties) are tied to the Windows System Colors at runtime – but only if their values are set to their Default properties!