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.
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?
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:
Don't use AutoScaleMode.Font
.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With