WM_DPICHANGED 消息
当窗口的有效的每英寸点数 (dpi) 发生更改时发送。 DPI 是窗口的缩放因子。 有多个事件可能导致 DPI 更改。 以下列表指示 DPI 更改的可能原因。
- 窗口会移动到一个使用另一 DPI 的新监视器。
- 承载窗口的监视器的 DPI 会更改。
窗口的当前 DPI 始终等于 WM_DPICHANGED 发送的最后 DPI。 对于了解 DPI 更改的线程,窗口应缩放到该缩放因子。
#define WM_DPICHANGED 0x02E0
参数
-
wParam
-
wParam 的 HIWORD 包含窗口新 DPI 的 Y 轴值。 wParam 的 LOWORD 包含窗口新 DPI 的 X 轴值。 例如,96、120、144 或 192。 对于 Windows 应用,X 轴和 Y 轴的值完全相同。
-
lParam
-
一个指向 RECT 结构的指针,该结构提供针对新 DPI 进行缩放的当前窗口的建议大小和位置。 我们期望应用会在处理此消息时根据 lParam 提供的建议重新定位窗口并重设窗口大小。
返回值
如果应用程序处理此消息,它应返回零。
注解
此消息仅与 PROCESS_PER_MONITOR_DPI_AWARE 应用程序或 DPI_AWARENESS_PER_MONITOR_AWARE 线程相关。 如果顶级窗口或进程以“DPI 未感知”或“系统 DPI 感知”方式运行,则可能会在某些 DPI 更改时收到该消息,但在这些情况下,可以放心地忽略该消息。 有关不同类型感知的详细信息,请参阅 PROCESS_DPI_AWARENESS 和 DPI_AWARENESS。 旧版 Windows 要求将 DPI 感知绑定到应用程序级别。 这些应用使用 PROCESS_DPI_AWARENESS。 目前,DPI 感知与线程和单个窗口相关,而不是与整个应用程序相关。 这些应用使用 DPI_AWARENESS。
缩放应用程序时,只需使用 X 轴或 Y 轴值,因为它们相同。
为了正确处理此消息,需要根据 lParam 提供的建议使用 SetWindowPos 重设窗口大小和重新定位窗口。 如果不这样做,窗口会相对于新显示器上的其他所有内容增大或缩小。 例如,如果用户使用多个显示器并将窗口从 96 DPI 显示器拖动到 192 DPI 显示器,则相对于 192 DPI 显示器上的其他项而言,窗口将显示为一半大。
DPI 的基值定义为 USER_DEFAULT_SCREEN_DPI,后者设置为 96。 若要确定显示器的缩放因子,请获取 DPI 值并将其除以 USER_DEFAULT_SCREEN_DPI。 下表提供了一些示例 DPI 值和相关缩放因子。
DPI 值 | 缩放百分比 |
---|---|
96 | 100% |
120 | 125% |
144 | 150% |
192 | 200% |
以下示例提供示例 DPI 更改处理程序。
case WM_DPICHANGED:
{
g_dpi = HIWORD(wParam);
UpdateDpiDependentFontsAndResources();
RECT* const prcNewWindow = (RECT*)lParam;
SetWindowPos(hWnd,
NULL,
prcNewWindow ->left,
prcNewWindow ->top,
prcNewWindow->right - prcNewWindow->left,
prcNewWindow->bottom - prcNewWindow->top,
SWP_NOZORDER | SWP_NOACTIVATE);
break;
}
以下代码将值从 100% (96 DPI) 线性缩放到由 g_dpi 定义的任意 DPI。
INT iBorderWidth100 = 5;
iBorderWidth = MulDiv(iBorderWidth100, g_dpi, USER_DEFAULT_SCREEN_DPI);
缩放值的另一种方法是将 DPI 值转换为缩放因子并使用它。
INT iBorderWidth100 = 5;
FLOAT fscale = (float) g_dpi / USER_DEFAULT_SCREEN_DPI;
iBorderWidth = iBorderWidth100 * fscale;
要求
要求 | 值 |
---|---|
最低受支持的客户端 |
Windows 8.1 [仅限桌面应用] |
最低受支持的服务器 |
Windows Server 2012 R2 [仅限桌面应用] |
标头 |
|