Windows 窗体中的自动缩放Automatic scaling in Windows Forms

借助自动缩放功能,在某台计算机上以某种显示分辨率或系统字体设计的窗体及其控件可以在其他计算机上以不同的显示分辨率或系统字体适当显示。Automatic scaling enables a form and its controls, designed on one machine with a certain display resolution or system font, to be displayed appropriately on another machine with a different display resolution or system font. 它确保窗体及其控件将以智能方式调整大小,以便与本机 Windows 以及用户和其他开发人员的计算机上的其他应用程序保持一致。It assures that the form and its controls will intelligently resize to be consistent with native windows and other applications on both the users' and other developers' machines. 自动缩放和视觉样式的.NET Framework 的支持使.NET Framework 应用程序保持一致的外观和感觉,与每个用户的计算机上的本机 Windows 应用程序相比。The support of the .NET Framework for automatic scaling and visual styles enables .NET Framework applications to maintain a consistent look and feel when compared to native Windows applications on each user's machine.

大多数情况下,自动缩放可充当应出现在.NET Framework 版本 2.0 及更高版本。For the most part, automatic scaling works as expected in .NET Framework version 2.0 and later. 但是,字体方案更改可能会产生问题。However, font scheme changes can be problematic. 有关如何解决此问题的示例,请参阅如何:响应 Windows 窗体应用程序中的字体方案更改For an example of how to resolve this, see How to: Respond to Font Scheme Changes in a Windows Forms Application.

自动缩放的必要性Need for automatic scaling

若不进行自动缩放,在分辨率或字体更改时,为某个显示分辨率或字体设计的应用程序将显示太大或太小。Without automatic scaling, an application designed for one display resolution or font will either appear too small or too large when that resolution or font is changed. 例如,如果应用程序是使用 Tahoma 9 point 作为基准而设计的,则在系统字体为 Tahoma 12 point 的计算机上运行时,若不进行调整它将显示太小。For example, if the application is designed using Tahoma 9 point as a baseline, without adjustment it will appear too small if run on a machine where the system font is Tahoma 12 point. 与其他应用程序相比,呈现的文本元素(如标题、菜单、文本框内容等)要小一些。Text elements, such as titles, menus, text box contents, and so on will render smaller than other applications. 此外,包含文本的用户界面 (UI) 元素(如标题栏、菜单和很多控件)的大小均取决于所使用的字体。Furthermore, the size of user interface (UI) elements that contain text, such as the title bar, menus, and many controls are dependent on the font used. 在此示例中,这些元素的显示也相对小一些。In this example, these elements will also appear relatively smaller.

如果应用程序是针对某种显示分辨率设计的,会发生类似情况。An analogous situation occurs when an application is designed for a certain display resolution. 最常见的显示分辨率为 96 点 / 英寸 (DPI) 等于 100%显示缩放,但更高分辨率显示支持 125%、 150%、 200%(哪个分别等于 120、 144 和 192 DPI) 和更高版本也越来越常见。The most common display resolution is 96 dots per inch (DPI), which equals 100% display scaling, but higher resolution displays supporting 125%, 150%, 200% (which respectively equal 120, 144 and 192 DPI) and above are becoming more common. 如果不进行调整,针对某个分辨率设计的应用程序(特别是基于图形的应用程序)在其他分辨率上运行时就会显示太大或太小。Without adjustment, an application, especially a graphics-based one, designed for one resolution will appear either too large or too small when run at another resolution.

自动缩放寻求解决这些问题,方法是更具相对字体大小或显示分辨率自动调整窗体及其子控件的大小。Automatic scaling seeks to ameliorate these problems by automatically resizing the form and its child controls according to the relative font size or display resolution. Windows 操作系统支持使用一种名为对话框单位的相对度量单位的自动缩放对话框。The Windows operating system supports automatic scaling of dialog boxes using a relative unit of measurement called dialog units. 对话框单位基于系统字体,并且它与像素的关系可由 Win32 SDK 函数 GetDialogBaseUnits 确定。A dialog unit is based on the system font and its relationship to pixels can be determined though the Win32 SDK function GetDialogBaseUnits. 当用户更改 Windows 使用的主题时,所有对话框均自动进行相应调整。When a user changes the theme used by Windows, all dialog boxes are automatically adjusted accordingly. 此外,.NET Framework 支持自动缩放,根据默认系统字体或显示分辨率。In addition, the .NET Framework supports automatic scaling either according to the default system font or the display resolution. 或者,可在应用程序中禁用自动缩放。Optionally, automatic scaling can be disabled in an application.

自动缩放的原始支持Original support for automatic scaling

