Windows窗口自动缩放机制
通过自动缩放功能,能使在一个计算机上设计的界面在另一个具有不同分辨率或系统字体的计算机上能正常显示。这样窗体及其控件就能通过智能化调整大小以保障在本地电脑和用户电脑上保持一致。
自动缩放的必要性
如果没有自动缩放功能,当改变显示分辨率或字体时,其对应的应用不是显得太大,就是显得太小。例如,为Tahoma 9 point字体设计的程序,在系统字体为Tahoma 12 point的计算机上运行时,如果不对它进行任何调整,该应用程序就会显得很小。其呈现的文本 与其他应用程序相比都要小一些。此外,包含文本的UI元素的大小也与使用的字体相关,此时这些元素也会显得相对小些。
如果程序是针对某种分辨率设计的,也会发生类似情况。最常见的显示分辨率为96DPI(dots per inch),按时高分辨率的显示器如120、133、170也越来越多。如果应用不随着分辨率调整,大小显示也会不正常。
自动缩放即根据相对字体大小或分辨率来对窗体及其控件的大小进行调整。Windows操作系统能使用一种称为对话框单位(dialog units)的相对单位,对对话框进行自动缩放。对话框单位基于系统字体,它与像素的关系可以通过Win32 SDK的GetDialogBaseUnits函数确定。当用户改变了Windows使用的主题,所有的对话框都会自动调整对话框。另外,.NET框架能根据默认系统字体会显示分辨率自动缩放。当然,也可以禁用自动缩放。
最早对自动缩放的支持
.NET 1.0和1.1 采用一种很直接的方法实现自动缩放,该方法依赖于UI使用的Windows默认字体,该字体由Win32 SDK的DEFAULT_GUI_FONT表示。通常只有在显示分辨率改变时,该字体才会改变。下面的机制用于实现自动缩放:
- 设计时,AutoScaleBaseSize属性(已被废弃)被设置为本地电脑上默认系统字体的高度和宽度。
- 运行时,使用用户电脑上的默认系统字体初始化Form类的Font属性。
- 在窗体显示前,调用ApplyAutoScaling方法缩放form。该方法先计算AutoScaleBaseSize和Font的相对大小,然后调用Scale方法实现form及其组件的缩放。
- 因为AutoScaleBaseSize的值已经更新,所以之后调用ApplyAutoScaling不再调整窗口。
该机制可满足大部分需求,但它还有以下缺陷:
- 因为AutoScaleBaseSize将baseline字体大小表示为整数值,所以某个窗体在经过多次分辨率更改后,其收入误差会越来越大。
- 尽在Form类中实现了自动调整,而ContainerControl中没有。所以只有在用户控件与窗体在相同的分辨率下进行设计,并在设计阶段将控件放入窗体,用户控件才能正确缩放。
- 只有在大家的计算机分辨率都相同的情况下,才能同时设计窗体及其子控件。并且还会使窗体的继承依赖于与父窗体关联的分辨率。
- 和.NET 2.0中引入的布局管理器(FlowLayoutPanel和TableLayoutPanel)不兼容。
- 不支持直接以与.NET 兼容框架所需的显示分辨率进行缩放。
所以,虽然该机制在.NET 2.0中保留以维护向后兼容性,但它已经被下面将要介绍的更可靠的机制所取代。因此,预期相关的类AutoScale, ApplyAutoScaling, AutoScaleBaseSize和某些Scale重载已过时。
现在对自动缩放的支持
在.NET 2.0中对Windows窗体的缩放的改进如下:
- 对ContainerControl类的缩放提供了支持,这样forms, native composite控件以及自动以控件获得了同一的缩放支持。添加了AutoScaleFactor, AutoScaleDimensions, AutoScaleMode和PerformAutoScale类。
- Control类添加了若干新成员,这些新成员用于辅助该类参与缩放并支持在同一窗体上进行混合缩放。具体地说,Scale, ScaleChildren, GetScaledBounds成员用于支持缩放。
- 添加了建立在爱屏幕分辨率基础上的缩放支持,如AusoScaleMode枚举类所定义的。该模式与.NET Compact Framework的自动缩放兼容,从而更易于进行应用程序的迁移。
- 自动缩放与FlowLayoutPanel和TableLayoutPanel等布局管理器兼容。
- 缩放因子现在以浮点值表示,通常为SizeF类型,所以消除了舍入误差。
注意:还不支持DPI和字体混合模式缩放。虽然可以使用一种模式(如DPI)缩放某个控件,然后使用另一个模式(字体)将该控件放置在窗体上,这样做没有问题,但是某个模式下的基窗体和另一个模式下的派生窗体混合时,会导致不可预料的结果。
自动缩放实现
Windows窗体现在使用下面的逻辑实现自动缩放:
- 设计时,每个ContainerControl分别在AutoScaleMode和AutoScaleDimensions中记录缩放模式和当前分辨率
- 运行时,实际分辨率存储在CurrentAutoScaleDimensions属性中。AutoScaleFactor属性会动态计算运行时分辨率和设计时分辨率的比值。
- 加载窗体时,如果CurrentAutoScaleDimensions和AutoScaleDimensions的值不同,则会调用PerformAutoScale方法对该空间及其子控件进行缩放。该方法会挂起布局并调用Scale方法执行实际的缩放。之后,更新AutoScaleDimensions以避免累计缩放。
- 在下面的情况也会调用PerformAutoScale:
- 如果缩放模式为Font,响应OnFontChanged事件。
- 继续执行容器控件布局时检测到AutoScaleDimensions或AutoScaleMode属性发生改变。
- 检测到父ContainerControl在被缩放。每个容器控件只负责使用自己的比例缩放自己的子控件,对父容器中的控件不负责。
- 子控件可通过以下的方式修改其缩放行为:
- 重写ScaleChildren属性以确定其子控件是否应缩放。
- 重写GetScaledBounds方法以调整控件缩放的边界,但不调整缩放逻辑。
- 重写ScaleControl方法更改当前控件的缩放逻辑。
Windows窗口自动缩放机制的更多相关文章
- (译)Windows Azure的7月更新:SQL数据库,流量管理,自动缩放,虚拟机
Windows Azure的7月更新:SQL数据库,流量管理,自动缩放,虚拟机 今早我们释出一些很棒的Windows Azure更新.这些新的提升包括:SQL数据库:支持SQL自动导出和一个新的高级层 ...
- C#自动切换Windows窗口程序,如何才能调出主窗口?
namespace AutoChangeWindow { partial class Form1 { /// <summary> /// 必需的设计器变量. /// </summ ...
- Windows内核读书笔记——Windows异常分发处理机制
本篇读书笔记主要参考自<深入解析Windows操作系统>和<软件调试>这两本书. IDT是处理异常,实现操作系统与CPU的交互的关口. 系统在初始化阶段会去填写这个结构. ID ...
- 【转】Windows 窗口层次关系
原文链接:undefined! 相信在Windows 下面编程的很多兄弟们都不是很清楚Windows 中窗口的层次关系是怎么样的,这个东西很久已经研究过一下,后来又忘记了,今天又一次遇到了这个问题,所 ...
- Windows程序内部运行机制 转自http://www.cnblogs.com/zhili/p/WinMain.html
一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...
- 关于Windows窗口框架
我们知道Windows的窗口消息处理函数是C方式, 面向过程的, 所以窗口框架的基本任务就是将它转成面向对象的方式, 确切的说如何将消息处理函数第一参数HWND转成对象指针. 关于这个问题, 其实网上 ...
- 深入浅出话VC++(1)——Windows程序内部运行机制
一.引言 要想熟练掌握Windows应用程序的开发,首先需要理解Windows平台下程序运行的内部机制,然而在.NET平台下,创建一个Windows桌面程序,只需要简单地选择Windows窗体应用程序 ...
- VC菜菜鸟:建立第一个基于Visual C++的Windows窗口程序
建立第一个基于VisualC++的Windows窗口程序: 发表于:http://blog.csdn.net/it1988888/article/details/10306585 a)执行命令:新建 ...
- Windows窗口消息大全(转)
Windows窗口消息大全,全不全自己看 ////////////////////////////////////////////////////////////////////////// #inc ...
随机推荐
- css定位之绝对定位
绝对定位可以做很多事情,如广告位,弹出框,遮罩层等一些功能 css的定位方式:1.静态定位, 2.绝对定位(固定定位和绝对定位) ,3.相对定位 绝对定位会受到影响的因素有 1.属性的取值. 2.元素 ...
- 2014年4月份第1周51Aspx源码发布详情
基于Extjs4+MVC4权限管理源码 2014-3-31 [VS2012]源码描述: 20140331更新:修改部门管理中bug 20140303更新:增加部门管理模块,主要包含部门添加,编辑,删 ...
- (转)JAVA实现Windows拨号、IP切换
原理: 通过调用windows下的dos命令实现拨号 PS:连接名称获取不一定都是适用,但苦于知道的dos命令太少了,只能将就这么用着. 如有更好的方法,烦请不吝赐教. public class Co ...
- vim使用过程
首先推荐几篇文章先: 用Vim编程——配置与技巧 有时候需要设置映射键,此时可以在.vimrc中配置一些项就可以轻松映射了. 以下是几个映射模式: map : 正常模式,可视化模式和运算符模式可用 n ...
- Eclipse Java 调试基本技巧
前言 这一部分是Eclipse中最为重要的部分.调试的重要性想必大家都清楚. 调试无疑是做项目最苦比的事情,但优秀的编码习惯,良好的调试方式能让这没那么苦,甚至还有点乐趣:). 本文讲解使用Eclip ...
- StatisticalOutlierRemoval源码
源代码 * * Software License Agreement (BSD License) * * Point Cloud Library (PCL) - www.pointclouds.org ...
- mysql加单引号和不加单引号的性能比较
刚刚我们说过了,生活中难免会有一些不如意,比如,我们用一个字符串类型的字段来作为主键,表面上,这太不如意了,然而,事实也证明这是有用的.问题也就出来了,当在查询语句中对该字段值加上单引号和不加查询耗时 ...
- spl_autoload_register更改框架文件引用模式
今天单点登陆要用到 spl_autoload_register,但是YII的Yii::autoload在包含失败的时候会抛异常,就不会执行(spl_autoload_call)其他spl_autolo ...
- Docker registry V2
部署私有Docker Registry 搭建 Insecure Registry 修改Registry server上的Docker daemon的配置,为DOCKER_OPTS增加–insecure ...
- Nginx日志常用分析命令汇总 (转)
三.常用日志分析命令 1.总请求数 1 wc -l access.log |awk '{print $1}' 2.独立IP数 1 awk '{print $1}' access.log|sort |u ...