为什么 1920 设备独立单位不是 1920 像素和 96 DPI?

Why is 1920 device-independent units not 1920 pixel with 96 DPI?

我的 Windows 设置的 DPI 设置为 96。但是当我创建以下内容时 Window 它会比我的屏幕小一点(分辨率设置为 1920* 1080):

<Window x:Class="WPF_Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WPF_Sandbox"
        mc:Ignorable="d"
        Title="MainWindow"
        Width="1920">
</Window>

根据 this msdn 博客 post:

1 device independent pixel = 1/96 inch.
1 physical pixel = 1/DPI (dependent on the system DPI)

Default system settings usually choose a DPI of 96 so these two types of pixels come out to be the same size.

然而,情况似乎并非如此,因为我的 Window 明显小于 1920 像素宽。
如果我最大化 Window 并检查它的 ActualWidth 它似乎是 1936.

为什么会这样?

您的屏幕规格是多少?例如我的显示器间距 = 0.282 毫米;等于 90.0709...ppi。 1920 像素宽 window 在 WPF 中的实际宽度为 2,046 个单位。

确定屏幕的 DPI(如果间距以毫米为单位,则为 25.4/间距)

96/DPI * 1920 => 实际宽度

window确实有1936像素的宽度!

当 window 最大化时,它周围的边框会被裁剪。尽管它不再可见,但仍被视为 window 的一部分。在 Aero 主题中,此边框每边的宽度均为 8px,因此额外增加了 16px:

如果您切换到经典主题,每边只有 4 像素,所以您的 window 将是 1928 像素宽。

问题大致如下:

Why does Window.ActualWidth report a width that does not appear to be the 'real' width of the Window?

答案是 看起来像 window 的全宽并不完全是 的宽度。

当您设置 Width、查询 ActualWidth,甚至使用 GetWindowRect 获取 "no-lies what does windows think my width is" 时,您正在设置或获取Window 包括 不可见部分

那些不可见的部分,尤其是在 Windows 10 上,包括一些额外的 space 以方便用户调整 window 的大小,即使它们有点小有点偏离边界:

(请注意,我的鼠标不在边框上,而是偏右了一点)

这意味着当你最大化你的 window 时,你的宽度仍然是 "padded" 而那个不可见的 space,因此你的 window 大小会比你的大屏幕尺寸。

如何检索额外 space 的宽度? GetSystemMetrics with SM_CXSIZEFRAME and SM_CXPADDEDBORDER is your friend here (example includes code from pinvoke.net):

int extraBorderStuff = GetSystemMetrics(SystemMetric.SM_CXSIZEFRAME)
                       + GetSystemMetrics(SystemMetric.SM_CXPADDEDBORDER);
double realWidthForSure = ActualWidth - borderSize * 2;

如果您随后最大化 window,您应该注意到 realWidthForSure 应该等于您期望的 1920px。