我为小企业创建了一个应用程序。办公室的一些员工无法正确查看表格。原因是他们的DPI设置为96dpi以上。有人知道一种方法来控制这个吗?如何在.NET中控制字体DPI WinForms应用程序
对于所有对winforms应用程序有经验的人,您如何控制表单布局以使DPI不影响应用程序的外观?
我为小企业创建了一个应用程序。办公室的一些员工无法正确查看表格。原因是他们的DPI设置为96dpi以上。有人知道一种方法来控制这个吗?如何在.NET中控制字体DPI WinForms应用程序
对于所有对winforms应用程序有经验的人,您如何控制表单布局以使DPI不影响应用程序的外观?
将AutoScaleMode设置为通过全局搜索/替换随处(即所有用户控件)继承,然后将AutoScaleMode设置为主窗体上的Dpi。
我也发现布局容器比锚更适合这种情况。
假设您不尝试尊重用户的UI字体选择(SystemFonts.IconTitleFont),并且仅对一种字体大小的表单进行硬编码(例如Tahoma 8pt,Microsoft Sans Serif 8.25pt),则可以设置表单的AutoScaleMode
至ScaleMode.Dpi
。
这将通过调用Form.Scale()
,这反过来recursivly调用保护ScaleControl()
方法本身以及所有子控件缩放形式由系数CurrentDpiSetting/96
大小和最它的子控件。 ScaleControl
将根据新缩放因子的需要增加控件的位置,大小,字体等。
警告:并非所有控件都能正确缩放自身。例如,一个 列表视图的列将不会获得 更宽的字体变大。在 为了处理您必须 手动执行额外的缩放作为 需要。我做到这一点通过重写 保护
ScaleControl()
方法,并 手动缩放列表视图列:public class MyForm : Form { protected override void ScaleControl(SizeF factor, BoundsSpecified specified) { base.ScaleControl(factor, specified); Toolkit.ScaleListViewColumns(listView1, factor); } } public class Toolkit { /// <summary> /// Scale the columns of a listview by the Width scale factor specified in factor /// </summary> /// <param name="listview"></param> /// <param name="factor"></param> /// <example>/* /// protected override void ScaleControl(SizeF factor, BoundsSpecified specified) /// { /// base.ScaleControl(factor, specified); /// /// //ListView columns are not automatically scaled with the ListView, so we /// //must do it manually /// Toolkit.ScaleListViewColumns(lvPermissions, factor); /// } ///</example> public static void ScaleListViewColumns(ListView listview, SizeF factor) { foreach (ColumnHeader column in listview.Columns) { column.Width = (int)Math.Round(column.Width * factor.Width); } } }
这是一切都很好,如果你仅仅使用控制。但是,如果您使用任何硬编码的像素大小,则需要按照当前表单的比例因子缩放像素宽度和长度。
如果THI
ScaleControl()
时,都会通过新因子修改运行缩放因子。 public class MyForm : Form
{
private SizeF currentScaleFactor = new SizeF(1f, 1f);
protected override void ScaleControl(SizeF factor, BoundsSpecified specified)
{
base.ScaleControl(factor, specified);
//Record the running scale factor used
this.currentScaleFactor = new SizeF(
this.currentScaleFactor.Width * factor.Width,
this.currentScaleFactor.Height * factor.Height);
Toolkit.ScaleListViewColumns(listView1, factor);
}
}
最初缩放因子是1.0
。如果形式随后通过1.25
缩放,该缩放因子,则变为:
1.00 * 1.25 = 1.25 //scaling current factor by 125%
如果窗体然后通过0.95
缩放,新缩放因子变得
1.25 * 0.95 = 1.1875 //scaling current factor by 95%
使用SizeF
的原因(而比单个浮点值)是缩放量在x和y方向上可能不同。如果表单设置为ScaleMode.Font
,表单将缩放为新的字体大小。字体可以具有不同的纵横比(,例如Segoe UI是比Tahoma更高的字体)。这意味着您必须独立缩放x和y值。
所以,如果你想在位置(11,56)
放置控制,你就必须从改变你的定位代码:如果你要挑选
Point pt = new Point(11, 56);
control1.Location = pt;
到
Point pt = new Point(
(int)Math.Round(11.0*this.scaleFactor.Width),
(int)Math.Round(56.0*this.scaleFactor.Height));
control1.Location = pt;
同样适用字体大小:
Font f = new Font("Segoe UI", 8, GraphicsUnit.Point);
必须成为:
Font f = new Font("Segoe UI", 8.0*this.scaleFactor.Width, GraphicsUnit.Point);
并提取32×32的图标的位图将改变从:
Image i = new Icon(someIcon, new Size(32, 32)).ToBitmap();
到
Image i = new Icon(someIcon, new Size(
(int)Math.Round(32.0*this.scaleFactor.Width),
(int)Math.Round(32.0*this.scaleFactor.Height))).ToBitmap();
等
支持非标准DPI显示器是一个tax that all developers should pay。但是,没有人愿意的事实是为什么Microsoft gave up and added to Vista the ability for the graphics card to stretch any applications that don't say they properly handle high-dpi。
我知道这有点激烈,但考虑在WPF中重写你的应用程序。每个DPI设置的WPF应用程序都具有相同的外观。
[如何编写自动缩放到系统字体和dpi设置的WinForms代码?](http://stackoverflow.com/questions/22735174/how-to-write-winforms-code-that-auto -scales-to-system-font-and-dpi-settings) – 2015-07-10 11:23:13
你也检查这个博客上的这个问题,我认为它提供了关于这个主题的很好的信息:http://www.telerik.com/blogs/winforms -large-dpi-settings-is-it-even-possible- – checho 2016-12-02 14:16:24