DPI适配之实践篇
获取当前系统的DPI缩放系数
使用如下方法来获得当前缩放系数:
float GetDPIFactor()
{
static float s_fDPI = -1;
if (s_fDPI < 0)
{
HDC hDC = ::GetDC(NULL);
s_fDPI = (float)GetDeviceCaps(hDC, LOGPIXELSX) / 96.0);
::ReleaseDC(NULL, hDC);
}
return s_nDPI;
}
#define MultiPlyDPI(nLen) (int((nVol)*GetDPIFactor()))
对话框缩放
对话框使用对话框字号来决定控件之间的布局,它们通常不需要进行特殊修改,就能在高DPI设备上工作。对话框本身的宽高,如果不手动设置的话,是会随着DPI缩放而缩放,一旦有手动设置,就不能简单写个数字,而是要乘以DPI缩放系数,保证在不同DPI下显示效果的一致。
控件缩放
控件缩放分为自身缩放以及相对位置缩放。
- 自身缩放
- 静态放置的控件,需要为额外分配一些宽度
- 动态调整的空间,在调整位置和大小时,需要乘以DPI缩放因子
- 相对位置缩放
- 位于对话框内部的控件之间的相对距离,有直接在资源编辑器中拖拽的,也有通过程序来控制。对于后者来说,间距调整要考虑DPI缩放因子,对于前者,操作系统使用“对话框度量单位”布局,可通过 [GetDialogBaseUnits](https://docs.microsoft.com/en-us/previous-versions/aa931044(v=msdn.10)来获得。
该度量单位是对话框资源中自带的,还没找到方法来修改它,对于这类情况,可在资源编辑器中预留适当间隔来满足不同DPI下的显示需求。
- 位于对话框内部的控件之间的相对距离,有直接在资源编辑器中拖拽的,也有通过程序来控制。对于后者来说,间距调整要考虑DPI缩放因子,对于前者,操作系统使用“对话框度量单位”布局,可通过 [GetDialogBaseUnits](https://docs.microsoft.com/en-us/previous-versions/aa931044(v=msdn.10)来获得。
字体创建
在创建字体时,推荐使用磅来指定字号,磅是逻辑大小,而不是像素高度,创建方法如下:
LOGFONT lf;
memset(&lf, 0, sizeof(lf));
lf.lfHeight = -(iPointSize * GetDeviceCaps(hdc, LOGPIXELSY)) / 72;
HFONT font = CreateFontIndirect(&lf);