2008-10-09 88 views
32

我为小企业创建了一个应用程序。办公室的一些员工无法正确查看表格。原因是他们的DPI设置为96dpi以上。有人知道一种方法来控制这个吗?如何在.NET中控制字体DPI WinForms应用程序

对于所有对winforms应用程序有经验的人,您如何控制表单布局以使DPI不影响应用程序的外观?

+0

[如何编写自动缩放到系统字体和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

+0

你也检查这个博客上的这个问题,我认为它提供了关于这个主题的很好的信息:http://www.telerik.com/blogs/winforms -large-dpi-settings-is-it-even-possible- – checho 2016-12-02 14:16:24

回答

16

将AutoScaleMode设置为通过全局搜索/替换随处(即所有用户控件)继承,然后将AutoScaleMode设置为主窗体上的Dpi。

我也发现布局容器比锚更适合这种情况。

63

假设您不尝试尊重用户的UI字体选择(SystemFonts.IconTitleFont),并且仅对一种字体大小的表单进行硬编码(例如Tahoma 8pt,Microsoft Sans Serif 8.25pt),则可以设置表单的AutoScaleModeScaleMode.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); 
     } 
    } 
} 

这是一切都很好,如果你仅仅使用控制。但是,如果您使用任何硬编码的像素大小,则需要按照当前表单的比例因子缩放像素宽度和长度。

  • 绘制25像素高矩形
  • 形式上绘制在位置(11,56)的图像
  • 拉伸绘制一个图标以48×48
  • :的本来可以硬编码的像素尺寸的情况下的一些例子使用Microsoft无衬线8.25pt
  • 得到一个图标的32×32格式,并将其塞进一个PictureBox

如果THI

  • 绘制文本s就是这种情况,您需要通过“电流比例因子”来缩放这些硬编码值。不幸的是没有提供“当前”的比例因子,我们需要自己记录。解决方法是假定初始缩放因子为1.0,并且每次调用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

  • 2

    我知道这有点激烈,但考虑在WPF中重写你的应用程序。每个DPI设置的WPF应用程序都具有相同的外观。

    相关问题