版本 1.0 和 1.1 版的.NET Framework 支持自动缩放直接的方式依赖 UI,由 Win32 SDK 值使用的 Windows 默认字体DEFAULT_GUI_FONTVersions 1.0 and 1.1 of the .NET Framework supported automatic scaling in a straightforward manner that was dependent on the Windows default font used for the UI, represented by the Win32 SDK value DEFAULT_GUI_FONT. 通常,此字体只在显示分辨率更改时才更改。This font is typically only changed when the display resolution changes. 已使用以下机制来实现自动缩放:The following mechanism was used to implement automatic scaling:

  1. 在设计时,将 AutoScaleBaseSize 属性(现已弃用)设置为开发人员计算机上默认系统字体的高度和宽度。At design time, the AutoScaleBaseSize property (which is now deprecated) was set to the height and width of the default system font on the developer's machine.

  2. 在运行时,用户计算机的默认系统字体用于初始化 Form 类的 Font 属性。At runtime, the default system font of the user's machine was used to initialize the Font property of the Form class.

  3. 在显示窗体前,调用 ApplyAutoScaling 方法以缩放窗体。Before displaying the form, the ApplyAutoScaling method was called to scale the form. 此方法计算 AutoScaleBaseSizeFont 的相对缩放大小,然后调用 Scale 方法来实际缩放窗体及其子窗体。This method calculated the relative scale sizes from AutoScaleBaseSize and Font then called the Scale method to actually scale the form and its children.

  4. 更新 AutoScaleBaseSize 的值,以便对 ApplyAutoScaling 的后续调用不会逐渐调整窗体大小。The value of AutoScaleBaseSize was updated so that subsequent calls to ApplyAutoScaling did not progressively resize the form.

虽然此机制足够实现大多数目的时,但具有以下限制:While this mechanism was sufficient for most purposes, it suffered from the following limitations:

  • 由于AutoScaleBaseSize属性将基准字体大小表示为整数值,会发生舍入错误,窗体循环使用多个解决方案时变得很明显。Since the AutoScaleBaseSize property represents the baseline font size as integer values, rounding errors occur that become evident when a form is cycled through multiple resolutions.

  • 自动缩放仅在 Form 类中实现,无法在 ContainerControl 类中实现。Automatic scaling was implemented in only the Form class, not in the ContainerControl class. 因此,只有在用户控件的分辨率设计为与窗体的相同且在设计时置于窗体时,用户控件才可正确缩放。As a result, user controls would scale correctly only when the user control was designed at the same resolution as the form, and it was placed in the form at design time.

  • 窗体及其子控件只可由计算机分辨率相同的多名开发人员进行同时设计。Forms and their child controls could only be concurrently designed by multiple developers if their machine resolutions were the same. 同样,如果窗体依赖与父窗体关联的分辨率,也会被继承。Likewise it also made inheritance of a form dependent on the resolution associated with the parent form.

  • 它不是与.NET framework 版本 2.0 中,如引入的较新布局管理器兼容FlowLayoutPanelTableLayoutPanelIt is not compatible with the newer layout managers introduced with the .NET Framework version 2.0, such as FlowLayoutPanel and TableLayoutPanel.

  • 它不支持直接基于.NET Compact Framework 的兼容所需的显示分辨率进行缩放。It did not support scaling based directly on the display resolution that is required for compatibility to the .NET Compact Framework.

尽管在.NET Framework 2.0 版,以保持向后兼容性保留了此机制,但它已由下文所述的更可靠的缩放机制取代。Although this mechanism is preserved in the .NET Framework version 2.0 to maintain backward compatibility, it has been superseded by the more robust scaling mechanism described next. 因此,AutoScaleApplyAutoScalingAutoScaleBaseSize 和某些 Scale 重载被标记为“已过时”。As a consequence, the AutoScale, ApplyAutoScaling, AutoScaleBaseSize, and certain Scale overloads are marked as obsolete.

备注

将旧代码升级到.NET Framework 2.0 版时,可以安全地删除对这些成员的引用。You can safely delete references to these members when you upgrade your legacy code to the .NET Framework version 2.0.

当前支持的自动缩放Current support for automatic scaling

