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 ...
随机推荐
- 持续集成-sourcetree的安装、使用记录
1.参考 http://blog.sina.com.cn/s/blog_672143a30102vold.html 2.问题-安装sourcetree后,打开时提示下载但是连接不上相应链接 自行下载g ...
- Java中面向对象的详解
1:成员变量和局部变量的区别(理解) (1)在类中的位置不同 成员变量:类中方法外 局部变量:方法定义中或者方法声明上 (2)在内存中的位置不同 成员变量:在堆中 局部变量:在栈中 (3)生命周期不同 ...
- Java技术的特点
Java技术是一套完整的IT行业解决方案,其中包含了很多技术.最初是从解决家电设备联网通讯的方案发展起来的,其特点适用于Internet,于是在Internet广泛应用的环境下,迅速发展成为一种计算机 ...
- 《JavaScript模式》第3章 字面量和构造函数
@by Ruth92(转载请注明出处) 第3章:字面量和构造函数 一.创建对象的三种方式 // 对象字面量 var car = {goes: "far"}; // 内置构造函数(反 ...
- python数据结构与算法——桶排序
桶排序的时间复杂度是O(M+N),通过建立对原始数据的有序统计表,实现非常快速的排序过程 可以用hashtable(或者dict)实现,查询复杂度为O(1) 贴代码: # 简单桶排序 从小到大 def ...
- c++构造函数的作用---13
原创博客:转载请标明出处:http://www.cnblogs.com/zxouxuewei/ http://blog.csdn.net/tidyjiang/article/details/52073 ...
- php wampserver 80 端口无法开启的解决方法
下载Microsoft Visual C++ 2005 Redistributable Package x86 和 x64(vc_redist.x86.exe/vc_redist.x64.exe) 安 ...
- python知识点记录(一):
1.如何使print输出不换行: 在print语句末尾加上一个英文逗号. 2.安装第三方模块时,用pip和easy_install是一样的.下载一个setuptools.exe安装好就有easy_in ...
- 《C与指针》第三章练习
本章问题 1.What is the range for characters and the various integer types on your machine? (在你的机器上,字符型和整 ...
- linux之各个文件夹作用
/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基点,比如用户user的主目录就是/home ...