47

I created an application that works perfectly until the user selects 125% or 150%. It would break my application. I later found a way to find the font size by detecting the DPI.

This was working great until people with Chinese versions of Windows 7 started using my application. The entire application breaks on Chinese Windows 7. From what I can tell (I can't really test it for I only have the English version and installation the language packs does not cause the problem) Chinese characters are causing a weird DPI that breaks my application.

My current code works like this:

if (dpi.DpiX == 120) // For 125% fonts
{
    // Resize form and set default font to correct problems
}
else if (dpi.DpiX == 96) // For 100 and 150% fonts
{
    // Resize form and set default font to correct problems
}

On English versions of Windows 7 that works great, but somehow Chinese versions skip right by this, and the form destroys itself, with controls not even showing up, font extremely large and pushing past the problem, picture boxes being moved around.

So what is a good way to detect the Windows font scale (100%, 125%, and 150%) without detecting DPI? I need something solid that will work on all Windows 7 operating systems and languages.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Landin Martens
  • 3,283
  • 12
  • 43
  • 61
  • I was typing really fast and made a few spelling mistakes. I meant to say "DPI" not "API". Sorry – Landin Martens Feb 21 '12 at 06:40
  • What you describe sounds much more like a problem with the video driver and/or installed fonts... – Yahia Feb 21 '12 at 06:40
  • Just suggession: if you have seriouse ammount of chinese clients, it worths to invest some time to create at least `VirtualMachine` for `VirtualBox` or `VmWare`, so you can test your app on it with as closest fedelity to the real os, as it is possible. – Tigran Feb 21 '12 at 06:45
  • The problem is I can't find a chinese version of windows 7 to use for the 30 day trial period. If you could link me I may be able to fix this. – Landin Martens Feb 21 '12 at 06:58
  • 1
    You can use your own version of `windows`, instal chinese language pack, set regional settings to your clients location and test. This will take one day or more – Tigran Feb 21 '12 at 07:02
  • 4
    Why is 150% denoted by 96dpi and why do you think there are only 3 dpi settings? Users can set lots of other values. – David Heffernan Feb 21 '12 at 07:31
  • 1
    I just want to say that this situation also happen to an English app that I work on. The user set the font scale to 125% and Windows 7 somehow hides controls (dropdown, checkbox, label) in the middle section of the WinForm. The dev team thought there was a configuration issue that dynamically hides the middle section, but it turns out it was the font scale causing the user not able to see the control on a fixed height WinForm. – dsum Jul 14 '15 at 12:47

4 Answers4

19

The correct way of handling variable DPI settings is not to detect them and adjust your controls' sizes manually in a switch statement (for starters, there are far more possibilities than those you show in your sample if statement).

Instead, you should set the AutoScaleMode property of your form to AutoScaleMode.Dpi and let the framework take care of this for you.

Add the following code to your form's constructor (or set this property at design time):

this.AutoScaleMode = AutoScaleMode.Dpi;

Although you might prefer to use AutoScaleMode.Font. For more information on automatic scaling, see the MSDN documentation.

Cody Gray - on strike
  • 239,200
  • 50
  • 490
  • 574
  • 1
    I tried doing that, but the problem is my application messes up with that – Landin Martens Feb 21 '12 at 09:54
  • 1
    @user What does "messes up" mean? What exactly goes wrong? How have you tried debugging it? Do you use relative positioning for your controls, like by placing them in containers and setting the `Anchor` and `Dock` properties? Absolute positioning will never work, even when the user changes their default font face/size, much less when DPI gets involved. – Cody Gray - on strike Feb 21 '12 at 18:34
  • 8
    using AutoScaleMode.none fixed my problem! – Landin Martens Feb 22 '12 at 06:59
  • 9
    @Landin `AutoScaleMode.None` is exactly what you shouldn't be using. – Mahmoud Al-Qudsi May 20 '12 at 21:30
  • 3
    using `AutoScaleMode.None` fixed my problem, too. In theory no promising, in reality it helped against problems with 125% font enlargement. – TaW Oct 01 '14 at 11:18
  • While that's a great suggestion for native controls it's not ideal if you're integrating with some other components that may not respect those settings. A Web Browser control for example. For that use case you may still want to know the actual scale ratio so you can adjust the browser display font size and scaling mode. – Rick Strahl Jul 29 '16 at 09:47
  • I've tried changing these values and they do nothing. I can tell that the various parts of my code that set absolute sizes are where things need changing. If I just had a scale factor to multiply by I could correct the sizes, but AutoScaleFactor is always (1, 1), and AutoScaleMode doesn't do anything no matter what I set it to. – Dave Cousineau Nov 30 '21 at 20:38
5

For C++/Win32 users, here is a good reference: Writing High-DPI Win32 Applications.

Sinan Ünür
  • 116,958
  • 15
  • 196
  • 339
nspire
  • 1,567
  • 23
  • 26
2

get system DPI scale using this:

Read from registry AppliedDPI dword located in Computer\HKEY_CURRENT_USER\Control Panel\Desktop\WindowMetrics. Then divide it by 96.

try
{
    double scale = 1.0;
    using (RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop\\WindowMetrics"))
    {
        if (key != null)
        {
            Object o = key.GetValue("AppliedDPI");
            if (o != null)
            {
                int value = (int)o;
                scale = (double)value / 96.0;
            }
        }
    }
}
catch (Exception ex)  //just for demonstration...it's always best to handle specific exceptions
{
    //react appropriately
}

for 100% --> value is 96 scale is 1.0

for 125% --> value is 120 scale is 1.25

for 150% --> value is 144 scale is 1.5

now you can resize your form and set new font size by this scale automatically;

-1

if your on a newer version of windows I recommend reinstalling your graphics card drivers ( e.g installing a newer version) I had the same problem, my display scale was set to 100% but the font was way off. hope this fixes your problem