Windows 10屏幕坐标偏移7个单位。

5

我在Windows 10上使用C++编程,采用直接的 Win32 API。

我想让一个窗口出现在屏幕右上角。在做这个的时候,我发现最大化窗口的屏幕坐标为 left=-8, top=-8, right=1936, bottom=1088。

此外,当我将窗口定位在 right=1920 和 top=0 时,右侧会有约 8 个像素的空隙。我试着移动窗口,看看得到了哪些屏幕坐标。

非最大化窗口的 rect.left 可以从 -7 到 1912。

这是怎么回事?微软搞什么鬼?

没有那个讨人厌的间隙,我应该如何设置 rec.right=1913 的值,以对齐屏幕的右侧显示我的窗口呢?

然而,rect.right 为 1920 还留下了一个间隙。因此,rect.right 为 1912 将留下更多的间隙...

我需要一个可在 Vista 上运行的解决方案。在 Windows 10 之前,rect.right 应该是你预期的值 1920。

这里到底发生了什么?我快要开始乱扔刀子了!

从代码上来看,这只是 GetWindowRect 报告的结果...(请原谅我的奇怪调试函数)

::GetWindowRect (_wndo, r);

DBG("ExtRc l=`d r=`d t=`d b=`d w=`d h=`d",
r->left, r->right, r->top, r->bottom, r->right-r->left, r->bottom-r->top);

不要乱扔刀子,会把窗户打碎的。 - rubenvb
那不是一个好问题 - 需要改进一下。代码?图片?你读了非客户区,是吗? - Roman R.
3
有趣的东西。尝试使用属性DWMWA_EXTENDED_FRAME_BOUNDS调用DwmGetWindowAttribute函数:https://msdn.microsoft.com/zh-cn/library/windows/desktop/aa969515(v=vs.85).aspx - Christopher Oicles
@ChristopherOicles 把那个放在答案里,因为那是我的答案。我也不想听 Raymond Chen 谈论与以前的 Windows 版本和可疑程序员保持兼容性。这对我来说看起来完全是错误的。而且,它需要一段时间才能工作,我不确定为什么。我在我认为应该是右上角打开一个对话框,它显示了间隙,但是如果窗口被隐藏打开,那个函数和 GetWindowRect 给我相同的值。我发誓我要去拿刀子!! - Stephen Hazel
2
继续并接受您自己的答案,它比我写的任何东西都更详细。Raymond Chen很酷。 - Christopher Oicles
显示剩余3条评论
2个回答

10
感谢@ChristopherOicles的帮助,以下是他的回答。您可以复制此回答(或进行微调),我会接受您的回答。
问题出在Windows 10破坏了边框宽度。GetWindowRect返回窗口外部屏幕坐标,GetClientRect返回窗口内部坐标。在Win10之前,它们之间的宽度和高度差就是边框的宽度和高度。
但是,在Win10中,边框宽度报告为16个像素,所以每边8个像素。但只有1个像素是可见的,其余7个是透明的。所以你需要考虑这些透明的7个像素,如果你要通过编程的方式将窗口与屏幕对齐的话。用户不想在屏幕边缘旁边留下这7个像素的缝隙!
使用DwmGetWindowAttribute属性DWMWA_EXTENDED_FRAME_BOUNDS可以获取屏幕坐标中实际上显示边框的宽度和高度。与GetWindowRect类似,但该矩形不包括隐藏的部分。
大多数情况下仍然需要使用GetWindowRect设置窗口的宽度和高度,并且需要这些边框上每侧的7个透明像素来正确地编程调整窗口大小。因此,使用GetWindowRect返回的.rect的.left和DwmTerribleName返回的.left之间的差异来获取这7个像素的偏移量。
在我看来,Microsoft中负责的人应该立即被枪毙。我不需要跳过这个问题。这破坏了与过去的兼容性。

似乎DwmGetWindowAttribute + DWMWA_EXTENDED_FRAME_BOUNDS只能在窗口可见后才告诉您窗口的真实位置(如果未调用ShowWindow,则与GetWindowRect给出相同的结果-包括7px边框)。这意味着您需要在窗口显示后重新定位窗口(向左移动7px)-如何避免此移动闪烁? - Haighstrom

2
这是因为窗口边框的宽度和其他因素的影响,这些因素取决于操作系统版本、用户偏好和 DPI 设置。请参见 GetSystemMetrics 函数。

好的,我已经发现GetWindowRect和GetClientRect报告了16像素的边框宽度差异。因此每边8个像素。但是在win10上实际的边框宽度只有1个像素。你有没有一个API可以帮我找出报告的8像素边框宽度中有多少是“空气”?我怎么才能从Windows API中得到那个神奇的7呢?我以前计算边框宽度的唯一方法是通过GetWindowRect宽度和GetClientRect宽度之差/2。这种计算在win10中不再适用。那么我如何知道要偏移7个像素? - Stephen Hazel
2
GetSystemMetrics无法获取那7像素的偏移量。使用具有属性DWMWA_EXTENDED_FRAME_BOUNDS的DwmGetWindowAttribute可以获取。 - Stephen Hazel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接