情况
我们正在向全球客户销售Windows Forms应用程序。 我们在欧洲和美国的几个国家安装了它。没问题。 上周我们在韩国安装了我们的软件并认识到了一种奇怪的行为......
问题仅发生在客户办公室PC上,而是发生在所有客户办公室PC上。 有些有Windows 7 Professional K,有些有Windows XP。
客户购买了一台安装了Windows 7旗舰版的新电脑。 在这台电脑上,没有问题。
功能
我们的应用程序中的所有元素都来自父母用户控制"提供特殊功能。 其中一个功能是"自动调整和定位"。 当父级更改大小时,将调用所有子级的此函数。
当我们的应用程序启动时,我们存储" 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%时,它看起来很相似。 但是,客户PC都设置为100%......
然后,我们考虑了屏幕分辨率。 所有都有不同的,有些和我的笔记本电脑一样......
所有人都有不同的grafic适配器......
所有人都有.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上看起来很好。但不是全部。
问题
这个问题的真正解决方案是什么? 哪里可以来自?
答案 0 :(得分:2)
如果您在每个包含控件上使用AutoScaleMode.Dpi
或AutoScaleMode.None
而不是AutoScaleMode.Font
,那么您是否在同一台计算机上遇到同样的问题?
如果这样可以解决您的问题,我认为您的问题可能与使用AutoScaleMode.Font
在较高级别according to MSDN,AutoScaleMode.Font
的效果是控件将相对于类正在使用的字体尺寸进行缩放,通常是系统字体。" (强调我的。)
我稍微挖掘了System.Windows.Forms.ContainerControl
源代码。在控件的PerformAutoScale
事件期间,方法OnLayout
为automatically 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
确实是罪魁祸首,那么你有几个选择:
请勿使用AutoScaleMode.Font
。
显式设置所有包含控件的字体
明确。这将确保ContainerControl
的字体
不会默认使用计算机的系统字体。
无论您做什么,请确保设置所有容器use the same AutoScaleMode
。混合和匹配会导致头痛。