为流程设置默认 DPI 感知
Windows 上的桌面应用程序可以在不同的 DPI 感知模式下运行。 这些模式可实现不同的 DPI 缩放行为,并且可以使用不同的坐标空间。 有关 DPI 感知的详细信息,请参阅在 Windows 上开发高 DPI 桌面应用程序。 请务必显式为进程设置默认 DPI 感知模式,以避免意外行为。
有两个主要方法可以指定进程的默认 DPI 感知:
1) 通过应用程序清单设置
2) 通过 API 调用以编程方式
建议通过清单设置指定默认进程 DPI 感知。 虽然支持通过 API 指定默认设置,但不建议这样做。
使用应用程序清单设置默认感知
有两个清单设置可用于指定进程默认 DPI 感知模式:<dpiAwareness> 和 <dpiAware>。 <dpiAware> 已在 Windows Vista 中引入,仅允许将进程默认设置设置为系统感知。 <dpiAwareness> 已在 Windows 10 版本 1607 中引入,可用于指定进程默认 DPI 感知模式的有序列表。 这样,便可以设置备份 DPI 感知模式,如果应用程序在 Windows 版本上运行,将无法支持指定的第一种感知模式。 在较旧版本的 Windows 上,将忽略较新的 <dpiAwareness> 标记。 这意味着,你可以使用这两个清单设置来启用一种方案,即进程默认值可能是较旧版本的 Windows 上的系统感知,而在大于 Windows 10 版本 1607 的版本上为按监视器。 在 Windows 10 版本 1607 及更高版本上,如果存在 <dpiAwareness> 元素,则忽略 <dpiAware> 设置。
下表显示了如何使用两个清单设置指定不同的进程默认 DPI 感知模式:
进程默认 DPI 感知模式 | <dpiAware> 设置 | <dpiAwareness> 设置 (Windows 10 1607 版及更高版本) |
---|---|---|
unaware | N/A(清单中没有 dpiAware 设置) 或 <dpiAware>false</dpiAware> |
<dpiAwareness>unaware</dpiAwareness> |
系统感知 | <dpiAware>true</dpiAware> | <dpiAwareness>system</dpiAwareness> |
按显示器 | <dpiAware>true/pm<dpiAware> | <dpiAwareness>PerMonitor</dpiAwareness> |
按监视器 V2 | 不支持 | <dpiAwareness>PerMonitorV2</dpiAwareness> |
下面的示例显示了同一清单文件中使用的 <dpiAwareness> 和 <dpiAware> 设置,用于为不同版本的 Windows 配置进程默认 DPI 感知行为。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
<asmv3:application>
<asmv3:windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
</asmv3:windowsSettings>
</asmv3:application>
</assembly>
以编程方式设置默认感知
虽然不建议这样做,但可以通过编程方式设置默认 DPI 感知。 在进程中创建窗口 (HWND) 后,不再支持更改 DPI 感知模式。 如果要以编程方式设置进程默认 DPI 感知模式,则必须在创建任何 HWND 之前调用相应的 API。
有多个 API 可用于为进程指定默认 DPI 感知。 当前建议的 API 是 SetProcessDpiAwarenessContext,因为较旧的 API 提供的功能更少。
API | Windows 的最低版本 | 无法感知 DPI | 系统 DPI 感知 | 按监视器 DPI 感知 |
---|---|---|---|---|
SetProcessDPIAware | Windows Vista | 空值 | SetProcessDPIAware() | 空值 |
SetProcessDpiAwareness | Windows 8.1 | SetProcessDpiAwareness(PROCESS_DPI_UNAWARE) | SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE) | SetProcessDpiAwareness(PROCESS_PER_MONITOR_DPI_AWARE) |
SetProcessDpiAwarenessContext | Windows 10 版本 1607 | SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE) | SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_SYSTEM_AWARE) | SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE) SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) |
进程默认值与线程默认值
本文档涉及为进程设置默认 DPI 感知。 这是因为 Windows 10 引入了在单个进程中运行多个 DPI 感知模式的支持(在 Windows 10 之前,整个进程必须符合单个 DPI 感知模式)。 在一个进程中支持运行多个 DPI 感知模式称为“混合模式 DPI 缩放”。 在进程中使用混合模式 DPI 缩放时,每个顶级窗口都可以在 DPI 感知模式下运行,该模式可能与进程默认值不同。 除非显式指定,否则在创建时,每个线程都将默认为进程默认值。 有关混合模式 DPI 缩放的详细信息,请参阅混合模式 DPI 缩放和 DPI 感知 API 一文。