【问题标题】:Wrong scaling on Korean PCs韩国 PC 上的错误缩放
【发布时间】:2014-11-16 17:54:32
【问题描述】:

情况

我们正在向世界各地的客户销售 Windows 窗体应用程序。 我们在欧洲和美国的几个国家安装了它。没问题。 上周我们在韩国安装了我们的软件并发现了一个奇怪的行为......

此问题仅出现在客户办公室的 PC 上,但也出现在所有的 PC 上。 有些有 Windows 7 Professional K,有些有 Windows XP。

客户购买了一台安装了 Windows 7 Ultimate 的新 PC。 在这台电脑上没有问题。

函数

我们应用程序中的所有元素都源自提供特殊功能的“父用户控件”。 其中一项功能是“自动调整大小和定位”。 当父级改变大小时,调用所有子级的这个函数。

当我们的应用程序启动时,我们存储“ClientSize”:

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

每当应用程序的大小发生变化时,我们都会计算缩放因子并使用它引发事件:

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);
}

现在,每个订阅的孩子都会执行自动调整大小和定位:

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));
    }

问题

当我们的应用程序在韩国客户的 PC 上启动时,宽度大约是 20% 到小。 这意味着,右侧是一个只有灰色背景的区域。 高度约为高的 10%。 这意味着,位于我们应用程序底部的项目在屏幕之外。

修复

首先,我们认为问题出在 Windows DPI 设置上。 当我将笔记本电脑设置为 125% 时,它看起来很相似。 但是,客户的电脑都设置为 100%...

然后,我们考虑了屏幕分辨率。 都有不同的,有些和我的笔记本电脑一样......

都有不同的图形适配器...

都有 .NET 4.5.1...

解决问题的唯一方法是一种奇怪的方法:

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);

在“Designer”文件中,手动将 ClientSize 从 (1016, 734) 更改为大约 (900, 800)。 这使它在大多数客户 PC 上看起来不错。但并非全部。

问题

什么是这个问题的真正解决方案? 哪里来的?

【问题讨论】:

  • +1 提出了一个很好的问题。很遗憾,我没有给你答案。
  • 这可能值得一看(韩语本地化的 UI 截断问题):stackoverflow.com/a/4458145/96089
  • @Steven,谢谢你的链接。当我尝试修改 Windows DPI 没有结果时,我认为这不是 DPI 问题。当我将安装了 Windows 7 Ultimate 的新 PC 设置为韩语(Windows、键盘、本地化)时,问题不会出现。最后,我无法在我的工作地点(德国)重现这个问题。它只出现在韩国的客户电脑上(现在是晚上 7 点)。
  • 程序员以非常难以诊断的方式陷入 dpiAware 问题。您需要记住,XP 支持一个糟糕的技巧,您可以增加系统字体的大小而不更改 DPI 设置。在东亚非常流行,在低分辨率屏幕上阅读错综复杂的字形并不容易。你不能在你的开发机器上重现这个,这个技巧已经停止了。粗略的诊断是你帮助太多了,Winforms 已经补偿了增加的系统字体大小,你又在做。
  • @HansPassant 谢谢汉斯,你是对的!不需要内置缩放,因为我们在父用户控件中这样做。

标签: c# winforms


【解决方案1】:

如果在每个包含控件上使用AutoScaleMode.DpiAutoScaleMode.None 而不是AutoScaleMode.Font,您是否在同一台计算机上遇到相同的问题?

如果这样可以解决您的问题,这就是为什么我认为您的问题可能与使用 AutoScaleMode.Font 有关

在较高的级别上,according to MSDNAutoScaleMode.Font 的效果是控件将“相对于类使用的字体的尺寸进行缩放,通常是系统字体 。” (强调我的。)

我深入研究了System.Windows.Forms.ContainerControl 源代码。在控件的OnLayout 事件期间,方法PerformAutoScaleautomatically called。如果AutoScaleMode 设置为Font,那么GetFontAutoScaleDimensions 会被OnLayout 间接调用。 comments in GetFontAutoScaleDimensions解释AutoScaleMode.Font是如何实现的:

// 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.

因此,该方法接受一个“长”字符串,将其发送到 GDI 并询问“这个字符串的尺寸是多少?”值得注意的是,这种方法考虑了控件的字体“通常是系统字体”。

你知道韩文字母(Hangul)is not represented in Arial吗? (直到我研究了这个答案,我才知道!)您的系统字体(例如 Tahoe 或 Arial)与您在韩国的客户不同,这是完全有道理的。两种不同的字体将显示具有不同高度和宽度的相同字符串也是有道理的。所以,我敢打赌,这些问题发生在系统字体与您的系统字体不同的工作站上。

因此,如果您进行一些测试并发现 AutoScaleMode.Font 确实是罪魁祸首,那么您有几个选择:

  1. 不要使用AutoScaleMode.Font

  2. 显式设置所有包含控件的字体 明确地。这将确保ContainerControl 的字体 不默认为计算机的系统字体。

无论您做什么,请确保所有容器的use the same AutoScaleMode 设置。混搭会让人头疼。

祝你好运!

【讨论】:

  • 感谢您的详细研究和回答。我将我们软件中的所有“AutoScaleMode.Font”都修改为“AutoScaleMode.None”,无法识别任何负面的视觉效果。所以下一步将是在韩国进行测试。由于我必须等待客户生产允许测试的时间范围,因此可能需要几天时间才能知道它是否有效。我一知道就告诉你。
  • 好的,我刚在韩国在线测试过,效果很好!!非常感谢!!
猜你喜欢
  • 2013-05-27
  • 1970-01-01
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多