.NET Framework 2.0 版通过引入以下更改 Windows 窗体的自动缩放,克服了上述限制:The .NET Framework version 2.0 surmounts previous limitations by introducing the following changes to the automatic scaling of Windows Forms:

  • 基本的缩放支持已移至 ContainerControl 类,以便窗体、本机复合控件和用户控件均接收一致的缩放支持。Base support for scaling has been moved to the ContainerControl class so that forms, native composite controls and user controls all receive uniform scaling support. 已添加新成员 AutoScaleFactorAutoScaleDimensionsAutoScaleModePerformAutoScaleThe new members AutoScaleFactor, AutoScaleDimensions, AutoScaleMode and PerformAutoScale have been added.

  • Control 类还具有使其可参与缩放并支持在同一个窗体上的混合缩放的几个新成员。The Control class also has several new members that allow it to participate in scaling and to support mixed scaling on the same form. 特别是 ScaleScaleChildrenGetScaledBounds 成员支持缩放。Specifically the Scale, ScaleChildren, and GetScaledBounds members support scaling.

  • 已按照 AutoScaleMode 枚举定义添加基于屏幕分辨率的缩放支持以补充系统字体支持。Support for scaling based upon the screen resolution has been added to complement system font support, as defined by the AutoScaleMode enumeration. 此模式适用于支持.NET Compact Framework 这样更易于应用程序迁移的自动缩放。This mode is compatible with automatic scaling supported by the .NET Compact Framework enabling easier application migration.

  • 已向自动缩放实现添加与布局管理器(如 FlowLayoutPanelTableLayoutPanel)的兼容性。Compatibility with layout managers such as FlowLayoutPanel and TableLayoutPanel has been added to the implementation of automatic scaling.

  • 缩放比例现在表示为浮点值,(通常采用 SizeF 结构),以便几乎消除舍入误差。Scaling factors are now represented as floating point values, typically using the SizeF structure, so that rounding errors have been practically eliminated.

注意

不支持任意混合的 DPI 和字体缩放模式。Arbitrary mixtures of DPI and font scaling modes are not supported. 虽然你可能成功使用某种模式(例如 DPI)缩放用户控件并以另一种模式(字体)将其放在窗体上,但混合使用一种模式下的基窗体和其他模式下的派生窗体时可能导致意外结果。Although you may scale a user control using one mode (for example, DPI) and place it on a form using another mode (Font) with no issues, but mixing a base form in one mode and a derived form in another can lead to unexpected results.

操作中的自动缩放Automatic scaling in action

Windows 窗体现在使用以下逻辑自动缩放窗体及其内容:Windows Forms now uses the following logic to automatically scale forms and their contents:

  1. 在设计时,每个 ContainerControl 分别在 AutoScaleModeAutoScaleDimensions 中记录缩放模式及其当前的分辨率。At design time, each ContainerControl records the scaling mode and it current resolution in the AutoScaleMode and AutoScaleDimensions, respectively.

  2. 在运行时,实际的分辨率存储在 CurrentAutoScaleDimensions 属性中。At run time, the actual resolution is stored in the CurrentAutoScaleDimensions property. AutoScaleFactor 属性动态计算运行时和设计时缩放分辨率之间的比率。The AutoScaleFactor property dynamically calculates the ratio between the run-time and design-time scaling resolution.

  3. 窗体加载时,如果 CurrentAutoScaleDimensionsAutoScaleDimensions 的值不同,则调用 PerformAutoScale 方法来缩放控件及其子项。When the form loads, if the values of CurrentAutoScaleDimensions and AutoScaleDimensions are different, then the PerformAutoScale method is called to scale the control and its children. 此方法将挂起布局并调用 Scale 方法来执行实际缩放。This method suspends layout and calls the Scale method to perform the actual scaling. 随后将更新 AutoScaleDimensions 的值以避免渐进式缩放。Afterwards, the value of AutoScaleDimensions is updated to avoid progressive scaling.

  4. 在以下情况下也可自动调用 PerformAutoScalePerformAutoScale is also automatically invoked in the following situations:

    • 如果缩放模式为 Font,则响应 OnFontChanged 事件。In response to the OnFontChanged event if the scaling mode is Font.

    • 当容器控件的布局继续执行并在 AutoScaleDimensionsAutoScaleMode 属性中检测到更改时。When the layout of the container control resumes and a change is detected in the AutoScaleDimensions or AutoScaleMode properties.

    • 如上所述,当父 ContainerControl 正在缩放时。As implied above, when a parent ContainerControl is being scaled. 每个容器控件负责使用自己的比例因子(而不是其父容器的比例因子)缩放其子控件。Each container control is responsible for scaling its children using its own scaling factors and not the one from its parent container.

  5. 子控件可通过多种方式修改其缩放行为:Child controls can modify their scaling behavior through several means:

    • 可重写 ScaleChildren 属性以确定是否应缩放其子控件。The ScaleChildren property can be overridden to determine if their child controls should be scaled or not.

    • 可重写 GetScaledBounds 方法以调整控件缩放到的边界,但不是调整缩放逻辑。The GetScaledBounds method can be overridden to adjust the bounds that the control is scaled to, but not the scaling logic.

    • 可重写 ScaleControl 方法以更改当前控件的缩放逻辑。The ScaleControl method can be overridden to change the scaling logic for the current control.

请参阅See also