Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wrong scaling on Korean PCs

Tags:

c#

winforms

The Situation

We are selling a Windows Forms Application to customers all over the world. We installed it in several countries in Europe and America. No problems. Last week we installed our software in South-Korea and recognized a strange behaviour...

The problem occurs only on the customers office PCs, but on all of them. Some have Windows 7 Professional K, some have Windows XP.

The customer bought a new PC with an installed Windows 7 Ultimate. On this PC, there is no problem.

The Function

All elements in our application are derived from a "parent-user-control" that offers special functions. One of these functions is "autosizing and positioning". When the parent changes size, this function of all childs is called.

When our application starts, we store the "ClientSize":

InitializeComponent();
this.m_actSize = this.ClientSize;

Whenever the size of the application changes, we calculate the scaling factor and raise an event with it:

void myFormSizeChanged(object sender, EventArgs e)
{
    this.m_xFactor = (float)this.ClientSize.Width / (float)this.m_actSize.Width;
    this.m_yFactor = (float)this.ClientSize.Height / (float)this.m_actSize.Height;
    if (this.m_MyOnResize != null)
        this.m_MyOnResize(this.m_xFactor, this.m_yFactor);
}

Now, each child that subscribed, performs automatic resizing and positioning:

void MyParentUserControl_MyOnResize(float v_xFactor, float v_yFactor)

    {
        this.Location = new Point((int)(this.m_actLocation.X * v_xFactor), (int)(this.m_actLocation.Y * v_yFactor));
        this.Size = new Size((int)(this.m_actSize.Width * v_xFactor), (int)(this.m_actSize.Height * v_yFactor));
    }

The Problem

When our application starts on the customers PCs in South-Korea, the width is about 20% to small. That means, on the right side is an area where is just a grey background. The height is about 10% to high. That means, the items located on the bottom of our application are outside the screen. enter image description here

The Fix

First, we thought the problem comes from the Windows DPI setting. When I set my Laptop to 125%, it looked similar. But, the customers PCs are all set to 100%...

Then, we thought about the screen resolution. All have different ones, some the same as my Laptop...

All have different grafic adapters...

All have .NET 4.5.1...

The only way, that solved the problem, was a strange one:

this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.SystemColors.ScrollBar;
this.ClientSize = new System.Drawing.Size(1016, 734);

In the "Designer" file, manually changing the ClientSize from (1016, 734) to about (900, 800). This made it look good on most customer PCs. But not on all.

The Question

What can be the real solution for this problem? Where can it come from?

like image 270
d.wing Avatar asked Nov 14 '14 07:11

d.wing


1 Answers

Do you have the same issues on the same computers if you use AutoScaleMode.Dpi or AutoScaleMode.None instead of AutoScaleMode.Font on each containing control?

If that solves your problem, here is why I think your issue may be related to using AutoScaleMode.Font

At a high level, according to MSDN, the effect of AutoScaleMode.Font is that the control will "scale relative to the dimensions of the font the classes are using, which is typically the system font." (Emphasis mine.)

I dug into the System.Windows.Forms.ContainerControl source code a bit. The method PerformAutoScale is automatically called during a control's OnLayout event. If AutoScaleMode is set to Font, then GetFontAutoScaleDimensions is called indirectly by OnLayout. The comments in GetFontAutoScaleDimensions explain howAutoScaleMode.Font is implemented:

// We clone the Windows scaling function here as closely as
// possible.  They use textmetric for height, and textmetric
// for width of fixed width fonts.  For variable width fonts
// they use GetTextExtentPoint32 and pass in a long a-Z string.
// We must do the same here if our dialogs are to scale in a
// similar fashion.

So, the method takes a "long" string, sends it out to GDI and asks, "what are the dimensions of this string?" Notably, this method takes into consideration the control's font "which is typically the system font."

Did you know that the Korean alphabet (Hangul) is not represented in Arial? (I didn't until I researched this answer!) It makes perfect sense that your system font (something like Tahoe or Arial) is different than that of your clients in South Korea. It also makes sense that two different fonts will display the same string of characters with a different height and width. So, I bet the issues in question occur on workstations with a system font different than your system font.

So, if you do some testing and find that AutoScaleMode.Font really is the culprit, then you have a few options:

  1. Don't use AutoScaleMode.Font.

  2. Explicitly set the font of all containing controls explicitly. This will ensure that the font of the ContainerControl does not default to the computer's system font.

No matter what you do, ensure all of your containers use the same AutoScaleMode setting. Mixing and matching will lead to headaches.

Good Luck!

like image 185
Mike Avatar answered Oct 27 '22 00:10

Mike