对抗对话框单位、DPI 和大字体






4.95/5 (22投票s)
保证基于资源的对话框在不同字体 DPI 下具有像素到像素匹配的外观
引言
基于资源的对话框,使用对话框编辑器创建,存在一个潜在的问题,即在较大的 Windows 字体分辨率下无法正确缩放,无论使用 MFC、ATL、WTL 还是纯 Win32 都可以发生这种情况。
提供的类允许为特定的对话框资源固定并修复特定的 DPI 模式。 此外,可以在运行时动态更改基于资源的对话框的 DPI 分辨率/缩放。
背景
例如,对话框上的静态位图通常不会被调整大小,因此如果想要创建一些精美的位图背景或匹配的插图,显然会遇到“大字体”Windows 模式的问题。 这对于向导式和登录对话框特别有用。
有些用户倾向于设置“大尺寸 (120 DPI)”字体模式,这对开发人员来说是一个问题,因为需要进行三重检查才能确定设计好的对话框在 120 DPI 模式下是否看起来正确。
如果程序界面主要基于位图,最好的方法是将分辨率锁定为 96 DPI 并禁止任何进一步的对话框缩放。 遗憾的是,Windows 似乎没有一种简单的方法来关闭 DPI 相关的对话框缩放和“对话框单位”。 我一直在网络上寻找,到目前为止还没有找到针对该问题的简单解决方案。
因此,我编写了一个类。 一旦在显示对话框之前在 WM_INITDIALOG
处理程序中调用了 Attach
方法,对话框将在运行时调整大小并调整以匹配指定的分辨率。
提供的代码包含一个子例程,用于重新解析对话框资源并重新计算 DPI 相关的数值,例如控件的位置和大小。 DPI 中的分辨率作为 Attach
方法的参数指定,标准 Windows 分辨率为 96 DPI。
使用代码
该代码在 MFC、ATL/WTL 和 Win32 框架中经过测试且功能正常。
MFC 示例
... BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); dpi.Attach(AfxFindResourceHandle(IMAKEINTRESOURCE(IDD), RT_DIALOG), m_hWnd,IDD,96.0); // 96 is the DPI // The rest of your initialization code goes here return TRUE; }
ATL/WTL 示例
... BOOL CMyDlg::OnInitDialog() { CDialog::OnInitDialog(); dpi.Attach(_AtlBaseModule.GetResourceInstance(),m_hWnd,IDD,96.0); // ^^^^ DPI // The rest of your initialization code goes here return TRUE; }
注意事项
我一直在寻找更简单的方法,但到目前为止还没有找到。 解析器仅适用于 DIALOGEX
结构,不适用于过时的 DIALOG
结构。
您还必须显式指定对话框字体。 为了正确调整大小,您需要使用 Microsoft Sans Serif
或 Tahoma
(不要使用 MS Sans Serif
或 MS Shell Dlg
)。 Tahoma
具有与 Microsoft Sans Serif
完全相同的度量值。 您可以使用任何其他 TrueType/OpenType 字体,避免使用位图字体,因为它们将无法很好地缩放。
由于显而易见的原因,复选框的大小不受影响,但它仍然会获得正确的放置和对齐。